wtorek, 31 maja 2011

Przemyślane praktyki Java EE

Dziś krótka recenzja książki Adama Biena Real World Java EE Patterns - Rethinking Best Practices.

Zacznę od konkluzji: czy warto? Tak. To jak bardzo warto zależy od Twojego dotychczasowego backroundu, ale gwarantuję, że nawet eksperci Javy EE znajdą dla siebie kilka ciekawych kawałków. Pozycja konkretna, na temat, z przykładami wykorzystującymi ciekawe kruczki z np. EJB 3.1.

Na początku obawiałem się, że przemyślenia dotyczą trywialnych CRUDów - na crudach opiera się ostatnio cała współczesna literatura programistyczna jak i blogi. Nie dziwota, gdyż jest to bardzo wdzięczna materia - można na nich pokazać jak prosta i łatwa jest technologia X, a później radźcie sobie sami.

Autor w części rozdziałów wychodzi od crudów jednak za chwilę porusza bardziej zaawansowane tematy, racjonalnie argumentując kiedy opłacalne jest wprowadzenie bardziej złożonych mechanizmów platformy.

Dla kogo przeznaczona jest książka?
Przede wszystkim dla weteranów J2EE, którzy przesiadając się na Java EE powinni zapomnieć stare nawyki.
Dla osób zaczynających od EE 5 lub przechodzących z innych technologii (Spring) odniesienia do "starych" praktyk będą jedynie ciekawostką archeologiczną.

Ale tak jak pisałem, znajdziemy w niej kilka ciekawych kruczków, sporo gotowych rozwiązań oraz dużo gotowego kodu. Kruczki i best practices związane z transakcjami, kod użytecznych interceptorów, które łatają braki w specyfikacji;) oraz nieco praktyk odnośnie dobrego designu. Część praktyk odnośnie designu jest dyskusyjna, jednak autor wyjaśnia w dalszej części, że aplikują się w pewnych kontekstach, natomiast gdy wymaga tego problem, wówczas zaczynamy sięgać po inne rozwiązania. Przykładowo obiekty transferowe są dobre tylko wtedy gdy są dobre:) - z czym nie sposób się nie zgodzić. DAO jest usprawiedliwione tylko gdy wnosi wartość - tak ale dyskutować można nad tym co jest wartością.

Mimo dyskusyjności niektórych pomysłów trzeba docenić inicjatywę, ponieważ generalnie brakuje na rynku pozycji wychodzących poza przysłowiowy Hello World...


Na uwagę zasługuje fakt, że autor otwarcie mówi o proceduralnym stylu promowanym przez platformę.
Mówi też otwarcie o innych sposobach skalowania - bez rozpraszania obiektów pomiędzy warstwami...
nota bene zgodnie z zasadą Fowlera odnośnie rozpraszania: "Just don't":)



Nie byłbym sobą gdybym nie znalazł jakiś błędów koncepcyjnych...
Wiem, że w każdej książce technicznej (w sensie opisującej jakąś technologię) projektowanie Object Oriented jest potraktowane po macoszemu ale skoro już polecam książkę to zwrócę uwagę na 2 przykłady:

Rozdział "Persistent Domain Object (Business Object)"
Po wstępie o tym dlaczego opłaca się stosować model OO (rich model) zamiast proceduralnego (anemic model) mamy taki oto przykład:

Klasa OrderItem, która między innymi potrafi policzyć swój koszt metodą getShippingCost (jest to metoda biznesowa a nie geter)

Dalej dziedzicząca po niej klasa BulkyItem, która liczy koszt nieco inaczej - nadpisuje metodę getShippingCost a w niej woła super wersję tej metody!

@Override
public int getShippingCost() {
return super.getShippingCost() + 5;
}



Nie róbcie tego w domu ani w pracy!:)
1. OrderItem ma wiele odpowiedzialności, więc wprowadzanie nowej klasy i dziedziczenia tylko dlatego, że zmieniła się jedna z odpowiedzialności jest błędem projektowania obiektowego. Taki sposób rozumowania szybko doprowadzi do ekspolozji kombinatorycznej, gdzie każda zmiana logiki (oraz kombinacje tych zmian) zamieszczana jest w swojej klasie dziedziczącej. Strategia jest jednym rozwiązań. A jeżeli nie chcemy wprowadzać strategii, to już na prawdę lepszy będzie serwis liczący koszt na podstawie getterów z OrderItem. Dobry kod proceduralny jest zawsze lepszy od słabego kodu obiektowego!

2. Wołanie super wersji metody z nadklasy jest tak zwany smrodkiem (code smell). Skoro nadpisuję metodę to jest już nieważna. Generalnie wskazuje to na słaby design.



Kolejna rzecz na jaką należy uważać to rozdział poświęcony "konfliktowi" pomiędzy Domain Driven Design a SOA.

Niestety muszę powiedzieć, że konflikt ten jest pozorny i wynika z niezrozumienia architektury aplikacji dla systemów, w których stosujemy DDD.
Autor we wcześniejszych rozdziałach promował swój pomysł pod tytułem Gateway i ten styl przeniósł na implementację DDD.
Nigdy nie "publikujemy" Modelu Domeny jako "API". Wiąże się z wieloma przykrymi konsekwencjami, ale tutaj odsyłam do Evansa. Model domenowy przykrywamy właśnie procedurami w stylu SOA - po prostu podstawowy pattern DDD: warstwa Serwisów Aplikacyjnych. I po problemie:)
Było to powiedziane już 5 lat temu: DDD the opposite of SOA? Uh, no.

//========================================

Polecam rozdział pod tytułem "Retired Patterns" przypomina nam jak smutne i przykre bywało drzewiej programowanie w EE:)

czwartek, 19 maja 2011

Stosowalność Wzorców Projektowych

Temat Wzorców Projektowych budzi wiele emocji. Niektórzy są ich zagorzałymi fanami, inni podchodzą z pogardą twierdząc, że w rzeczywistym świecie są bezużyteczne.

Wzorce Projektowe są jedynie narzędziem, a emocjonalne podchodzenie do "młotka" jest po prostu nieracjonalne. Dlatego zaproponuję nieco inne podejście - kontekstowe.

Swoją drogą ciekawe, że podczas rozmów coraz częściej słyszę z ust wytrawnych programistów wyraz irytacji nad bezkontekstowym podejściem naszej branży do wszelkich technik, praktyk, metodyk, produktów, rozwiązań. Mówi się, że jesteśmy sterowani modą bardziej niż Mediolan lub Paryż;)
Odczuwa się silne zmęczenie marketingiem.

W swojej karierze programistycznej miałem okazję pracować nad systemami różnej klasy. Przez klasę rozumiem klasę problemów jakie stanowiły główne wyzwania. Ale to praca trenera i konsultanta dała mi dostęp do wglądu w spektrum klas problemów, w ilości jaką standardowo kolekcjonuje się w okolicach emerytury.

Piszę o tym aby przejść do kontekstu stosowalności Wzorców Projektowych. Z moich obserwacji wynika, że kontekst ten jest rozpięty na 2-wymiarach: wspomnianej już klasie problemu oraz w wymiarze osobowości (otrzemy się o aspekty psychologii programistów).


KONTEKST KLASY PROBLEMU

Jeżeli jesteśmy w kontekście aplikacji biznesowych, a nasza praca polega na implementowania kolejnych wymagań, to stoją przed nami wyzwania typu:
- okiełzanie nielogicznych wymagań
- modelowanie narzędzia dla biznesu (naszej aplikacji), który działa z natury procesowo
- tworzenie intuicyjnego GUI
- wpasowanie się w istniejącą bazę danych, która była projektowana przed III Wojną Mandżulską, w czasach gdy nikt jeszcze tak na prawdę nie rozumiał domeny.

W tym kontekście często nie potrzebujemy nawet używania technik OO - aczkolwiek programujemy z użyciem obiektów (bo niby jak inaczej w mainstreamowych językach?).

Z szerokiego wachlarza Wzorców Projektowych możemy posłużyć się w tym kontekście - w pewnych bardziej złożonych - przypadkach:
- Strategią - jeżeli mamy odmiany tego samego zachowania/czynności biznesowej. Podejście promowane przez ten wzorzec staje się ostatnio modne za sprawą języków funkcyjnych. By czymże innym na poziomie syntaktycznym jest przekazanie obiektu implementującego interfejs z jedną metodą niż zwykłym przekazaniem funkcji na poziomie semantycznym?
- Łańcuchem Odpowiedzialności - łańcuch zaczyna się nam opłacać gdy chcemy modelować podejmowanie decyzji o tym, który z wariantów logiki biznesowej chcemy wykonać. Opłaca się gdy spodziewamy się modyfikowania ilości wariantów.
- Specyfikacją - pozwala na przejrzyste modelowanie złożonych reguł określających czy dany obiekt biznesowy powinien podlegać jakiemuś przetwarzaniu. Opłaca się gdy reguły są zawiłe i istnieją pomiędzy nimi zależności logiczne. Złożony wzorzec, że wystąpić kilka razy w całym kodzie.
- Stanem - bardzo złożony wzorzec, może wystąpić raz, może dwa w średniej wielkości systemie. Pozwala na przejrzyste modelowanie maszyny stanów, dla obiektów biznesowych, które mają np różne statusy i w zależności od statusu a) mogą lub nie przechodzi w inne oraz b) inaczej się zachowują. Opłaca się gdy mamy wiele statusów i zawiła logikę sterującą zachowaniem zależnym od statusów.
- Metodą Szablonową - prosty wzorzec, klasyka polimorfizmu, pozwala modelować różne warianty algorytmów biznesowych. Z czasem gdy sytuacja się komplikuje przestaje się opłacać i warto dokonać refaktoringu do Strategii.
- Fasadą - trywialny wzorzec, który nie zasługuje na miano wzorca, ale wygodnie upraszcza to co najpierw skomplikowaliśmy;)
- Dekoratorem - wprowadzenie dekoratora zaczyna się nam opłacać gdy chcemy !w runtime! (nie podczas programowania czy kompilacji) decydować o dodawaniu nowych zachowań. Bardzo silny, ale rzadko logika biznesowa daje się tak elegancko zamodelować.

Pomijam Singletona, który w większości przypadków jest antywzorcem zabijającym testowalność. Poza tym jego istnienie w modelu biznesowym rzadko bywa sensowne.

O ile pojawienie się w aplikacji biznesowej wielu przypadków wykorzystania Strategii, Metody Szablonowej, Fasady jest normalnym zjawiskiem o o tyle duża ilość Łańcuchów, Dekoratorów czy Stanów wskazuje na overengineering i "chorobę wzorcową".

Pozostałe wzorce z katalogu nie mają zbyt dużej szansy na potencjalne pojawienie się w aplikacji biznesowej - po prostu służą do rozwiązywania problemów innych klas.

W aplikacjach biznesowych za to więcej pożytku niosą wzorce innego rodzaju:
- sposoby modelowania, oraz strategicznego modelowa z zestawu Domain Driven Design
- archetypy modeli biznesowych
- najlepsze praktyki odnośnie Usability



Jeżeli natomiast jesteśmy w kontekście tworzenia oprogramowania klasy: platforma, framework, server, wysokowydajny dedykowany portal, oprogramowanie specjalistyczne typu: narzędzia do projektowania/komponowania, itp wówczas stajemy przed problemami zupełnie innej klasy:
- otwartość na rozbudowę z jednoczesną ochroną publicznego api przed zmianami core,
- wydajność, oszczędność pamięci,
- bezpieczeństwo,
- giętkość api,
- wyważenie ograniczeń
- itp.

Przeglądając kody źródłowe tego typu aplikacji możemy dostrzec wiele wystąpień wzorców lub struktur do nich podobny zmodyfikowanych z powodu pewnych intencji. Czasem są po prostu nazwane inaczej z powodu niewiedzy autora - ale ciekawe jest, że wpadł na pewne pomysły niezależnie, nie znając wzorca wcześniej.

Oprócz wspomnianych wcześniej wzorców opłacalne w tym kontekście dodatkowo mogą być:
- Builder - aby odseparować plany budowy obiektów od ostatecznego kształtu konstrukcji. Opłacalny gdy przewidujemy pojawianie się kolejnych "produktów"
- Visitor - aby umożliwić użytkownikom api wprowadzanie nowych zachowań poprzez dodawanie swojego kodu zamiast modyfikowania biblioteki/frameworka. Double Dispach dla ubogich np. w celu otwarcia core na rozbudowę
- Proxy - aby umozliwić model programistyczny w stylu Aspect Oriented
- Mediator - śmietnik na chaos sieci współpracujących obiektów. Jeżeli musisz mieć chaos, to explicite ogranicz jego zakres.
- Most - jeżeli masz niestabilny core i chcesz zaryzykować publikowanie stabilnego api
- Prototyp - jeżeli chcesz fabrykować wiele klas i nie chcesz tworzyć analogicznej do nich, lustrzanej hierarchii fabryk.
- Flyweight - jeżeli musisz mieć ogromną ilość obiektów, ale część ich pół możesz uwspólnić, ponieważ nie jest to ich zmienny stan - oszczędzasz pamięć.


Podając przykłady dla obu klas problemów chciałem pokazać, że po prostu inni programiści/projektanci/architekci mogą żyć w innym świecie. To że coś jest dla nas bezużytecznie, nie oznacza, je jest to bezużyteczne w ogólności.

Wrzucanie wszystkich programistów do jednego worka (najlepiej wspólnego worka z Informatykami;) powoduje utratę kontekstu a co za tym idzie rozmycie wymaganych do danego zadanie kompetencji.

Warto też zastanowić się nad klasami problemów jakie nas intrygują i rozwijać odpowiedni skillset - bez odpowiedniego poziomu kompetencji pewne klasy projektów będą dla nas zawsze zamknięte.



KONTEKST OSOBOWOŚCI

Chyba każdy programista przyzna, że zależy mu na zaprojektowaniu najprostszego rozwiązania. Być może to poszukiwanie prostoty jest tym, co przyciąga ludzi do programowania - no może za wyjątkiem robotników umysłowych napędzanych chęcią łatwego (hehe naiwni) zarobku.

Problem leży w postrzeganiu prostoty.
Niektórzy mówią, że jakieś podejście jest proste jeżeli można szybko zacząć się w tym orientować. I nie ważne, że później okaże się to pogmatwane w szczegółach. Ważne aby szybko zacząć "łapać" o co chodzi, a później - trudno, świat jest pogmatwany.
Inni mówią, że coś jest proste, jeżeli u swoich założeń ma dające się dokładnie zrozumieć fundamenty, które pozwalają wyobrazić sobie całe rozwiązanie mentalnie. Nie ważne, że może na początku trzeba zainwestować czas - dużo czasu - w zrozumienie pryncypiów i nowych rzeczy, które powierzchownie wydają się złożone. Jeżeli później okaże się, że było to proste, to mówią, że jest to proste.

Które podejście jest lepsze - jak zwykle, zależy to od kontekstu. W kontekście IT np. może zależeć od ograniczeń czasowych, czyli tego ile czasu możemy poświęcić. Innym ograniczeniem może być opłacalność w perspektywie czasu (czasem robimy eksperyment biznesowy i zobaczy jak się to rozwinie:). Dlatego w każdym przykładzie wzorca pisałem o tym kiedy może się nam opłacać wprowadzenie danej konstrukcji.

Strategia poznawcza, jaką przyjmuje nasz mózg w podejściu do prostoty (musi być proste od razu, musi być proste docelowo) wiąże się mocno z typem naszej osobowości.
- część z nas jest zorientowana na postrzeganie podobieństw, inni na postrzeganie różnic - model meta-programów .
- część z nas jest otwarta na nowe doświadczania, inni są bardziej konserwatywni - model Big 5.
- część z nas ma swój wewnętrzny świat, w którym modeluje postrzeganą rzeczywistość, inni są nastawieni na natychmiastowe działanie i niemal namacalne doświadczanie - model MBTI
- część z nas żyje w przyszłości, w jakimś jej modelu, inni żyją tu i teraz w czasie.


MODEL DREYFUS


O modelu kompetencji Braci Dreyfus pisałem już kilkakrotnie. Tutaj przytoczę tylko poziom Competent. Rozwijając jakąś umiejętność, na tym poziomie w naturalny sposób zaczynamy szukać najlepszych praktyk, wzorców (nomen omen). Tak więc naturalne jest, że rozwijając kompetencję pod tytułem "Programowanie/Projektowanie OO" w pewnym momencie zaczniemy szukać wzorców.
Na kolejnych etapach rozwoju tej kompetencji będziemy zadawać pytanie, kwestionować, szukać szerzej. Jednak na trzecim poziomie (Competent) katalog wzorców daje dużego kopa i pozwala po prostu zoptymalizować proces uczenia się. Jak powiedział Jim Copelin, z czasem odrzucasz "boczne kółka od swego rowerka" i przestajesz mówić o wzorcach, po prostu intuicyjnie robisz to co należy.


//==============================================

Czasem można spotkać głosy, że wzorce projektowe są "zbyt akademickie". Hmm moim zdaniem wręcz odwrotnie. Do katalogu wzorców nie trafiają żądne rozwiązania, które nie są odkryte i przedyskutowane przez community praktyków. Oczywiście, stosując zbyt wyrafinowany wzorzec do zbyt błahego problemu będziemy odczuwać przerost formy nad treścią. Ale wówczas powodem jest nieumiejętne użycie w nieodpowiednim kontekście - czyli jego niezrozumienie.

Aby nabrać wyobrażenia o tym, co to znaczy "akademickie" podejście do OO należy zapoznać się z tym tekstem.

poniedziałek, 9 maja 2011

Ułóż swoją Confiturę 2011

Już tylko miesiąc pozostał do Confitury - największej i darmowa konferencji poświęconej Javie (konferencji znanej do tej pory pod nazwą Javarsovia).

Pod tym adresem można głosować na prezentacje, które chcielibyście zobaczyć 11 czerwca.

Ankieta nie zawiera abstraktów dlatego opiszę pokrótce 3 zgłoszone tematy. Liczę na feedback z Waszej strony (również krytyczny:) odnośnie:
- tematów (czy są interesujące)
- ich zakresu (czy nie jest zbyt pobieżny aby zbyt oczywisty)
- ew. propozycji zmian

1. Context and Dependency Injection w służbie Domain Driven Design

CDI bazuje na zdobyczach nowoczesnej inżynierii oprogramowania dostarczając silnych technik programistycznych. Jednak po przejrzeniu przykładów o złożoności "Hello world" można zadać sobie pytanie - kiedy, jak i do czego powinienem użyć tych technik w praktyce.

Podczas prezentacji przedstawię w jaki sposób możemy wykorzystać model programistyczny (styl/sposób podejścia do problemu) oferowany przez CDI do implementacji DDD.

Po krótkim wstępie na temat modelu programistycznego DDD oraz architektury aplikacji wykorzystamy mechanizmy CDI takie jak fabrykowanie w runtime, dekoratory, zdarzenia, interceptory do implementacji wszystkich Building Blocków DDD. W szczególności poświęcę wiele czasu na wykorzystanie zdarzeń do modelowania wydarzeń biznesowych orkiestrowanych w modelu Sagi.

Prezentacja z założenia przeznaczona jest dla uczestników początkujących w zgadnieniach CDi i DDD. Przedstawione techniki DDD będą na tyle ogólne, że z łatwością można implementować je na innych nić CDI platformach (np. Spring) na zasadzie analogii.


2. Domain Driven Design - Wszystko ma swoje miejsce i wszytko jest na miejscu

//prezentacja wygłoszona w zeszłym roku na NYAC

Czy zastanawialiście się co jest przyczyną rozkładu średnich i dużych
systemów? Czy jest on nieunikniony i jest jedynie kwestią czasu? A
może jednak istnieje jakiś sposób na utrzymanie entropii w ryzach?

Podczas prezentacji zobaczymy w jaki sposób Domain Driven Design
pomaga w okiełznaniu chaosu. W prezentacji znajdą się główne techniki
modelowania takie jak Ubiquitous Language, Bounded Context, Strategic
Design.

Zostaną przedstawione również podstawowe techniki implementacji DDD:
przykłady Building Blocks, Command-query Responsibility Segregation,
system zdarzeń (w tym Sagi), przypadki racjonalnego wykorzystania zarówno ORM jak i
czystego i SQL.


3. Command-query Responsibility Segregation - ewolucja architektury warstwowej w stronę modularyzacji i skalowania

//prezentacja wygłaszana na 4dev i 33rd degree

Z biegiem kariery, tworząc kolejny system lub aplikację, stajemy przed problemami innej klasy. Inna klasa problemu to inne wymagania odnośnie technologii, metodyki i architektury.

Popularne architektury (1/2/3) warstwowe mogą być nieodpowiednie do pewnych klas problemów - mogą np. narzucać nieracjonalne wykorzystanie ORM lub promować naiwne modelowanie domeny biznesowej.

Podczas prezentacji przedstawię nowe ujęcie warstw - architekturę Command-query Responsibility Segregation, która wspiera aplikacje średniej i dużej skali. Architektura CqRS promuje zdobycze nowoczesnej inżynierii oprogramowania takie jak: Domain Driven Design i noSQL, otwiera system na skalowanie oraz w naturalny sposób rozwiązuje typowe problemy z mapowaniem relacyjno-obiektowym.

Główne składowe nowej architektury to: dwa stosy warstw, rozwarstwienie logiki, zdarzeniowa komunikacja pomiędzy modułami oraz opcjonalnie Event Sourcing (składowanie danych w modelu behawioralnym - w przeciwieństwie do klasycznego modelu strukturalnego)

//=======================

Pierwsza z prezentacji jest całkowicie nowa - tym razem planuję lekką zmianę formuły i pokazanie dużej ilości kodu.
Drugą z prezentacji być może widzieliście na NYAC lub we Wrocławiu - planowałem pokazać ją również na zeszłorocznej Warsjavie ale niestety mały, głupi i właściwie martwy (bo niemetabolizujący a jedynie replikujący) wirus był ode mnie silniejszy:/
Trzecia z prezentacji zapewne dla większości z Was będzie replayem z kwietnia.


Zapraszam do głosowania, ale przede wszystkim do uczestnictwa w konferencji - na prawdę warto!

środa, 4 maja 2011

DDD i CqRS w Toruniu i Lublinie

Dziś post czysto ogłoszeniowy.

Lublin: 9. maja
Zapraszam na prezentację poświęconą CqRS, która przedstawię na lubelskich dniach informatyki (szczegóły).

Toruń: 13. maja
Zapraszam czytelników bloga z Torunia i okolic na dwie prezentacje poświęcone DDD i CqRS, które wygłoszę 13 maja w ramach toruńskiej grupy .NET (szczegóły).


//============================

Jeżeli ktoś widział te prezentacje na konferencjach NYAC, 4Develoeprs lub 33rd Degree to zapewniam, że pojawi się kilka nowych szczegółów:)