29 paź 2008

MDD

No więc to nie będzie o UMLu, ani o MDA ani o MDSD ani niczym podobnym. Tylko o projektowaniu aplikacji OO.
- Jak Ty zaczynasz swoją aplikację?
- Hmm, no więc... zwykle to... jakoś tak wychodzi...
- No, no! Przyznaj się! Od UI czy od bazy danych?

No więc? Od czego?
Jakoś tak wychodzi, że zastraszająco dużo projektów zaczyna się od tzw. d* strony. Czyli właśnie albo od UI albo od DB. Generalnie od jakiejś infrastruktury. Od frameworków. Od bibliotek. I myślę, że jednym z powodów jest brak jasnej wizji aplikacji na początku jej tworzenia. A jak wykorzystać frameworki wiadomo. Jak ma wyglądać UI też zwykle (przynajmniej z grubsza) wiadomo. A potem się gdzieś te funkcjonalności wsadzi. A żeby móc zacząć pisać funkcjonalności trzeba mieć konkretną wizję systemu, którą można mieć wyłącznie poprzez wcześniejsze jego zamodelowanie.

Model-Driven Design
Model-Driven Design oznacza, że development aplikacji prowadzimy (drive'ujemy :) ) modelem.
W książce o DDD Eric Evans wyróżnił 8 głównych wzorców budowy aplikacji. I tak naprawdę nic nowego pewnie tu nie ma poza tym, że pewnie powinni tego uczyć na każdym kursie OO na uczelniach. A że chyba nikt tego nie robi, więc są tu :)
  • Layered Architecture
  • Entities
  • Value Objects
  • Services
  • Modules
  • Aggregates
  • Factories
  • Repositories
Zachowałem oryginalne angielskie nazewnictwo, bo tak naprawdę są to wzorce projektowe a częścią idei wzorców jest uwspólnienie języka.

Layered Architecture
Jeśli warstwowość rozumiemy jako oddzielenie zagadnień (separation of concerns) czyli np. nie wrzucanie do jednej klasy kodu UI, DB i jeszcze funkcjonalności aplikacji, to jest to oczywiście rzecz wielce porządana. Zwykle wyróżnia się: UI, aplikacja (koordynacja aplikacji, bez logiki biznesowej), dziedzina (obiekty dziedziny wraz z logiką i stanem), infrastruktura (komunikacja między warstwami, utrwalanie obiektów, dodatkowe funkcje usługowe dla aplikacji, etc.)

Entities
To te elementy dziedziny, które mają określony identyfikator. I to nie atrybuty tych obiektów decydują o tym czym są, tylko właśnie identyfikator. Typowe przykłady to Klient, Firma, Faktura itp.

Value Objects
To przeciwieństwo entities. Tu wyróżnikiem jest zawartość obiektu, jego atrybuty, a nie identyfikator. Przykłady to np. Pieniądz (ważna zwykle wartość a nie nr seryjny) czy Książka (ważny jest autor i tytuł a nie konkretny egzemplarz).

Services
Czasem się okazuje, że są takie elementy aplikacji które kiepsko pasują do idei modelowania i dziedziny, a muszą być zaimplementowane. Czasem jakaś funkcjonalność nie pasuje do żadnego z wyróżnionych obiektów a jednak ich dotyczy. Albo dotyczy wielu różnych obiektów i modelowanie jej za pomocą dziedziczenia psuło by tylko model. Pisałem kiedyś aplikację w której musieliśmy zwracać w postaci RSS różne zupełnie obiekty (nie miały ze sobą nic wspólnego) i dodawanie funkcjonalności eksportu w postaci RSS do każdego z nich nie miało sensu. I wtedy taka usługa abstrahująca od typu obiektu była idealna (Tak trochę off-topic to są języki w których można to zrobić ładnie i w ramach dziedziny. Np. w Scali można zrobić trait i zaaplikować do wszystkich obiektów o które nam chodzi. W aspectj, groovym i rubym można zrobić mixin. Więc co właściwie pasuje do tej kategorii zależy trochę od języka z którego korzystasz.)

Modules
To normalna praktyka programistyczna. Dzielenie aplikacji (w tym przypadku chodzi głównie o model dziedziny) na moduły o niskim poziomie zależności pomiędzy nimi, ale o wysokiej wewnętrznej spójności (zarówno z punktu widzenia komunikacji jak i funkcjonalności).

Aggregates
To znowu wzorzec strukturalny. Tym razem chodzi o zebranie w jeden agregat tych obiektów dziedziny które mają wspólny cykl życia (tworzenie, usuwanie). To powoduje zmniejszenie liczby relacji między obiektami dziedziny (zamiast odnosić się do poszczególnych drobnoziarnistych obiektów, dotyczą całego agregatu). Dobry agregat ma dobrze określone granice dostępu do niego, tzn. jest w nim jeden główny obiekt (korzeń) i tylko przez niego (przez jego relacje) możemy dostać się do obiektów zależnych. Zewnętrzne obiekty nie mogą mieć odniesień do żadnych elementów wewnętrznych agregatu poza tym jednym - korzeniem.

Factories
Biorąc pod uwagę, że tworzenie encji, a tym bardziej agregatów, może być dość złożone dla bardziej skomplikowanych obiektów, warto wykorzystać fabrykę (a'la GoF) .

Repositories
Jednym z podstawowych założeń dobrego projektu jest minimalna zależność dziedziny od reszty aplikacji. W szczególności dotyczy to kontaktu z UI i infrastrukturą (np. DB). Dlatego dobry rozwiązaniem jest obiekt, który realizuje CRUD na obiektach dziedziny. Dzięki temu nie muszą one same dostawać się do innych (przez bezpośredni dostęp do bazy ani DAO) lecz mają specyfikowany wygodny interfejs, który w dodatku może realizować dodatkowe funkcjonalności takie jak caching czy rozwiązywanie zależności.

Oczywiście najważniejszym elementem w MDD jest modelowanie dziedziny. I to nie raz, na początku projektu. To ciągła weryfikacja i modyfikacja poprawności, logiczności, sensowności struktury aplikacji. Wraz z jej rozwojem i Twoim rozumieniem dziedziny. Tutaj kłania się oczywiście TDD, ale to inna bajka.
A jak to się ma do tego jak robisz swoje aplikacje?

Brak komentarzy: