piątek, 25 lipca 2008

Z pamiętnika zdomenowanego modelarza: #2 Architektura

- Ogry są... jak cebula!
- Śmierdzą?!
- Tak... nie! ... Ogry mają WARSTWY!

Jak już pisałem pracowałem ostatnio nad architekturą dla nowego systemu. Wymagania niefunkcjonalne sprawiły, że przybrała ona kształt niezbyt wyrafinowany, jednak z paroma ciekawymi smaczkami. Do tego jest ona zanurzona w Springu i przykryta Seamem (o integracji w następnym odcinku).

Architektura promowana przez Seam to w ogóle jakieś śmieszne nieporozumienie rodem z programów zaliczeniowych na studiach;)
Z tego powodu, jak i z innych, o których napiszę później Seam został potraktowany jako framework prezentacji dostarczający paru fajnych ficzerów; za obsługę persystencji dziękujemy.

Architektura nie jest jeszcze dopracowana w szczegółach i pewne rzeczy mogą się zmienić ale z grubsza wygląda to tak...
Oczywiście mamy warstwy:
- warstwa prezentacji - klasyczne backing beany przykryte JSF, właściwie to faceletami, właściwie to RichFaces. Seamowe akcje i model odpadają ponieważ zakładam bardzo rozbudowaną logikę prezentacji czyli modyfikowanie, przestawianie, przełączanie i zmienianie komponentów JSF. Zatem potrzebuję odrębnej warstwy na tego typu rzeźbę...
- warstwa logiki aplikacji - aplikacja będzie głównie "UseCase oriented" więc w tym miejscu pojawią się klasy odpowiadające konkretnym juzkejsom. Taki UC zazwyczaj składa się z wielu kroków (metod), zatem przydałoby się przechowywać jego stan w sesji. No ale zasięg sesji to obciach - lepiej nadaje się do tego Seamowy zasięg konwersacji (przynajmniej do czegoś przyda się ten badziewiasty framework;)
Oczywiście nie wszystko będzie juzkejsem. Pojawią się tu również usługi aplikacyjne, które z powodu niemocy twórczej tymczasowo nazwałem sobie Fasadami (chociaż nie podoba mi się ta nazwa).

Warstwa logiki aplikacji będzie stanowić granicę systemu - ponad nią znajduje się po prostu jakaś mniej lub bardziej wyrafinowana powłoka (oczywiście najważniejsza z punktu widzenia marketingowego - ludzie uwielbiają gówno w kolorowym papierku).
Oprócz logicznego podziału na kroki juzkejsów będzie ona zawierać całą logikę, którą nie zaliczamy do logiki biznesowej (bo ta jest piętro niżej). Zatem znajdą się tu wszelkiego rodzaju podsystemy powiadomień, interakcji z systemem i innymi systemami itp.

- warstwa logiki domenowej - tu mieszka Domain Driven Design czyli serce naszego systemu. Większość klas z tej warstwy modeluje naszą dziedzinę. Będzie tu na przykład Pacjent, Oddział, Lek, itp. W DDD mamy kilka rodzajów "artefaktów" biznesowych: Encje, ValueObjects, Servisy, Fabryki, Agregaty - długo by o tym pisać, dlatego ta warstwa będzie tematem następnego posta.

- warstwa DAO - tak, tak... oldskulowe DAO. Co prawda z jego funkcjonalnością będzie pretendować do miana Repozytorium, ale nie będziemy się wydurniać z tą nazwą.


Typowy przepływ wygląda tak:
1. Akcja użytkownika rozpoczyna use case
2. Use case jest inicjalizowany i umieszczany w konwersacji Seama.
3. Kolejne akcje użytkownika odpalają metody odpowiadające krokom UC, gdzie dla każdego kroku zazwyczaj:
4. UC używa DAO aby pobrać Encje (ewentualnie tworzy agregaty encji przy pomocy fabryk)
5. UC stymuluje;) encje do wchodzenia w reakcje między sobą oraz wykonywania logiki biznesowej
6. UC może ewentualnie posiłkować się servisami biznesowymi (ustawiając im DAO), które zazwyczaj produkują ValueObjects
7. UC zazwyczaj w ostatnim kroku dokonuje utrwalenia encji przy pomocy DAO
Ogólnie to Kolejne kroki UC zmieniają jego stan, który jest jakoś prezentowany na GUI.


Tak pokrótce wyglądają warstwy. Jak widać architektura różni się od klasycznej proceduralnej-quasi-obiektowej architektury jedynie paroma konwencjami, a jednak intuicja podpowiada mi, że będzie to lepiej pracować i odsunie o kilkanaście miesięcy moment zwiększenia entropii do poziomu popularnie zwanego syfem w kodzie.
Różnie cą następujące:
- Stan juzkejsu w jednym miejscu zamiast w wielu backing beanach.
- Logika nie jest rozsiana pomiędzy procedury.
- Model domenowy nie jest anemiczny - jego klasy posiadają odpowiedzialność, możemy zagrać w nim wzorcami projektowymi w celu zmniejszenia komplikacji (chyba, że ktoś ma pecha i nie zna wzorców - wówczas komplikacja pozornie rośnie;)
- Paczki procedur ograniczone do minimum - servisy biznesowe


//==============================
W kolejnych postach opiszę bardziej szczegółowo każdą warstwę wraz z przykładową implementacją oraz przesłanki, które doprowadziły do niektórych strategicznych decyzji - niektóre z decyzji są dosyć kontrowersyjne, np: rezygnacja z lazy loading, uzywanie detached objects.
Przedstawię też integrację Seam ze Spring

Brak komentarzy: