Posts Tagged ‘projektowanie’

Agile estimating and planning

Author: tomasz.szulik (tomasz.szulik) | maj 17th, 2010
W firmie XSolve tradycją stały się już piątkowe prezentacje. Tym razem zaszczytną rolę prelegenta wywalczyłem sobie ja. Zainspirowany lekturą “Agile Estimating and Planning” autorstwa Mike Cohn postanowiłem przedstawić teorię związaną z podejściem “agile” do zagadnienia estymacji.
Zagadnienie estymacji jest dosyć trudnym tematem, dlatego dobrze zapoznać się z teorią oraz praktykami wykorzystywanymi przez doświadczonych “graczy”. Słowo “graczy” wydaje się być trafione jako że, jedna z technik estymacji nosi nazwę: “Planning poker”.
Sądząc po dyskusji, która wywiązała się pod koniec prezentacji, temat jest na prawdę niebanalny i interesujący, dlatego zamieszczam tutaj parę odnośników do materiałów, które pomogą Wam w zaspokojeniu wiedzy.

Przyjemnej lektury!

Insight w programowanie msejf: .NET

Author: jaroslaw.kroczek (jaroslaw.kroczek) | maj 17th, 2010

Poniższym wpisem chcielibyśmy rozpocząć serię postów dedykowanych technologiom, w jakich tworzymy aplikację msejf. Projekt i jego poszczególne elementy wymagają połączenia różnych rozwiązań i dzięki temu jest wyjątkowo ciekawy z punktu widzenia programistów i web developerów.

Cykl chcielibyśmy zacząć od przyjrzenia się technologii .NET, w oparciu o którą zbudowaliśmy część desktopową aplikacji. Spośród typowych bibliotek tej platformy z których korzystaliśmy szczególnie dwie zasługują na szczególną uwagę: WPF i WCF.

WPF (Windows Presentation Foundation) to silnik graficzny bazujący na platformie .NET od wersji 3.0. Co takiego ciekawego jest w WPF, że postanowiliśmy użyć jej do naszej aplikacji? WPF daje nam ogromne możliwości co do kształtowania wyglądu aplikacji. msejf ma być niebanalny, a jeśli tak, to WPF jest naturalnym wyborem. Tworząc interfejs użytkownika praktycznie nie musimy się niczym ograniczać. Nie musimy martwić się o to, że nie będziemy w stanie przełożyć kreatywności naszych grafików na działającą aplikację.

Dla nas, programistów, WPF ma też inne zalety. Przede wszystkim, WPF zmienia całkowicie sposób implementacji aplikacji desktopowych, zbliżając się stylem do aplikacji webowych. Nasze aplikacje oparte są o wzorzec projektowy Model-View-ViewModel, co skutkuje przejrzystym i łatwiejszym w utrzymaniu kodem.

WCF to drugie w kolejności ciekawe rozwiązanie, w oparciu o które zbudowaliśmy klienta msejf. WCF (Windows Communication Foundation) to część .NET Framework’a, która dostarcza ujednolicony model programistyczny dla aplikacji opartych o usługi. Większości będzie się to zapewne kojarzyć z komunikacją z zewnętrznymi serwisami. My wykorzystujemy WCF do komunikacji międzyprocesowej. Technologia znakomicie sprawdza się w tej roli, upraszczając wymianę informacji między komponentami. Jej zastosowanie daje nam też duże możliwości łatwej zmiany konfiguracji oraz monitorowania pracy komponentów dzięki wbudowanym mechanizmom logowania.

Co jeszcze w msejf desktop zasługuje na szczególną uwagę? Zastosowaliśmy mnóstwo ciekawych  rozwiązań. Długo zastanawialiśmy się nad wyborem optymalnej architektury, co zaowocowało sprawnie działającą, łatwą w utrzymaniu i stabilną aplikacją. Na każdym etapie prac staraliśmy się trzymać najlepszych praktyk wytwarzania i projektowania oprogramowania.

msejf desktop to nie tylko ciekawe technologie, ale przede wszystkim innowacyjna aplikacja, a efekt końcowy naszych prac będzie można już wkrótce podziwiać.

źródło: blog.msejf.pl

Najprostszy sposób na zalogowanie użytkownika

Author: Krzysztof Wawoczny (Krzysztof Wawoczny) | kwiecień 26th, 2010

Obecnie, w niemal każdej aplikacji biznesowej wymagane jest zalogowanie się, by w pełni móc korzystać z możliwości, jakie taka aplikacja daje, lub by wogóle móc cokolwiek zrobić. Jakiś czas temu zrobiłem krótki research po sieci w poszukiwaniu jakiegoś sprytniejszego rozwiązania niż to, które używam w swoich aplikacjach. Cóż… Dziwni są ludzie, którzy zatrudniają do obrony swojego zamku legiony, a pozwalają do niej wejść zwykłym OR 1=1 (to tak na marginesie), nie rozumię też rozwiązania, które zostało pozytywnie ocenione na jednym z for programistycznych, a wygląda ono tak:
W aplikacji sprawdzamy, czy ustawiony jest w bazie znacznik informujący o zalogowaniu, jeśli nie, to po zalogowaniu generujemy go, a usuwamy, gdy użytkownik zamknie aplikację… A co, jeśli zwiesi się komp, zabraknie prądu albo wydarzy się coś innego? Przecież po wystąpieniu tak nieoczekiwanego zdarzenia wartość w bazie może się nie zmienić, a wtedy każdy, kto skorzysta z komputera będzie zalogowany. Naprawdę nie rozumię wielu tych wielkich idei, dlatego na razie nadal korzystam z bardzo prostego rozwiązania, które wygląda następująco:

W aplikacji w sekcji odpowiedzialnej za przechowanie predefiniowanych zmiennych globalnych (jak np. nazwa bazy, string wyświetlany w górnej belce aplikacji etc.) ustawiam sobie zmienną, określającą, czy użytkownik jest zalogowany (domyślnie ustawioną na false) oraz metodę pozwalającą zmienić wartość tej zmiennej:

public class GlobalAppVariables
{
    /// Globalna zmienna, której wartość jest ustwaiona na 1, gdy użytkownik się zaloguje.
    static int _logged = 0;

    /// Dostęp/zmiana wartości globalnej zmiennej _logged
    public static int Logged
    {
      get
      {
        return _logged;
      }
      set
      {
        _logged = value;
      }
    }
}

Samo logowanie polega na wywołaniu metody, która połączy się z bazą, sprawdzi, czy dla podanych parametrów istnieje wpis i na tej podstawie zwróci wynik pozytywny/negatywny, co z kolei pozwoli mi ustawić wartość zmiennej _logged w następujący sposób:

private void button1_Click(object sender, EventArgs e)
{
    object result = Queries.StartSession(this.loginTxt.Text, this.PasswordTxt.Text);
   //Queries to osobna klasa, w której przechowywane są metody odpowiedzialne za operacje na bazie
    if (result != null)
    {
        this.Close(); //zamknięcie okna logowania
        GlobalAppVariables.Logged = 1; // w tej chwili wiem, że już mam zalogowanego użytkownika
    }
    else
    {
       //info o nieudanym logowaniu
    }
}

Jeśli już mam zalogowanego użytkownika, mogę odblokować domyślnie wyłączone opcje, lub zrobić coś innego.
Jeśli nie potrzebujesz wymyślnego systemu logowania skorzystaj z przedstawionego sposobu. Jest on wystarczający dla wielu nieskomplikowanych aplikacji. AVE!

Dynamiczne generowanie kontrolek

Author: Krzysztof Wawoczny (Krzysztof Wawoczny) | kwiecień 24th, 2010

W czasie pracy nad swoim małym projektem w C#, stanąłem przed problemem dynamicznego generowania kontrolek na formie. Nie chciałem, aby cały kod za to odpowiedzialny znajdował się w zdarzeniu kliknięcia w button, wiec stworzyłem przykładową klasę, którą nazwałem ControlGenerator.
klasa
Generalnie, trzeba by ją jakoś połączyć z główną formą aplikacji (w projekcie Form1 – standardowe nazewnictwo, gdyż więcej form nie przewiduję). W klasie ControlGenerator utworzyłem zmienną typu Form1 służącą za łącznik klasa – forma:

public class ControlGenerator
{
    /// Prywatna zmienna typu Form1
    private Form1 pf;
   //...
}

Następnie, konstruktor klasy musi posiadać takie przypisanie zmienej pf, aby wskazywała ona na referencję instancji mojej Form1 (trochę to może zamieszane, więc kawałek kodu wyjaśni, co miałem na myśli):

public ControlGenerator(Form1 f1)
{
  pf = f1;
}

Tak właśnie wygląda konstruktor, o którym była mowa, a jak to wygląda ‘na żywo’ jest ukazane poniżej.

W formie głównej aplikacji (Form1) po kliknięciu w jeden z przycisków powinny wygenerować się kontrolki, inicjuję więc obiekt klasy ControlGenerator w następujący sposób:

private void button1_Click(object sender, EventArgs e)
{
    ControlGenerator generate = new ControlGenerator(this);
   // właśnie tu do konstruktora przekazuje referencję do Form1 za pomocą this
}

Skoro moje połączenie klasa – forma jest już aktywne, to pora napisać metodę generującą kontrolki. Do owej metody powinna być przekazana informacja jak wiele kontrolek utworzyć. W poniższym przykładzie ograniczę się do wygenerowania TextBoxów z Labelkami zawartymi w GroupBoxie (które mogą być oczywiście dodatkowo osadzone na jakimś panelu, czy czymkolwiek się chce).
Gotowa funkcja prezentuje się następująco:

    public void GenerateRegisterControls(int number, string text)
    {
      int[] textboxes = new int[number];
      string[] labels = { "Imię", "Nazwisko", "PESEL", "Ulica", "Numer budynku",
                              "Miasto", "Kod pocztowy", "Województwo", "Telefon" };
      int i = 0, move = 0;

      //tworzę GroupBoxa, do którego wrzucę tworzone kontrolki (opis metody w następnym listingu)
      GroupBox box = GenerateGroupBoxControl(text); 

      foreach (int element in textboxes)
      {
        TextBox textbox = new TextBox(); //tworzę nowego TextBoxa
        Label label = new Label(); //tworzę nowy Label
        //lokalizacja TextBoxa
        textbox.Location = new System.Drawing.Point(200, 70 + move);
        textbox.Name = "textbox" + i.ToString();
        textbox.Size = new System.Drawing.Size(360, 20 + move); //wymiary TextBoxa
        //Rozmiar czcionki w TextBoxie - funkcja nie zostanie przedstawiona
        //w tym wpisie
        textbox.Font = SetFontForElement(40, textbox.Font);
        textbox.TabIndex = i;
        textbox.Visible = true;
        //automatyczna zmiana rozmiarów TextBoxa przy zmianie rozmiaru okna
        textbox.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
        textbox.BorderStyle = BorderStyle.FixedSingle; //styl ramki
        //lokalizacja Labela
        label.Location = new System.Drawing.Point(20, 80 + move);
        label.Name = "label" + i.ToString();
        //nazwa Labela wzięta z wcześniej utworzonej tablicy stringów
        label.Text = labels[i];
        label.Font = SetFontForElement(28, label.Font);
        label.Size = new System.Drawing.Size(160, 28);
        label.Visible = true;

        box.Controls.Add(textbox); //dodaję do GroupBoxa utworzone TextBoxy
        box.Controls.Add(label); //dodaję do GroupBoxa utworzone Labele

        i++;
        move += 50;
      }
      //dodaję GroupBoxa z kontrolkami do panelu w kontenerze Form1
      pf.splitContainer1.Panel2.Controls.Add(box);
    }

Jak widać funkcja nie jest specjalnie skomplikowana, a tablicę z nazwami labelek można by przekazać jako parametr – jednak nie ma potrzeby w tym wpisie rozmieniać się na drobne. Tworzenie TextBoxów i Labelek można by dodatkowo zostawić osobnym funkcjom wywołanym w GenerateRegisterControls, jak np. GenerateGroupBoxControl, która wygląda następująco:

    private GroupBox GenerateGroupBoxControl(string text)
    {
      GroupBox box = new GroupBox();

      box.Name = "GroupBoxRegister";
      box.Text = text;
      box.Location = new System.Drawing.Point(1, 9);
      box.Size = new System.Drawing.Size(pf.splitContainer1.Panel2.Width - 20, pf.splitContainer1.Panel2.Height - 20);
      box.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom;

      return box;
    }

Samo wygenerowanie kontrolek po kliknięciu w jeden z przycisków wygląda następująco:

    private void button1_Click(object sender, EventArgs e)
    {
      ControlGenerator generate = new ControlGenerator(this);
      //9 TextBoxów i 9 Labelek, GroupBox będzie opatrzony tekstem Rejestracja
      generate.GenerateRegisterControls(9, "Rejestracja");
    }

Efekt:
efekt

Jeśli ktoś dopiero zaczyna swoją przygodę z C#, to informacje, które przedstawiłem z pewnością się przydadzą, albo przynajmniej wskażą drogę poszukiwań w google. AVE!