460 likes | 591 Views
Efektywne tworzenie oprogramowania 2008/2009. cvs.ii.uni.wroc.pl/eto2008. Wzorce GRASP. Wprowadzenie do projektowania obiektów w łatwy i zrozumiały sposób Odpowiedzialności Wzorce GRASP Expert (information expert) Creator Low Coupling High Cohesion. Wzorce GRASP.
E N D
Efektywne tworzenie oprogramowania2008/2009 cvs.ii.uni.wroc.pl/eto2008
Wzorce GRASP • Wprowadzenie do projektowania obiektów w łatwy i zrozumiały sposób • Odpowiedzialności • Wzorce GRASP • Expert (information expert) • Creator • Low Coupling • High Cohesion
Wzorce GRASP • GRASP to skrót od General Responsibility Assignment Software Patterns • To są podstawowe zasady projektowania obiektów • Wzorce GRASP koncentrują się na jednym z najważniejszych aspektów projektowania obiektów, przypisywania odpowiedzialności do klas • Nie dotyczą projektowania architektury
Czym jest projektowanie obiektów • Uproszczona definicja • w czasie analizy kolejnych iteracji • identyfikujemy przypadki użycia i tworzymy ich opis, aby mieć wymagania • tworzymy i ulepszamy model dziedziny • aby utworzyć fragment projektu obiektów • przypisujemy metody do klas • projektujemy jak klasy współpracują, aby zrealizować funkcjonalność przedstawioną w przypadkach użycia
Krytyczne kroki w projektowaniu • Centralne zadania projektowania to: • decyzja, które metody i gdzie należą • jak obiekty powinny współpracować • Realizacja przypadków użycia opisuje jak poszczególne p.u. są realizowane w modelu projektowym w terminach współpracy obiektów • Praca związana z realizacją p.u. jest projektowaniem, projekt rozrasta się przy realizacji każdego nowego p.u. • Przy realizacji p.u. stosujemy diagramy interakcji i wzorce
Odpowiedzialności • Odpowiedzialności są związane z dziedziną problemu • W modelu projektowym – zobowiązania obiektu do określonych zachowań • Dwa typy odpowiedzialności: • Odpowiedzialności typu robić • Odpowiedzialności typu wiedzieć
Odpowiedzialności • Typu robić • robić coś samodzielnie, np. tworzyć obiekt, wykonywać obliczenia • inicjalizować akcję w innym obiekcie • kontrolować i koordynować działania w innych obiektach • Typu wiedzieć • znać prywatne dane • znać powiązane obiekty • wiedzieć o rzeczach, które można wyprowadzić lub obliczyć Typ wiedzieć jest łatwiejszy do wyprowadzenia z modelu dziedziny, gdzie ilustruje się atrybuty i powiązania
Odpowiedzialności • Tłumaczenie odpowiedzialności z dziedziny problemu na klasy i metody zależy od granulacji odpowiedzialności • odpowiedzialność to nie to samo co metoda ale implementujemy metody, aby spełniały odpowiedzialności • Przykład • klasa Sale może definiować metody, aby znać całkowitą kwotę – metodę getTotal • ta klasa może współpracować z innymi obiektami, jak przesłanie komunikatu getSubtotal do każdego obiektu SalesItem zapytując o jego kwotę
GRASP - pomoc • GRASP – pomoc w zrozumieniu istoty projektowania obiektów • Projektowanie przebiega w sposób metodyczny i racjonalny • Podejście GRASP bazuje na przypisywaniu odpowiedzialności, tworząc podstawową strukturę obiektów i sterowania • jest prowadzone przez wzorce przypisywania odpowiedzialności
Odpowiedzialności i diagramy interakcji • Odpowiedzialności są przypisywane do obiektów przy projektowaniu obiektów w czasie tworzenia diagramów interakcji • diagramy sekwencji (przebiegu) • diagramy współpracy • Przykłady: • „Sale jest odpowiedzialna za utworzenie SalesLineItems” (robić) lub • „Sale” jest odpowiedzialna za wiedzę o swojej całkowitej kwocie” (wiedzieć)
Odpowiedzialności i diagramy interakcji • Odpowiedzialności są ilustrowane i przypisywane do klas przez tworzenie diagramów sekwencji (przebiegu) • W czasie projektowania – perspektywa specyfikacji (interfejs usług obiektu) a nie wewnętrzna implementacja Obiekty Sale mają odpowiedzialność tworzenia płatności Odpowiedzialność jest wywoływana komunikatem makePayment
Creator • Problem • Kto powinien być odpowiedzialny za tworzenie nowych instancji klas? • Rozwiązanie • Przypisz klasie B odpowiedzialność za tworzenie instancji klasy A, jeśli jest spełniony 1 lub więcej z poniższych warunków: • B agreguje obiekty A • B zawiera obiekty A • B zapisuje instancje obiektów A • B ściśle korzysta z obiektów A • B posiada inicjalizujące dane, które są przekazywane do A, gdy jest ono tworzone
Przykład kreatora • Kto powinien być odpowiedzialny za tworzenie instancji SalesLineItem? • Stosując Creator, szukamy klasy, która agreguje, zawiera itd., instancje SalesLineItem • Rozważmy następujący model (częściowy) dziedziny
Tworzenie SalesLineItem • Sale zawiera wiele obiektów SalesLineItem, więc wzorzec Creator sugeruje, że Sale jest dobrym kandydatem do posiadania odpowiedzialności tworzenia instancji SalesLineItem To przypisanie odpowiedzialności wymaga, żeby zdefiniować metodę makeLineItem w Sale
Creator - uwagi • Podstawa – znalezienie kreatora. Który musi być połączony z tworzonym obiektem • Wtedy przypisanie „odpowiedzialności tworzenia” wspomaga niskie powiązanie • Obiekty złożone są dobrymi kandydatami na tworzenie swoich części • Czasami identyfikujemy kreatora patrząc na klasę, która inicjalizuje dane, które będą przekazywane do konstruktora w czasie tworzenia • w rzeczywistości to jest zastosowanie wzorca Expert • Np., instancja Payment musi zostać zainicjalizowana, przy tworzeniu całej kwoty Sale • Ponieważ Sale zna całą kwotę, więc jest kandydatem na kreatora Payment
Plusy i minusy • Minusy • Często tworzenie jest złożonym projektem, w którym występuje wiele sił • Wówczas lepiej przekazać (delegować) tworzenie do innej klasy - fabryki • Plusy • Niewielkie powiązanie, które implikuje niższe koszty pielęgnacji i zwiększa możliwości powtórnego użycia
Information Expert • Problem • Jaka jest ogólna zasada przypisywania odpowiedzialności do obiektów? • Rozwiązanie • Przypisz odpowiedzialność ekspertowi informacji, tzn. klasie która ma informacje konieczne do zrealizowania odpowiedzialności
Information Expert • Pytanie • Czy szukamy klas, które mają potrzebne informacje, w modelu dziedziny czy w modelu projektu? • Odpowiedź • Jeśli odpowiednie klasy są w modelu projektu, to tam patrzymy • W przeciwnym razie, spoglądamy na model dziedziny i dążymy do wykorzystania (lub rozszerzenia) jego reprezentacji, aby zainspirować utworzenie odpowiedniej klasy w modelu projektu
Przykład • Rozpoczynamy od jasnego określenia odpowiedzialności • „Kto jest odpowiedzialny za wiedzę o całkowitej kwocie sprzedaży?” • Stosujemy wzorzec „Information Expert” • Zakładając, że rozpoczynamy projektowanie i nie ma lub jest niewielki model projektowy, więc • Szukamy ekspertów informacji w modelu dziedziny; dobrym kandydatem jest sprzedaż (Sale) ze świata rzeczywistego • Wtedy dodajemy klasę programową do modelu projektu nazwaną Sale, i przypisujemy jej odpowiedzialność wiedzy o całkowitej kwocie, wyrażonej metodą getTotal
Przykład Częściowy model dziedziny
Dyskusja • Jaka informacja jest potrzebna, aby określić wartość całkowitą? • Trzeba wiedzieć wszystko o instancjach SalesItemLines sprzedaży i sumie ich podsum • Instancja Sale zawiera te informacje, a więc zgodnie z Information Expert, Sale jest odpowiednią klasą obiektów dla tej odpowiedzialności
Odpowiedzialności • Jaka informacja jest potrzebna, aby określić sumę częściową jednostki w wierszu • Zgodnie z zasadą Expert, SalesItemLine musi znać cenę produktu • Aby spełnić tę odpowiedzialność, SalesItemLine musi znać cenę produktu • Zgodnie z wzorcem Expert, ekspertem informacji (w odpowiedzi o cenę produkt) jest ProductDescription • Aby spełnić odpowiedzialność wiedzy i odpowiedzieć n.t. całkowitej kwoty sprzedaży, odpowiedzialności przypisano do 3 klas projektowych
Dyskusja • Information Expert – podstawowa zasada wykorzystywana w projektowaniu obiektowych klasach obiektów • Spełnienie tej zasady często wymaga informacji, która jest rozproszona w wielu różnych klasach obiektów • To wskazuje, że jest wiele „częściowych” ekspertów informacji, którzy będą współpracować z sobą • Różne obiekty będą musiały współpracować poprzez komunikaty, aby dzielić pracę Najwcześniej rozpatrywana zasada w każdym projekcie, jeśli projekt nie implikuje kontrolera lub kreatora
Przeciwwskazania • Nieraz rozwiązania wskazanego przez eksperta nie bierzemy pod uwagę z powodu problemów ze spójnością i powiązaniem • Kto jest odpowiedzialny za przechowywanie Sale w b.d.? • Gdyby była Sale, to wtedy każda klasa ma swoją własną usługę zapisywania do b.d. Klasa Sale musi zawierać logikę związaną z obsługą b.d. (związaną z SQL, JDBC) • To zwiększa powiązanie i duplikuje logikę; projekt łamie zasadę oddzielania zagadnień – podstawowy cel projektowania
Korzyści • Jest pielęgnowana enkapsulacja informacji, bo obiekty korzystają ze swojej własnej informacji aby zrealizować zadanie • To zwykle wspiera niskie powiązanie • Zachowanie jest rozproszone między klasami, które mają potrzebną informację • To wzmacnia spójną „lekką” definicję klas, które są łatwiejsze do zrozumienia i pielęgnacji
Niskie powiązanie • Problem Jak wspomagać niską zależność, niewielki wpływ zmian i wzrost powtórnego wykorzystania? • Rozwiązanie Przypisać odpowiedzialności tak, aby powiązanie było najniższe • Powiązanie (coupling) jest miarą tego jak silnie jeden element jest powiązany, a wiedzę lub zależy od innych elementów • Element z niskim (lub słabym) powiązaniem nie jest zależny od wielu innych elementów
Coupling – za dużo powiązań do innych klas • Klasy ze zbyt dużym powiązaniem mają następujące problemy • Wymuszanie lokalnych zmian z powodu zmian w powiązanych klasach • Trudniejsze do zrozumienia w izolacji • Ciężej wykorzystuje się powtórnie, ponieważ ich wykorzystanie wymaga dodatkowo obecności klas, od której zależy
Przykład • Częściowy diagram klas • Chcemy utworzyć instancję Payment i połączyć ją z Sale • Która klasa powinna za to odpowiadać • Wzorzec Creator sugeruje, że Register jest kandydatem do tworzenia Payment
Niepotrzebne duże powiązanie • Odpowiadający diagram współpracy • To przypisanie odpowiedzialności wiąże klasę Register (aby posiadała wiedzę o klasie) Payment • Register jest również powiązana z Sale, to wskazuje na konieczność innego rozwiązania, zgodnie z zasadą małego powiązania
Rozwiązanie – niskie powiązanie • ? Lepsze rozwiązanie tworzenia Payment • Dwa wzorce sugerują różne projekty. Tworząc projekt balansujemy między przeciwnymi siłami • W` praktyce niskie powiązanie nie jest rozpatrywane w izolacji od pozostałych zasad; niemniej jest b. ważną zasadą
Dyskusja • W językach OO powszechną postacią powiązania TypX do TypY jest • TypX ma atrybut, który odnosi się do instancji TypY lub do samego TypY • TypX ma metodę, która odnosi się do instancji TypY lub samego TypY. To zwykle zawiera parametr lub zmienną lokalną typu TypY lub obiekt zwrócony z komunikatu, będący instancją TypY • TypX jest bezpośrednio lub pośrednio podklasą TypY • TypY jest interfejsem a TypXimplementuje ten interfejs
Przeciwskazania • Problem to nie samo duże powiązanie; problemem jest duże powiązanie elementów, które są niestabilne, takie jak ich interfejsy, implementacja • Powiązanie elementów stabilnych to na ogół nie jest problem • A więc • Koncentruj się na punktach o dużej niestabilności lub przeznaczonych do dalszej ewolucji • Otocz zmienność • Ustal małe powiązanie między częścią zmienną i resztą systemu
Wysoka spójność • Problem Jak panować nad złożonością • Rozwiązanie Przypisz odpowiedzialności tak, aby była duża spójność • Spójność (spójność funkcjonalna) to miara tego jak silnie są powiązane i zogniskowane odpowiedzialności elementu • Element z wielu powiązanymi odpowiedzialnościami i nie wykonujący zbyt dużo niepowiązanych rzeczy i ma za dużo różnej pracy ma wysoki poziom spójności • Klas z niską spójnością wykonuje wiele niepowiązanych rzeczy lub wykonuje za dużo pracy
Niska spójność • Problemy dotykające klas z niską spójnością: trudne do • zrozumienia • powtórnego wykorzystania • pielęgnacji Ponadto b. łamliwe – ciągle dotykane przez zmiany Klasy z niską spójnością mają odpowiedzialności, które powinny być oddelegowane do innych klas
Przykład • Częściowy diagram klas • Chcemy utworzyć instancję Payment i połączyć ją z Sale • Która klasa powinna za to odpowiadać • Ponieważ Register jest kandydatem do tworzenia Payment w rzeczywistym świecie dziedziny • Instancja Register powinno przesłać komunikat addPayment do Sale, przekazując nową Payment jako parametr
Sugerowane rozwiązanie • Umieszczenie w Register części odpowiedzialności za utworzenie płatności • Jednak, jeśli będzie odpowiedzialny za większość, to stanie się niespójny
Rozwiązanie – lepsze? • Ten projekt deleguje tworzenie płatności do Sale, co wspomaga większą spójność Register • Ten projekt wspiera zarówno wysoką spójność jak niskie powiązanie
Dyskusja • Duża spójność, podobnie jak małe powiązanie to zasada, którą bierzemy ciągle pod uwagę przy decyzjach projektowych • Poziomy spojności • B. niska spójność • Niska spójność • Wysoka spójność • Średnia spójność
Bardzo niska spójność • Sama klasa jest odpowiedzialna za wiele rzeczy z różnych obszarów funkcjonalności • i obsługą zdalnych wywołań procedur
Niska spójność • Klasa ma pojedynczą odpowiedzialność za złożone zadanie w jednej przestrzeni funkcjonalnej za interakcję • Załóżmy, że klasa RDBInterface jest w całości odpowiedzialna za interakcję z bazami relacyjnymi • Metody klasy są powiązane ale jest ich za dużo • Klasę należy podzielić na rodzinę „lekkich” klas dzielących pracę dostarczania dostępu do b.d.
Wysoka spójność • Klasa ma umiarkowaną odpowiedzialność w jednej przestrzeni funkcyjnej i współpracuje z innymi klasami, aby wykonać zadanie • Klasa RDBInterface ma tylko częściową odpowiedzialność za współpracę z relacyjną b.d.
Umiarkowana spójność • Klasa ma małe i samodzielne odpowiedzialności w kilku różnych obszarach, które są logicznie powiązane z koncepcją klasy, ale nie z innymi • Załóżmy, że klasa nazywa się Company i jest w całości odpowiedzialna za • wiedzę o pracownikach i • wiedzę o finansach Te obszary nie są mocno związane ale logicznie powiązane z koncepcją firmy. Ponadto, całkowita liczba metod publicznych jest niewielka
Istota • Gdy są alternatywne wybory projektowe to patrzymy dokładniej na spójność i implikacje powiązania ze względu na alternatywy oraz przyszłe implikacje tych alternatyw. Wybieramy według zasad spójności i przyszłych implikacji; istotna wysoka spójność i sprzężenie
Plusy • Jasność i łatwość projektowania • Uproszczone i wzmocniona pielęgnacja