środa, 29 sierpnia 2007

Ankieta o UML oraz Unified Process

Jakiś czas temu otworzyłem na blogu ankietę, pytającą o stosunek do języka UML. Wyniki ankiety są wzorcowe, jeżeli można tak powiedzieć :) Oto one:

"UML...
- trzeba wszystko w tym modelować!!! - 0%;
- używać gdy potrzeba - 75%;
- jak muszę to używam - 12%;
- spalić na stosie specyfikację! - 12%.

Pierwszą opcję można było odebrać jako symbol procesu wodospadowego (liniowego), w którym najpierw wykonywało się drobiazgowy projekt, a następnie przekazywano do "produkcji" programistom. Oczywiście teraz już nikt tak nie robi :) Tak samo nie ma sensu wykonywać kompletnej dokumentacji w UML do wykonanego kodu - w końcu dobry kod sam się "komentuje". Drugą dostępną opcją w ankiecie było przesłanie Agile Development - tylko tyle UMLa, aby zrozumieć problem, nie więcej. Trzecia pozycja: "jak muszę to używam" to ukłon do programistów, którzy muszą dokumentować swoją twórczość w UMLu, a niezbyt im się to podoba ;) Ostatnia opcja... no cóż, w małych projektach zalety modelowania nie są aż tak dobrze widoczne jak w większych. "Za dużo UMLa" może zniechęcać... wszyscy (prawie :P) to znamy.

Unified Process
Jak już piszę o UMLu to przedstawię pewien schemat, zaczerpnięty z książki "Applying UML and Patterns", który pokazuje przebieg procesu/metodyki wytwarzania oprogramowania, zwanej Unified Process. Jest to podstawowa metodyka iteracyjna, jej pochodne to: RUP, Agile UP, XP, Scrum, itp.
Ok, teraz najważniejsze, po co komu "proces"?! Czy nie wystarczy, aby każdy robił "swoje"? W małych projektach na pewno, w dużych takie podejście powoduje problemy (dowodem na to jest pewien post na grupie dyskusyjnej pl.praca.dyskusje z końca roku 2006 dot. dużej firmy programistycznej w Polsce ;). UP mówi kto/jakie/kiedy dokumenty/diagramy/kody wytwarza - można by powiedzieć: "taki ogromny plik todo" :D
No to teraz konkretny schemat - oparty na wspomnianej książce:

(based on "Applying UML and Patterns", 3rd ed)

Powyższy schemat przedstawia jedną iterację (długość jednej iteracji to około miesiąc). Po ogólnej analizie problemu, iterację rozpoczyna się od wykonania diagramów przypadków użycia (ud), aby zidentyfikować nazwy i relacje między przypadkami użycia (części wspólne, itp). Następnie na podstawie diagramu ud pisze się teksty przypadków użycia, czyli parustronicowe dokumenty przedstawiające działanie systemu z punktu widzenia użytkownika. Mając przypadki użycia tworzy się systemowy diagram sekwencji (SSD), na którym system traktuje się jako "black box", a użytkownik wykonuje na nim konkretne operacje (w przedstawionym porządku). Te trzy wymienione elementy (ud, use cases, SSD) razem tworzą "Use-Case Model" i stanowią podstawę dalszej analizy problemu.
Korzystając z powyższego modelu można zbudować model domenowy ("Domain Model"). Jest to uproszczony diagram klas (tylko atrybuty i relacje), ale nie służy on do reprezentacji klas języka programowania, tylko domen problemu. Na powyższym schemacie przykładowe domeny to "Sprzedaż", "Kasa" i "KatalogProduktów", relacje między nimi i ich atrybuty pozwalają na statyczną analizę problemu - czyli rozłożenie problemu na czynniki pierwsze.

Mając wykonane dwa powyższe modele można przystąpić do budowy modelu projektu ("Design Model"). Ten model jest inspirowany bezpośrednio przez dwa poprzednie, ale nie w stosunku 1:1 (dlatego słowo "inspirowany" jest jak najbardziej na miejscu). W jego ramach tworzy się _jednocześnie_ diagram klas (DCD) oraz diagram sekwencji, a stworzone diagramy mogą być wykorzystane przez programistów. Oczywiście diagramy nie mają pokryć 100% kodu, ani nawet nie 50%. Diagramy mają być wskazówką i przedstawiać "high level architecture". Dzięki budowie modelu łatwiej jest zmusić programistów, aby pisane przez nich kody współgrały ze sobą. Dodatkowo widząc graficzną strukturę kodu łatwiej jest zastosować wzorce projektowe, wzorce aplikacyjne i przede wszystkim zasady projektowania obiektowego. Dzięki temu wytwarzany kod jest lepszy jakościowo.

Oczywiście Unified Process jest konfigurowalny, w razie konieczności można dodać, czy usunąć pewne elementy (np. w prostych przypadkach tworzenie modelu domenowego może być zbędne, natomiast w skomplikowanych problemach pomocny może być dodatkowy model analityczny).

No to się rozpisałem, ale w sumie uprzedzałem, że coś z książki "Applying" umieszczę na blogu ;)

poniedziałek, 27 sierpnia 2007

Książka "Agile Principles, Patterns, and Practices in C#"

Z powodu sprzyjających warunków i zaciekawienia tematem OOA/D niedługo po przeczytaniu „Applying UML and Patterns” zabrałem sie za „Agile Principles, Patterns, and Practices in C#”.

Książka zapowiadała się nieźle (dlatego po przeczytaniu „Applying" umieściłem ją na liście „to read” jako numer jeden). W sumie warto było ją przeczytać, ale ma ona swoje wady... „Applying” jednak jest „the best” ;)

Generalnie książka ma u mnie duży plus za szczegółowy opis jedenastu zasad projektowania obiektowego (OOD Principles), których w „Applying” zabrakło, dobry opis wzorców projektowych (Proxy, Monostate, Null Object, itp) oraz opis niektórych wzorców aplikacyjnych (Table Gateway). Wszystko poparte praktycznymi diagramami UML. Dodatkowym plusem są dwa rozdziały końcowe: pierwszy opisuje jak połączyć model obiektowy z relacyjną bazą danych, przy zachowaniu zasad dobrego projektowych, natomiast drugi pokazuje, jak wykorzystać model MVP przy tworzeniu GUI w WinForms/.NET.

Zasady OOD, opisane w tej książce, są uszczegółowieniem zasad GRASP. Mówią jaki powinien być projekt i czego unikać, a zasady GRASP raczej ogólnie wspomagają „myślenie” obiektowe (oczywiście nie tylko). Na stronie Uniwersytetu Berkeley o zasadach OOD, opisanych w tej książce, można przeczytać: „These principles are the hard-won product of decades of experience in software engineering. They are not the product of a single mind, but they represent the integration and writings of a large number of software developers and researchers. Although they are presented here as principles of object-oriented design, they are really special cases of long-standing principles of software engineering”.

Podobnie jak w „Applying”, przez książkę przewija się jeden „real world” system informatyczny, budowany od podstaw aż po bazę danych i GUI. Wszystko poparte jest diagramami UML oraz kodem źródłowym. Ciekawe są elementy, w których autor pokazuje, jak zazwyczaj kursanci* wykonują projekty, a jak po zastosowaniu zasad projektowych powinny one wyglądać. Kolejnym ciekawym elementem jest ewolucja projektu, według zasad Agile Development, projekt wykonuje się tylko do aktualnie tworzonych funkcjonalności, nie tworząc nadmiaru, który może niepotrzebnie go komplikować. Po paru rozdziałach projekt się nieznacznie zmienia, aby odzwierciedlać nową funkcjonalność (ale dzięki trzymaniu się zasad OOD zmiany te nie są problemem).

* - autor jest znanym konsultantem, dodatkowo prowadzi kursy dla zaawansowanych programistów Javy, C# i C++ z projektowania obiektowego. Koszt 4-dniowego kursu podstaw OOD to $2050.

No może przejdźmy do wad:
- książka pcha czytelnika w eXtreme Programming, namawia usilnie na TDD oraz Pair Programming i inne techniki wchodzące w skład XP, jednocześnie nie mówi o problemach, które te techniki mogą spowodować;
- w książce jest bardzo dużo kodów źródłowych, praktycznie za każdym razem autor wkleja prawie cały listing klasy. Dodatkowo każda do każdej klasy jest listing i omówienie testów jednostkowych. Imho tych kodów powinno być o wiele mniej. Na szczęście zawsze można po prostu te kody pominąć przy czytaniu ;)
- używana wersja języka UML odzwierciedla XP, a nie rzeczywistą notację. Przez to jest uproszczona i trochę zmieniona;
- opis niektórych wzorców projektowych jest nieco zbyt długi, przez co nudny. W dodatku przykład wzorca ModelViewPresenter jest zbyt prosty, żeby można było go dokładnie zrozumieć.

Warto jeszcze nadmienić, że książka ma kody źródłowe w C#, ale istnieje także wydanie z kodami w Javie.

Informacje o książce
Tytuł: Agile Principles, Patterns, and Practices in C#
Autor: Robert C. Martin
Wydanie: Prentice Hall PTR; 1 edition (July 20, 2006)
Język: angielski (nie ma jeszcze polskiego tłumaczenia)

sobota, 11 sierpnia 2007

Książka "Applying UML and Patterns" i inne

Właśnie skończyłem czytać książkę „Applying UML and Patterns” i mogę powiedzieć tyle: polecam, polecam i jeszcze raz polecam :) Książka jest po prostu super, ale po kolei...

O czym jest ta książka?
Podtytuł jest bardzo wymowny „An Introduction to Object-Oriented Analysis and Design and Iterative Development”. Książka jest o procesie wytwarzania oprogramowania oraz o analizie i projektowaniu systemów informatycznych przy wykorzystaniu wzorców projektowych oraz notacji UML, czyli Object Oriented Analysis and Design (OOA/D). Omawianym modelem produkcji oprogramowania jest model iteracyjny Unified Process w ujęciu Agile – brzmi zapewne „dziwnie”, ale w rzeczywistości jest to jedna z „lżejszych” modyfikacji najczęściej wykorzystywanego modelu wytwarzania oprogramowania o dużej skuteczności. Jednak głównym tematem książki jest analiza i projektowanie zorientowane obiektowo. Książka dosłownie uczy jak z wymagań stworzyć projekt, który spełnia podstawowe zasady i wykorzystuje wzorce projektowe GRASP oraz GoF a następnie zapisać go w notacji UML.

Zasadniczym elementem książki są dwa „case studies”, czyli przeprowadzone od początku do prawie końca projekty systemów informatycznych. Pierwszy - NextGenPOS - jest systemem obsługi sprzedaży detalicznej w supermarketach, drugi, znacznie prostszy, jest symulacją gry w Monopol. Oba ciekawe i przy każdym autor opisuje tok myślenia (mniej lub bardziej szczegółowo), które doprowadziło do takiego a nie innego projektu – cały czas opierając się na zasadach OOD, GRASP oraz wzorcach projektowych GoF. Dodatkowo prezentowane są krótkie kody w Javie pokazujące jak mapować UML na kod.
IMHO bardzo ważne jest pokazanie, jak z tekstu przypadków użycia (use case text) przejść do systemowych diagramów sekwencji (SSD), a następnie zbudować model domenowy (domain model). Potem przedstawione jest jak na podstawie tych trzech artefaktów budowane są jednocześnie diagramy klas i diagramy sekwencji.

Dlaczego akurat ta książka do OOA/D?
Książkę wybrałem po przeczytaniu wielu dobrych opinii o niej, tych z Amazon oraz opinii czołowych postaci w świecie OOA/D (np.: M. Fowler'a). Książka ta, używana na wielu uniwersytetach w USA i UK, zazwyczaj jest określana jako „The Book” jeżeli chodzi o wprowadzenie do OOA/D.

Dla kogo jest ta książka?
Mimo, że książka jest o OOA/D, to według mniej jest to „essential reading” dla każdego, kto chce być zawodowym programistą, a nie tylko pisać programy hobbistycznie. Kto tak na prawdę pracuje w firmie, w której dostaje gotowy projekt w UML do wykonania? Jak już, to zazwyczaj jest ogólny schemat systemu (co jest akurat pozytywne według Agile :) Programista sam wykonuje część pracy projektowej, więc aby tworzyć lepszy soft, potrzebuje podstaw, które ta książka daje.

Dlaczego nie wystarczy książka do języka UML?
„Owning a hammer doesn't make one an architect” - jedną z podstawowych tez tej książki jest: UML to tylko narzędzie do wizualizacji. Książka pokazuje jak je wykorzystać. Chodź „Applying” opisuje podstawy notacji UML to polecałbym najpierw przejrzeć książkę, która jest tylko i wyłącznie poświęcona językowi UML (aczkolwiek nie jest to niezbędne).

Wnioski
Jak będę miał czas to post'ne na bloga jakieś detale z książki, np. wzorce GRASP, model iteracyjny UP (Unified Process), czy tekst o artefaktach w modelu Agile Software Development.

Informacje o książce
Tytuł: Applying UML and Patterns
Podtytuł: An Introduction to Object-Oriented Analysis and Design and Iterative Development
Autor: Craig Larman
Wydanie: 3rd Edition, Prentice Hall PTR
Język: angielski (nie ma jeszcze polskiego tłumaczenia)

Uff, ale wyszła z tego reklama ;) Dla równowagi...

Inne książki
Na „Applying" świat OOA/D się nie kończy ;) Dlatego poszukałem jeszcze innych książkę, rozwijających tą tematykę. Jednak szukałem takich, które nie skupiają się na podstawach, a raczej na zastosowaniach (przykłady). Zaznaczam, że ta lista NIE jest losowym zbiorem wygenerowanym przez google, a dobrze przefiltrowanym przeze mnie zbiorem:
- „Agile Principles, Patterns, and Practices in C#", Robert C. Martin, Prentice Hall – zapowiada się konkretnie, dalsze zasady, wzorce i przykłady. Książka nagradzana i polecana + sławny autor. Dla „nie c#'owców" nadmienię, że ta książka ma też wersję z kodami w Javie;
- „UML in Practice. The Art of Modeling Software Systems Demonstrated through Worked Examples and Solutions", Pascal Roques, Wiley – w tej książce są tylko i wyłącznie omówienia przykładowych projektów w UML. Zawiera też ćwiczenia, które zmuszają czytelnika do nauki ;) Koniecznie będę musiał się jej bliżej przyjrzeć;
- „Wzorce projektowe. Elementy oprogramowania obiektowego wielokrotnego użytku", GoF, WNT – tej pozycji chyba nie muszę przedstawiać;
- „Architektura systemów zarządzania przedsiębiorstwem", Martin Fowler – pomimo mylącego tytułu i podobno słabego tłumaczenia, książka jest polecana. Imho warta jest zaznajomienia, ponieważ nie opisuje wzorców projektowych, jak większość książek, a wzorce aplikacyjne;
- „Object-Oriented Analysis and Design with Applications", Grady Booch – ta książka opisuje podstawy i konkretne projekty. Wygrała parę konkursów, a jej autor jest także jednym z autorów języka UML. Dla mnie pozycja ciekawa tylko ze względu na rozdział o „applications", bo pierwsza cześć o podstawach wydaje się nudna (zbyt dokładna).

Może od razu powiem, jakiej książki do OOA/D nie polecam, a mianowicie: „Head First Object-Oriented Analysis and Design". Książka jest bardzo pobieżna, a kosztuje sporo :-\ W sumie jakby tytuł brzmiał „Head First Introduction to System Analysis" to bym się nie czepiał. Zawartość książki przejrzałem pobieżnie, wyszukując ciekawych zagadnień. Z tematu OOD opisano tylko podstawowe zasady (zaledwie na 50 stronach :-\), nie pokazano nawet użycia diagramów sekwencji – czyli podstawowego w OOD (na równi z diagramem klas). Za to obszernie opisano podstawy programowania obiektowego, które są znane każdemu programiście z książek do programowania w jakimś języku OO.

W sumie „HFOOA/D" opisuję zwłaszcza dlatego, że akurat – ze wszystkich dobrych książek o OOA/D - tą pozycje postanowił wydać Helion :-\

poniedziałek, 6 sierpnia 2007

Nowości w C# 3.0

Od paru lat MS przygotowuje nową wersję języka C#. Ostatnio miały miejsce dwa związane z nią event'y: udostępnienie zbiorczej dokumentacji do języka C# uwzględniającej wersję 3.0 oraz udostępnienie beta wersji Visual Studio 2008 „Orcas”, która ma wbudowaną obsługę C# 3.0. Jako, że ciekawość pierwszym krokiem do... poznania, postanowiłem bliżej się przyjrzeć tej „technologii jutra".

Zaraz przedstawię wprowadzone mechanizmy, najpierw jednak napiszę, że wszystkie są częścią „The LINQ Project". O LINQ słyszałem pierwszy raz dawno temu, ale nie myślałem, zostanie wprowadzony do C#.

Aby szybko przedstawić o co chodzi, zacytuje wstęp ze strony projektu: „The LINQ Project is a codename for a set of extensions to the .NET Framework that encompass language-integrated query, set, and transform operations. It extends C# and Visual Basic with native language syntax for queries and provides class libraries to take advantage of these capabilities".

Przegląd mechanizmów wprowadzonych w C# 3.0

Własne tłumaczenia nazw mechanizmów umieściłem w nawiasach, zapewne oficjalne nazwy będą inne ;)

Implicitly typed local variables and arrays (domyślne typy zmiennych lokalnych oraz tablic)

Wprowadzono nowe słowo kluczowe „var", służące do zastąpienia deklaracji typu zmiennej. Typ będzie określany na podstawie wyrażenia inicjalizującego wartość zmiennej. Na przykład w ciele metody można napisać:

var i = 1; // automatycznie typ int
var p = new Point(); // automatycznie typ Point
var ar = new[] {1,2,3,4}; // automatycznie typ jest tablicą int'ów

Uwaga: jeżeli zrobiło ci się słabo na widok słowa „var" i braku określenia typu (co przywodzi na myśl skryptowe języku pokroju PHP) to mogę ciebie pocieszyć, że to tylko tak wygląda. Zmienna będzie miała „trwały" typ, niezmienny w czasie, ale będzie on określony na podstawie wyrażenia „po prawej stronie", a nie jawnej deklaracji. Próba przypisania do zmiennej zainicjalizowanej jako 1 (int) wartości „abc" (string) spowoduje błąd kompilacji (uff). Także deklaracja zmiennej przy użyciu „var" bez inicjalizacji jest nielegalna. Mam nadzieje, że to ciebie uspokoiło, bo mnie tak :) Wprowadzenie takich "elementów" byłoby po prostu niebezpieczne. W końcu C# to coś więcej niż język do pisania sklepików internetowych!
Mechanizm "Implicitly typed variables" wprowadzono głównie ze względu na "query extensions", szczegóły dalej ;)
Jeszcze mała uwaga do nazwy tego mechanizmu... w C# zmienne mogą być tylko lokalne, więc słowo local można by IMHO z nazwy wyrzucić.

Extension methods (metody dodawane)

Ten mechanizm umożliwia rozszerzenie istniejących typów dodając nowe metody bez zmiany definicji danej klasy. Dodane metody są definiowane w innej klasie statycznej, ale ich wywołanie jest identyczne jak wywołanie zwykłych metod klasy.
Dla wyjaśnienia przykład (ze specyfikacji):

public static class Extensions
{
public static int ToInt32(this string s)
{
return Int32.Parse(s);
}
}
...
{
string s = "123";
int i = s.ToInt32();
}

Zauważ słowo kluczowe „this" w nagłówku metody ToInt32(), klasa określona po słowie "this" będzie klasą rozszerzoną. Klasa String nie ma metody ToInt32(), dodając metodę poprzez ten mechanizm możemy ją wywołać tak jakby należała do tej klasy „od zawsze".

Prawdę mówiąc to rozszerzenie nie podoba mi się. Nie wyobrażam sobie projektowania w UML'u takiego rozwiązania, które by na nim bazowało. Importując dowolną bibliotekę może ona zmienić typy wbudowane :-\ W ogóle ciekawe jak Reflection będzie widział takie metody. Sam bałagan. Dlatego specyfikacja mówi: „is recommended that extension methods be used sparingly and only in situations where instance methods are not feasible or possible". Oczywiście jest to kolejne rozszerzenie wymagane przez "query extensions".


Lambda expressions (wyrażenia lambda)
Wyrażenie lambda mają zastąpić aktualną składnię metod anonimowych, dzięki nim będzie ona prostsza oraz będzie umożliwiała pełniejszą integracje z... "query extensions" :D Przykład notacji standardowej dla C# 2.0:

delegate void AADelegate();

static void Main(string[] args)
{
AADelegate myDelegate = delegate()
{
Console.Writeline("Witam");
};
myDelegate();
}

Można zastąpić poprzez:

delegate void AADelegate();
static void Main(string[] args)
{
AADelegate myDelegate = () => Console.WriteLine("Witam") ;
myDelegate();
}

Jak widać, wyrażenie lambda zostało „delegatem”. Jak dla mnie super, w końcu definiowanie metod anonimowych będą prostsze (czyt. ładniejsza składnia :). Jednak tak na prawdę, możliwość zastąpienie metod anonimowych poprzez ten mechanizm to tylko czubek góry lodowej! Coś mi się wydaje, że o wyrażeniach lambda będzie gruby rozdział w książkach do C#.

Object and collection initializers (inicjalizatory obiektów i kolekcji obiektów)
Ten mechanizm pozwala skrócić zapis inicjalizacji zmiennych poprzez automatyczne przypisanie do właściwości obiektu określonych przez programiste wartości.

Załóżmy że mamy klasę Osoba z właściwościami Imie, Nazwisko i NIE ma ona konstruktora. Standardowo trzeba przeprowadzić inicjalizację tak:


Osoba o = new Osoba();
o.Imie = „Jan”;
o.Nazwisko = „Kowalski”;

W C# 3.0 można zrobić tak:


Osoba o = new Osoba {Imie=”Jan”, Nazwisko=”Kowalski”};

Oba listingi są sobie równoważne. Podobne rozszerzenie dotyczy kolekcji, np.:

List list = new List {„aa”, „bb”, „cc”};

Według mnie, ten sposób inicjalizacji szybko się przyjmie :) Zwłaszcza, że przedstawione przykłady nie wyczerpują jego możliwości.


Anonymous types (Typu anonimowe)
Ten mechanizm pozwala na tworzenie typów w sposób podobny do metod anonimowych. Tworzony typ nie ma nazwy, a tylko wyszczególnione właściwości. Na przykład:

var p1 = new { Name = "Lawnmower", Price = 495.00 };

Stworzona będzie klasa zawierająca właściwości Name i Price, a jej instancja będzie od razu zainicjalizowana i przypisana do p1. Ten mechanizm według mnie będzie mało przydatny dla programisty, aczkolwiek uproszcza znacznie składnię "query extensions".


Expression trees (drzewa wyrażeń)
Expression trees pozwalają na reprezentację (traktowanie) funkcji anonimowych jako struktury danych. W sumie dostępna [mi] specyfikacja na razie jest dość krótka, ale wiadomo, że takie wyrażenie będzie dziedziczyć po klasie Expression, co implikuje ciekawe możliwości :) No zobaczymy co z tego wyjdzie.

Query expressions
To rozszerzenie jest właśnie kwintesencją LINQ. Jest to zintegrowany z językiem C# język zapytań, podobny do SQL czy XQuery. Pozwala w podobny sposób wyodrębniać dane ze struktur, baz danych i plików XML. Dzięki wszystkim opisanym do tej pory rozszerzeniom uzyskana składnia jest relatywnie prosta, dzięki czemu sam mechanizm jest „powerful”.
Przykład:


void DoSth()
{
var overdrawnQuery = from account in db.Accounts
where account.Balance = 0
select new { account.Name, account.Address };

foreach (var i in overdrawnQuery) {
Console.WriteLine(i.ToString());
}
}

No prawie jak SQL, tyle że nie trzeba tworzyć żadnych commandów, parametrów, itp. Niby super, ale myślę, że zanim LINQ naprawdę się przyjmie, to będzie już .NET 4.0. Idea jest fajna, ale mam obawy co do wydajności.


Podsumowanie
Jak widać większość rozszerzeń jest tak na prawdę „na usługach” LINQ. Jednak takie mechanizmy jak wyrażenia lambda czy inicjalizatory obiektów powinny szybko się przyjść.


Linki
- Skrócona specyfikacja C# 3.0;
- 101 LINQ Samples;
- Film: C# 3.0 Language Enhancements in action (var, Extension methods, Lambda expressions);
- Film: C# 3.0 LINQ in action (query on in-memory objects);
- Film: C# 3.0 DLinq in action (VS8 import database and query on db);
- Film: C# 3.0 XLinq in action (query on xml);