Projektowanie zorientowane obiektowo Wzorce projektowe Wydanie II probw2

background image

Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63

e-mail: helion@helion.pl

PRZYK£ADOWY ROZDZIA£

PRZYK£ADOWY ROZDZIA£

IDZ DO

IDZ DO

ZAMÓW DRUKOWANY KATALOG

ZAMÓW DRUKOWANY KATALOG

KATALOG KSI¥¯EK

KATALOG KSI¥¯EK

TWÓJ KOSZYK

TWÓJ KOSZYK

CENNIK I INFORMACJE

CENNIK I INFORMACJE

ZAMÓW INFORMACJE

O NOWOCIACH

ZAMÓW INFORMACJE

O NOWOCIACH

ZAMÓW CENNIK

ZAMÓW CENNIK

CZYTELNIA

CZYTELNIA

FRAGMENTY KSI¥¯EK ONLINE

FRAGMENTY KSI¥¯EK ONLINE

SPIS TRECI

SPIS TRECI

DODAJ DO KOSZYKA

DODAJ DO KOSZYKA

KATALOG ONLINE

KATALOG ONLINE

Projektowanie zorientowane
obiektowo. Wzorce
projektowe. Wydanie II

Zmieñ podejcie do programowania — zastosuj wzorce projektowe

• Skorzystaj z metod modelowania obiektowego w jêzyku UML
• Poznaj ró¿ne typy wzorców projektowych
• Wykorzystaj wzorce projektowe w swoich programach

Wzorce projektowe to modele rozwi¹zañ wielu zagadnieñ programistycznych,
oparte na zasadach programowania obiektowego. Zastosowanie ich w projektach
informatycznych zapewnia szybsz¹ i bardziej efektywn¹ pracê zarówno podczas
projektowania i tworzenia oprogramowania, jak i na etapie jego wdro¿enia. Sprawne
korzystanie z wzorców projektowych wi¹¿e siê jednak z koniecznoci¹ poznania metod
modelowania obiektowego, zrozumienia zasad obiektowoci i umiejêtnoci podzielenia
projektowanego systemu na komponenty.

Ksi¹¿ka „Programowanie zorientowane obiektowo. Wzorce projektowe. Wydanie drugie”
to przewodnik po wzorcach projektowych, przedstawiaj¹cy je od strony najbardziej
istotnej dla programisty — od strony praktycznej. Przyk³ady w jêzyku Java, diagramy
UML i wyczerpuj¹ce komentarze — wszystko to sprawia, ¿e po przeczytaniu tej ksia¿ki
staniesz siê ekspertem w dziedzinie wzorców projektowych i bêdziesz wykorzystywaæ
je we wszystkich swoich projektach.

• Zasady obiektowoci
• Modelowanie obiektowe w jêzyku UML
• Standardowe rozwi¹zania obiektowe
• Wprowadzenie do wzorców projektowych
• Zasady stosowania wzorców projektowych
• Katalog wzorców projektowych
• Projektowanie i programowanie z zastosowaniem wzorców projektowych

Korzystaj¹c z wzorców projektowych, zwiêkszysz szybkoæ i efektywnoæ swojej pracy
nad aplikacjami.

Autorzy: Alan Shalloway, James R. Trott
T³umaczenie: Piotr Rajca
ISBN: 83-7361-782-5
Tytu³ orygina³u:

Design Patterns Explained A New

Perspective on Object-Oriented Design, 2nd Edition

Format: B5, stron: 368

background image

Spis treści

Wstęp ............................................................................................. 11

Od obiektowości poprzez wzorce projektowe do prawdziwej obiektowości ................. 13
Od sztucznej inteligencji poprzez wzorce aż do prawdziwej obiektowości..................... 17
Informacje o konwencjach zastosowanych w niniejszej książce ..................................... 19
Nowości dodane w drugim wydaniu książki ................................................................... 21

Część I

Wprowadzenie do programowania obiektowego ...............23

Rozdział 1. Obiektowość ................................................................................... 25

Przegląd........................................................................................................................... 25
Zanim pojawiły się obiekty: dekompozycja funkcjonalna............................................... 26
Problem określenia wymagań.......................................................................................... 27
Zmiany wymagań a dekompozycja funkcjonalna............................................................ 29
Postępowanie w sytuacji zmieniających się wymagań .................................................... 31
Obiektowość.................................................................................................................... 34
Programowanie obiektowe w praktyce............................................................................ 40
Szczególne rodzaje metod ............................................................................................... 42
Podsumowanie ................................................................................................................ 43
Pytania kontrolne............................................................................................................. 44

Rozdział 2. Język UML ....................................................................................... 47

Przegląd........................................................................................................................... 47
Czym jest język UML?.................................................................................................... 47
Zastosowanie języka UML.............................................................................................. 48
Diagram klas ................................................................................................................... 49
Diagramy interakcji ......................................................................................................... 54
Podsumowanie ................................................................................................................ 57
Pytania kontrolne............................................................................................................. 57

Część II Ograniczenia tradycyjnie pojmowanego

projektowania obiektowego ............................................59

Rozdział 3. Problem wymagający rozwiązania uniwersalnego............................... 61

Przegląd........................................................................................................................... 61
Pozyskanie informacji z systemu CAD/CAM ................................................................. 61
Terminologia dziedziny zastosowań................................................................................ 62

background image

6

Projektowanie zorientowane obiektowo. Wzorce projektowe

Opis problemu ................................................................................................................. 64
Prawdziwe wyzwania i rozwiązania ................................................................................ 65
Podsumowanie ................................................................................................................ 68
Pytania kontrolne............................................................................................................. 69

Rozdział 4. Standardowe rozwiązanie obiektowe................................................. 71

Przegląd........................................................................................................................... 71
Rozwiązanie wykorzystujące specjalizację ..................................................................... 71
Podsumowanie ................................................................................................................ 78
Pytania kontrolne............................................................................................................. 79

Część III Wzorce projektowe.........................................................81

Rozdział 5. Wprowadzenie do wzorców projektowych.......................................... 83

Przegląd........................................................................................................................... 83
Wzorce projektowe wywodzą się z architektury i antropologii....................................... 84
Wzorce projektowe — od architektury do programowania ............................................. 86
Po co studiować wzorce projektowe?.............................................................................. 89
Inne zalety studiowania wzorców projektowych ............................................................. 93
Podsumowanie ................................................................................................................ 94
Pytania kontrolne............................................................................................................. 95

Rozdział 6. Wzorzec fasady................................................................................ 97

Przegląd........................................................................................................................... 97
Wprowadzenie do fasady................................................................................................ 97
Fasada.............................................................................................................................. 98
Praktyczne uwagi na temat zastosowania fasady........................................................... 100
Zastosowanie fasady w rozwiązaniu problemu CAD/CAM .......................................... 101
Podsumowanie .............................................................................................................. 101
Pytania kontrolne........................................................................................................... 102

Rozdział 7. Wzorzec adaptera .......................................................................... 105

Przegląd......................................................................................................................... 105
Wprowadzenie do wzorca adaptera ............................................................................... 105
Adapter.......................................................................................................................... 106
Praktyczne uwagi na temat zastosowania adaptera........................................................ 111
Zastosowanie adaptera w celu rozwiązania problemu CAD/CAM................................ 113
Podsumowanie .............................................................................................................. 113
Pytania kontrolne........................................................................................................... 114

Rozdział 8. Poszerzamy horyzonty .................................................................... 115

Przegląd......................................................................................................................... 115
Obiekty — w rozumieniu tradycyjnym i nowym .......................................................... 116
Hermetyzacja — w rozumieniu tradycyjnym i nowym ................................................. 118
Określ zmienność i hermetyzuj ją ................................................................................. 121
Analiza wspólności i zmienności a klasy abstrakcyjne.................................................. 124
Cechy programowania inteligentnego ........................................................................... 127
Podsumowanie .............................................................................................................. 131
Pytania kontrolne........................................................................................................... 131

Rozdział 9. Wzorzec strategii ........................................................................... 133

Omówienie .................................................................................................................... 133
Sposób obsługi nowych wymagań ................................................................................ 133
Studium problemu — międzynarodowy system do handlu elektronicznego:

początkowe wymagania .............................................................................................. 136

background image

Spis treści

7

Obsługa nowych wymagań............................................................................................ 136
Wzorzec strategii........................................................................................................... 144
Praktyczne uwagi na temat stosowania wzorca strategii ............................................... 146
Podsumowanie .............................................................................................................. 147
Pytania kontrolne........................................................................................................... 148

Rozdział 10. Wzorzec mostu .............................................................................. 149

Przegląd......................................................................................................................... 149
Wprowadzenie do wzorca mostu................................................................................... 149
Przykład problemu wymagającego zastosowania mostu.............................................. 150
Obserwacja dotycząca zastosowań wzorców projektowych .......................................... 159
Wyprowadzenie wzorca mostu...................................................................................... 160
Wzorzec mostu — retrospekcja..................................................................................... 167
Praktyczne uwagi na temat zastosowań mostu .............................................................. 167
Podsumowanie .............................................................................................................. 171
Pytania kontrolne........................................................................................................... 173

Rozdział 11. Wzorzec fabryki abstrakcyjnej ........................................................ 175

Przegląd......................................................................................................................... 175
Wprowadzenie do wzorca fabryki abstrakcyjnej ........................................................... 175
Fabryka abstrakcyjna — przykład zastosowania ........................................................... 176
Implementacja wzorca fabryki abstrakcyjnej ................................................................ 182
Praktyczne uwagi na temat stosowania fabryki abstrakcyjnej ....................................... 187
Zastosowanie fabryki abstrakcyjnej w rozwiązaniu problemu CAD/CAM................... 190
Podsumowanie .............................................................................................................. 190
Pytania kontrolne........................................................................................................... 190

Część IV Projektowanie z wykorzystaniem wzorców.....................193

Rozdział 12. W jaki sposób projektują eksperci? ................................................ 195

Przegląd......................................................................................................................... 195
Tworzenie przez dodawanie wyróżnień ........................................................................ 195
Podsumowanie .............................................................................................................. 201
Pytania kontrolne........................................................................................................... 202

Rozdział 13. Rozwiązanie problemu CAD/CAM z wykorzystaniem

wzorców projektowych ................................................................... 203

Przegląd......................................................................................................................... 203
Przypomnienie problemu CAD/CAM ........................................................................... 204
Projektowanie z wykorzystaniem wzorców................................................................... 205
Projektowanie z wykorzystaniem wzorców — etap 1 ................................................... 206
Projektowanie z wykorzystaniem wzorców — etap 2a ................................................. 207
Projektowanie z wykorzystaniem wzorców — etap 2b ................................................. 210
Projektowanie z wykorzystaniem wzorców — etap 2c ................................................. 214
Projektowanie z wykorzystaniem wzorców — powtórzone etapy 2a i 2b (fasada) ..... 214
Projektowanie z wykorzystaniem wzorców — etapy 2a i 2b (adapter) ......................... 215
Projektowanie z wykorzystaniem wzorców — etapy 2a i 2b (fabryka abstrakcyjna).... 216
Projektowanie z wykorzystaniem wzorców — etap 3 ................................................... 216
Porównanie z poprzednimi wersjami rozwiązania......................................................... 217
Podsumowanie .............................................................................................................. 218
Pytania kontrolne........................................................................................................... 219

background image

8

Projektowanie zorientowane obiektowo. Wzorce projektowe

Część V Zdążając w kierunku nowego sposobu projektowania ....221

Rozdział 14. Zasady i strategie projektowania z wykorzystaniem wzorców .......... 223

Przegląd......................................................................................................................... 223
Zasada otwarcia i zamknięcia........................................................................................ 224
Zasada projektowania w kontekście .............................................................................. 225
Zasada hermetyzacji zmienności ................................................................................... 229
Klasy abstrakcyjne a interfejsy...................................................................................... 230
Zasada zdrowego sceptycyzmu ..................................................................................... 232
Podsumowanie .............................................................................................................. 232
Pytania kontrolne........................................................................................................... 233

Rozdział 15. Analiza wspólności i zmienności ..................................................... 235

Przegląd......................................................................................................................... 235
Analiza wspólności i zmienności a projektowanie aplikacji.......................................... 235
Rozwiązanie problemu CAD/CAM przy wykorzystaniu analizy wspólności i zmienności . 236
Podsumowanie .............................................................................................................. 242
Pytania kontrolne........................................................................................................... 242

Rozdział 16. Macierz analizy .............................................................................. 243

Przegląd......................................................................................................................... 243
Zmienność w świecie rzeczywistym.............................................................................. 243
Studium zmienności: międzynarodowy system handlu elektronicznego....................... 244
Uwagi praktyczne.......................................................................................................... 251
Podsumowanie .............................................................................................................. 255
Pytania kontrolne........................................................................................................... 255

Rozdział 17. Wzorzec dekoratora ....................................................................... 257

Przegląd......................................................................................................................... 257
Nowe szczegóły............................................................................................................. 257
Wzorzec dekoratora....................................................................................................... 259
Zastosowanie dekoratora w omawianym studium problemu......................................... 260
Inne zastosowania: operacje wejścia i (lub) wyjścia...................................................... 263
Praktyczne uwagi na temat stosowania dekoratora........................................................ 265
Istota wzorca dekoratora................................................................................................ 265
Podsumowanie .............................................................................................................. 267
Pytania kontrolne........................................................................................................... 268

Część VI Inne zalety wzorców .....................................................269

Rozdział 18. Wzorzec obserwatora ..................................................................... 271

Przegląd......................................................................................................................... 271
Kategorie wzorców........................................................................................................ 271
Nowe wymagania aplikacji wspomagającej handel elektroniczny ................................ 273
Wzorzec obserwatora .................................................................................................... 274
Zastosowanie wzorca obserwatora ................................................................................ 274
Praktyczne uwagi na temat zastosowania obserwatora.................................................. 279
Podsumowanie .............................................................................................................. 281
Pytania kontrolne........................................................................................................... 281

Rozdział 19. Wzorzec metody szablonu .............................................................. 283

Przegląd......................................................................................................................... 283
Nowe wymagania .......................................................................................................... 283
Wzorzec metody szablonu............................................................................................. 284
Zastosowanie wzorca metody szablonu......................................................................... 284

background image

Spis treści

9

Zastosowanie wzorca metody szablonu do redukcji nadmiarowości............................. 286
Praktyczne uwagi na temat zastosowania szablonu metody .......................................... 291
Podsumowanie .............................................................................................................. 292
Pytania kontrolne........................................................................................................... 293

Część VII Fabryki ........................................................................295

Rozdział 20. Wnioski płynące ze stosowania wzorców projektowych — fabryki.... 297

Przegląd......................................................................................................................... 297
Fabryki .......................................................................................................................... 297
Uniwersalny kontekst raz jeszcze.................................................................................. 299
Fabryki działają zgodnie z wytycznymi ........................................................................ 301
Ograniczanie wektorów zmian ...................................................................................... 302
Inny sposób rozumienia................................................................................................. 303
Różne zastosowania fabryk ........................................................................................... 303
Praktyczne uwagi dotyczące fabryk .............................................................................. 304
Podsumowanie .............................................................................................................. 304
Pytania kontrolne........................................................................................................... 305

Rozdział 21. Wzorzec singletonu oraz wzorzec blokowania dwufazowego ............. 307

Przegląd......................................................................................................................... 307
Wprowadzenie do wzorca singletonu ............................................................................ 308
Zastosowanie wzorca singletonu ................................................................................... 308
Wariant: wzorzec blokowania dwufazowego ................................................................ 310
Reflekcje ....................................................................................................................... 314
Praktyczne uwagi na temat zastosowania singletonu i blokowania dwufazowego ........... 314
Podsumowanie .............................................................................................................. 315
Pytania kontrolne........................................................................................................... 315

Rozdział 22. Wzorzec puli obiektów ................................................................... 317

Przegląd......................................................................................................................... 317
Problem wymagający zarządzania obiektami ................................................................ 318
Wzorzec puli obiektów.................................................................................................. 325
Obserwacje: tworzenie obiektów nie jest jedynym możliwym zastosowaniem fabryk . 325
Podsumowanie .............................................................................................................. 327
Pytania kontrolne........................................................................................................... 328

Rozdział 23. Wzorzec metody fabryki ................................................................. 329

Przegląd......................................................................................................................... 329
Nowe wymaganie .......................................................................................................... 329
Wzorzec metody fabryki ............................................................................................... 330
Wzorzec metody fabryki a obiektowe języki programowania....................................... 331
Praktyczne uwagi dotyczące zastosowania wzorca metody fabryki .............................. 331
Podsumowanie .............................................................................................................. 332
Pytania kontrolne........................................................................................................... 333

Rozdział 24. Fabryki — podsumowanie .............................................................. 335

Przegląd......................................................................................................................... 335
Etapy procesu tworzenia oprogramowania .................................................................. 335
Podobieństwa fabryk i zasad programowania ekstremalnego........................................ 336
Skalowanie .................................................................................................................... 337

background image

10

Projektowanie zorientowane obiektowo. Wzorce projektowe

Część VIII Podsumowanie.............................................................339

Rozdział 25. Wzorce projektowe i nowa perspektywa projektowania obiektowego ... 341

Przegląd ......................................................................................................................... 341
Podsumowanie zasad obiektowości............................................................................... 342
Hermetyzacja implementacji za pomocą wzorców projektowych ................................. 343
Analiza wspólności i zmienności a wzorce projektowe................................................. 343
Dekompozycja dziedziny problemu poprzez określenie odpowiedzialności ................. 344
Wzorce i projektowanie w kontekście ........................................................................... 345
Powiązania wewnątrz wzorców..................................................................................... 346
Wzorce projektowe i praktyki programowania inteligentnego ...................................... 347
Uwagi praktyczne.......................................................................................................... 347
Podsumowanie .............................................................................................................. 348
Pytania kontrolne........................................................................................................... 348

Rozdział 26. Bibliografia .................................................................................... 351

Programowanie zorientowane obiektowo: strony WWW.............................................. 351
Zalecana lektura ............................................................................................................ 352
Lektura przeznaczona dla programistów korzystających z języka Java ........................ 353
Lektura przeznaczona dla programistów korzystających z języka C++ ........................ 354
Lektura przeznaczona dla programistów korzystających z języka COBOL .................. 355
Lektura dotycząca metodyki programowania ekstremalnego .......................................... 355
Zalecana lektura dotycząca programowania .................................................................. 356
Ulubiona lektura autorów .............................................................................................. 356

Dodatki .......................................................................................359

Skorowidz...................................................................................... 361

background image

Rozdział 8.

Poszerzamy horyzonty

Przegląd

W poprzednich rozdziałach omówiłem trzy podstawowe koncepcje,
na których opiera się projektowanie obiektowe: obiekty, hermetyzację
oraz klasy abstrakcyjne. Właściwe zrozumienie tych pojęć przez pro-

jektanta jest niezwykle istotne. Tradycyjne sposoby ich rozumienia mają wiele ograni-
czeń, dlatego też w niniejszym rozdziale powrócę raz jeszcze do omawianej wcześniej
problematyki. Moją intencją będzie przedstawienie nowych sposobów rozumienia pro-
jektowania obiektowego, które wynikają z perspektywy wzorców projektowych. Niestety,
tradycyjne sposoby mają bardzo duże ograniczenia.

W rozdziale ponownie zastanowię się nad zagadnieniami przedstawionymi we wcześniej-
szej części książki, jak również zaprezentuję kilka nowych tematów. Chciałbym przed-
stawić czytelnikowi nowy sposób spojrzenia na projektowanie obiektowe, perspektywę,
która wyłania się dzięki zrozumieniu wzorców projektowych. Następnie opiszę kluczowe
cechy kodu o wysokiej jakości. Znaczenie tych cech podkreślają propagatorzy i zwo-
lennicy programowania inteligentnego (ang. agile coding), czyli tworzenia kodu zgodnie
z zasadami programowania ekstremalnego (ang. extreme programming, programowa-
nia bazującego na testowaniu). Co ciekawe, te same cechy występują także we wzorcach
projektowych, a jeśli będziemy postępować zgodnie z zasadami i metodologią wzorców
projektowych, to pojawią się one w sposób naturalny. Mam nadzieję, że prezentując te
cechy zarówno pod kątem programowania inteligentnego, jak i wzorców projektowych,
wypełnię lukę występującą pomiędzy tymi dwoma podejściami do projektowania.

Niniejszy rozdział:

przedstawia i porównuje tradycyjny sposób rozumienia obiektów (jako zestawu
danych i metod) z nowym sposobem (jako bytów o określonej odpowiedzialności),

przedstawia i porównuje tradycyjny sposób rozumienia hermetyzacji
(jako ukrywania danych) z nowym sposobem (jako możliwości ukrycia
w ogóle); szczególnie istotne będzie tu zrozumienie tego, że hermetyzacja
służyć może także jako sposób ukrycia różnic w zachowaniu obiektów,

W rozdziale

background image

116

Część III ♦ Wzorce projektowe

przedstawia i porównuje różne sposoby obsługi różnic w zachowaniu,

przedstawia i porównuje tradycyjny sposób wykorzystania dziedziczenia
(służący specjalizacji oraz ponownemu wykorzystaniu istniejącego kodu)
z nowym sposobem (polegającym na wykorzystaniu dziedziczenia w celu
klasyfikacji obiektów); pokazuje również, że sposoby te umożliwiają
zawarcie zmienności w zachowaniu obiektów,

opisuje analizę wspólności i zmienności,

przedstawia to, jak perspektywy koncepcji, specyfikacji oraz implementacji
mają się do klas abstrakcyjnych i ich klas pochodnych,

porównuje wzorce projektowe oraz programowanie inteligentne; choć
początkowo może się wydawać, iż oba te podejścia nie są ze sobą zgodne,
to okazuje się jednak, że zwracają one uwagę na podobne jakości
programowania — nadmiarowość, czytelność oraz łatwość testowania.

Przedstawiona przeze mnie nowa perspektywa obiektowości nie jest
zupełnie oryginalna. Stosowali ją z pewnością projektanci poszukujący

wzorców projektowych. Jest także zgodna z wynikami prac Christophera Alexandra,
Jima Copliena (do jego pracy będę się odwoływać w dalszej części rozdziału) oraz
Bandy Czworga

1

.

Mimo to perspektywa obiektowości nie doczekała się dotąd takiego przedstawienia,
jakie zamieszczam w niniejszym rozdziale książki. Powstało ono na podstawie anali-
zy wzorców projektowych i sposobu ich opisu przez innych autorów.

Pisząc tutaj o „nowej” perspektywie obiektowości mam na myśli to, że przedstawiony
dalej sposób rozumienia obiektowości będzie prawdopodobnie nowością dla wielu
projektantów. Podobnie jak był dla mnie, kiedy po raz pierwszy zapoznawałem się
z tematyką wzorców projektowych.

Obiekty
— w rozumieniu tradycyjnym i nowym

Tradycyjnie przez obiekty rozumiemy dane oraz operujące na nich
metody. Jeden z moich wykładowców nazwał je też kiedyś „inteli-
gentnymi danymi”, gdyż chciał odróżnić je od bazy danych. Obiekty
są zatem postrzegane jako inteligentny sposób obsługi danych: „Za-
cznijmy od danych opisujących stan dziedziny problemu, dodajmy do

nich metody operujące na tych danych (czyli niezbędne działanie) i voilà — mamy
gotowe obiekty!”. Jednak jest to zbyt uproszczony sposób patrzenia na obiekty, można
by rzec — sposób jednowymiarowy. Taki sposób widzenia obiektów mieści się jed-
nak w perspektywie implementacji.

1

Gdyż pisząc niniejszą książkę, udało mi się poznać kilka osób zajmujących się tworzeniem programów
w języku Smalltalk. Niemal wszystkie one miały takie samo podejście do projektowania obiektowego
jak to, które prezentuję w niniejszej książce.

Podziękowanie

Rozumienie
tradycyjne:
dane oraz metody

background image

Rozdział 8. ♦ Poszerzamy horyzonty

117

Bardziej przydatna okazuje się tu definicja obiektu powstająca w per-
spektywie koncepcji — jako bytu o określonej odpowiedzialności.
Odpowiedzialność ta określa z kolei sposób zachowania obiektu. Dla-
tego też czasami możemy w skrócie powiedzieć, że obiekt reprezentuje
byt o określonym zachowaniu.

Zaletą nowej definicji jest to, że pomaga ona skoncentrować się na zadaniach obiektu,
a nie na sposobie ich implementacji. Dzięki temu w procesie tworzenia oprogramowania
możemy wyróżnić dwa etapy:

1.

wstępnego projektu — na etapie tym możemy uniknąć zajmowania się
szczegółami implementacji.

2.

implementacji projektu.

Skoncentrowanie uwagi na tym, co obiekt ma robić, pozwala także nie przejmować
się zbyt wcześnie szczegółami jego implementacji. Pozwala na ukrycie szczegółów
tej implementacji. To z kolei pomaga w pisaniu oprogramowania, które w przyszłości
będzie można łatwiej modyfikować… oczywiście jeśli zajdzie taka konieczność.

Jest to możliwe dzięki temu, iż zwracając uwagę na działanie obiektu, koncentrujemy
się jedynie na jego interfejsie publicznym, czyli na „oknie komunikacyjnym”, za pomocą
którego można poprosić obiekt o wykonanie pewnej czynności. Dysponując dobrym
interfejsem, można „poprosić” obiekt o wykonanie dowolnej czynności mieszczącej się
w granicach jego odpowiedzialności i jednocześnie mieć pewność, że obiekt ją wyko-
nana. Nie trzeba przy tym dysponować żadnymi informacjami odnośnie zdarzeń za-
chodzących wewnątrz obiektu. Nie trzeba wiedzieć, w jaki sposób obiekt wykorzysta
przekazane do niego informacje ani jak zdobędzie inne dane, które są mu potrzebne.
Przekazujemy odpowiedzialność obiektowi i więcej nic nas nie interesuje.

Zastanówmy się na przykład nad obiektem klasy

, którego odpowiedzialność bę-

dzie stanowić:

przechowanie informacji o jego położeniu na ekranie,

narysowanie własnej reprezentacji na ekranie,

usunięcie reprezentacji z ekranu.

Istnienie tych obowiązków określa wprost zestaw potrzebnych metod:



Nie określam przy tym żadnych szczegółów wewnętrznej implementacji obiektu, a je-
dynie wymieniam jego obowiązki. Obiekt może przechowywać odpowiednie atrybuty
lub posiadać dodatkowe metody, które wyznaczą odpowiednie wartości (na przykład
na podstawie informacji zawartych w innych obiektach). Obiekt klasy

może

więc zawierać atrybuty określające jego położenie lub pobierać te informacje na przykład
z obiektu reprezentującego bazę danych. W ten sposób uzyskujemy wysoką elastycz-
ność ułatwiającą osiągnięcie zadań projektowania (bądź zmianę kodu, jeśli cele ulegną
zmianie).

Nowe rozumienie:
byty posiadające
odpowiedzialność

background image

118

Część III ♦ Wzorce projektowe

Czytelnik z pewnością zauważy też, że koncentracja na motywacji (a nie na implemen-
tacji) jest koncepcją powtarzającą się we wzorcach projektowych. Wynika to z faktu, iż
użycie interfejsu do ukrycia implementacji w zasadniczy sposób oddziela ją od obiektów,
które z niej korzystają.

Proponuję, by czytelnik przyjął zaprezentowany tu sposób widzenia obiektów. Rezul-
tatem takiej decyzji będzie lepsza jakość tworzonych rozwiązań.

Hermetyzacja
— w rozumieniu tradycyjnym i nowym

Podczas wykładów poświęconych wzorcom projektowym często zadaję
moim studentom pytanie: „Kto z Państwa spotkał się z definicją her-
metyzacji mówiącą o ukrywaniu danych?”. Prawie wszyscy podnoszą
w odpowiedzi rękę.

Następnie opowiadam im historię mojego parasola. Proszę pamiętać, że mieszkam
w Seattle, które posiada — nieco przesadzoną — opinię wyjątkowo deszczowej okolicy.
Prawdą jest jednak, że od jesieni do wiosny jest tutaj dość mokro i wtedy parasole
i kurtki z kapturem należą do artykułów pierwszej potrzeby.

Opowiem teraz o moim wielkim parasolu. Jest tak duży, że oprócz mnie mogą się pod
nim zmieścić jeszcze trzy, a nawet cztery osoby! Kiedy już jesteśmy w jego wnętrzu,
czyli poza zasięgiem deszczu, możemy się za jego pomocą przemieszczać. Dodatko-
wo zabawia nas w tym czasie jego system stereofoniczny, a klimatyzacja zapewnia
odpowiednią temperaturę. Prawda, że to niezwykły parasol?

Jest przy tym bardzo wygodny w użyciu. Nie muszę go ze sobą nosić, bo zawsze czeka
na mnie na zewnątrz. Wyposażony jest ponadto w koła, żeby łatwiej można się było
przemieszczać. Ale nie muszę go pchać ani ciągnąć, ponieważ posiada własny napęd.
Korzystam z niego nawet wtedy, gdy nie pada. Jeśli świeci słońce i chcę nacieszyć się
jego promieniami, otwieram górną część parasola (powód, dla którego używam parasola
nawet wtedy, gdy nie pada, nie jest dla mnie jasny).

Mieszkańcy Seattle używają setki tysięcy podobnych parasoli w przeróżnych kolorach.

Większość ludzi nazywa je jednak samochodami.

Sam jednak częściej myślę o moim samochodzie jak o parasolu, ponieważ zwykle chroni
mnie przed deszczem. Czekając na kogoś na dworze często siadam pod moim „paraso-
lem”, aby nie zmoknąć.

Jednak samochód nie jest parasolem. Możemy go wykorzystywać jako
schronienie przed deszczem, ale jest to dość ograniczony sposób wyko-
rzystania możliwości, jakie daje samochód. Podobnie jest z hermetyzacją
— nie służy ona jedynie do ukrywania danych. Taki sposób myśle-
nia o hermetyzacji ogranicza moje możliwości jako projektanta.

Definicje mogą
narzucać
ograniczenia

Mój obiektowy
parasol

background image

Rozdział 8. ♦ Poszerzamy horyzonty

119

O hermetyzacji powinno myśleć się jak o ukrywaniu w ogóle. Innymi słowy
— hermetyzacja może służyć do ukrycia danych. Ale może także ukrywać:

sposób implementacji,

klasy pochodne,

szczegóły projektowe,

reguły tworzenia obiektów.

We wcześniejszych rozważaniach dotyczących ukrywania implementacji w zasadzie
„hermetyzowałem” ją. Aby posunąć się jeszcze dalej, przeanalizujmy diagram przed-
stawiony na rysunku 8.1, który został po raz pierwszy zamieszczony w rozdziale 7.,
zatytułowanym „Wzorzec adaptera”. Klasy

,

,

oraz

dziedziczą

po klasie

. Dodatkowo klasa

„opakowuje” lub zawiera klasę

.

Rysunek 8.1 przedstawia kilka rodzajów hermetyzacji.

Rysunek 8.1. Dostosowanie klasy XXOkrag za pomocą klasy Okrag

Diagram ten przedstawia wiele sposobów zastosowania hermetyzacji:

Hermetyzację danych — dane wewnątrz obiektów klas

,

oraz

są ukryte przed obiektami innych klas.

Hermetyzację metod — na przykład metoda

w klasie

.

Hermetyzację innych obiektów — jedynie obiekt klasy

posiada dostęp

do zawartego w nim obiektu klasy

.

Hermetyzację typów — użytkownicy klasy

nie wiedzą o istnieniu

klas

,

,

.

Hermetyzację typów uzyskuje się zatem w przypadku, gdy istnieje klasa abstrakcyjna
mająca kilka klas pochodnych (lub interfejs wraz z jego implementacjami) wykorzy-
stywanych w oparciu o zasady polimorfizmu. Użytkownik korzystający z tej klasy

W jaki sposób myśleć
o hermetyzacji

Kilka poziomów
hermetyzacji

background image

120

Część III ♦ Wzorce projektowe

abstrakcyjnej nie zna typu klasy pochodnej obiektu, którym się w danej chwili posłu-
guje. To właśnie ten rodzaj hermetyzacji ma zazwyczaj na myśli Banda Czworga.

Rozumienie hermetyzacji w szerszy sposób przyczynia się do uzyskania
lepszej struktury programu. Hermetyzacja ułatwia określenie interfej-
sów, na których opiera się projekt. Ukrywając za pomocą klasy

istnienie klas reprezentujących poszczególne rodzaje figur, można później dodawać ich
kolejne rodzaje bez obawy o to, że będzie to wymagać zmian w programie użytkownika.
Podobnie — ukrywając istnienie obiektu klasy

wewnątrz klasy

, można

później zmienić w dowolny sposób implementację rysowania okręgu.

W początkowym okresie (tuż po zaprezentowaniu paradygmatu obiek-
towego) uważano, że jedną z jego najważniejszych zalet jest możliwość
ponownego wykorzystania istniejącego kodu poprzez tworzenie klas po-
chodnych za pomocą dziedziczenia z istniejących klas bazowych. W ten
sposób powstał termin specjalizacja, który służy do określenia procesu
tworzenia klas pochodnych (dlatego też klasy pochodne nazywa się cza-
sem klasami wyspecjalizowanymi, a klasy bazowe — klasami ogólnymi).

Nie zamierzam tutaj podważać słuszności takiego twierdzenia. Proponuję jednak wyko-
rzystanie dziedziczenia w sposób, który uważam za bardziej doskonały. Załóżmy, na
przykład, że chciałbym posługiwać się pięciokątem. Definiuję zatem klasę

,

która będzie zawierać stan nowej figury oraz metody pozwalające na jej wyświetlenie,
usunięcie itd. Nieco później okazuje się, że potrzebny mi jest pięciokąt ze specjalnymi
krawędziami. Mogę zatem użyć klasy

i na jej podstawie stworzyć bardziej

wyspecjalizowaną klasę pochodną dysponująca niezbędnym algorytmem wyświetlania
krawędzi (rysunek 8.2).

Rysunek 8.2.
Klasa
PieciokatZKrawedzia
dziedziczy po klasie
Pieciokat

Był to przykład zastosowania dziedziczenia w celu specjalizacji. Wykorzystałem klasę

, aby stworzyć nową klasę —

. Rozwiązanie to spisuje

się dobrze, choć przysparza trzech problemów opisanych w tabeli 8.1.

Innym sposobem zastosowania dziedziczenia jest klasyfikacja klas pod kątem identycz-
nego zachowania. Zagadnienie to rozwinę w dalszej części rozdziału.

Zalety tej nowej
definicji

Dziedziczenie
jako pojęcie
a dziedziczenie
jako sposób
wielokrotnego
zastosowania

background image

Rozdział 8. ♦ Poszerzamy horyzonty

121

Tabela 8.1. Problemy, jakich przysparza zastosowanie dziedziczenia w celu specjalizacji.

Problem

Opis

Może przyczyniać się
do występowania niskiego
stopnia spójności.

Zastanówmy się, co by się stało, gdyby istniało wiele różnych typów
krawędzi? Okazuje się, że w takim przypadku klasa

2KGEKQMCV

(oraz jej klasy pochodne) nie opisuje już wyłącznie samej figury,
lecz także jej krawędzie, a to sprawia, iż klasa ta musi zajmować się
dodatkowymi problemami. Co więcej, w klasie mogą się także pojawić
inne zmienne aspekty (na przykład rodzaj wypełnienia pięciokąta).

Ogranicza możliwości
wielokrotnego stosowania
kodu.

Jeśli stworzę w klasie

2KGEKQMCV

(i jej klasach pochodnych) kod

obsługujący różne rodzaje krawędzi, to w jaki sposób będę mógł
z niego skorzystać w innych klasach? Zadanie to byłoby bardzo
trudne, gdyż za każdym razem zmienia się kontekst, a co więcej,
gdyż kod obsługujący znajduje się w klasie

2KGEKQMCV

i raczej

nie będzie dostępny poza nią.

Utrudnia obsługę zmian.

Metoda specjalizacji w celu wielokrotnego zastosowania doskonale
nadaje się do przedstawiania w klasie, gdyż można ją zademonstrować
i przejść do dalszych zagadnień, zanim ktokolwiek zdąży zapytać,
co się stanie, gdy pojawi się możliwość modyfikacji jakiegoś innego
czynnika. Na przykład co zrobić, jeśli pojawią się dwa różne rodzaje
cieniowania? Aby je obsłużyć, trzeba by stworzyć nowe, bardziej
wyspecjalizowane wersje klasy

2KGEKQMCV

(co oznaczałoby

częściowe powielenie kodu).

Określ zmienność i hermetyzuj ją

Autorzy książki Design Patterns: Elements of Reusable Object-Oriented
Software sugerują, co następuje:

Spróbujmy określić, co jest zmienną w naszym projekcie. Takie
podejście stanowi przeciwieństwo koncentrowania się na przyczynach
zmian w projekcie. Zamiast zastanawiać się, co może spowodować
wprowadzenie zmian do projektu, skoncentrujmy się na tym,
co możemy zmienić bez konieczności modyfikacji projektu.

Skoncentrujmy się zatem na hermetyzacji tego, co ulega zmianie, czyli
sposobie stosowanym przez wiele wzorców projektowych

2

.

Osobiście preferuję nieco inne ujęcie tej samej kwestii: Znajdź, co się zmienia i hermetyzuj to.

Takie stwierdzenie, może wydać się czytelnikowi mało zrozumiałe, jeśli nadal myśleć
będzie o hermetyzacji jak o ukrywaniu danych. Stanie się dużo bardziej czytelne, jeśli
czytelnik pomyśli o hermetyzacji jako o ukrywaniu klas pochodnych za pomocą klasy
abstrakcyjnej lub interfejsu — czyli o „hermetyzacji typu”

3

. Udostępnienie referencji

2

Gamma E., Helm R., Johnson R., Vlissides J., Design Patterns: Elements of Reusable Object-Oriented
Software, Boston: Addison-Wesley, 1995, s. 29.

3

Ogólnie rzecz biorąc, to właśnie o tym rodzaju hermetyzacji myśli Banda Czworga, używając terminu

„hermetyzacja”.

Wzorce projektowe
wykorzystujące
dziedziczenie w celu
sklasyfikowania
odmiennego
zachowania

background image

122

Część III ♦ Wzorce projektowe

do takiej abstrakcyjnej klasy lub interfejsu (agregacja) ukrywa klasy pochodne repre-
zentujące różnice w sposobie działania. Innymi słowy, pewna klasa posiada referencję
do klasy abstrakcyjnej lub do interfejsu posiadających więcej niż jedną klasę pochodną.
Jednak te klasy pochodne są ukryte (hermetyzowane) przez klasę, która ich używa.

Wiele wzorców projektowych stosuje hermetyzację w celu utworzenia warstw pomiędzy
obiektami, co umożliwia wprowadzanie zmian po jednej ze stron warstwy bez wpływu
na obiekty znajdujące się po przeciwnej stronie warstwy. Jest to możliwe dzięki wprowa-
dzeniu przez wzorzec niskiego stopnia powiązania pomiędzy obiektami po obu stronach
warstwy.

Sposób ten stanowi podstawę działania wzorca mostu, który przedstawię
w rozdziale 10. zatytułowanym „Wzorzec mostu”. Wcześniej chciał-
bym jednak omówić pewien błąd, który często popełniają projektanci.

Przypuśćmy, że pracuję nad projektem, który tworzy modele przezna-
czone do opisu różnych cech zwierząt. Wymagania będą w tym przy-

padku określone następująco:

zwierzęta mogą posiadać różną liczbę nóg,

obiekty reprezentujące zwierzęta muszą umożliwić przechowanie tej
informacji i jej uzyskanie,

różne zwierzęta mogą poruszać się w różny sposób,

obiekty reprezentujące zwierzęta muszą umożliwić uzyskanie informacji o tym,
ile czasu zajmie im pokonanie określonego dystansu na danym terenie.

Typowym sposobem, w jaki programista poradzi sobie z problemem różnej ilości nóg,
będzie utworzenie zmiennej składowej wewnątrz obiektu, która przechowywać będzie
odpowiednią wartość, a także metod umożliwiających nadanie wartości zmiennej i po-
branie jej wartości. Jednak — aby uporać się z problemem zmienności w zachowaniu
obiektów — potrzebne będzie inne rozwiązanie.

Przypuśćmy, że określone są dwa sposoby poruszania się: chodzenie i latanie. Dla każde-
go z nich potrzebny będzie osobny fragment kodu, gdyż sama zmienna niczego tutaj
nie rozwiąże (choć można jej użyć w celu określenia, jaki sposób poruszania się jest
dostępny). W tym wypadku programista wybierze raczej jedno z dwu rozwiązań:

utworzenie zmiennej składowej, która przechowywać będzie informację
o sposobie poruszania się zwierzęcia,

utworzenie osobnej klasy pochodnej klasy bazowej

dla reprezentacji

zwierząt, które chodzą, i osobnej klasy dla tych, które latają.

Okazuje się jednak, że w sytuacjach, gdy problem staje się złożony, to oba te rozwiązania
zawodzą. Doskonale spełniają swe zadania, gdy istnieje tylko jeden zmienny czynnik
(sposób poruszania się), jednak co się stanie, gdy liczba tych czynników wzrośnie? Na
przykład co w sytuacji, jeśli pojawią się orły (latające drapieżniki), lwy (drapieżniki po-
ruszające się na lądzie), wróble (ptaki roślinożerne) oraz krowy (zwierzęta roślinożerne
poruszające się po lądzie)? Wykorzystanie instrukcji wyboru do określania typu zwie-
rzęcia spowodowałoby skojarzenie sposobów poruszania się oraz odżywiania — czyli

Zawieranie
zmienności danych
a zmienności
zachowania

background image

Rozdział 8. ♦ Poszerzamy horyzonty

123

czynników, które nie wydają się być ze sobą połączone. Z kolei wykorzystanie dziedzi-
czenia do obsługi każdej z sytuacji wyjątkowych prowadzi do ogromnego wzrostu
ilości klas. Poza tym co się stanie, jeśli zwierzęta raz przejawiają jeden sposób za-
chowania, a w innych przypadkach zachowują się inaczej (na przykład większość
ptaków potrafi zarówno latać, jak i poruszać się po lądzie)?

Istnieje jeszcze inny problem. Tworzenie klas obsługujących coraz to więcej czynni-
ków zmiennych (na przykład wykorzystując w tym celu instrukcje wyboru) może do-
prowadzić do zmniejszenia spójności kodu. Oznacza to, że im więcej przypadków
szczególnych obsługuje klasa, tym trudniej jest zrozumieć jej kod.

Innym rozwiązaniem może okazać się umieszczenie wewnątrz obiektu
klasy

obiektu określającego sposób poruszania się, co ilustruje

diagram pokazany na rysunku 8.3.

Rysunek 8.3.
Obiekt klasy Zwierze
zawiera obiekt klasy
SposobRuchu

Rozwiązanie to może na pierwszy rzut oka wyglądać nadmiarowo.
Jednak w praktyce oznacza ono jedynie tyle, że obiekt klasy

zawiera odpowiedni obiekt określający sposób jego poruszania się.
Jest więc analogiczne do rozwiązania, w którym zmienną wykorzystu-

jemy do przechowania informacji o liczbie nóg zwierzęcia (z tą różnicą, że w tym
przypadku zmienna składowa reprezentuje różnicę w zachowaniu, a nie w liczbie).
Może jedynie wydawać się, że oba te rozwiązania się różnią, choćby na podstawie
różnic w diagramach przedstawionych na rysunkach 8.3 i 8.4.

Rysunek 8.4.
Obiekt zawierający
atrybuty

Wielu projektantów uważa, że pomiędzy zawieraniem przez obiekt
innego obiektu, a zawieraniem przez obiekt atrybutów istnieje różnica.
Jednak mimo że atrybuty są zmiennymi typów prostych (na przykład

,

) i nie przypominają obiektów, to są nimi z punktu

widzenia projektowania obiektowego. Pamiętajmy, że w programowaniu obiektowym
wszystko stanowi obiekt (nawet podstawowe typy danych, których zachowanie okre-
śla arytmetyka). Specyficzna składnia posługiwania się tymi obiektami (na przykład

odpowiadająca

) ukrywa jedynie fakt, iż są to obiekty o określonym za-

chowaniu.

Obsługa zmienności
działania poprzez
zastosowanie obiektów

Porównanie
obu rozwiązań

To nie jest żadna
przesada

background image

124

Część III ♦ Wzorce projektowe

W ten sposób rozwiązanie zastosowane w przypadku zmienności atrybutów i rozwiązanie
w przypadku zmienności zachowania okazują się do siebie podobne. Najłatwiej będzie
to pokazać na przykładzie. Załóżmy, że opracować muszę system obsługi punktu sprze-
daży. Kluczowy element tego systemu stanowić będzie faktura. Na fakturze tej znajdzie
się całkowita wartość zakupu. Początkowo dla jej reprezentacji mógłbym użyć typu
prostego

. Jeśli jednak system będzie musiał wystawiać faktury w różnych walu-

tach, to szybko pojawi się problem odpowiedniej konwersji. Dlatego też zdecyduję się
raczej utworzyć klasę

, która przechowywać będzie informacje o kwocie i jej

walucie. Tak więc suma na fakturze będzie teraz manifestacją obiektu klasy

.

Choć może wydawać się na początku, że jedynym zadaniem obiektu klasy

jest

przechowanie odpowiedniej informacji, to jednak szybko okaże się, że zgodnie z zasadą
odpowiedzialności obiekty tej klasy muszą posiadać także metody służące konwersji
pomiędzy różnymi walutami. Jak się okazuje, zadanie konwersji nie sprowadza się tyl-
ko do przechowania w obiekcie kolejnej informacji (o aktualnym przeliczniku walut).

Komplikację wprowadzić może na przykład konieczność dokonywania konwersji po-
między walutami na podstawie ich kursów pochodzących z przeszłości. W takim przy-
padku atrybut można by zastąpić klasą

!

. Dodawanie zachowań do klasy

lub

!

dodaje je także do klasy

"#

, która zależy od umieszczonych w niej

obiektów

(a zatem także i obiektów

!

). Niemniej jednak takie rozwiązanie

ani nie powoduje zwiększenia stopnia złożoności klasy

"#

, ani nie wymaga

wprowadzania w niej jakichkolwiek zmian.

Strategię polegającą na uzyskiwaniu określonego zachowania obiektu w zależności od
rodzaju zawieranego obiektu zademonstruję omawiając kilka następnych wzorców
projektowych.

Analiza wspólności i zmienności
a klasy abstrakcyjne

Książka Copliena omawiająca problem analizy wspólności i zmienności,
pokazuje, jak odnajdywać w dziedzinie problemu czynniki zmienne
oraz elementy wspólne: „Określ, gdzie („analiza wspólności”) oraz
jak („analiza zmienności”) elementy się od siebie różnią”.

Coplien stwierdza, iż: „Analiza wspólności polega na poszukiwaniu
wspólnych elementów, które pozwalają zrozumieć, na czym polega
podobieństwo członków tej samej rodziny”

4

. Pod pojęciem „człon-

ków rodziny” Coplien rozumie elementy, które są ze sobą powiązane ze względu na
sytuację, w jakiej się pojawiają, lub funkcje, jakie wykonują. Proces odnajdywania
cech wspólnych definiuje rodzinę, do której należą elementy (a zatem, także, jakie są
różnice pomiędzy nimi). Na przykład, gdyby ktoś pokazał nam flamaster do pisania
na tablicy, pióro oraz ołówek, to moglibyśmy stwierdzić, iż ich wspólną cechę jest

4

Coplien J., Multi-Paradigm Design for C++, Boston: Addison-Wesley, 1998, str. 63.

Analiza wspólności
i zmienności

Analiza wspólności

background image

Rozdział 8. ♦ Poszerzamy horyzonty

125

przeznaczenie — wszystko są to przedmioty służące do pisania. Proces, jaki wykona-
liśmy, aby określić wszystkie te przedmioty w identyczny sposób, nazywamy analizą
wspólności. Dysponując cechami wspólnymi (przedmioty do pisania), łatwiej można
określić, czym poszczególne przedmioty różnią się od siebie (na czym się pisze,
kształt przedmiotu i tak dalej).

Analiza zmienności ma na celu określenie, czym poszczególni człon-
kowie rodziny różnią się od siebie. Te odmienności mają sens wyłącz-
nie w odniesieniu do elementów, dla których określono cechy wspólne:

Analiza wspólności poszukuje struktury, która jest niezmienna, natomiast analiza
zmienności poszukuje struktury, która może się zmieniać. Analiza zmienności
ma sens wyłącznie w kontekście zdefiniowanym przez odpowiednią analizę
wspólności… W odniesieniu do architektury analiza wspólności zapewnia
jej długowieczność, natomiast analiza zmienności — przydatność

5

.

Innymi słowy, jeśli czynnikiem zmiennym są konkretne klasy należące do dziedziny
problemu, to czynniki wspólne definiują te pojęcia dziedziny, które łączą te klasy ze
sobą. Pojęcia wspólne będą reprezentowane przez klasy abstrakcyjne. Różnice wskaza-
ne przez analizę zmienności będą implementowane przez konkretne klasy (to znaczy
przez klasy pochodne klasy abstrakcyjnej).

Często niedoświadczeni projektanci programów obiektowych są in-
struowani, aby analizować dziedzinę problemu oraz „odnajdywać
istniejące rzeczowniki i tworzyć klasy, które będą je reprezentować,
a następnie odnajdywać czasowniki (czyli akcje) i implementować je
poprzez dodawanie metod do wcześniej utworzonych obiektów”. Taki

proces, polegający na skoncentrowaniu uwagi na rzeczownikach i czasownikach, za-
zwyczaj prowadzi do powstawania większych hierarchii klas, niż można by sobie tego
życzyć. Sugeruję, by podstawowym narzędziem podczas tworzenia obiektów była ana-
liza wspólności i zmienności, gdyż metoda ta jest lepsza od wyróżniania rzeczowni-
ków i czasowników (jest ona częściowo zgodna z metodą postulowaną przez Copliena).

Rysunek 8.5 obrazuje związki zachodzące pomiędzy:

analizą wspólności i zmienności,

perspektywami koncepcji, specyfikacji oraz implementacji,

klasą abstrakcyjną, jej interfejsem i klasami pochodnymi.

Jak pokazano na rysunku 8.5, analiza wspólności związana jest z war-
stwą koncepcyjną dziedziny zastosowań, a analiza zmienności odnosi
się do warstwy implementacji (czyli specyficznych przypadków pro-
blemu).

5

Ibidem, strony 60 i 64.

Analiza zmienności

Nowy paradygmat
znajdowania
obiektów

Projektowanie
obiektowe obejmuje
wszystkie trzy
perspektywy

Teraz specyfikacja
pozwala na lepsze
zrozumienie klas
abstrakcyjnych

background image

126

Część III ♦ Wzorce projektowe

Rysunek 8.5. Związki pomiędzy analizą wspólności i zmienności, perspektywami i klasą abstrakcyjną

Warstwa specyfikacji znajduje się pośrodku. Zarówno analiza wspólności, jak i zmienno-
ści jest z nią związana. Warstwa specyfikacji określa sposób komunikacji z obiektami,
które są koncepcyjnie podobne. Natomiast poszczególne obiekty reprezentują zmien-
ność problemu. W warstwie implementacji specyfikacja przyjmuje postać klasy abs-
trakcyjnej bądź interfejsu.

W nowej perspektywie projektowania obiektowego możemy wyróżnić związki przed-
stawione w tabeli 8.2.

Tabela 8.2. Zalety zastosowania klas abstrakcyjnych do specjalizacji

Związek

Omówienie

Klasa abstrakcyjna a główne pojęcie
łączące klasy

Klasa abstrakcyjna stanowi kluczowe pojęcie łączące
klasy pochodne i definiuje część wspólną problemu.

Część wspólna a określenie używanych
klas abstrakcyjnych

Część wspólna problemu definiuje klasę abstrakcyjną.

Część zmienna a klasy pochodne

Zmienność, którą możemy zidentyfikować wewnątrz
części wspólnej, określa klasy pochodne klasy
abstrakcyjnej.

Specyfikacja a interfejs klasy abstrakcyjnej

Interfejs klasy abstrakcyjnej — a tym samym jej klas
pochodnych — określony jest w warstwie specyfikacji.

Proces projektowania klas upraszcza się w ten sposób do procedury złożonej z dwu etapów
przedstawionych w tabeli 8.3.

Tabela 8.3. Dwuetapowa procedura projektowania

Definicja

Pytanie

Klasa abstrakcyjna (część wspólna)

Jak powinien wyglądać interfejs, by mógł umożliwiać
realizację wszystkich odpowiedzialności tej klasy?

Klasy pochodne

W jaki sposób powinna zostać zaimplementowana
część zmienna problemu w ramach danej specyfikacji?

background image

Rozdział 8. ♦ Poszerzamy horyzonty

127

Związek pomiędzy perspektywą specyfikacji i perspektywą koncepcji jest więc nastę-
pujący: specyfikacja określa interfejs potrzebny do obsługi wszystkich przypadków danego
problemu (czyli część wspólną określoną przez perspektywę koncepcji).

Związek pomiędzy perspektywą specyfikacji i perspektywą implementacji możemy
natomiast określić: biorąc pod uwagę określoną specyfikację i ustalając, w jaki spo-
sób należy zaimplementować poszczególne przypadki (czyli część zmienną).

Cechy programowania inteligentnego

Podejście do projektowania wykorzystujące wzorce projektowe często
określa się jako „projektowanie od góry do dołu”. Zaleca ono rozpo-
czynanie projektowania od najbardziej ogólnych pojęć i sukcesywne
uwzględnianie coraz większej ilości szczegółów.

Istnieje także podejście alternatywne, postulowane przez zasady pro-
gramowania ekstremalnego, które wydaje się stać w całkowitej sprzecz-

ności z metodą przedstawioną powyżej. Programowanie ekstremalne koncentruje się na
realizacji niewielkich etapów oraz weryfikację ich poprawności. Całościowy obraz roz-
wiązania wyłania się na podstawie tych etapów.

Osobiście uważam, że zasady programowania ekstremalnego oraz metody projektowania
z wykorzystaniem wzorców projektowych nie są względem siebie sprzeczne, lecz ra-
czej się uzupełniają. Obu tych metod można użyć w celu osiągnięcia tego samego celu
— utworzenia efektywnego, solidnego i elastycznego kodu. Ale jak to jest możliwe? Są-
dzę, iż wynika to z faktu, że zasady, na których bazują obie te metody, są pokrewne.

Ponieważ stosunkowo wcześnie zacząłem stosować praktyki pro-
gramowania inteligentnego, dlatego też musiałem rozstrzygnąć pewien
problem:

z powodzeniem stosowałem projektowanie metodą
„od góry do dołu”,

stosowanie zasad programowania inteligentnego pozwoliło mi na ograniczenie
projektowania wcześniejszą metodą (a czasami nawet na całkowite jej
uniknięcie),

uzyskiwane rezultaty były jeszcze lepsze.

Mój dylemat polegał na tym, iż byłem świadom, że wzorce projektowe przyczyniły
się do mych sukcesów i nie chciałem rezygnować z ich stosowania. Jednak metody
programowania inteligentnego, którymi pragnąłem się posługiwać, nie zalecały takie-
go postępowania. Pomimo to czułem, że obie metody projektowania muszą mieć jakieś
cechy wspólne — programowanie inteligentne wymaga kodu zapewniającego dużą ła-
twość modyfikacji, a wzorce projektowe — elastycznego kodu. Być może różnica pole-
gała raczej na samej stosowanej metodzie niż na efektach, jakie pozwalała uzyskać.

Projektowanie
metodą „od góry
do dołu”
a projektowanie
„w trakcie pracy”

Wnioski
ze stosowania
programowania
inteligentnego

background image

128

Część III ♦ Wzorce projektowe

Ostatecznie udało mi się rozwiązać mój problem, gdy zauważyłem, że obie metody
wymuszają tworzenie kodu o tych samych cechach, a różnią się jedynie sposobami
postępowania. Różne cechy kodu są w rzeczywistości ściśle ze sobą powiązane. Na
przykład, jeśli metoda jest hermetyzowana, to w efekcie jest także odseparowana od
pozostałych fragmentów programu. Praktyki zalecane przez programowanie inteligentne
koncentrowały się na innych cechach niż te, o których wspominałem wcześniej. Jednak
cechy te były ściśle powiązane z cechami kodu, który tworzyłem, posługując się
wcześniejszymi metodami projektowania. Tymi dodatkowymi cechami są: (1) brak po-
wtarzalności kodu, (2) czytelność, (3) łatwość testowania (przy czym podana kolej-
ność cech nie jest odzwierciedleniem ich ważności).

Niezwykle ważną strategią tworzenia kodu, którą należy stosować
jest implementowanie konkretnej reguły tylko w jednym miejscu. Od
bardzo dawna mantrą programistów obiektowych było stwierdzenie:
„Jedna reguła, jedno miejsce”. Reprezentuje ono najlepsze praktyki pro-

jektowe. Całkiem niedawno Kent Beck nazwał ten sposób projektowania „regułą jedy-
nego wystąpienia”

6

.

Zdefiniował ją jako element narzucanych ograniczeń:

1.

System (rozumiany jako połączenie kodu i testów) musi przekazywać
wszystko, co chcemy przekazać.

2.

System nie może zawierać powtarzającego się kodu (oba te punkty tworzą
regułę jedynego wystąpienia).

Innymi słowy, jeśli istnieje jakaś reguła określająca sposób wykonywania pewnej
operacji, to należy ją zaimplementować tylko jeden raz. Zazwyczaj wymaga to stwo-
rzenia kilku niewielkich metod. Dodatkowy koszt takiego postępowania jest prze-
ważnie minimalny, jednak pozwala uniknąć powtarzania kodu i bardzo często chroni
przed przyszłymi problemami. Powielanie jest niekorzystne nie tylko ze względu na
większą ilość kodu, który należy wpisać, lecz także dlatego, iż jeśli w przyszłości
trzeba będzie coś zmienić, to można zapomnieć wprowadzić modyfikacje we wszyst-
kich niezbędnych miejscach.

Nie jestem bynajmniej purystą, niemniej jednak uważam, że jeśli jest jakaś zasada,
której zawsze należy przestrzegać, to jest to właśnie ta zasada. Istnieje bardzo silny
związek pomiędzy powielaniem kodu oraz powiązaniami. Jeśli w programie wystę-
puje powtarzający się kod, to istnieje bardzo duże prawdopodobieństwo, że w razie
konieczności zmiany fragmentu tego programu trzeba będzie wprowadzić zmiany
także w jego innych miejscach. Wynika to z faktu, że powtarzające się fragmenty ko-
du programu są ze sobą powiązane.

Co ciekawe, w celu wyeliminowania powtarzania się kodu wystarczy postępować
zgodnie z praktykami projektowania na podstawie interfejsu, a następnie wydzielić
fragmenty zmienne i zapewnić wysoki stopień spójności. Jest to możliwe dzięki temu,
iż kod będzie umieszczony nie w kilku, lecz w jednym miejscu. Aby uniknąć silnych
powiązań, należy hermetyzować kod i precyzyjnie zdefiniować interfejs pozwalający
na jego stosowanie.

6

Ang. „once and only once rule”. Beck K., Extreme Programming Explained: Embrace Change,
Boston: Addison-Wesley, 2000, strony 108 – 109.

Brak powtarzalności
kodu

background image

Rozdział 8. ♦ Poszerzamy horyzonty

129

Czytelność jest kolejną cechą kodu, której zachowanie postulują za-
sady programowania inteligentnego. Czytelność jest związana z wy-
sokim stopniem spójności. Niemniej jednak Ron Jeffries (propagator

programowania ekstremalnego), przedstawiając zasadę „programowania intencyjnego”

7

,

posuwa się jeszcze o krok dalej. Najprościej rzecz ujmując, zasada ta stwierdza, iż jeśli
podczas pisania programu należy stworzyć pewną funkcję, trzeba udać, że funkcja ta
już istnieje, nadać jej nazwę „określającą jej przeznaczenie”

8

, umieścić w kodzie jej

wywołanie i zabrać się do dalszej pracy (zaimplementować kod funkcji później). In-
nymi słowy, tworzenie programu sprowadza się do napisania serii wywołań funkcji,
których nazwy w czytelny sposób określają ich przeznaczenie.

Takie postępowanie pozwala na tworzenie czytelnego kodu, gdyż na poziomie większego
modułu osoba analizująca kod łatwo może zrozumieć jego przeznaczenie. Do takiego
postępowania zachęca także Martin Fowler, stwierdzając: „Za każdym razem, gdy poczuje-
my chęć skomentowania jakiegoś fragmentu kodu, zmieńmy go na funkcję”

9

. W efekcie

tworzone metody są krótsze i bardziej zwięzłe (a przez to także i bardziej spójne).

Programowanie intencyjne jest bardo podobne do metody stosowanej podczas korzy-
stania z wzorców projektowych — projektowania według interfejsu. Podając „nazwę
określającą przeznaczenie” metody, tworzymy jej interfejs i nie przejmujemy się jej
implementacją. Także i w tym przypadku wydaje się, że programowanie inteligentne
oraz wzorce projektowe stosują podobne sposoby zapewniania wysokiej jakości kodu.

Łatwość testowania jest niezwykle ważną cechą dobrego kodu. Jej za-
pewnienie jest jedyny z kluczowych założeń zasad programowania inte-
ligentnego. Nim zacznę szczegółowo opisywać to zagadnienie, muszę

jednak wyjaśnić różnice pomiędzy „łatwością testowania” a zasadą pisania testów przez
stworzeniem kodu zalecaną w programowaniu ekstremalnym.

Jednym z unikalnych założeń programowania ekstremalnego jest tworzenie testów przed
stworzeniem właściwego kodu. Postępowanie takie ma kilka celów:

W efekcie uzyskujemy zbiór zautomatyzowanych testów.

Jesteśmy zmuszeni do projektowania według interfejsu, a nie według
implementacji, dzięki czemu powstające metody są lepiej hermetyzowane
i cechują się mniejszym stopniem powiązań.

Skoncentrowanie się na testach wymusza skoncentrowanie się na fragmentach
kodu, które można przetestować, a to zwiększa stopień spójności i zmniejsza
wzajemne powiązania różnych fragmentów kodu.

Osobiście określam kod łatwy do testowania mianem testowalnego. Jest to kod, który
można przetestować niezależnie od pozostałych fragmentów tworzonego programu
oraz bez konieczności zwracania uwagi na jego powiązania z innymi fragmentami kodu.

7

Jeffries R., Anderson A., Hendrickson C., Extreme Programming Installed, Boston: Addison-Wesley,
2001, strony 73 – 74.

8

Czyli nazwę, która w ścisły i precyzyjny sposób wyjaśni przeznaczenie funkcji oraz zakres jej obowiązków.

9

Fowler M., Refactoring: Improving the Design of Existing Code, Boston: Addison-Wesley Longman,
1999, str. 77.

Łatwość testowania

Czytelność

background image

130

Część III ♦ Wzorce projektowe

Zasada tworzenia testów przed przystąpieniem do pisania kodu leżąca u podstaw pro-
gramowania ekstremalnego nieodmiennie prowadzi do powstawania kodu, który można
łatwo testować

10

.

Łatwość testowania w ścisły sposób łączy się z innymi praktykami:

Spójność kodu ułatwia jego testowanie, gdyż dany fragment kodu dotyczy
tylko jednej operacji.

Kod o niskim stopniu powiązań jest łatwiejszy do testowania w porównaniu
z kodem, w którym występują ścisłe powiązania, gdyż jest on niemal
pozbawiony interakcji z innymi fragmentami kodu.

Fakt powtarzania się kodu nie ma wpływu na łatwość testowania, lecz wymusza
wykonywanie większej ilości testów. Oznacza to, że wraz ze wzrostem ilości
powtarzającego się kodu zmniejsza się łatwość testowania całego systemu.

Kod o dużej czytelności jest jednocześnie łatwiejszy do testowania, gdyż
nazwy metod oraz ich parametry w precyzyjny sposób określają ich
przeznaczenie.

Kod hermetyzowany jest łatwiejszy do testowania, gdyż jest on w bardzo
niewielkim stopniu powiązany z innymi fragmentami kodu.

Oto przykład potwierdzający powyższe stwierdzenia. Miałem kiedyś klienta, z którym,
przed przeprowadzeniem kursu pt. „Efektywna analiza i projektowanie obiektowe”,
omawiałem zagadnienia testowania. Powiedział mi, bym nie poświęcał zbyt dużo uwagi
testom jednostkowym, gdyż ma z nimi złe doświadczenia. Kiedy spytałem, co się stało,
odpowiedział, że podczas prób zastosowania testów jednostkowych przy okazji two-
rzenia wcześniejszego projektu okazało się, iż jest to bardzo trudne zadanie. Aby napisać
testy, trzeba było napisać specjalne narzędzia umożliwiające tworzenie obiektów, które
chciał testować w prosty i szybki sposób, a obiekty te były powiązane z innymi obiektami.

W odpowiedzi zapytałem, czy przed przystąpieniem do pisania kodu zastanowił się nad
sposobem, w jaki ten kod będzie testowany. Mój rozmówca odparł, iż nie zastanawiał
się nad tym. Zapytałem wtedy, czy gdyby uwzględnił sposób testowania kodu, napisałby
go w inny sposób. Mój rozmówca zamilkł i uświadomił sobie, że gdyby zastanowił
się nad sposobem testowania kodu, mógłby poprawić jakość swojego projektu.

Wielu programistów posuwa się jeszcze o krok dalej i, tworząc kod, w całości bazuje
na testach. Metodologia ta jest określana jako „programowanie w oparciu o testy”
(ang. test-driven developnent, w skrócie TDD), a jej przedstawienie wykracza poza
ramy niniejszej książki. Osobiście stosunkowo często stosowałem tę metodę i uwa-
żam, że jest ona doskonała. Podobnie jak inne inteligentne metody także i programowa-
nie w oparciu o testy początkowo wydaje się być sprzeczne z wzorcami projektowymi,
jednak tak nie jest. Metoda ta opiera się na tych samych zasadach co wzorce, a jedynie
samo podejście do tworzenia kodu jest w niej inne.

10

Ze względu na fakt, iż niniejsza książka jest poświęcona wzorcom projektowym, nie będę w niej
opisywał doskonałych zasad stosowania testów jednostkowych i projektowania w oparciu o testy.

background image

Rozdział 8. ♦ Poszerzamy horyzonty

131

Podsumowanie

Tradycyjny sposób rozumienia obiektów, hermetyzacji oraz dziedzi-
czenia jest stosunkowo ograniczony. Możliwości zastosowania her-
metyzacji stają się dużo szersze i wykraczają poza ukrywanie danych

dzięki rozszerzeniu jej definicji na ukrywanie w ogólności. Hermetyzacja służyć może
do tworzenia warstw obiektów, co umożliwia wprowadzanie zmian po jednej ze stron
warstwy pozostających bez wpływu na obiekty po drugiej stronie warstwy.

Dziedziczenie natomiast lepiej jest stosować jako sposób organizacji klas konkretnych
powiązanych w warstwie koncepcji niż tylko jako środek służący specjalizacji.

Koncepcja zastosowania obiektów dla reprezentacji zmienności zachowania innych
obiektów nie różni się od powszechnej praktyki stosowania zmiennych składowych
dla reprezentacji zmienności danych. W obu przypadkach wykorzystywana jest herme-
tyzacja zawartego obiektu bądź zmiennej, co umożliwia bezproblemową rozbudowę.

Analiza wspólności i zmienności pozwala na bardziej efektywne określanie obiektów
występujących w dziedzinie problemu niż metoda bazująca na poszukiwaniu rzeczow-
ników i czasowników.

Cechy kodu tworzonego w oparciu o metody zalecane przez programowanie inteligentne,
a w szczególności przez programowanie ekstremalne, dokładnie odpowiadają cechom,
które staramy się uzyskać, tworząc kod o wysokim stopniu spójności i hermetyzacji
oraz niewielkich powiązaniach.

Pytania kontrolne

Obserwacje

1.

Jaki jest poprawny sposób myślenia o hermetyzacji?

2.

Jakie są trzy perspektywy analizy problemu? (Być może, odpowiadając na to
pytanie, czytelnik będzie musiał zajrzeć do rozdziału 1., „Obiektowość”.)

Interpretacje

1.

Obiekty można wyobrażać sobie na dwa sposoby: jako „dane z metodami”
oraz „byty posiadające określoną odpowiedzialność”.

Co sprawia, że ten drugi sposób wyobrażania sobie obiektów jest lepszy
od pierwszego?

Jakie dodatkowe aspekty obiektów można dzięki niemu zrozumieć?

W rozdziale

background image

132

Część III ♦ Wzorce projektowe

2.

Czy jeden obiekt może zawierać inne obiekty? Czy taki obiekt umieszczony
wewnątrz innego obiektu w jakikolwiek sposób różni się od składowej zmiennej?

3.

Jakie jest znaczenie zalecenia: „znajdź to, co się zmienia, i hermetyzuj to”?
Proszę podać przykład.

4.

Proszę podać związki pomiędzy analizą wspólności i zmienności oraz trzema
perspektywami, z jakich można analizować obiekty.

5.

Klasa abstrakcyjna odpowiada „głównemu pojęciu łączącemu”.
Co to oznacza?

6.

„Analiza zmienności wyjaśnia, czym różnią się od siebie poszczególni
członkowie rodziny. Zmienność ma sens wyłącznie w granicach określonej
cechy wspólnej”.

Co to oznacza?

Jakie typy obiektów są używane do reprezentacji wspólnych pojęć?

Jakie typy obiektów są używane do reprezentacji zmienności?

Opinie i zastosowania

1.

Dlaczego koncentrowanie się na motywacjach jest lepsze od koncentrowania
się na implementacji? Proszę podać przykłady sytuacji, w których takie
podejście okazało się pomocne.

2.

Z góry przyjęte sposoby pojmowania ograniczają nasze możliwości rozumienia
pojęć. Stwierdzenie to okazało się prawdziwe w odniesieniu do hermetyzacji.
Czy czytelnik jest w stanie podać przykład, gdy z góry przyjęte wyobrażenia
miały wpływ na zrozumienie wymagań projektu? Jakie były skutki i jak udało
się rozwiązać problemy?

3.

Termin dziedziczenie określa zarówno sytuację, w której tworzona jest nowa
klasa, wyspecjalizowana klasa dziedzicząca po pewnej klasie nieabstrakcyjnej,
jak również, gdy na podstawie abstrakcyjnej klasy bazowej zostaje utworzona
klasa stanowiąca zupełnie nową implementację. Czy nie byłoby lepiej, gdyby
istniały dwa odrębne terminy opisujące te pojęcia?

4.

W jaki sposób można zastosować analizę stałości i zmienności, aby ułatwić
sobie opracowywanie sposobów modyfikacji systemu?

5.

Ważne jest, by zmienności poszukiwać jak najwcześniej oraz jak najczęściej.
Czy czytelnik uważa, iż stwierdzenie to jest prawdziwe? Proszę uzasadnić
odpowiedź. Dlaczego odnajdywanie zmienności może pomóc unikać problemów?

6.

Analiza zmienności i stałości jest jednym z podstawowych narzędzi
służących do określania obiektów, znacznie lepszym od metody
polegającej na wyszukiwaniu rzeczowników. Czy czytelnik zgadza się
z tym stwierdzeniem? Proszę uzasadnić odpowiedź.

7.

W niniejszym rozdziale starałem się przedstawić nowe spojrzenie na obiekty.
Czy mi się to udało? Proszę uzasadnić odpowiedź.


Wyszukiwarka

Podobne podstrony:
Projektowanie zorientowane obiektowo Wzorce projektowe Wydanie II probw2
Projektowanie zorientowane obiektowo Wzorce projektowe Wydanie II probw2
Projektowanie zorientowane obiektowo Wzorce projektowe Wydanie II
Projektowanie zorientowane obiektowo Wzorce projektowe Wydanie II
Projektowanie zorientowane obiektowo Wzorce projektowe Wydanie II
Projektowanie zorientowane obiektowo Wzorce projektowe Wydanie II 2
Projektowanie zorientowane obiektowo Wzorce projektowe Wydanie II 2
Projektowanie zorientowane obiektowo Wzorce projektowe Wydanie II
Projektowanie zorientowane obiektowo Wzorce projektowe probwz
Projektowanie zorientowane obiektowo Wzorce projektowe
Projektowanie zorientowane obiektowo Wzorce projektowe 2
J2ME Praktyczne projekty Wydanie II j2mep2
HTML XHTML i CSS Praktyczne projekty Wydanie II htxpp2
J2ME Praktyczne projekty Wydanie II 2
HTML XHTML i CSS Praktyczne projekty Wydanie II
Alfabet zarzadzania projektami Wydanie II alzap2 2
Zarzadzanie projektami Wydanie II zazpr2
HTML XHTML i CSS Praktyczne projekty Wydanie II 2

więcej podobnych podstron