Domain Driven Development
-
Upload
konrad-russa -
Category
Education
-
view
317 -
download
0
Transcript of Domain Driven Development
Domain Driven Design
!= Anemic Domain Model
Agenda● Dlaczego projektowanie dziedziny jest ważne?● Czym różni się od modelu anemicznego?● OO i OOP oraz SOA zamiast pisania procedur.● Ubiquitous Language.● Bounded Context.● Context Mapping i wzorce integracyjne.● Core Domain.● Architektura warstwowa i wzorce projektowe.● Dependency Injection oraz Aspect Oriented Programming.
Projektowanie dziedziny● Bardzo ważne przy tworzeniu złorzonego
oprogramowania.● Obiektowy model dziedziny, posiada stan i
zachowanie.● Rozwiązanie problemów złożoności.● Modelowanie rozwiązywanego problemu.● Odpowiedzialność we właściwym miejscu.● DRY
Model anemiczny dziedziny● Przerośnięta warstwa usług, zawiera całą logikę
biznesową.● Trudna w utrzymaniu warstwa usług.● Degradacja warstwy dziedziny.● Przeniesienie korzyści na rzecz fasady.● Ograniczenie możliwości testowania modelu.
Programowanie zorientowane obiektowo
● OOP stworzone dla lepszego rozwiązywania problemów.
● Zacierane przez niektóre technologie np. EJB, nie ma obiektów mamy np. encje, beany.
● Wprowadzenie terminu POJO – zwykłe obiekty języka Java.
● Często obsługa logiki sprowadza się do pisania kodu procedur.
Ubiquitous Language● Tworzony w czasie rozmów z klientem.● Wspólny język dla dziedziny, wynika z analizy.● Wspólny język projektu dla projektantów,
programistów zaczerpnięty z żargonu świata rzeczywistego.
Związany kontekst● Każdy model ma swój kontekst.● Integralność modelu.● Jest logiczną ramą rozwijanego modelu.● Pojedyńczy model łatwiej zarządzany przez jeden
zespół.● Każdy związany kontekst powinien mieć nazwę
ze wspolnego języka opisu.
Mapa kontekstu
Mapa kontekstu cd.● Shared Kernel● Customer-Supplier● Conformist● Separate Ways● Open Host Services● Anticorruption Layer
Mapa kontekstu cd.● Shared Kernel oraz Customre-Supplier to
wzorce dajace wysoki stopien interakcji pomiedzy kontekstami.
● Separate Way może być stosowany jeśli chcemy by konteks był odseparowany i rozwijany oddzielnie.
● Open Host Service oraz Anticorruption Layer w przypadku interakcji z zewnetrznymi systemami.
Mapa kontekstu cd. Shared Kernel
Mapa kontekstu cd. Shared Kernel
● Redukuje duplikacje, ale w dalszym ciągu utrzymuje odseparowane konteksty. Wymaga uwagi gdyż różne zespoły modyfikują rdzeń.
● Testy oraz Continuous Integration.
Mapa kontekstu cd. Customer-Supplier
● Jeśli jeden podsystem zalerzy mocno od innego.● Rezultat procesu jest przekazywany do
podsystemu.● Zespoły są mocno zainteresowane wzajemną
relacją tworzonych podsystemów.● Dostawca powinien wspierać klienta.
Mapa kontekstu cd. Conformist
● Podobnie jak w przypadku wzorca Shared Kernel, jednak bez możliwości dokonywania zmian.
● Jeśli używanykomponent ma złorzony interfejs, używane w modelu jako własny.
● Jeśli komponent ma niewielki interfejs, warto zastanowić się nad adapterem do translacji pomiędzy naszym modelem a modelem z którego komponent się wywodzi.
Mapa kontekstu cd. Anticorruption Layer
● Jeśli integracja przez protokół komunikacyjny, lub przez bazę danych.
● Brak informacji o modelu, dostępne są prymitywne dane.
● Istnieje ukryta semantyka danych.● Potrzeba izolacji modelu od systemu
zewnętrznego.
Mapa kontekstu cd. Anticorruption Layer
● Warstwa komunikuje się z zewnętrznym modelem wykorzystując zewnętrzny język.
● Spełnia formę dwu kierunkowego translatora pomiędzy dziedzinami i językami.
● Service jako fasada z zastosowaniem adaptera.
Mapa kontekstu cd. Anticorruption Layer
Mapa kontekstu cd. Separate Ways
● Jeśli jest pewność że można podzielić aplikację na kilka mniejszych niezależnych od siebie aplikacji.
Mapa kontekstu cd. Open Host Service
● Jeśli podsystem ma się integrować z różnymi klientami i trzeba tworzyć warstwę translacji dla każdego.
● Potrzeba utworzenia jednego protokołu komunikacji reprezentującego przeźroczystą grupę usług.
Mapa kontekstu
Core Domain● Po pierwsze wyszukanie i zdefiniowanie głównej
domeny projektu jako najbardziej priorytetowej.● Zaniedbania w tej części mogą stać się
katastrofalne dla systemu.● Podporządkowanie innych części jako wsparcie.
Core Domain cd.Generic Subdomains
● Istotne dla funkcionowania systemu i pełnego wyrażenia modelu.
● Identyfikowanie spójntch poddomen, które jednak nie są motorem działania systemu.
● Osadzanie w osobnych modułach.
Architektura warstwowa.● Interfejs użytkownika - prezentacja i interpretacja poleceń
użytkownika.● Warstwa aplikacji - koordynuje czynności aplikacji. Nie zawiera
logiki bienzsowej ani stanu obiektów biznesowych. Zachowuje stan zadań.
● Warstwa dziedziny – serce aplikacji, zarządza informacją o dziedzinie. Stan obiektów biznesowych. Utrwalanie obiektów w warstwie infrastruktury.
● Warstwa infrastruktury – jest wsparciem dla innych warstw. Dostarcza komunikację między warstwami, implementuje utrwalanie obiektów, zawiera dodatkowe wsparcie dla interfejsu użytkownika.
Wzorce projektowe● Implementacja modelu, też może zawieść.
Wzorce projektowe cd.● Entities● Value Objects● Services● Aggregates● Factories● Repositories
Wzorce projektowe cd.Entities
● Posiadają tożsamość.● Nie zmieniają stanu.● Są to instancje trzymane w pamięci.● Referencja spełnia warunek tożsamości.● Kombinacja unikalnych atrybutów.● Konieczny obiekt w modelu dziedziny.
Wzorce projektowe cd.Value Objects
● Nie posiada tożsamości.● Ważne są atrybuty.● Ułatwia to tworzenie obiektów i zwalnianie.● Powinny być immutable (tworzone przez
konstruktor i niemodyfikowalne).● Mogą być współdzielone, zachowują integralność
danych.● Mogą zawierać inne obiekty VO lub referencje do
Entity.
Wzorce projektowe cd.Services
● Nie wszystkie aspekty domeny mogą być mapowane do obiektów.
● Jeśli akcja nie jest w zasięgu obiektu.● Nie posiada wewnętrznego stanu.● Grupuje funkcionalność dla wielu obiektów.● Interfejsy dostarczające operacje wewnątrz
konceptu dziedziny.● Operacje są bezstanowe.
Wzorce projektowe cd.Aggregates
● Należy do cyklu życia obiektu domeny.● Określa właściwości obiektu i jego granice.● Asocjacje one-to-one, one-to-many, many-to-
many.● Bidirectional ale samochod ma silnik.● Aggregates posiada jednego roota – Entity
(jedyny obiekt widziany z zewnątrz)
Wzorce projektowe cd.Factories
● Tworzą złorzone czasem struktury Encji I Agregatów.
● Proces musi być atomowy tak aby obiekty były we własciwym stanie.
Wzorce projektowe cd.Repositories
● Baza danych jest częscią infrastruktury.● Może przetrzymywać referencje do obiektów.
Wzorce projektowe
Dependency Injection● public class MoneyTransferServiceImpl implements MoneyTransferService {● private final AccountRepository accountRepository;● private final BankingTransactionRepository bankingTransactionRepository;● @Autowired
● public MoneyTransferServiceImpl(AccountRepository accountRepository,● BankingTransactionRepository
● bankingTransactionRepository) {
● this.accountRepository = accountRepository;● this.bankingTransactionRepository = bankingTransactionRepository;● }
● public class HibernateAccountRepository● implements AccountRepository {● private HibernateTemplate hibernateTemplate;● @Autowired
● public HibernateAccountRepository(HibernateTemplate template) {● hibernateTemplate = template;
● }
● }
Dependency Injection● <beans>
● <context:annotation-config/>
● <bean name="moneyTransferService" class="MoneyTransferServiceImpl"/>
● <bean name="accountRepository" class="HibernateAccountRepository"/>
● </beans>
AOP● <bean id="authorization.loggingListener" class="...impl.listener.LoggingListener" />
● <bean id="authorization.ConnectionAdvice" class="...impl.listener.ConnectionAorund">
● <property name="Listeners" >
● <list>
● <ref bean="authorization.loggingListener" />
● </list>
● </property>
● </bean>
● <aop:config>
● <aop:pointcut id="authorization.ConncetionPointcut" expression="execution(* ...impl.helper.TopUpConnection.*Invocation(..))" />
● <aop:aspect id="authorization.ConnectionAspect" ref="authorization.ConnectionAdvice">
● <aop:around method="around" pointcut-ref="authorization.ConncetionPointcut"/>
● </aop:aspect>
● </aop:config>
AOP● public Object around(ProceedingJoinPoint call) throws Throwable {● for(Listener listener : listeners) {● notify(listener, call, null);● }
● Object result = call.proceed();
● for(Listener listener : listeners) {● notify(listener, call, result);
● }
● return result;● }
Literatura● Domain-Driven Design: Tackling Complexity in the
Heart of Software – Eric Evans● Patterns of Enterprise Application Architecture –
Martin Fowler● http://domaindrivendesign.org● http://martinfowler.com