Transcript Sale - AGH

Techniki projektowania – wzorce
projektowe
PROJEKTOWANIE
Stan „posiadania”
▫
▫
▫
▫
Przypadki użycia
Model dziedziny
Operacje systemowe
Kontrakty dla operacji systemowych
Problemy do rozwiązania
▫ Zakres odpowiedzialności poszczególnych klas?
▫ Współdziałanie (kooperacja) obiektów w celu realizacji warunków zapisanych
w kontrakcie
2
DOMAIN DRIVEN DESIGN (W SKRÓCIE DDD)
• Domain Driven Design jest koncepcją projektowania systemów
informatycznych, w której kluczową rolę odgrywa model dziedziny
• Autorem DDD jest Eric Evans (Domain-Driven Design: Tackling
Complexity in the Heart of Software, 2003)
• W literaturze polskiej funkcjonują następujące tłumaczenia terminu DDD:
▫ Projektowanie Zorientowane na Dziedzinę
▫ Projektowanie Sterowane Modelem/Dziedziną
• Koncepcja DDD to zbiór podstawowych zasad, wzorców oraz sprawdzonych
praktyk ułatwiających projektowanie systemu
• Systemy projektowane zgodnie z duchem DDD mają strukturę warstwową
3
PODSTAWOWE ELEMENTY DDD
• Encja (ang. Entity)
• Wartość (ang. Value Object)
• Serwis (ang. Service)
• Agregat (ang. Aggregate)
• Repozytorium (ang. Repository)
• Fabryka (ang. Factory)
4
OBIEKTY ENCYJNE I WARTOŚCI
Entity – obiekty identyfikowalne
▫ Tożsamość obiektu jest niezależna od jego stanu
▫ Obiekt może zmienić stan i nadal będzie postrzegany jako ten
sam obiekt
▫ Przykłady: Osoba, Rachunek, Produkt
Value Object – obiekty nieidentyfikowalne
▫ Tożsamość obiektu stanowi jego stan
▫ Obiekt po zmianie stanu jest postrzegany już jako inny obiekt
▫ Przykłady: Pieniądz, Data, Punkt, Adres
5
AGREGAT – CO TO JEST?
• Agregat to podzbiór elementów modelu, który stanowi spójną
całość w ramach której spełniane są warunki integralności
danych
• W każdym agregacie istnieje dokładnie jeden element zwany
korzeniem i pozostałe elementami zwane wewnętrznymi
korzeń
agregatu
agregat
6
element
wewnętrzny
AGREGAT – HERMETYZACJA
• Korzeń agregatu jest dostępny dla świata zewnętrznego, tzn. obiekty spoza
agregatu mogą się do niego bezpośrednio odwoływać
• Obiekty wewnętrzne nie są bezpośrednio dostępne dla świata zewnętrznego
• Obiekty wewnętrzne mogą się jednak odwoływać do innych korzeni
agregatów
• Dostęp do obiektów wewnętrznych jest możliwy tylko poprzez korzeń
agregatu
• Agregaty nie mogą współdzielić elementów wewnętrznych – dany element
(obiekt) może być częścią tylko jednego agregatu
7
AGREGAT – KORZYŚCI
• Agregat ułatwia zarządzanie cyklem życia obiektów –
agregaty są zapisywane, odtwarzane i usuwane jako całość, co
sprzyja utrzymaniu integralności danych
• Agregat chroni swoje obiekty wewnętrzne – żaden obiekt ze
świata zewnętrznego nie może wykonać operacji na obiektach
wewnętrznych agregatu inaczej niż za pośrednictwem korzenia,
dzięki temu istniej możliwość kontroli działań wykonywanych na
obiektach wewnętrznych, co również sprzyja utrzymaniu
integralności danych
8
IDENTYFIKACJA AGREGATÓW
• Jeżeli obiekty klasy A mogą wystąpić samodzielnie (tj. bez związku z
innymi obiektami), to obiekty klasy A powinny być korzeniami
agregatu
• Jeżeli obiekty klasy B posiadają powiązania tylko z obiektami klasy
A, które to są korzeniami agregatu i ponadto obiekty klasy B nie
mogą występować samodzielnie (bez powiązania z jakimś obiektem
klasy A), to obiekty klasy B powinny wchodzić w skład agregatu
zbudowanego wokół obiektów klasy A
9
AGREGAT – PRZYKŁAD
• Klasy Wydarzenie i Osoba są jedynymi klasami, których
obiekty mogą występować samodzielnie → Obiekty klas
Wydarzenie i Osoba są korzeniami agregatów
korzeń
•
Obiekty klasy Alarm mogą być powiązane tylko z obiektami
klasy Wydarzenie, nie mogą też pojawić się samodzielnie →
obiekty klasy Alarm są elementami wewnętrznymi w
agregacie Wydarzenie
•
Obiekty klasy Adres mogą być powiązane tylko z obiektami
klasy Osoba, nie mogą też pojawić się samodzielnie →
obiekty klasy Adres są elementami wewnętrznymi w
agregacie Osoba
•
Obiekty klasy Uczestnictwo bez związków z obiektami klas
Osoba i Wydarzenie nic nie znaczą, powinny być zarządzane
przez jeden z wcześniej zidentyfikowanych agregatów →
obiekty klasy Uczestnictwo będą elementami wewnętrzymi
w agregacie Wydarzenie
agregat
korzeń
10
PROBLEM Z DOSTĘPEM DO OBIEKTÓW BIZNESOWYCH
• Jeśli klient chce wykonać pewną operację na jednym z obiektów
biznesowych, to możliwe są następujące scenariusze:
1.
Jeśli obiekt biznesowy nie istnieje, klient tworzy taki obiekt i
wykonuje na nim operację
2.
Jeśli obiekt biznesowy istnieje, klient uzyskuje dostęp do
interesującego obiektu i wykonuje na nim operację
• Scenariusz 1 nie stwarza większych problemów w realizacji, pod
warunkiem jednak że klient posiada kompletne dane potrzebne do
utworzenia obiektu biznesowego
• Scenariusz 2 może stanowić problem, w sytuacji dużej liczby obiektów
biznesowych
• Rozwiązanie dla scenariusza 2 polegające na przechowywaniu
wszystkich obiektów biznesowych przez klienta zwiększa niestety
liczbę powiązań pomiędzy warstwami i tym samym poziom zależności
miedzy warstwami
11
PROBLEM Z DOSTĘPEM DO OBIEKTÓW BIZNESOWYCH (2)
• W wielu systemach informatycznych wymaga się zapisywania stanu systemu
w bazie danych po wykonaniu ciągu operacji systemowych i odtworzenia
tegoż stanu w przypadku awarii lub w chwili uruchomienia systemu od nowa
• W wielu systemach informatycznych liczba obiektów biznesowych jest na
tyle duża, że nie jest możliwe ich jednoczesne przetwarzanie w pamięci
operacyjnej – potrzebna jest baza danych, w której te obiekty są
przechowywane i udostępnianie na żądanie
• Wszystkie powyższe problemy mogą być efektywnie rozwiązane
poprzez wprowadzenie repozytoriów obiektów biznesowych
12
REPOZYTORIUM
• Wzorzec repozytorium umożliwia dostęp do puli obiektów
biznesowych ukrywając przed klientem wszelkie mechanizmy
dostępu do bazy danych
• Z punktu widzenia klienta repozytorium może być traktowane jako
kolekcja obiektów biznesowych
• Repozytorium udostępnia swoim klientom operacje zapisu, odczytu,
aktualizacji, usuwania oraz wyszukiwania obiektów biznesowych
• Koncepcja DDD zaleca utworzenie jednego repozytorium dla każdego
13
agregatu
REPOZYTORIUM – PRZYKŁAD
Repozytorium wydarzeń –
obsługuje agregat Wydarzenie,
który składa się z następujących
klas:
• Wydarzenie
• Alarm
• Uczestnictwo
warstwa logiki
biznesowej
warstwa
infrastruktury
Repozytorium osób – obsługuje
agregat Osoba, który składa się z
następujących klas:
• Osoba
• Adres
14
SERWIS
• W myśl koncepcji DDD serwisy to specjalizowane klasy przeznaczone
do wykonywania operacji biznesowych, których nie można przypisać
do jednego obiektu biznesowego
• W szerszym znaczeniu serwisem jest również klasa odpowiedzialna
za koordynacje działań związanych z wykonywaniem operacji
systemowych w ramach jednego przypadku użycia
• Serwisy nie posiadają wewnętrznego stanu – zwykle tworzone są na
potrzeby konkretnego zadania i po jego wykonaniu są usuwane
• Serwis jest obiektem rozpoczynającym obsługę operacji systemowej
15
SERWISY – PRZYKŁAD
Serwis Wydarzeń –
odpowiada za zarządzanie
wykonywaniem operacji
systemowych związanych
wydarzeniami, np.:
•UtworzWydarzenie()
•DodajAlarm()
•DodajUczestnika()
Serwis Osób –
odpowiada za zarządzanie
wykonywaniem operacji
systemowych związanych
osobami, np. :
•UtworzOsobe()
•UsunOsobe()
warstwa
aplikacji
warstwa logiki
biznesowej
warstwa
infrastruktury
16
17
Techniki projektowania - wzorce GRASP
Przykład: Kasa fiskalna
Opis dziedziny problemu
System jest przeznaczony do obsługi procesu sprzedaży. Podstawowa
funkcjonalność systemu obejmuje takie czynności jak: wprowadzanie kodów
towarów kupowanych przez klienta, obliczanie kwoty do zapłaty, obsługa
wszystkich rodzajów płatności (m.in. gotówka, karta kredytowa). System
powinien współpracować z systemami finansowo-księgowymi. Ze względu
na zmieniające się przepisy podatkowe system powinien umożliwiać zmianę
reguł obliczania podatków. System musi ponadto utrzymywać aktualną bazę
dostępnych towarów
18
Techniki projektowania - wzorce GRASP
Identyfikacja klas konceptualnych (1)
• Store – reprezentuje sklep. Sklep opisany jest atrybutami
oznaczającymi jego nazwę i fizyczną lokalizację (name, address)
• Register – reprezentuje kasę fiskalną, na której dokonywane są
transakcje
• Cashier – reprezentuje osobę obsługującą kasę fiskalną
• Customer – reprezentuje klienta dokonującego zakupu
19
Techniki projektowania - wzorce GRASP
Identyfikacja klas konceptualnych (2)
• ProductCatalog – reprezentuje katalog produktów oferowanych
do sprzedaży
• ProductDescription – reprezentuje opis produktu. Zawiera
takie atrybuty jak description (opis produktu) oraz price (cena)
• Payment – reprezentuje płatność . Zawiera atrybut
amountTendered do przechowywania zapłaconej kwoty
20
Techniki projektowania - wzorce GRASP
Identyfikacja klas konceptualnych (3)
• Sale – reprezentuje bieżącą sprzedaż (i jednocześnie dokument
sprzedaży). Zawiera atrybut date do przechowywania daty
transakcji oraz atrybut total do przechowywania całkowitej kwoty
do zapłaty
• SaleLineItem – reprezentuje jedną pozycję na dokumencie
sprzedaży. Zawiera atrybut quantity do przechowywania ilości
zakupionego towaru
21
Techniki projektowania - wzorce GRASP
Model dziedziny
22
Techniki projektowania - wzorce GRASP
Przypadek użycia
Przypadek użycia: Obsługa sprzedaży
Wyzwalacz: Klient przychodzi do kasy z produktami, które zamierza kupić
Scenariusz główny:
1. Kasjer rozpoczyna nowy proces sprzedaży
2. Kasjer skanuje kod towaru
3. System rejestruje pozycje sprzedaży, wyświetla opis produktu, cenę oraz oblicza
kwotę do zapłaty
4. Kroki 2-3 są powtarzane dla wszystkich produktów
5. System wyświetla kwotę do zapłaty
6. Kasjer informuje klienta o kwocie do zapłaty
7. Klient za pośrednictwem kasjera dokonuje płatności
8. System rejestruje płatność
23
Techniki projektowania - wzorce GRASP
Diagram sekwencji systemowych
Główny scenariusz:
1.
2.
3.
4.
5.
6.
7.
8.
Kasjer rozpoczyna nowy proces sprzedaży
Kasjer skanuje kod towaru
System rejestruje pozycje sprzedaży,
wyświetla opis produktu, cenę oraz oblicza
kwotę do zapłaty
Kroki 2-3 są powtarzane dla wszystkich
produktów
System wyświetla kwotę do zapłaty
Kasjer informuje klienta o kwocie do zapłaty
Klient za pośrednictwem kasjera dokonuje
płatności
System rejestruje płatność
24
Techniki projektowania - wzorce GRASP
Kontrakty dla operacji systemowych (1)
Operacja: MakeNewSale()
Warunki początkowe:
• Istnieje obiekt r klasy Register
Warunki końcowe:
• Utworzono obiekt s klasy Sale
• Atrybutowi s.dateTime przypisano bieżącą datę i czas
• Utworzono związek pomiędzy obiektem s a obiektem r
25
Techniki projektowania - wzorce GRASP
Kontrakty dla operacji systemowych (2)
Operacja: EnterItem(itemId, quantity)
Warunki początkowe:
• Istnieje obiekt s klasy Sale oraz obiekt pd klasy ProductDescription
Warunki końcowe:
• Utworzono obiekt sli klasy SaleLineItem
• Atrybutowi sli.quantity przypisano wartość argumentu quantity
• Utworzono związek pomiędzy obiektem sli a obiektem s
• Utworzono związek pomiędzy obiektem sli a obiektem pd
26
Techniki projektowania - wzorce GRASP
Kontrakty dla operacji systemowych (3)
Operacja: EndSale()
Warunki początkowe:
• Istnieje obiekt s klasy Sale
Warunki końcowe:
• Atrybutowi s.isComplete przypisano wartość true
27
Techniki projektowania - wzorce GRASP
Kontrakty dla operacji systemowych (4)
Operacja: MakePayment(amount)
Warunki początkowe:
• Istnieje obiekt s klasy Sale
Warunki końcowe:
• Utworzono obiekt p klasy Payment
• Atrybutowi p.amountTendered przypisano wartość argumentu amount
• Utworzono związek pomiędzy obiektem p a obiektem s
28
Projektowanie interakcji wg DDD –
wskazówki
• Operacja systemowa trafia do jednego z
serwisów
• Do zadań serwisu należy pobranie z
repozytorium obiektu biznesowego, którego
dotyczy operacja oraz delegowanie
wykonania operacji do tegoż obiektu
• Jeśli operacja nie może być przypisana do
jednego obiektu biznesowego, wówczas
serwis wykonuje wszystkie czynności
wymagane przez operacje
29
Diagram sekwencji dla operacji
DodajUczestnika()
Serwis Wydarzeń znajduje obiekt
Wydarzenie w Repozytorium
Wydarzeń oraz obiekt Osoba w
Repozytorium Osób
Wydarzenie tworzy obiekt klasy
Uczestnik i dodaje go do swojej
listy (DodajUczestnika)
Komunikat systemowy
DodajUczestnika() jest
odbierany przez obiekt
Serwis Wydarzeń
Serwis Wydarzeń deleguje
wykonanie operacji dodania
uczestnika do obiektu Wydarzenie
przekazując mu obiekt Osoba
30
Techniki projektowania - wzorce GRASP
Projektowanie
• Stan wyjściowy:
Operacje systemowe są specyfikacją zachowania systemu
widzianego z poziomu jego klienta (np. interfejsu użytkownika).
Kontrakty dla operacji systemowych opisują stan systemu przed i po
wykonaniu operacji systemowej
• Problem do rozwiązania:
Jak przypisać odpowiedzialności do poszczególnych klas i
zaprojektować interakcje obiektów, aby zrealizować warunki
zapisane w kontrakcie?
31
Techniki projektowania - wzorce GRASP
Wzorce GRASP
• GRASP - General Resposibility Assignment Software Patterns
• GRASP to zbiór kilku wzorców projektowania obiektowego
związanych z przypisywaniem odpowiedzialności do klas.
• Autorem wzorców GRASP jest Craig Larman
• Każdy ze wzorców GRASP to rodzaj zalecenia projektowego, którego
uwzględnienie z reguły prowadzi do lepszego rozwiązanie problemu
32
Techniki projektowania - wzorce GRASP
Wzorce GRASP
• Ekspert (ang. Expert)
• Kreator (ang. Creator)
• Kontroler (ang. Contoller)
• Luźne sprzężenie (ang. Low Coupling)
• Wysoka spójność (ang. High Cohesion)
• Pure Fabrication
• Polimorfizm (ang. Polimorphism)
33
Techniki projektowania - wzorce GRASP
Wzorce GRASP - Kreator
• Problem: Która klasa powinna być odpowiedzialna za tworzenie
nowych instancji danej klasy?
• Rozwiązanie: Przypisz klasie B odpowiedzialność tworzenia
nowych instancji klasy A, jeśli zachodzi jeden lub kilka z poniższych
warunków:
▫
▫
▫
▫
Klasa B zawiera (agreguje) obiekty klasy A
Klasa B rejestruje obiekty klasy A
Klasa B intensywnie używa obiekty klasy A
Klasa B posiada dane niezbędne do zainicjalizowania obiektów klasy A
34
Techniki projektowania - wzorce GRASP
Wzorce GRASP – Kreator
• Im więcej z powyższych punktów jest spełnione, tym mocniejsze jest
uzasadnienie dla wyboru klasy B jako kreatora obiektów klasy A
• W sytuacji, gdy kilka klas kandyduje do bycia kreatorem obiektów
klasy A, wówczas wybieramy te klasę, która spełnia najwięcej z
powyższych warunków
35
Techniki projektowania - wzorce GRASP
Kreator - przykład
Problem: Która klasa powinna być
odpowiedzialna za utworzenie obiektu typu
SalesLineItem?
Kandydaci:
• Sale
• zawiera obiekty typu
SalesLineItems
• używa obiekty typu SalesLineItems
• posiada niezbędne dane (quantity)
do zainicjowania obiekt typu
SalesLineItems
model dziedziny (fragment )
•
ProductDescription - jest opisem dla
obiektów SalesLineItems
36
Techniki projektowania - wzorce GRASP
Kreator - przykład
Rozwiązanie:
Na podstawie wzorca Kreator obiekty klasy SalesLineItem powinny być
tworzone przez obiekt klasy Sale
37
Techniki projektowania - wzorce GRASP
Kreator - przykład
Elementy modelu projektowego:
Model projektowy (fragment)
•
kierunek nawigacji od Register do Sale
•
atrybut currentSale w klasie Register –
realizacja związku Register – Sale
•
kierunek nawigacji od Sale do
SalesLineItem
•
atrybut lineItems w klasie Sale – realizacja
związku Sale - SalesLineItems
38
Techniki projektowania - wzorce GRASP
Wzorce GRASP - Ekspert
• Problem: Jak brzmi najbardziej ogólna zasada
przypisywania odpowiedzialności? Której klasie
przypisać daną odpowiedzialność?
• Rozwiązanie: Przypisz odpowiedzialność klasie, która
ma niezbędne informacje, aby ją zrealizować
39
Techniki projektowania - wzorce GRASP
Wzorce GRASP - Ekspert
• Wzorzec Ekspert jest jedną z elementarnych zasad projektowania
obiektowego
• Mimo iż powyższa zasada brzmi jak coś oczywistego, jej zastosowanie może
nieraz nastręczać trudności
• Potencjalne problemy z poprawnym stosowaniem wzorca ekspert wynikają
najczęściej z rozproszenia informacji po wielu różnych klasach
40
Techniki projektowania - wzorce GRASP
Wzorce GRASP - Ekspert
• Do poprawnego zastosowania wzorca Ekspert w przypadku rozproszenia
informacji konieczny jest podział odpowiedzialności pomiędzy wszystkie
klasy posiadające częściowe informacje
• Każda z klas posiadających częściowe informacje jest tzw. częściowym
ekspertem
• Innym problemem związanym ze wzorcem Ekspert jest naturalna skłonność
do przypisywania odpowiedzialności kierując się zasadą, by klasy systemu
informatycznego zachowywały się podobnie jak klasy w świecie
rzeczywistym, co nie zawsze jest dobrym rozwiązaniem
41
Techniki projektowania - wzorce GRASP
Ekspert - przykład
Problem: Która klasa powinna być
odpowiedzialna za obliczenie kwoty do
zapłaty
Kandydaci:
• Sale – zawiera atrybut total do
przechowywania kwoty do zapłaty
model dziedziny (fragment )
•
SalesLineItem – zawiera atrybut
quantity niezbędny do obliczenia
kwoty do zapłaty za każdy z
produktów z osobna
•
ProductDescription – zawiera
atrybut price z bieżącą ceną
każdego z produktów
42
Techniki projektowania - wzorce GRASP
Ekspert - przykład
Rozwiązanie:
•
Klasy SalesLineItem i ProductDescription są częściowymi ekspertami - zawierają
jedynie cześć informacji niezbędnej do obliczenia całkowitej kwoty do zapłaty
•
Do obliczenia całkowitej kwoty do zapłaty należy zaprojektować odpowiednią interakcję
pomiędzy wszystkimi klasami posiadającymi cząstkową informację
43
Techniki projektowania - wzorce GRASP
Ekspert - przykład
Elementy modelu projektowego:
Model projektowy (fragment)
•
kierunek nawigacji od SalesLineItem do
ProductDescription
•
atrybut description w klasie SalesLineItem
– realizacja związku SalesLineItem ProductDescription
•
Operacja GetTotal() w klasie Sale
•
Operacja GetSubtotal() w klasie
SalesLineItem
•
Operacja GetPrice() w klasie
ProductDescription
44
Techniki projektowania - wzorce GRASP
Wzorce GRASP – Kontroler
• Problem: Która klasa spoza interfejsu użytkownika powinna jako
pierwsza obsługiwać operacje systemową?
• Rozwiązanie: Przypisz odpowiedzialność klasie, dla której
prawdziwe jest jedno z poniższych stwierdzeń:
▫ reprezentuje cały system, podsystem, obiekt leżący najwyżej w hierarchii
(ang. root object)
▫ reprezentuje przypadek użycia, w którym operacja systemowa ma miejsce
45
Techniki projektowania - wzorce GRASP
Wzorce GRASP – Kontroler
• Kontroler reprezentujący cały system, podsystem itp. pełni role fasady dla
całej warstwy logiki biznesowej
• Na ogół kontroler nie posiada wystarczającej wiedzy, aby kompletnie
obsłużyć żądanie, stąd jego praca polega na znalezieniu odpowiedniego
obiektu z warstwy logiki biznesowej i przekazaniu do niego sterowania
(delegacja)
• Kontroler typu fasada stosuje się w niewielkich systemach, gdzie nie ma
zbyt wielu operacji systemowych
• Jeśli w systemie jest dużo operacji systemowych, wówczas stosuje się
kontrolery reprezentujące pojedyncze przypadki użycia, bądź też grupujące
kilka przypadków użycia
46
Techniki projektowania - wzorce GRASP
Wzorce GRASP – Kontroler
• Kontrolery reprezentujące przypadki użycia są w istocie w istocie tworami
sztucznymi, nie mającymi odpowiednika w dziedzinie problemu
• Kontrolera GRASP nie należy mylić z kontrolerem ze wzorca Model-WidokKontroler, który jest elementem warstwy interfejsu użytkownika
• Kontroler GRASP należy do warstwy logiki biznesowej (znajduje się na
granicy tej warstwy)
ROZWIĄZANIE I – KONTROLER TYPU FASADA
Klasy
pełniące role
kontrolerów
Kontroler
•
•
Zarządzanie wykonywaniem
operacji systemowych
Przechowywanie i
udostępnianie obiektów
warstwy biznesowej
warstwa
aplikacji
warstwa logiki
biznesowej
47
KONTROLER TYPU FASADA – CHARAKTERYSTYKA
• Kontroler reprezentujący cały system, podsystem itp. pełni role
fasady dla całej warstwy logiki biznesowej
• W zakresie odpowiedzialności kontrolera typu fasada leży:
▫ koordynacja działań związanych z wykonywaniem operacji
systemowych
▫ przechowywanie i udostępnianie obiektów warstwy logiki
biznesowej
• Kontroler typu fasada stosuje się w niewielkich systemach, gdzie nie
48
ma zbyt wielu operacji systemowych
ROZWIĄZANIE II – KONTROLER TYPU PRZYPADEK UŻYCIA
Klasy
pełniące role
kontrolerów
Kontroler
•
Zarządzanie
wykonywaniem operacji
systemowych
warstwa
aplikacji
warstwa logiki
biznesowej
warstwa
infrastruktury
Repozytorium
•
Przechowywanie i
udostępnianie obiektów
warstwy biznesowej
49
KONTROLER TYPU PRZYPADEK UŻYCIA CHARAKTERYSTYKA
• W zakresie odpowiedzialności kontrolera leży koordynacja działań
związanych z wykonywaniem operacji systemowych
• Klasa Repozytorium jest odpowiedzialna za przechowywanie i
udostępnianie obiektów warstwy biznesowej
• Kontrolery reprezentujące pojedyncze przypadki użycia (lub kilka
przypadków użycia) stosuje się w bardziej złożonych systemach,
gdzie występuje większa liczba operacji systemowych i/lub
wymagane jest zapisywanie i odtwarzanie stanu systemu po
wykonaniu pewnego ciągu operacji systemowych
50
REPOZYTORIUM
• Zasada Persistence Ignorance
„System należy projektować w sposób niezależny od
infrastruktury, w tym od wszystkich mechanizmów dostępu
do danych”
• Cała logika związana z dostępem do bazy danych w
celu odtworzenia, zapisania lub wyszukania obiektów
biznesowych zaszyta jest w Repozytorium
• Z punktu widzenia warstwy logiki biznesowej
Repozytorium pełni rolę kolekcji obiektów
biznesowych
51
REPOZYTORIUM – PRZYKŁAD
Repozytorium wydarzeń
•
•
•
Wydarzenie
Alarm
Uczestnictwo
Repozytorium osób
•
•
Osoba
Adres
52
53
Techniki projektowania - wzorce GRASP
Kontroler - przykład
Problem: Która klasa jako pierwsza
obsługuje operacje systemowe takie jak:
MakeNewSale(), EnterItem(),
EndSale(), MakePayment()?
model dziedziny (fragment)
Kandydaci:
• Store - reprezentuje cały system
• Register - reprezentuje
podsystem
• ProcessSaleHandler – klasa
utworzona specjalnie w tym celu
54
Techniki projektowania - wzorce GRASP
Kontroler - przykład
Rozwiązanie 1: funkcje
kontrolera pełni klasa Register.
Jest to kontroler typu fasada stosuje się w sytuacji, gdy liczba
operacji systemowych jest
nieduża
Rozwiązanie 2: funkcje kontrolera pełni
specjalnie w tym celu utworzona klasa
ProcessSaleHandler. Jest to kontroler
typu przypadek użycia - stosuje się w
sytuacji, gdy liczba operacji systemowych
jest znaczna
Komentarz: Obydwa rozwiązania są do zaakceptowania. Niemniej praktyka
pokazuje, że liczba identyfikowanych operacji systemowych w kolejnych
iteracjach projektu wzrasta, stąd preferowane są rozwiązania z dedykowanym
kontrolerem (rozwiązanie 2)
55
Techniki projektowania - wzorce GRASP
Kontroler - przykład
Elementy modelu projektowego:
Model projektowy (fragment)
•
Operacja MakeNewSale() w klasie Register
•
Operacja EnterItem() w klasie Register
•
Operacja MakePayment() w klasie Register
•
Operacja EndSale() w klasie Register
56
Techniki projektowania - wzorce GRASP
Sprzężenie
Sprzężenie (ang. coupling) – miara wzajemnej zależności obiektów
Niski poziom sprzężeń:
•
•
Stosunkowo niewielka liczba
związków między klasami
Możliwość grupowania klas ściślej
ze sobą powiązanych
Wysoki poziom sprzężeń:
•
•
Duża liczba związków między
klasami
Brak możliwości grupowania klas –
wszystkie klasy są ze sobą ściśle
powiązane
57
Techniki projektowania - wzorce GRASP
Wzorce GRASP - Luźne sprzężenie
• Problem: W jaki sposób spowodować, żeby zmiany we
fragmencie modelu jak najmniej wpływały na pozostała
część modelu? Co należy czynić, aby zwiększyć
możliwość ponownego wykorzystania kodu?
• Rozwiązanie: Przypisuj odpowiedzialności w taki
sposób, aby ograniczyć liczbę związków między klasami
58
Techniki projektowania - wzorce GRASP
Wzorce GRASP - Luźne sprzężenie
• Model zawierający dużo związków między klasami charakteryzuje wiele
negatywnych cech:
▫ zmiany w jednej klasie implikują zmiany w innych klasach
▫ problem ze zrozumieniem modelu
▫ trudności w ponownym użyciu (wymaga to użycia wszystkich klas powiązanych)
• Z drugiej strony związki między klasami są nieodłączną cechą każdego
modelu obiektowego - umożliwiają realizację zasady podziału
odpowiedzialności
• Postulat luźnych sprzężeń nie sugeruje w żaden sposób usunięcia związków
między klasami. Sugeruje jedynie, że jeśli istnieje możliwość zrealizowania
określonej funkcjonalności bez zwiększania poziomu zależności, to należy
taką opcję wybrać
59
Techniki projektowania - wzorce GRASP
Luźne sprzężenie - przykład
Problem: Która klasa powinna być
odpowiedzialna za utworzenie obiektu
typu Payment i powiązanie go z
obiektem typu Sale? Zaproponować
rozwiązanie w oparciu o zasadę „Luźne
sprzężenie”
model dziedziny (fragment )
Kandydaci:
• Register
• Sale
60
Techniki projektowania - wzorce GRASP
Luźne sprzężenie - przykład
nowy związek
Rozwiązanie 1:
•
Klasa Register jest odpowiedzialna za utworzenie obiektu klasy Payment (zastosowano wzorzec
Kreator - w świecie rzeczywistym kasa fiskalna rejestruje płatności)
•
Klasa Register odpowiada za utworzenie powiązania pomiędzy obiektem klasy Sale i obiektem
klasy Payment (metoda AddPayment())
Wniosek: Rozwiązanie 1 zwiększa liczbę związków między klasami - powstał nowy związek pomiędzy
klasą Register a klasą Payment
61
Techniki projektowania - wzorce GRASP
Luźne sprzężenie - przykład
Rozwiązanie 2: (preferowane)
•
Klasa Register deleguje do klasy Sale utworzenie obiektu klasy Payment
•
Klasa Sale odpowiada za utworzenie obiektu klasy Payment i utworzenie powiązania pomiędzy
obiektem klasy Sale i nowo utworzonym obiektem klasy Payment
Wniosek: Rozwiązanie 2 nie zwiększa liczby związków między klasami - rozwiązanie preferowane z
punktu widzenia zasady „Luźne sprzężenie”
62
Techniki projektowania - wzorce GRASP
Luźne sprzężenie - przykład
Elementy modelu projektowego:
•
kierunek nawigacji od Sale do Payment
•
atrybut payment w klasie Sale – realizacja
związku Sales - Payment
•
Operacja MakePayment() w klasie Sale
63
Techniki projektowania - wzorce GRASP
Spójność
Spójność (ang. cohession) – miara wzajemnego zintegrowania metod
składowych klas
Niski poziom spójności:
Średni poziom spójności
Wysoki poziom spójności
•
•
•
•
Klasa A wykonuje
samodzielnie wszystkie
operacje
Duża liczba operacji w
klasie A
•
Klasa A deleguje odpowiedzialność
do innych klas
Klasa A koordynuje wszystkie
operacje
•
Klasa A deleguje odpowiedzialność
do innych klas
Operacje w klasach pomocniczych
również delegują część
odpowiedzialności
64
Techniki projektowania - wzorce GRASP
Wzorce GRASP – Wysoka spójność
• Problem: Jak sprawić, aby klasa była łatwa do
zarządzania, zorientowana na jedno określone zadanie, a
jej kod był zrozumiały?
• Rozwiązanie: Przypisz odpowiedzialność w taki
sposób, aby spójność była jak największa
65
Techniki projektowania - wzorce GRASP
Wzorce GRASP – Wysoka spójność
• Klasa, która ma zbyt wiele niezwiązanych ze sobą odpowiedzialności
posiada niską spójność (kohezję)
• Niską kohezją charakteryzuje się również klasa, która co prawda odpowiada
za jedno zadanie, ale zadanie to jest mocno skomplikowane i jest
realizowane samodzielnie przez jedną klasę
• Aby poprawić kohezje w tym przypadku należy realizację tego zadania
rozłożyć na kilka współpracujących ze sobą klas
66
Techniki projektowania - wzorce GRASP
Wzorce GRASP – Wysoka spójność
• Klasa o wysokiej spójności to klasa skupiona na realizacji ściśle określonej
funkcjonalności, posiłkująca się innymi klasami w sytuacji, gdy nie posiada
wystarczających informacji lub realizacja funkcjonalności jest złożonym
procesem
• Klasy o wysokiej kohezji to klasy, które posiadają stosunkowo niewiele
metod, metody są ze sobą powiązane, kod metod jest krótki i czytelny, a w
sytuacji bardziej złożonej logiki następuje delegacja odpowiedzialności do
klas współpracujących
67
Techniki projektowania - wzorce GRASP
Wysoka spójność- przykład
Problem: Która klasa powinna być
odpowiedzialna za utworzenie obiektu
typu Payment i powiązanie go z
obiektem typu Sale? Zaproponować
rozwiązanie w oparciu o zasadę
„Wysoka spójność”
model dziedziny (fragment )
Kandydaci:
• Register
• Sale
68
Techniki projektowania - wzorce GRASP
Wysoka spójność - przykład
Rozwiązanie 1:
•
Klasa Register jest odpowiedzialna za utworzenie obiektu klasy Payment (zastosowano wzorzec
Kreator - w świecie rzeczywistym kasa fiskalna rejestruje płatności)
•
Klasa Register odpowiada również za utworzenie powiązania pomiędzy obiektem klasy Sale i
obiektem klasy Payment (metoda AddPayment())
Wniosek: Rozwiązanie 1 zwiększa zakres odpowiedzialność klasy Register. W tym konkretnym
przypadku jest do zaakceptowania, niemniej może prowadzić do obniżenia spójności klasy Register
(duża liczba odpowiedzialności)
69
Techniki projektowania - wzorce GRASP
Wysoka spójność - przykład
Rozwiązanie 2 (preferowane):
•
Klasa Register deleguje do klasy Sale utworzenie obiektu klasy Payment
•
Klasa Sale odpowiada za utworzenie obiektu klasy Payment i utworzenie powiązania pomiędzy
obiektem klasy Sale i nowo utworzonym obiektem klasy Payment
Wniosek: Rozwiązanie 2 nie zwiększa zakresu odpowiedzialności klasy Register. Klasa Register
deleguje wykonanie określonych czynności do klasy Sale - rozwiązanie preferowane z punktu
widzenia zasady „Wysoka spójność”
70
Techniki projektowania - wzorce GRASP
Realizacja operacji MakeNewSale()
Operacja: MakeNewSale()
Warunki początkowe:
• Istnieje obiekt r klasy Register
Warunki końcowe:
• Utworzono obiekt s klasy Sale
• Atrybutowi s.dateTime
przypisano bieżącą datę i czas
• Utworzono związek pomiędzy
obiektem s a obiektem r
Kontroler
Kreator
71
Techniki projektowania - wzorce GRASP
Realizacja operacji EnterItem()
Operacja: EnterItem(itemId, quantity)
Warunki początkowe:
• Istnieje obiekt s klasy Sale oraz obiekt pd klasy
ProductDescription
Warunki końcowe:
• Utworzono obiekt sli klasy SaleLineItem
• Atrybutowi sli.quantity przypisano wartość
argumentu quantity
• Utworzono związek pomiędzy obiektem sli a
obiektem s
• Utworzono związek pomiędzy obiektem sli a
obiektem pd
Kontroler
Kreator
Ekspert
72
Techniki projektowania - wzorce GRASP
Realizacja operacji MakePayment()
Operacja: MakePayment(amount)
Warunki początkowe:
• Istnieje obiekt s klasy Sale
Warunki końcowe:
• Utworzono obiekt p klasy Payment
• Atrybutowi p.amountTendered
przypisano wartość argumentu
amount
• Utworzono związek pomiędzy
obiektem p a obiektem s
Kontroler
Kreator
73
Techniki projektowania - wzorce GRASP
Realizacja operacji EndSale()
Operacja: EndSale()
Warunki początkowe:
• Istnieje obiekt s klasy Sale
Warunki końcowe:
• Atrybutowi s.isComplete
przypisano wartość true
Kontroler
Ekspert
74
Techniki projektowania - wzorce GRASP
Model projektowy – wersja finalna
75
Techniki projektowania - wzorce GRASP
Literatura
• Craig Larman: Applying UML and Patterns: An
Introduction to Object-Oriented Analysis and Design
and Iterative Development