SlideShare a Scribd company logo
1 of 20
Download to read offline
UML. In¿ynieria
                           oprogramowania.
                           Wydanie II
                           Autor: Perdita Stevens
                           T³umaczenie: Ireneusz Jakóbik
                           ISBN: 978-83-246-0805-8
                           Tytu³ orygina³u: Using UML: Software Engineering
                           with Objects and Components (2nd Edition)
                           Format: B5, stron: 304



                                                  Praktyczny podrêcznik do nauki jêzyka UML
                               • Jak zaprojektowaæ dobry system?
                               • Jak poprawnie tworzyæ i odczytywaæ modele?
                               • Jak w praktyce stosowaæ UML i poprawiæ jakoœæ projektowanych produktów?
                           W œwiecie informatyki dobry projekt to czêsto wiêcej ni¿ po³owa sukcesu, a wraz ze
                           wzrostem popularnoœci obiektowych jêzyków programowania UML — ujednolicony jêzyk
                           modelowania przeznaczony do reprezentacji elementów w analizie obiektowej i programowaniu
                           obiektowym — sta³ siê podstawowym narzêdziem do tworzenia modeli. Dlatego te¿
                           trudno wyobraziæ sobie dobrego informatyka, który nie potrafi przygotowaæ poprawnego
                           projektu w tym jêzyku lub odczytaæ modelu utworzonego przez kogoœ innego.
                           „UML. In¿ynieria oprogramowania. Wydanie II” to przystêpny podrêcznik dla studentów
                           i informatyków pragn¹cych nie tylko poznaæ ujednolicony jêzyk modelowania, ale przede
                           wszystkim nauczyæ siê korzystaæ z niego w kontekœcie in¿ynierii oprogramowania.
                           Czytaj¹c go, dowiesz siê, jak powinien wygl¹daæ dobry system, poznasz sk³adniê
                           i funkcje jêzyka UML, a przedstawione studia przypadku pozwol¹ Ci zobaczyæ, jak
                           u¿ywaæ go do projektowania praktycznych rozwi¹zañ.
                               • Projektowanie systemów bazuj¹cych na komponentach
                               • Wprowadzenie do obiektowoœci
                               • Efektywny proces projektowania
                               • Opracowywanie modeli klas
                               • Przygotowywanie modeli przypadków u¿ycia
                               • Tworzenie diagramów interakcji, stanów i aktywnoœci
                               • Przygotowywanie diagramów struktury i wdro¿eñ
Wydawnictwo Helion             • Stosowanie komponentów i wzorców
ul. Koœciuszki 1c              • Dbanie o jakoœæ procesu i produktu
44-100 Gliwice                 • Praktyczne przyk³ady projektowania systemów
tel. 032 230 98 63           Jeœli chcesz tworzyæ oprogramowanie najwy¿szej jakoœci, zacznij od dobrego projektu
e-mail: helion@helion.pl
X            Wstęp ...................................................................................................... 13

Część I      Tło koncepcyjne .................................................................. 19
Rozdział I   Inżynieria oprogramowania z użyciem komponentów ......................... 21
             1.1. Co to jest dobry system? ......................................................................................... 21
             1.2. Czy istnieją dobre systemy? ..................................................................................... 22
                     1.2.1. Problemy… ............................................................................................... 22
                     1.2.2. …a nawet katastrofalne niepowodzenia .................................................... 24
                     1.2.3. Obietnice, obietnice .................................................................................. 25
             1.3. Jakie są dobre systemy? ............................................................................................ 26
                     1.3.1. Hermetyzacja: słabe powiązania ................................................................ 27
                     1.3.2. Abstrakcja: wysoki stopień spójności ......................................................... 30
                     1.3.3. Architektura i komponenty ........................................................................ 31
                     1.3.4. Projektowanie oparte na komponentach: modularność ............................ 33
             1.4. Jak są zbudowane dobre systemy? ........................................................................... 33
Rozdział 2   Koncepcje obiektów ............................................................................... 35
             2.1. Czym jest obiekt? ..................................................................................................... 35
                     2.1.1. Przykład ..................................................................................................... 37
                     2.1.2. Komunikaty ................................................................................................ 37
                     2.1.3. Interfejsy .................................................................................................... 38
                     2.1.4. Klasy .......................................................................................................... 39
             2.2. Jaki to ma związek z celami poprzedniego rozdziału? .............................................. 42
                     2.2.1. Co wspólnego z komponentami mają obiekty? ......................................... 43
             2.3. Dziedziczenie ........................................................................................................... 44
             2.4. Polimorfizm i wiązanie dynamiczne ......................................................................... 46
Rozdział 3   Wstępne studium przypadku ................................................................. 49
             3.1. Problem ................................................................................................................... 49
                     3.1.1. Sprecyzowanie wymagań ........................................................................... 49
                     3.1.2. Model przypadków użycia ......................................................................... 51
             3.2. Zakres oraz iteracje ................................................................................................. 53
             3.3. Identyfikowanie klas ................................................................................................. 55
             3.4. Relacje między klasami ............................................................................................. 57
             3.5. System w akcji ......................................................................................................... 60
                     3.5.1. Zmiany w systemie: diagramy stanów ....................................................... 64
                     3.5.2. Dalsze prace .............................................................................................. 64
4 UML. Inżynieria oprogramowania

Rozdział 4    Proces projektowania ............................................................................. 67
              4.1. Definicje terminów .................................................................................................. 67
                     4.1.1. Modele i języki modelowania .................................................................... 68
                     4.1.2. Proces i jakość ........................................................................................... 70
              4.2. Proces projektowania .............................................................................................. 70
                     4.2.1. Zunifikowana metodologia? ....................................................................... 72
                     4.2.2. Procesy stosowane w UML ....................................................................... 73
              4.3. System, projekt, model, diagram ............................................................................. 75
                     4.3.1. Wykorzystanie modeli ............................................................................... 76

Część II      UML ..................................................................................... 79
Rozdział 5    Podstawy modeli klas ............................................................................. 81
              5.1. Identyfikowanie obiektów i klas ............................................................................... 81
                      5.1.1. Co sprawia, że model klasy jest dobry? ..................................................... 81
                      5.1.2. Jak zbudować dobry model klasy ............................................................... 82
                      5.1.3. Jakim rodzajem rzeczy są klasy? ................................................................. 85
                      5.1.4. Obiekty ze świata rzeczywistego a ich reprezentacje w systemie ............ 85
              5.2. Powiązania ............................................................................................................... 86
                      5.2.1. Wielokrotności .......................................................................................... 88
              5.3. Atrybuty i operacje .................................................................................................. 89
                      5.3.1. Operacje .................................................................................................... 89
                      5.3.2. Atrybuty ..................................................................................................... 89
              5.4. Generalizacja ............................................................................................................ 90
                      5.4.1. Korzystanie z języka polskiego w celu sprawdzenia, czy zachodzi
                       generalizacja ...................................................................................................... 93
                      5.4.2. Implementacja generalizacji: dziedziczenie ................................................ 93
              5.5. Model klasy podczas opracowywania ...................................................................... 94
              5.6. Karty CRC ............................................................................................................... 95
                      5.6.1. Tworzenie kart CRC ................................................................................. 95
                      5.6.2. Używanie kart CRC podczas opracowywania projektu ............................ 96
                      5.6.3. Przykład karty CRC ................................................................................... 97
                      5.6.4. Refaktoring ................................................................................................ 98
Rozdział 6    Więcej na temat modeli klas ................................................................ 101
              6.1. Więcej na temat powiązań ..................................................................................... 101
                      6.1.1. Agregacja i kompozycja ........................................................................... 101
                      6.1.2. Role ......................................................................................................... 103
                      6.1.3. Możliwości nawigacji ............................................................................... 104
                      6.1.4. Powiązania kwalifikowane ....................................................................... 105
                      6.1.5. Powiązania pochodne .............................................................................. 107
                      6.1.6. Ograniczenia ............................................................................................ 108
                      6.1.7. Klasy powiązań ........................................................................................ 110
              6.2. Więcej na temat klas .............................................................................................. 112
                      6.2.1. Interfejsy .................................................................................................. 113
                      6.2.2. Klasy abstrakcyjne .................................................................................... 115
              6.3. Klasy sparametryzowane ....................................................................................... 117
              6.4. Zależność ............................................................................................................... 118
              6.5. Komponenty i pakiety ............................................................................................ 119
              6.6. Widoczność i ochrona ........................................................................................... 119
Spis treści 5


Rozdział 7    Najważniejsze informacje na temat modeli przypadków użycia ........ 121
              7.1. Szczegóły dotyczące aktorów ................................................................................ 123
              7.2. Przypadki użycia w szczegółach ............................................................................. 125
              7.3. Granice systemu .................................................................................................... 126
              7.4. Używanie przypadków użycia ............................................................................... 127
                     7.4.1. Przypadki użycia podczas gromadzenia wymagań ................................... 127
                     7.4.2. Przypadki użycia podczas projektowania ................................................ 128
              7.5. Możliwe problemy z przypadkami użycia .............................................................. 130
Rozdział 8    Więcej informacji na temat modeli przypadków użycia ..................... 133
              8.1. Relacje między przypadkami użycia ....................................................................... 133
                     8.1.1. Przypadki użycia do wielokrotnego użycia: <<include>> .................... 134
                     8.1.2. Komponenty i przypadki użycia ............................................................... 136
                     8.1.3. Rozdzielanie wariantów zachowania: <<extend>> ............................. 138
              8.2. Generalizacje ......................................................................................................... 139
              8.3. Aktorzy i klasy ........................................................................................................ 140
                     8.3.1. Notacja: aktorzy jako klasy ...................................................................... 141
Rozdział 9    Najważniejsze informacje na temat diagramów interakcji .................. 143
              9.1. Współprace ............................................................................................................ 144
              9.2. Diagramy komunikacji ........................................................................................... 145
              9.3. Diagramy sekwencji ............................................................................................... 147
              9.4. Więcej zaawansowanych funkcji ............................................................................ 150
                     9.4.1. Komunikaty z obiektu do samego siebie ................................................. 150
                     9.4.2. Zwracane wartości .................................................................................. 151
                     9.4.3. Tworzenie i usuwanie obiektów ............................................................. 152
              9.5. Diagramy interakcji służące innym celom .............................................................. 154
                     9.5.1. Pokazywanie, jak klasa udostępnia operację ............................................ 154
                     9.5.2. Opisywanie, jak działa wzorzec projektowy ........................................... 154
                     9.5.3. Opisywanie, jak można użyć komponentu .............................................. 154
Rozdział 10 Więcej informacji na temat diagramów interakcji ............................... 155
              10.1. Więcej niż tylko proste sekwencje komunikatów ................................................ 155
                     10.1.1. Zachowania warunkowe ....................................................................... 155
                     10.1.2. Iteracja ................................................................................................... 157
              10.2. Współbieżność ..................................................................................................... 158
                     10.2.1. Modelowanie ścieżek kontroli ............................................................... 159
Rozdział 11 Najważniejsze informacje na temat diagramów stanów i aktywności ......165
              11.1. Diagramy stanów ................................................................................................. 166
                     11.1.1. Niespodziewane komunikaty ................................................................ 167
                     11.1.2. Poziom abstrakcji ................................................................................... 168
                     11.1.3. Stany, zmiany stanu i zdarzenia .............................................................. 168
                     11.1.4. Akcje ...................................................................................................... 169
                     11.1.5. Dozór .................................................................................................... 171
              11.2. Diagramy aktywności ........................................................................................... 174
Rozdział 12 Więcej informacji na temat diagramów stanów ................................... 179
              12.1. Inne rodzaje zdarzeń ........................................................................................... 179
              12.2. Inne rodzaje akcji ................................................................................................. 180
              12.3. Zaglądanie do wnętrza stanów ............................................................................ 181
              12.4. Współbieżność w obrębie stanów ....................................................................... 183
6 UML. Inżynieria oprogramowania

Rozdział 13 Diagramy architektury i wdrożeń ....................................................... 185
                 13.1. Diagramy struktury komponentów ..................................................................... 185
                 13.2. Model wdrożeń ................................................................................................... 187
                        13.2.1. Warstwa fizyczna ................................................................................... 187
                        13.2.2. Wdrażanie oprogramowania na sprzęcie ............................................... 187
Rozdział 14 Pakiety i modele ................................................................................... 191
                 14.1. Pakiety ................................................................................................................. 191
                        14.1.1. Kontrolowanie przestrzeni nazw ........................................................... 192
                 14.2. Modele ................................................................................................................. 194

Część III Studia przypadków ........................................................... 197
Rozdział 15 Administrowanie I4 .............................................................................. 199
                 15.1. Studium przypadku .............................................................................................. 199
                        15.1.1. Model klas .............................................................................................. 203
                        15.1.2. Dynamika ............................................................................................... 204
                        15.1.3. Diagramy stanów ................................................................................... 204
                        15.1.4. Diagramy aktywności ............................................................................. 204
                 15.2. Dyskusja ............................................................................................................... 205
Rozdział 16 Gry planszowe ...................................................................................... 207
                 16.1. Zakres i wstępna analiza ...................................................................................... 208
                         16.1.1. „Kółko i krzyżyk” ................................................................................... 208
                         16.1.2. Szachy .................................................................................................... 209
                 16.2. Interakcja ............................................................................................................. 213
                 16.3. Z powrotem do szkieletu aplikacji ....................................................................... 215
                 16.4. Stany .................................................................................................................... 217
Rozdział 17 Symulacja metodą kolejnych zdarzeń ................................................. 219
                 17.1. Wymagania ........................................................................................................... 219
                        17.1.1. Bardziej szczegółowy opis ..................................................................... 220
                 17.2. Zarys modelu klasy .............................................................................................. 222
                 17.3. Przypadki użycia .................................................................................................. 224
                        17.3.1. Podsumowanie przypadku użycia tworzenie modelu ............................ 224
                        17.3.2. Podsumowanie przypadku użycia obserwowanie zachowania .............. 225
                        17.3.3. Podsumowanie przypadku użycia zbieranie danych statystycznych ...... 225
                        17.3.4. Podsumowanie przypadku użycia uruchomienie modelu ...................... 225
                 17.4. Standardowy mechanizm symulacji opartej na procesie ...................................... 226
                 17.5. Powiązania i możliwości nawigacji ....................................................................... 227
                 17.6. Klasy w szczegółach ............................................................................................. 230
                        17.6.1. Klasa Zarzadca ....................................................................................... 230
                        17.6.2. Klasa JednostkaAktywna ........................................................................ 231
                        17.6.3. Klasa JednostkaPasywna ........................................................................ 233
                        17.6.4. Klasa Zasob ............................................................................................ 233
                 17.7. Klasa Raport ......................................................................................................... 236
                 17.8. Klasa DaneStatystyczne ....................................................................................... 236
                        17.8.1. Klasa Srednia .......................................................................................... 236
                 17.9. Budowanie kompletnego modelu symulacji ......................................................... 237
                 17.10. Ucztujący filozofowie ......................................................................................... 238
Spis treści 7


Część IV W stronę praktyki ............................................................. 241
Rozdział 18 Wielokrotne używanie: komponenty i wzorce .................................... 243
              18.1. Praktyczne informacje na temat wielokrotnego używania ................................... 243
                     18.1.1. Co może być użyte wielokrotnie i w jaki sposób? ................................. 244
                     18.1.2. Dlaczego używać powtórnie? ................................................................ 246
                     18.1.3. Dlaczego używanie wielokrotne jest trudne? ........................................ 247
                     18.1.4. Które komponenty w naturalny sposób nadają się
                               do powtórnego użycia? ........................................................................ 248
                     18.1.5. A co z budowaniem własnych komponentów? ...................................... 249
                     18.1.6. Jaką różnicę sprawia zorientowanie obiektowe? ................................... 250
              18.2. Wzorce projektowe ............................................................................................. 251
                     18.2.1. Przykład: Fasada .................................................................................... 254
                     18.2.2. Język UML i wzorce .............................................................................. 254
              18.3. Szkielety ............................................................................................................... 256
Rozdział 19 Jakość produktu: weryfikowanie, walidacja i testowanie .................... 257
              19.1. Omówienie jakości .............................................................................................. 257
              19.2. W jaki sposób można osiągnąć wysoką jakość? .................................................... 258
                     19.2.1. Nastawienie na produkt ........................................................................ 258
                     19.2.2. Nastawienie na proces .......................................................................... 258
                     19.2.3. Dalsza lektura ........................................................................................ 259
              19.3. Weryfikacja .......................................................................................................... 259
              19.4. Walidacja .............................................................................................................. 260
                     19.4.1. Użyteczność .......................................................................................... 261
              19.5. Testowanie .......................................................................................................... 262
                     19.5.1. Wybieranie i przeprowadzanie testów .................................................. 263
                     19.5.2. Dodatkowe problemy związane ze zorientowaniem obiektowym ....... 265
                     19.5.3. Dlaczego testowanie jest często przeprowadzane źle? ......................... 267
              19.6. Przeglądy i inspekcje ............................................................................................ 268
                     19.6.1. Problemy związane z przeglądami FTR ................................................. 269
Rozdział 20 Jakość procesu: zarządzanie, zespoły i kontrola jakości ...................... 271
              20.1. Zarządzanie ......................................................................................................... 271
                     20.1.1. Zarządzanie projektem .......................................................................... 272
                     20.1.2. Szacowanie projektu iteracyjnego ......................................................... 273
                     20.1.3. Zarządzanie projektowaniem opartym na komponentach .................... 274
                     20.1.4. Zarządzanie ludźmi ................................................................................ 275
              20.2. Zespoły ................................................................................................................ 276
              20.3. Przywództwo ...................................................................................................... 277
                     20.3.1. Zmiana procesu projektowania ............................................................. 278
              20.4. Kontrola jakości ................................................................................................... 279
                     20.4.1. Kontrola jakości w procesach iteracyjnych ............................................ 281
                     20.4.2. Kompleksowe zarządzanie jakością ....................................................... 281
              20.5. Dalsza lektura ...................................................................................................... 283
              Skorowidz ............................................................................................ 289
W tym rozdziale będziemy kontynuować udzielanie odpowiedzi na pytanie „jakie są dobre
systemy?”, opisując zorientowany obiektowo paradygmat, który zawdzięcza swoją popular-
ność częściowo temu, że wspiera on projektowanie dobrych systemów. Korzystanie jednak
ze zorientowania obiektowego nie jest ani niezbędne, ani wystarczające do budowania do-
brych systemów. Udzielimy odpowiedzi na następujące pytania:
· Czym jest obiekt?
· W jaki sposób porozumiewają się obiekty?
· Jak jest zdefiniowany interfejs obiektu?
· Co obiekty mają wspólnego z komponentami?

Pod koniec omówimy dziedziczenie, polimorfizm i wiązanie dynamiczne.
    Treści zawarte w tym rozdziale odnoszą się do standardowych, nowoczesnych, opartych
na klasach, obiektowo zorientowanych języków, takich jak Java, C# i C++. Większość roz-
działu można odnieść też do języków Smalltalk, Eiffel, CLOS, Perl5 i innych obiektowo zo-
rientowanych języków, z którymi można się spotkać, jednak dokładne ich porównywanie
wykracza poza zakres tej książki.
    W niniejszym rozdziale są zawarte pytania na temat sposobów, w jaki języki programo-
wania używane przez Czytelnika udostępniają omawiane obiektowo zorientowane funkcje.
Jeśli Czytelnik zna już jakiś język programowania, powinien być w stanie udzielić odpowie-
dzi na te pytania. Jeśli nie, warto aby przeczytał ten rozdział do końca, poznał podstawy wy-
branego języka, a następnie powrócił do pytań w celu sprawdzenia swojej wiedzy na temat
sposobów realizowania przez język zorientowania obiektowego. W pytaniach język progra-
mowania używany przez Czytelnika będziemy w skrócie nazywać „Twoim językiem”.



2.1. Czym jest obiekt?
Pojęciowo obiekt jest elementem, z którym można wchodzić w interakcje: można wysyłać
do niego różne komunikaty, a on będzie reagował. Zachowania obiektu zależą od jego bie-
żącego stanu wewnętrznego, który może ulegać zmianie, na przykład na skutek reakcji na
36 Część I ¨ Tło koncepcyjne

otrzymany komunikat. Ważne jest, z którym obiektem zachodzi interakcja, i dlatego odnie-
sienie do obiektu następuje za pośrednictwem jego nazwy. Obiekt ma zatem swoją tożsa-
mość, która odróżnia go od wszystkich innych obiektów. Obiekt jest więc elementem posia-
dającym swoje zachowanie, stan i tożsamość; w taki sposób charakteryzuje go Grady Booch
[7]. Rozważymy te aspekty bardziej szczegółowo.

Przedmiot
Pojęcie przedmiotu jest bardziej interesujące, niż może się to początkowo wydawać. Obiekt
nie jest tylko elementem systemu; reprezentuje on w systemie koncepcję przedmiotu. Obiekt
może być na przykład reprezentacją prawdziwego przedmiotu, takiego jak zegar, tablica
rozdzielcza albo klient. W rzeczywistości obiekty pojawiły się jawnie po raz pierwszy w ję-
zyku Simula, w którym reprezentowały obiekty z realnego świata — te, które były symulo-
wane. Oczywiście, aby systemy programistyczne ogólnego przeznaczenia mogły być two-
rzone w oparciu o obiekty, obiekty nie muszą reprezentować fizycznie istniejących rzeczy.
Do kwestii sposobu rozpoznawania obiektów powrócimy w rozdziale 5.
P: Które z elementów następującej listy mogą być obiektami: młotek, kula, proces chemiczny,
miłość, mgła, rzeka, złość, kot, szarość, szary kot?

Stan
Stan obiektu to wszystkie dane aktualnie w nim zapisane. Zwykle obiekt ma wiele nazwa-
nych atrybutów (zmiennych obiektu, danych składowych), z których każdy ma określoną
wartość. Niektóre z atrybutów mogą podlegać zmianom, to znaczy ich wartości mogą się zmie-
niać. Obiekt reprezentujący na przykład klienta może mieć atrybut o nazwie adres, którego
wartość ulegnie modyfikacji po przeprowadzce klienta. Inne atrybuty mogą być niezmienne,
czyli stałe. Obiekt reprezentujący klienta może mieć atrybut, którego wartością będzie numer
identyfikacyjny klienta, pozostający bez zmian przez cały czas trwania życia obiektu. W większo-
ści współczesnych obiektowo zorientowanych języków programowania zestaw atrybutów
przypisanych obiektowi nie może ulec zmianie podczas trwania życia tego obiektu, chociaż
wartości atrybutów mogą się zmieniać.

Zachowanie
Zachowanie oznacza sposób, w jaki obiekt działa i reaguje w sensie zmian swojego stanu
i przekazywania komunikatów. Obiekt rozumie niektóre komunikaty, co znaczy, że może je
odbierać i zgodnie z nimi postępować. Zestaw komunikatów rozumianych przez obiekt, po-
dobnie jak i zestaw atrybutów, jest zwykle stały. Sposób, w jaki obiekt reaguje na komunikat,
może zależeć od aktualnych wartości jego atrybutów. Dzięki temu, nawet jeśli świat zewnętrzny
nie ma zagwarantowanego bezpośredniego dostępu do atrybutów (a zazwyczaj właśnie tak
jest), może pośrednio wpływać na ich wartości. W taki sposób wartości atrybutów decydują
o stanie obiektu.
Rozdział 2. ¨ Koncepcje obiektów 37


Tożsamość
To zagadnienie może być trochę trudne. Idea jest taka, że obiekty są definiowane nie tylko
przez bieżące wartości swoich atrybutów. Istnienie obiektu jest ciągłe. Wartości atrybutów
mogą na przykład ulec zmianie, zwykle w odpowiedzi na komunikat, ale to będzie ciągle ten
sam obiekt. Odniesienie do obiektu następuje zazwyczaj przez jego nazwę (wartość zmien-
nej w programie-kliencie, na przykład Klient), ale nazwa obiektu to nie to samo, co sam
obiekt, ponieważ obiektowi można nadać kilka różnych nazw (co może być zaskakujące dla
programistów funkcyjnych, a niektórzy z nich twierdzą, że zorientowanie obiektowe można
zrealizować w czysto funkcyjny sposób; jednak tego zagadnienia nie będziemy poruszać
w niniejszej książce).


2.1.1. Przykład
Rozważmy obiekt o nazwie mojZegar, który rozumie komunikaty podajCzas i ustawCzasNa(07:43),
i w ogólności ustawCzasNa(nowyCzas) dla sensownych wartości parametru nowyCzas. Można to
zrealizować, tworząc interfejs, który ogłosi, że przyjmuje komunikaty w postaci podajCzas
i ustawCzasNa(nowyCzas: Czas), gdzie Czas jest typem1, którego elementy są sensownymi
wartościami wspomnianego parametru nowyCzas.
    W jaki sposób zaimplementować taką funkcję? Świat zewnętrzny nie musi tego wiedzieć
(informacja powinna być ukryta), ale być może obiekt ma atrybut Czas, którego wartość
zwraca w odpowiedzi na komunikat podajCzas i który jest ustawiany na wartość nowyCzas po
otrzymaniu przez obiekt komunikatu ustawCzasNa(nowyCzas). Jest też możliwe, że komuni-
kat jest przekazywany do innego obiektu, znanego obiektowi mójZegar, i że to właśnie ten
inny obiekt pracuje z komunikatami.


2.1.2. Komunikaty
Z poprzedniego przykładu można wysnuć kilka wniosków na temat komunikatów. W skład
komunikatu wchodzi słowo kluczowe nazywane selektorem. W przykładzie selektorami są
podajCzas i ustawCzasNa. Komunikat może, ale nie musi, zawierać jeden lub więcej argu-
mentów, które są wartościami przekazywanymi obiektowi, podobnie jak są przekazywane
wartości w przypadku wywoływania funkcji. W powyższym przykładzie 07:43 jest argu-
mentem, stanowiącym część komunikatu ustawCzasNa(07:43). Zazwyczaj dla danego selektora
istnieje pojedyncza „prawidłowa” liczba argumentów, które powinny znajdować się w ko-
munikacie rozpoczynającym się tym od tego selektora. Nie można oczekiwać, że obiekt mojZegar
zrozumie komunikat ustawCzasNa bez żadnego argumentu lub w postaci ustawCzasNa(4, 12:30)
i tak dalej. Akceptowalne wartości argumentów również są ustalane w interfejsie obiektu2.



1
    Albo klasą; klasy omówimy w podrozdziale 2.1.4.
2
    Podając klasę (patrz podrozdział 2.1.4) lub niekiedy tylko interfejs, do których powinien należeć obiekt
    przekazywany jako argument, lub jego typ, jeśli należy do typu podstawowego, takiego jak int albo
    bool — szczegóły zależą od konkretnego języka.
38 Część I ¨ Tło koncepcyjne

P: Jaka jest składnia przesyłania komunikatów w Twoim języku?
    Warto zauważyć, że wartości, na przykład wartości atrybutów obiektu albo wartości ar-
gumentów przesyłane w komunikatach, nie muszą należeć do typu podstawowego (takiego
jak znaki, liczby całkowite i tak dalej. Rodzaje typów podstawowych zależą od konkretnego
języka). Mogą to być również obiekty.
P: Jakie są podstawowe typy w Twoim języku?
   Jedną z czynności, którą może wykonać obiekt w odpowiedzi na komunikat, jest wysła-
nie komunikatu do innego obiektu. Jeśli tak ma się stać, to powinien on w jakiś sposób po-
znać nazwę tego obiektu. Prawdopodobnie wartością jednego z jego atrybutów mógłby być
na przykład obiekt, którego nazwa byłaby wykorzystywana podczas wysyłania komunikatu.
P: Niech o będzie obiektem. Do jakich innych obiektów może wysyłać komunikaty obiekt o, oprócz
obiektów, dla których może być wartością ich atrybutów?
    Warto zwrócić uwagę na to, że podczas wysyłania komunikatu do obiektu nie wiadomo,
jaki kod zostanie w wyniku wykonany, gdyż informacja o tym jest hermetyzowana. Będzie to
istotne pod koniec niniejszego rozdziału, kiedy omówimy wiązanie dynamiczne.


2.1.3. Interfejsy
Publiczny interfejs definiuje komunikaty, które będą przyjmowanie przez obiekt niezależnie
od miejsca ich pochodzenia. Zazwyczaj interfejs zapisuje selektory tych komunikatów, łącznie
z niektórymi informacjami na temat wymaganych argumentów oraz wartości, która ewentu-
alnie mogłaby być zwrócona. Jak wspomnieliśmy w rozdziale 1., korzystne byłoby, gdyby
interfejs zawierał jakiś rodzaj specyfikacji dotyczącej skutków wysłania komunikatu do obiektu.
Informacje tego typu są jednak podawane jedynie w komentarzach i dokumentacji. W więk-
szości języków programowania atrybuty mogą być zawarte również w publicznym interfejsie
obiektu. Umieszczenie atrybutu x w interfejsie jest równoważne z zadeklarowaniem, że
fragment danych tego obiektu, x, może być widziany i zmieniany z zewnątrz.

 Zagadnienie do przedyskutowania 9
 Jeśli korzystasz z języka, który nie zezwala na umieszczanie atrybutów w interfejsie publicz-
 nym, to w jaki sposób możesz osiągnąć taki sam efekt, używając komunikatów w celu uzyska-
 nia dostępu do danych? Czy są jakieś zalety stosowania takiego rozwiązania nawet w językach,
 które dopuszczają używanie atrybutów w interfejsie? A wady?

   Często jest tak, że nie każdy element systemu powinien mieć możliwość wysyłania do
obiektu wszystkich komunikatów, które dany obiekt mógłby zrozumieć. Dlatego też obiekt
może zwykle zrozumieć pewne komunikaty, które nie są częścią jego publicznego interfejsu.
Jak już na przykład wyjaśniliśmy w rozdziale 1., struktura danych używana przez moduł po-
winna być hermetyzowana, co jest zgodne z założeniem, że interfejs publiczny obiektu nie
powinien zazwyczaj zawierać atrybutów.
   Obiekt zawsze może wysłać sam do siebie komunikat, który będzie w stanie zrozumieć.
Wysyłanie komunikatów samemu sobie może wydawać się dziwne lub zbyt skomplikowane,
Rozdział 2. ¨ Koncepcje obiektów 39


jednak powód takiego postępowanie wyjaśnimy w dalszej części niniejszego rozdziału przy
okazji omawiania wiązania dynamicznego.
    Zazwyczaj obiekt ma przynajmniej dwa interfejsy: publiczny, z którego może korzystać
dowolny element systemu, oraz obszerniejszy interfejs prywatny, z którego może korzystać
zarówno sam obiekt, jak i inne uprzywilejowane elementy systemu. Czasami może być jesz-
cze przydatny interfejs pośredni, udostępniający więcej możliwości niż interfejs publiczny,
ale mniej niż interfejs prywatny. Czasami w danym kontekście jest potrzebna tylko część
publicznego interfejsu obiektu, co powoduje wzrost liczby obiektów, które potencjalnie mo-
głyby być używane zastępczo. Może być zatem przydatne zapisywanie naprawdę potrzeb-
nych funkcji w mniejszym interfejsie, zamiast umieszczania ich w całym interfejsie publicz-
nym obiektu. Z tego względu obiekt może mieć (lub realizować) więcej niż tylko jeden
interfejs. I odwrotnie — wiele różnych obiektów może realizować taki sam interfejs.
    W tej książce określenie „interfejs” zawsze będzie oznaczać interfejs publiczny. Jeśli bę-
dzie inaczej, zostanie to wyraźnie określone.


2.1.4. Klasy
Do tej pory omawialiśmy obiekty, jak gdyby każdy z nich był osobno definiowany, każdy miał
swój własny interfejs i sposób sprawdzania, który inny obiekt może wysyłać do niego komu-
nikaty. Oczywiście taki sposób tworzenia typowego systemu nie jest rozsądny, ponieważ
obiekty mają ze sobą wiele wspólnego. Jeśli przedsiębiorstwo ma 10 000 klientów i potrzeb-
ne jest zbudowanie systemu z obiektami reprezentującymi każdą z tych osób, to wszystkie
obiekty reprezentujące klientów będą posiadały wiele wspólnych cech. Ich zachowania po-
winny być spójne, aby programiści i osoby opiekujące się systemem mogły je zrozumieć.
Potrzebna będzie klasa obiektów reprezentująca klientów. Klasa opisuje zestaw obiektów
pełniących w systemie takie same funkcje.
    W opartych na klasach, zorientowanych obiektowo językach programowania każdy obiekt
należy do klasy, a klasa obiektu determinuje jego interfejs3. Obiekt mojZegar może należeć do
klasy Zegar, której interfejs publiczny określa, że każdy obiekt klasy Zegar będzie udostępniał
operację ustawCzasNa(nowyCzas: Czas). Znaczy to, że będzie rozumiał komunikaty z selekto-
rem ustawCzasNa i pojedynczym argumentem, który jest obiektem klasy (typu) Czas.
    W rzeczywistości nawet sposób, w jaki obiekt reaguje na komunikaty, jest zdeterminowany
przez jego klasę, łącznie z wartościami atrybutów obiektu. Metoda jest określonym frag-
mentem kodu, w którym są zaimplementowane operacje. W interfejsie obiektu widoczne
jest jedynie to, że obiekt wykonuje operację; metoda, w której jest zaimplementowana funk-
cja, jest ukryta.
    Podobnie zestaw atrybutów posiadanych przez obiekt jest zdeterminowany przez klasę,
chociaż oczywiście wartości przyjmowane przez atrybuty obiektu nie są określone w klasie
i mogą ulegać zmianom. Być może na przykład obiekty należące do klasy Zegar mają pry-
watny atrybut o nazwie czas. Jeśli taki sam komunikat zostanie wysłany do dwóch obiektów
tej samej klasy, w obu przypadkach zostanie wykonana ta sama metoda, chociaż efekt jej
wykonania może być znacząco różny, gdy atrybuty obiektów będą mieć inne wartości.


3
    W rzeczywistości obiekt może należeć do więcej niż jednej klasy, z których klasa najbardziej szczególna
    decyduje o jego interfejsie.
40 Część I ¨ Tło koncepcyjne

    Podsumowując, obiekty tej samej klasy mają takie same interfejsy. Publiczne i prywatne
interfejsy klasy Zegar mogłyby być opisane następująco:
   - czas : Czas
   + podajCzas() : Czas
   + ustawCzasNa (nowyCzas: Czas)

    W skład interfejsu publicznego wchodzą wiersze oznaczone znakiem +, a w skład inter-
fejsu prywatnego także wiersz ze znakiem –.
P: W jaki sposób definiuje się klasę, taką jak Zegar w Twoim języku? Czy interfejs i implementacja
są definiowane oddzielnie? Jak jest nazywany interfejs publiczny, a jak prywatny (może właśnie: pu-
bliczny i prywatny)? Czy są może jeszcze jakieś inne możliwości? Co one oznaczają?
    Proces tworzenia nowego obiektu należącego do klasy Zegar jest nazywany tworzeniem
egzemplarza klasy Zegar, a powstały w wyniku obiekt egzemplarzem klasy Zegar. To właśnie
dlatego zmienne, których wartości należą do obiektu i które mogą ulegać zmianie w czasie
życia obiektu, są nazywane zmiennymi egzemplarza. Utworzenie obiektu oznacza utworze-
nie nowego egzemplarza klasy posiadającego własny stan i tożsamość, które będą pozosta-
wać spójne w obrębie wszystkich obiektów klasy. Proces tworzenia zazwyczaj obejmuje także
nadanie wartości atrybutom. Wartości mogą zostać określone w zleceniu utworzenia lub na-
dane przez klasę obiektu jako domyślne wartości początkowe. W językach takich jak C++
i Java klasa odgrywa bezpośrednią rolę podczas tworzenia nowych obiektów — w rzeczy-
wistości wykonuje całą pracę, nie ograniczając się jedynie do roli szablonu. Dlatego klasa
może być często uważana za fabrykę obiektów.
P: W jaki sposób jest tworzony w Twoim języku nowy obiekt danej klasy?
   W wielu językach klasy mogą zachowywać się, jak gdyby same były obiektami. Klasa
Klient mogłaby mieć atrybut liczbaEgzemplarzy, który byłby liczbą całkowitą zwiększaną za
każdym razem, gdy tworzony jest nowy obiekt typu Klient. Takie rozwiązanie konsekwentnie
przyjęto w języku Smalltalk, a w językach C++ i Java można odnaleźć jego ślady. W Smalltalk
na przykład nowy obiekt typu Klient zostałby utworzony przez wysłanie komunikatu (przy-
kładowo new) do klasy Klient. Reakcją klasy byłoby utworzenie nowego obiektu i zwrócenie
go do metody wywołującej.

 Zagadnienie do przedyskutowania 10
 Zastanów się, co by było, gdyby konsekwentnie stosować takie rozwiązanie. Stwierdziliśmy
 już, że każdy obiekt ma swoją klasę. Jeśli więc klasa k zostanie uznana za obiekt, to co będzie
 klasą dla k? I co będzie klasą tej klasy?

P: Czy Twój język posiada takie funkcje? Jakie dokładnie?

Dygresja: po co istnieją klasy?
Dlaczego nie wystarczą obiekty, które posiadają wymagany stan, zachowanie i tożsamość?
   Klasy w zorientowanych obiektowo językach programowania służą dwóm celom. Po pierw-
sze, są wygodnym sposobem na opisanie zbioru (klasy) obiektów posiadających takie same
właściwości. W językach zorientowanych obiektowo klasy są używane przede wszystkim dla
Rozdział 2. ¨ Koncepcje obiektów 41


wygody. Nie ma na przykład potrzeby przechowywania kopii kodu opisującego zachowania
obiektu w każdym obiekcie, chociaż można wyobrażać sobie, że w każdym obiekcie znajduje
się jego kod. Zamiast tego programista może jednorazowo napisać definicję klasy, a kompi-
lator utworzy pojedynczą reprezentację klasy i pozwoli obiektom na uzyskiwanie dostępu do
reprezentacji klasy w celu pobierania potrzebnego kodu.
    Należy pamiętać, że taka wygoda wcale nie jest czymś błahym. Zasadniczym celem jest
przecież uczynienie systemów łatwiejszymi do zrozumienia, aby ich projektowanie i pielę-
gnacja były jak najbardziej tanie, łatwe i niezawodne. Sprawienie, że podobne obiekty dzielą
ten sam projekt oraz implementację, jest ważnym krokiem w tym kierunku.
    W taki sposób przejawia się zasada4, która jest tak ważna w inżynierii oprogramowania
— nie tylko w odniesieniu do kodu — że ją wykrzyczymy:

    PISZ TYLKO RAZ!

    Oznacza to, że jeśli dwie kopie jakiegoś produktu inżynierii oprogramowania, na przy-
kład fragment kodu, fragment diagramu czy fragment tekstu pochodzący z dokumentu, po-
winny być spójne, to nie powinny istnieć w dwóch egzemplarzach. Za każdym razem, gdy ta
sama informacja jest zapisywana w więcej niż jednym miejscu, nie tylko marnuje się wysiłek
na powtórne robienie tego samego, zamiast zrobienia czegoś nowego, ale też naraża się na
kłopoty związane z pielęgnacją, ponieważ dwie wersje nigdy nie będą zsynchronizowane
bez żadnych starań. Sztuka stosowania tej zasady polega na stwierdzeniu, czy dwie kopie infor-
macji są rzeczywiście takie same, czy też zdarzyło się, że potencjalnie różne informacje są
akurat w danym momencie identyczne. W tym drugim przypadku skopiowanie i wklejenie
odpowiedniego fragmentu jest jak najbardziej prawidłowe. W pierwszym przypadku niechęć
do powielania informacji w więcej niż jednym miejscu jest zaletą. Należy tak postąpić wy-
łącznie wtedy, gdy istnieją ku temu dobre powody.

    Zagadnienie do przedyskutowania 11
    Czy ta zasada oznacza, że powielanie danych w rozproszonych bazach danych jest złym pomy-
    słem? Dlaczego?

    Zauważmy, że istnieją inne sposoby na tworzenie wielu podobnych obiektów, pisząc ich
kod tylko raz. Można na przykład zdefiniować prototyp obiektu, a następnie definiować ko-
lejne obiekty jako będące „takie jak tamten, ale z następującymi różnicami”. W takim przy-
padku również wystarczyłoby przechowywanie tylko jednej kopii kodu. Mniej więcej w taki
sposób postępuje się, programując w eleganckim, opartym na prototypach, języku Self. Ję-
zyki programowania oparte na klasach zdominowały jednak obecnie zorientowanie obiekto-
we i zapewne tak już pozostanie.
    Po drugie, w większości zorientowanych obiektowo językach programowania klasy są
używane w taki sam sposób, jak w wielu innych językach są wykorzystywane typy — w celu
określenia, jakie wartości są dopuszczalne w określonych kontekstach, umożliwiając tym
samym kompilatorowi (oraz, co jest równie ważne, osobie czytającej kod) zrozumienie in-
tencji programisty i sprawdzenie, czy pewne rodzaje błędów nie wystąpią w programie.

4
    Na którą kładzie nacisk zwłaszcza Kent Beck.
42 Część I ¨ Tło koncepcyjne

   Wiele osób uważa, że klasy i typy oznaczają tę samą rzecz. Rzeczywiście, jest to wygod-
ne i często nie prowadzi do żadnych nieporozumień, niemniej taki sposób myślenia jest
błędny. Należy pamiętać, że klasa definiuje nie tylko to, jakie komunikaty zrozumie obiekt,
co tak naprawdę wystarcza, aby sprawdzać, czy jest on akceptowalny w danym kontekście.
Określa również czynności obiektu wykonywane w odpowiedzi na komunikaty.



2.2. Jaki to ma związek z celami poprzedniego rozdziału?
Szukamy modułów, najlepiej nadających się do wielokrotnego używania wymiennych mo-
dułów, które mogłyby być dobrymi komponentami. Gdzie można je znaleźć w systemie
obiektowo zorientowanym?
    Poszczególne obiekty mogłyby być uważane za moduły, ale nie byłyby one dobre. W syste-
mie znajduje się bowiem zazwyczaj wiele różnych modułów, które są blisko spokrewnione
pojęciowo. Gdyby każdy obiekt był uważany za odrębny moduł, to albo istniałyby wprowa-
dzające w błąd nieścisłości między pojęciowo powiązanymi modułami, albo potrzeba za-
chowania spójności powodowałaby tworzenie silnych skojarzeń.
    Klasy powinny być słabo skojarzonymi, wysoce spójnymi modułami. Można zatem mieć
nadzieję (być może na próżno, co przedyskutujemy w następnym podrozdziale), że będzie
realne uzyskanie korzyści przedstawionych w rozdziale 1., a mianowicie niskiego kosztu
i krótkiego czasu opracowywania, łatwości pielęgnacji i wysokiej niezawodności. Zalety te
nie są cechą charakterystyczną zorientowania obiektowego, chociaż jest ono obecnie najle-
piej poznaną ścieżką do nich prowadzącą.
    Kolejna uznana zaleta zorientowania obiektowego należy do innej kategorii. Naturalne
jest postrzeganie otaczającego świata w kategoriach obiektów. Warto przypomnieć sobie, że
głównym wymogiem stawianym przed dobrym systemem jest spełnianie oczekiwań użyt-
kowników i że prawidłowe uchwycenie tych oczekiwań oraz śledzenie ich zmian należą do
najtrudniejszych zadań związanych z tworzeniem systemów. Ważne jest, aby model systemu
(model domeny problemu i zachodzących procesów) był zgodny z modelem użytkownika.
Wydaje się, że obiekty z domeny problemu rzadziej ulegają zmianom, a same zmiany są
mniej dramatyczne, niż jest to w przypadku działania systemu wymaganego przez użytkow-
nika. Jeśli zatem system jest zbudowany w oparciu o te obiekty, to zmiany w systemie praw-
dopodobnie będą mniej rewolucyjne, niż gdyby system powstał w oparciu o bardziej ulotne
aspekty funkcjonalne. Podsumowując, należy mieć nadzieję, że system będzie zgodny z mo-
delem świata użytkownika, dzięki czemu będzie możliwe:
· łatwiejsze i dokładniejsze uchwycenie wymagań;
· lepsze nadążanie za zmianami wymagań użytkownika;
· tworzenie systemów, które prowadzą interakcje w bardziej naturalny sposób. Łatwiejsze
  jest zaimplementowanie na przykład interfejsu użytkownika, który pozwala użytkowni-
  kowi na interakcję z plikiem, zegarem albo drukarką jako całością (co ma sens z punktu
  widzenia użytkownika, ponieważ te przedmioty są podobne do obiektów z rzeczywistego
  świata), jeśli są one spójnymi obiektami także z punktu widzenia systemu. Z tego powo-
  du interfejsy użytkownika były jednymi z pierwszych głównych obszarów, w których zo-
  rientowanie obiektowe stało się popularne.
Rozdział 2. ¨ Koncepcje obiektów 43


Należy jednak zaznaczyć, że te argumenty nie są bezdyskusyjne. W niektórych przypad-
kach, takich jak na przykład systemy obsługi zamówień, podejście zorientowane obiektowo
wydaje się bardzo naturalne, w innych (na przykład kompilatory) taka argumentacja jest
mniej przekonująca.
    W każdym jednak przypadku gdy zorientowanie obiektowe osiąga swój cel, zwykle nie
jest tak z powodu charakterystycznych cech zorientowania obiektowego. Jest tak, ponieważ:
· podstawami zorientowania obiektowego są modularność, hermetyzacja i abstrakcja,
· zorientowane obiektowo języki programowania sprawiają, że osiąganie celów staje się
  względnie proste, ponieważ istnieje uzasadnione prawdopodobieństwo, że oczywisty sposób
  zrobienia czegoś jest również dobrym sposobem na zrobienie tego.

   Zorientowanie obiektowe jest religią: to ludzie zostają zorientowani w stronę obiektów.

 Zagadnienie do przedyskutowania 12
 Istnienie jakich konsekwencji, dobrych i złych, może sugerować stwierdzenie, że „zorientowanie
 obiektowe jest religią”?



2.2.1. Co wspólnego z komponentami mają obiekty?
Euforia towarzysząca zorientowaniu obiektowemu mogłaby czasami sugerować, że każda
klasa jest automatycznie komponentem, nadającym się do wielokrotnego używania. Oczywi-
ście nie jest to prawdą. W rozdziale 1. omówiliśmy powody, dla których możliwość wielo-
krotnego używania komponentu nie jest po prostu faktem o komponencie jako takim, ale
zależy od kontekstu projektu i proponowanego sposobu jego powtórnego użycia. Innym ważnym
czynnikiem jest to, że struktura klasy może być zbyt szczegółowa, aby mogła być efektywnie
wielokrotnie wykorzystywana. Aby na przykład można było wielokrotnie korzystać z poje-
dynczej klasy w sposób praktyczny i łatwy, należałoby pisać programy w tym samym języku
i sięgać do zgodnej architektury. Nie zawsze jest to niewykonalne. Istnieją powszechnie używa-
ne biblioteki klas, które odniosły sukces, i ich biblioteki mogą być uważane za komponenty
do wielokrotnego używania. Często jednak określenie komponentu odnosi się do grupy po-
wiązanych klas. Im więcej wysiłku włoży się w dostosowanie komponentu do kontekstu, tym
więcej korzyści powinien przynieść dany komponent, jeśli ten wysiłek ma być opłacalny.
     Celowo rozmyliśmy kwestię tego, czy komponenty są zbudowane z obiektów, czy z klas;
nie dokonaliśmy jeszcze wyraźnego rozróżnienia między typem a egzemplarzem. Powód jest
taki, że wziąwszy pod uwagę szeroką definicję komponentu, oba te przypadki mogą być
prawdziwe. Klasa albo zbiór klas może być komponentem na poziomie kodu źródłowego.
Kontekst, w którym jest używany komponent, korzysta z udogodnień danego języka w celu
tworzenia obiektów klasy. W innych przypadkach komponent może realizować dostęp do
określonego, gotowego obiektu jakiejś klasy, realizując również dostęp do funkcji związa-
nych z tworzeniem kolejnych obiektów tej klasy. Należy pamiętać, że sam komponent ma
dobrze zdefiniowany interfejs. Jeśli komponent składa się z obiektów i (lub) klas, to interfejs
komponentu zwykle nie pozwala na dostęp do wszystkiego, co znajduje się w interfejsach
obiektu i wewnątrz klas. Komponent sam stara się być hermetyzowaną abstrakcją i prawdo-
podobnie jest właściwe, że ukrywa część lub całość swojej wewnętrznej struktury — na
przykład czy i jak składa się z obiektów i klas.
44 Część I ¨ Tło koncepcyjne


    Zagadnienie do przedyskutowania 13
    Skorzystaj z sieci Web i innych dostępnych zasobów w celu odszukania popularnych kompo-
    nentów architektury, takich jak JavaBeans, CORBA albo .NET. Co to jest architektura? Jaką
    wewnętrzną strukturę może mieć komponent i jak jest zdefiniowany interfejs komponentu?



2.3. Dziedziczenie
Do tej pory omówiliśmy jedynie pojęciowe podstawy tego, co czasami jest nazywane pro-
jektem opartym na obiektach. W tym podrozdziale weźmiemy pod uwagę dziedziczenie,
które będąc pojęciowym elementem leżącym u podstaw obiektowo zorientowanego pro-
jektu, jest niczym lukier dla pączka. Jak wskazuje metafora, pojęcie to jest uważane za atrak-
cyjne i ważne, ale tak naprawdę jest mniej treściwe niż to, co do tej pory opisaliśmy w książce.
    W niniejszym podrozdziale rozpatrzymy dziedziczenie jako techniczną właściwość języ-
ków zorientowanych obiektowo, użyteczną (w ograniczonym zakresie) podczas niskopozio-
mowego wielokrotnego wykorzystywania. W rozdziale 5. omówimy korzystanie z dziedzi-
czenia w modelowaniu.
    Poniższy przykład został zaczerpnięty ze studium przypadku z rozdziału 15. W rozważa-
nym systemie istnieje klasa, której obiekty reprezentują wykładowców, oraz klasa, której
obiekty reprezentują opiekunów studiów. Opiekun studiów jest kimś w rodzaju wykładowcy,
a dokładniej jest wykładowcą, który oprócz pełnienia zwykłych obowiązków jest odpowiedzialny
także za nadzorowanie postępów poszczególnych studentów. W systemie OpiekunStudiow
powinien rozumieć takie same komunikaty jak Wykladowca i dodatkowo powinien być w sta-
nie odpowiedzieć na komunikat podopieczni, zwracając zbiór obiektów typu Student.
    Załóżmy, że klasa Wykladowca została już zaimplementowana i teraz należy zaprojektować
klasę OpiekunStudiow. Załóżmy też (wyłącznie dla skonkretyzowania przykładu), że używany
jest język podobny do C++, w którym interfejs klasy i jego implementacja są przechowywane
w oddzielnych plikach. Co jest potrzebne do zaimplementowania nowej klasy tak szybko jak
to tylko możliwe? Można skopiować i wkleić kod definiujący interfejs klasy Wykladowca do
nowego pliku z interfejsem i dodać u dołu opis dodatkowego komunikatu. Podobnie można
skopiować do pliku z implementacją nowej klasy kod, w którym zaimplementowano reakcję
obiektów klasy Wykladowca na komunikat, a następnie dokonać niezbędnych zmian. Jak już
jednak wspomnieliśmy, wielokrotne używanie kodu przez jego kopiowanie ma wady. Naj-
ważniejsza z nich jest taka, że w przypadku konieczności dokonania zmian w zduplikowa-
nym kodzie (na przykład wykryto błąd w programie) należy wprowadzić zmiany w dwóch
miejscach zamiast w jednym. Jest to uciążliwe i prawdopodobnie doprowadzi do błędów.
    Zamiast tego obiektowo zorientowane języki programowania dopuszczają utworzenie
nowej klasy OpiekunStudiow na podstawie istniejącej klasy Wykladowca. Wystarczy zadekla-
rować, że klasa OpiekunStudiow jest podklasą klasy Wykladowca, a następnie dopisać jedynie
to, co ma związek z dodatkowymi atrybutami lub operacjami klasy OpiekunStudiow 5.
    Co więcej, ponieważ w zorientowaniu obiektowym wiedza na temat kodu, jaki zostanie
wykonany przez obiekt po tym, gdy otrzyma on komunikat, jest hermetyzowana, istnieje

5
    W niektórych językach, a zwłaszcza w języku Eiffel, można w podklasach usuwać atrybuty i operacje
    nadklas, jednak takie postępowanie nie jest zazwyczaj uważane za dobry zwyczaj.
Rozdział 2. ¨ Koncepcje obiektów 45


możliwość, aby w klasie OpiekunStudiow zaimplementować w odpowiedzi na komunikat inne
zachowania niż te, które są zaimplementowane w klasie Wykladowca. Oznacza to, że w klasie
OpiekunStudiow można przesłonić niektóre z metod klasy Wykladowca. Oprócz dziedziczenia
metod po klasie Wykladowca, klasa OpiekunStudiow może zawierać nową metodę implemen-
tującą taką samą operację, dla której klasa Wykladowca miała już metodę. Kiedy obiekt klasy
OpiekunStudiow otrzyma komunikat z żądaniem wykonania operacji, wywołana metoda bę-
dzie wyspecjalizowaną wersją metody udostępnianej przez klasę OpiekunStudiow.

 Podklasa jest rozszerzoną, wyspecjalizowaną wersją swojej nadklasy. Zawiera operacje oraz
 atrybuty nadklasy i możliwie jeszcze inne, dodatkowe elementy.

P: W jaki sposób jest definiowana podklasa w Twoim języku? Czy klasa może być bezpośrednią
podklasą kilku klas (dziedziczenie wielokrotne), czy nie?

Terminologia
Mówi się, że:
· klasa OpiekunStudiow dziedziczy po klasie Wykladowca,
· klasa OpiekunStudiow jest podklasą (lub klasą pochodną) klasy Wykladowca,
· klasa OpiekunStudiow jest specjalizacją klasy Wykladowca,
· klasa OpiekunStudiow jest bardziej wyspecjalizowana niż klasa Wykladowca,
· klasa Wykladowca jest nadklasą (lub klasą bazową) klasy OpiekunStudiow,
· klasa Wykladowca jest generalizacją klasy OpiekunStudiow.

Wszystkie powyższe określenia mają niemal to samo znaczenie. Często pojęcia podklasy i nad-
klasy są używane przy opisie konkretnych relacji pomiędzy pojęciami reprezentowanymi
w klasach. Zazwyczaj zachodzi między nimi związek. Związki pojęciowe jednak niekoniecz-
nie muszą być widoczne w strukturze klasy. Przeciwnie, niektórzy programiści używają
dziedziczenia w strukturze klasy w przypadkach, w których nie ma pojęciowego związku
dziedziczenia pomiędzy klasami (nie zawsze można polecać takie rozwiązanie. Może być
ono wygodne w krótszym okresie czasu, jednak niemal zawsze spowoduje nieporozumienia
po upływie dłuższego czasu).
    Czy można powiedzieć, że klasa OpiekunStudiow należy do klasy Wykladowca? Można, jeśli
myśli się o klasach jak o zbiorach obiektów. Gdy mówi się o obiektach klasy Wykladowca,
z pewnością chce się uwzględnić także obiekty klasy OpiekunStudiow — po prostu ciągłe pi-
sanie o „klasie Wykladowca i dowolnych podklasach” jest zbyt niewygodne. Co więcej, zasa-
da, że obiekt podklasy powinien być zastępowalny obiektem nadklasy, jest fundamentalna.
Za każdym razem więc, gdy będzie mowa o obiektach należących do klasy, będzie to ozna-
czać także obiekty należące do podklas. Z drugiej strony bardzo wygodna byłaby możliwość
mówienia o „klasie tego obiektu”, jak gdyby należał on wyłącznie do jednej klasy. Przez
określenie „klasa” obiektu będziemy więc rozumieć najbardziej wyspecjalizowaną klasę, do
której należy dany obiekt. Oznacza to, że twierdzenie, iż zachowanie obiektu jest określone
przez jego klasę, pozostaje prawdziwe.
46 Część I ¨ Tło koncepcyjne


2.4. Polimorfizm i wiązanie dynamiczne
Te dwa określenia są często w środowisku zorientowanym obiektowo używane zamiennie.
W rzeczywistości oznaczają one całkiem różne koncepcje. Ogólnie w językach programowa-
nia jedno pojęcie może istnieć bez drugiego, chociaż w językach zorientowanych obiektowo
są one spokrewnione i mają związek z dziedziczeniem.
    Przede wszystkim należy zauważyć, że sam fakt, iż jedną klasę można definiować na
podstawie innej klasy, korzystając ponownie z jej kodu, nie musi mieć żadnego wpływu na
to, w jaki sposób kod-klient będzie traktował obiekty tych klas. Możliwy byłby język, w którym
dziedziczenie byłoby tylko sposobem na wielokrotne wykorzystywanie kodu. Można by zdefi-
niować klasę OpiekunStudiow na podstawie klasy Wykladowca, lecz cały kod klienta (a także
kompilator) musiałby dokładnie znać klasę każdego obiektu, z którym by wchodził w inte-
rakcję. Technicznie rzecz biorąc oznacza to, że można by utworzyć język z takim rodzajem
dziedziczenia, w którym występowałyby wyłącznie typy monomorficzne. Języki zoriento-
wane obiektowo radzą sobie jednak lepiej.

Polimorfizm
Określenie to, wywodzące się z języka greckiego, oznacza mający wiele kształtów. W języ-
kach obiektowo zorientowanych odnosi się do sytuacji, w której obiekt może należeć do jednego
z kilku typów. W obiektowo zorientowanej sytuacji zmienna polimorficzna mogłaby odnosić
się (w różnych przypadkach) do obiektów kilku różnych klas. Funkcja polimorficzna może
pobierać argumenty różnych typów. Powiedzieliśmy już, że obiekt podklasy powinien być
stosowany w każdej sytuacji, w której mógłby zostać użyty obiekt nadklasy. Powinno to oznaczać
w szczególności, że obiekt podklasy powinien być akceptowany jako wartość zmiennej, jeśli
jest akceptowany jako obiekt klasy bazowej. Innymi słowy, w obiektowo zorientowanym ję-
zyku każda zmienna jest polimorficzna — przynajmniej w tym ograniczonym znaczeniu.
Podobnie, jeśli jakaś funkcja (na przykład metoda) może pobierać argument klasy B, powin-
na być w stanie pobrać argument dowolnej klasy C, która jest podklasą klasy B; tak więc
również każda funkcja jest polimorficzna w tym ograniczonym sensie. Funkcja, która na
przykład oczekuje jako argumentu obiektu Wykladowca, nie powinna zgłosić błędu, jeśli jako
argument otrzyma obiekt OpiekunStudiow.

 Zagadnienie do przedyskutowania 14
 Czy w Twoim języku (w C albo w typologicznie funkcjonalnym języku programowania) jest re-
 alizowany polimorfizm? Czy na polimorfizm są nałożone większe, czy mniejsze ograniczenia niż
 w polimorfizmie obiektowo zorientowanym, który został tu opisany? Czy jest on przydatny?
 W jaki sposób?

   Polimorfizm pozwala na znaczne ograniczenie duplikacji kodu. Swoje prawdziwe możli-
wości pokazuje jednak w powiązaniu z związaniem dynamicznym.
Rozdział 2. ¨ Koncepcje obiektów 47


Wiązanie dynamiczne
Słowo „wiązanie” w określeniu wiązanie dynamiczne (albo też późne wiązanie — oba te
określenia są używane zamiennie) odnosi się do procesu identyfikowania kodu, który powi-
nien zostać wykonany na skutek otrzymanego komunikatu. Zrozumienie tego będzie łatwiej-
sze po rozważeniu kilku przykładów.
    Załóżmy, że interfejs obiektu Wykladowca zawiera funkcję mozeWykonac (obowiazek: Obowia-
zek), która jako argument pobiera obiekt reprezentujący obowiązek administracyjny, a w wyniku
zwraca wartość logiczną, której wartością jest prawda, jeśli wykładowca może wypełnić dany
obowiązek. Przyjmijmy też założenie (trochę nierealne), że OpiekunStudiow jest w stanie zrobić
wszystko, a tym samym że zawsze powinien zwracać wartość prawda. Znaczy to, że podklasa
OpiekunStudiow przeimplementowała (przesłoniła) funkcję mozeWykonac, prawdopodobnie za-
stępując skomplikowany kod sprawdzający informacje na temat zainteresowań lub doświad-
czenia wykładowcy prostym kodem, który zawsze zwraca wartość prawda.
    Załóżmy teraz, że wykladowcy są zmienną odnoszącą się do zbioru obiektów klasy Wykladowca.
W tym zbiorze mogą być oczywiście zawarte także obiekty typu OpiekunStudiow, ponieważ
jeśli do zmiennej wykladowcy można dodawać obiekty klasy Wykladowca, to można do niej do-
dawać również obiekty klasy OpiekunStudiow. Przypuśćmy, że klient-zadanie próbujące znaleźć
kogoś do zorganizowania seminarium wykonuje kod w rodzaju poniższego pseudokodu:
     dla kazdy o w wykladowca
      o.mozeWykonac(organizacjaSeminarium)

Warto zwrócić uwagę na zapis z kropką w wierszu z wysyłanym komunikatem, który jest
wspólny dla wielu języków programowania. Wyrażenie o.mozeWykonac(organizacjaSeminarium)
oznacza wysłanie komunikatu mozeWykonac(organizacjaSeminarium)do obiektu o. Może ono
być również używane w celu reprezentowania wartości, którą obiekt o zwróci klientowi po
przetworzeniu komunikatu.
    Przyglądając się kodowi można przypuszczać, że obiekt o należy do klasy Wykladowca. Warto
przypomnieć ideę, że w obiekcie hermetyzowane jest jego zachowanie, a klasy wprowadzo-
no jedynie z potrzeby zwięzłości zapisu. Jeśli obiekt o znajduje się wyłącznie w klasie Wykla-
dowca, to powinien zostać wykonany kod obiektu Wykladowca dla komunikatu mozeWykonac,
czyli jego zachowanie w reakcji na komunikat. Co powinno się stać, gdy pętla dla osiągnie
obiekt o, który w rzeczywistości należy do klasy OpiekunStudiow? Oczywiście w takim przy-
padku powinien wykonać się kod klasy OpiekunStudiow (gdyby obiekt o rzeczywiście zabierał
ze sobą swój kod, działoby się tak automatycznie; fakt, że tak nie jest, wynika po prostu
z optymalizacji). Znaczy to, że ten sam fragment składni powinien spowodować wykonanie
dwóch różnych fragmentów kodu w różnych sytuacjach. Wysyłany komunikat jest dyna-
micznie wiązany z odpowiednim kodem6.
    Na koniec rozważmy inny bardzo prosty przykład wiązania dynamicznego, który ilu-
struje także przypadek wysyłania przez obiekt komunikatu do samego siebie.



6
    W najprostszy sposób można to zrobić, sprawdzając typ obiektu podczas wykonywania się programu.
    W nowoczesnych językach jednak większość pracy bierze na siebie kompilator, co pozwala na większą
    wydajność.
48 Część I ¨ Tło koncepcyjne

   Przypuśćmy, że interfejs klasy Wykladowca zawiera komunikat mozliwosci; w odpowiedzi
na niego obiekt klasy Wykladowca powinien zwrócić zbiór czynności, które wykładowca może
wykonać. Być może kod klasy Wykladowca jest zaimplementowany w podobny sposób jak
w poniższym pseudokodzie (w którym instrukcja sam.mozeWykonac(obowiazek) oznacza wy-
nik zwracany po wysłaniu do tego obiektu komunikatu z selektorem mozeWykonac i argu-
mentem obowiazek):
     coMogeWykonac := pustyZbior
     dla kazdy obowiazek w listaWszystkichObowiazkow
     jesli (sam.mozeWykonac(obowiazek)) wtedy dodaj obowiazek do coMogeWykonac
     inaczej zrob nic
     zwroc coMogeWykonac

    Oczywiście tę operację można przesłonić w nowej klasie OpiekunStudiow, tylko po co tak
robić (wydajność raczej nie będzie ważna)? Załóżmy, że kod pozostanie na swoim miejscu,
dzięki czemu zostanie bez zmian odziedziczony przez obiekty klasy OpiekunStudiow. Przy-
pomnijmy jednak, że w klasie OpiekunStudiow została przesłonięta operacja mozeWykonac. Co
się stanie, gdy obiekt klasy OpiekunStudiow otrzyma komunikat mozliwosci? Zostanie wyko-
nany powyższy kod — w czym nie ma nic szczególnego — co spowoduje wysłanie komuni-
katu mozeWykonac do siebie samego. Jest to obiekt klasy OpiekunStudiow, tak więc po otrzy-
maniu komunikatu mozeWykonac zostanie wykonana wyspecjalizowana wersja kodu zdefiniowana
w klasie OpiekunStudiow.
    W przypadku używania czystego języka obiektowo zorientowanego takie zachowanie szybko
powinno stać się drugą naturą. Ostrożność należy zachować w przypadku języka C++: takie
zachowanie wykazują tylko metody wirtualne. Niektóre osoby, łącznie ze mną7, są głęboko
przekonane, że zaczynając programowanie obiektowo zorientowane w języku C++ powin-
no się początkowo tworzyć wyłącznie metody wirtualne8, a dopiero potem nauczyć się two-
rzenia metod niewirtualnych.

    PODSUMOWANIE


Ten rozdział był krótkim wprowadzeniem do zorientowania obiektowego. Opisaliśmy, czym
jest obiekt i jak między obiektami są przesyłane komunikaty. Pokazaliśmy, że obiekty w systemie
można z pożytkiem podzielić na klasy, zamiast rozpatrywać je indywidualnie, oraz rozpo-
częliśmy rozpatrywanie powiązań między obiektami i komponentami. Omówiliśmy, jak za
pomocą dziedziczenia klasa może zostać zdefiniowana z wykorzystaniem definicji innej kla-
sy. Na koniec przedstawiliśmy inną cechę dziedziczenia w językach zorientowanych obiek-
towo — możliwość udostępniania polimorfizmu i wiązania dynamicznego.
W następnym rozdziale dokonamy wprowadzenia do głównego tematu tej książki — Ujed-
noliconego Języka Modelowania, który może być używany do określania specyfikacji i pro-
jektowania systemów korzystających z przewagi, jaką zapewnia zorientowanie obiektowe.




7
    Stevens.
8
    Łącznie (zwłaszcza) z destruktorami, ale nigdy z konstruktorami. Dlaczego?

More Related Content

Similar to UML. Inżynieria oprogramowania. Wydanie II

Agile. Programowanie zwinne: zasady, wzorce i praktyki zwinnego wytwarzania o...
Agile. Programowanie zwinne: zasady, wzorce i praktyki zwinnego wytwarzania o...Agile. Programowanie zwinne: zasady, wzorce i praktyki zwinnego wytwarzania o...
Agile. Programowanie zwinne: zasady, wzorce i praktyki zwinnego wytwarzania o...Wydawnictwo Helion
 
Architektura korporacyjna. Aspekty teoretyczne i wybrane zastosowania praktyc...
Architektura korporacyjna. Aspekty teoretyczne i wybrane zastosowania praktyc...Architektura korporacyjna. Aspekty teoretyczne i wybrane zastosowania praktyc...
Architektura korporacyjna. Aspekty teoretyczne i wybrane zastosowania praktyc...Andrzej Sobczak
 
Aplikacje w Visual C++ 2005. Przykłady
Aplikacje w Visual C++ 2005. PrzykładyAplikacje w Visual C++ 2005. Przykłady
Aplikacje w Visual C++ 2005. PrzykładyWydawnictwo Helion
 
Wzorce projektowe. Analiza kodu sposobem na ich poznanie
Wzorce projektowe. Analiza kodu sposobem na ich poznanieWzorce projektowe. Analiza kodu sposobem na ich poznanie
Wzorce projektowe. Analiza kodu sposobem na ich poznanieWydawnictwo Helion
 
Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0Wydawnictwo Helion
 
J2EE. Podstawy programowania aplikacji korporacyjnych
J2EE. Podstawy programowania aplikacji korporacyjnychJ2EE. Podstawy programowania aplikacji korporacyjnych
J2EE. Podstawy programowania aplikacji korporacyjnychWydawnictwo Helion
 
CATIA V5. Przykłady efektywnego zastosowania systemu w projektowaniu mechanic...
CATIA V5. Przykłady efektywnego zastosowania systemu w projektowaniu mechanic...CATIA V5. Przykłady efektywnego zastosowania systemu w projektowaniu mechanic...
CATIA V5. Przykłady efektywnego zastosowania systemu w projektowaniu mechanic...Wydawnictwo Helion
 
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychTworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychWydawnictwo Helion
 
Więcej niż architektura oprogramowania
Więcej niż architektura oprogramowaniaWięcej niż architektura oprogramowania
Więcej niż architektura oprogramowaniaWydawnictwo Helion
 
C++Builder Borland Developer Studio 2006. Kompendium programisty
C++Builder Borland Developer Studio 2006. Kompendium programistyC++Builder Borland Developer Studio 2006. Kompendium programisty
C++Builder Borland Developer Studio 2006. Kompendium programistyWydawnictwo Helion
 
Microsoft SQL Server 2005. Podręcznik programisty
Microsoft SQL Server 2005. Podręcznik programistyMicrosoft SQL Server 2005. Podręcznik programisty
Microsoft SQL Server 2005. Podręcznik programistyWydawnictwo Helion
 
Visual Studio 2005. Programowanie z Windows API w języku C++
Visual Studio 2005. Programowanie z Windows API w języku C++Visual Studio 2005. Programowanie z Windows API w języku C++
Visual Studio 2005. Programowanie z Windows API w języku C++Wydawnictwo Helion
 
PHP5. Zaawansowane programowanie
PHP5. Zaawansowane programowaniePHP5. Zaawansowane programowanie
PHP5. Zaawansowane programowanieWydawnictwo Helion
 
Praktyczny kurs Java. Wydanie II
Praktyczny kurs Java. Wydanie IIPraktyczny kurs Java. Wydanie II
Praktyczny kurs Java. Wydanie IIWydawnictwo Helion
 
Excel z elementami VBA w firmie
Excel z elementami VBA w firmieExcel z elementami VBA w firmie
Excel z elementami VBA w firmieWydawnictwo Helion
 
Excel w zastosowaniach inżynieryjnych
Excel w zastosowaniach inżynieryjnychExcel w zastosowaniach inżynieryjnych
Excel w zastosowaniach inżynieryjnychWydawnictwo Helion
 
Projektowanie obiektowe. Role, odpowiedzialność i współpraca
Projektowanie obiektowe. Role, odpowiedzialność i współpracaProjektowanie obiektowe. Role, odpowiedzialność i współpraca
Projektowanie obiektowe. Role, odpowiedzialność i współpracaWydawnictwo Helion
 
Język C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistówJęzyk C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistówWydawnictwo Helion
 

Similar to UML. Inżynieria oprogramowania. Wydanie II (20)

Agile. Programowanie zwinne: zasady, wzorce i praktyki zwinnego wytwarzania o...
Agile. Programowanie zwinne: zasady, wzorce i praktyki zwinnego wytwarzania o...Agile. Programowanie zwinne: zasady, wzorce i praktyki zwinnego wytwarzania o...
Agile. Programowanie zwinne: zasady, wzorce i praktyki zwinnego wytwarzania o...
 
Architektura korporacyjna. Aspekty teoretyczne i wybrane zastosowania praktyc...
Architektura korporacyjna. Aspekty teoretyczne i wybrane zastosowania praktyc...Architektura korporacyjna. Aspekty teoretyczne i wybrane zastosowania praktyc...
Architektura korporacyjna. Aspekty teoretyczne i wybrane zastosowania praktyc...
 
Aplikacje w Visual C++ 2005. Przykłady
Aplikacje w Visual C++ 2005. PrzykładyAplikacje w Visual C++ 2005. Przykłady
Aplikacje w Visual C++ 2005. Przykłady
 
Wzorce projektowe. Analiza kodu sposobem na ich poznanie
Wzorce projektowe. Analiza kodu sposobem na ich poznanieWzorce projektowe. Analiza kodu sposobem na ich poznanie
Wzorce projektowe. Analiza kodu sposobem na ich poznanie
 
Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0
 
J2EE. Podstawy programowania aplikacji korporacyjnych
J2EE. Podstawy programowania aplikacji korporacyjnychJ2EE. Podstawy programowania aplikacji korporacyjnych
J2EE. Podstawy programowania aplikacji korporacyjnych
 
CATIA V5. Przykłady efektywnego zastosowania systemu w projektowaniu mechanic...
CATIA V5. Przykłady efektywnego zastosowania systemu w projektowaniu mechanic...CATIA V5. Przykłady efektywnego zastosowania systemu w projektowaniu mechanic...
CATIA V5. Przykłady efektywnego zastosowania systemu w projektowaniu mechanic...
 
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychTworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
 
Więcej niż architektura oprogramowania
Więcej niż architektura oprogramowaniaWięcej niż architektura oprogramowania
Więcej niż architektura oprogramowania
 
C++Builder Borland Developer Studio 2006. Kompendium programisty
C++Builder Borland Developer Studio 2006. Kompendium programistyC++Builder Borland Developer Studio 2006. Kompendium programisty
C++Builder Borland Developer Studio 2006. Kompendium programisty
 
Microsoft SQL Server 2005. Podręcznik programisty
Microsoft SQL Server 2005. Podręcznik programistyMicrosoft SQL Server 2005. Podręcznik programisty
Microsoft SQL Server 2005. Podręcznik programisty
 
Visual Studio 2005. Programowanie z Windows API w języku C++
Visual Studio 2005. Programowanie z Windows API w języku C++Visual Studio 2005. Programowanie z Windows API w języku C++
Visual Studio 2005. Programowanie z Windows API w języku C++
 
PHP5. Zaawansowane programowanie
PHP5. Zaawansowane programowaniePHP5. Zaawansowane programowanie
PHP5. Zaawansowane programowanie
 
Praktyczny kurs Java. Wydanie II
Praktyczny kurs Java. Wydanie IIPraktyczny kurs Java. Wydanie II
Praktyczny kurs Java. Wydanie II
 
Excel z elementami VBA w firmie
Excel z elementami VBA w firmieExcel z elementami VBA w firmie
Excel z elementami VBA w firmie
 
Excel w zastosowaniach inżynieryjnych
Excel w zastosowaniach inżynieryjnychExcel w zastosowaniach inżynieryjnych
Excel w zastosowaniach inżynieryjnych
 
Projektowanie obiektowe. Role, odpowiedzialność i współpraca
Projektowanie obiektowe. Role, odpowiedzialność i współpracaProjektowanie obiektowe. Role, odpowiedzialność i współpraca
Projektowanie obiektowe. Role, odpowiedzialność i współpraca
 
Język C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistówJęzyk C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistów
 
Praktyczny kurs SQL
Praktyczny kurs SQLPraktyczny kurs SQL
Praktyczny kurs SQL
 
Solid Edge 17. Podstawy
Solid Edge 17. PodstawySolid Edge 17. Podstawy
Solid Edge 17. Podstawy
 

More from Wydawnictwo Helion

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyWydawnictwo Helion
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikWydawnictwo Helion
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczneWydawnictwo Helion
 
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesieE-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesieWydawnictwo Helion
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsWydawnictwo Helion
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IIWydawnictwo Helion
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuWydawnictwo Helion
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIWydawnictwo Helion
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningWydawnictwo Helion
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykWydawnictwo Helion
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaWydawnictwo Helion
 

More from Wydawnictwo Helion (20)

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. Projekty
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnik
 
Access w biurze i nie tylko
Access w biurze i nie tylkoAccess w biurze i nie tylko
Access w biurze i nie tylko
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
 
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesieE-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółu
 
Windows PowerShell. Podstawy
Windows PowerShell. PodstawyWindows PowerShell. Podstawy
Windows PowerShell. Podstawy
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie II
 
JavaScript. Pierwsze starcie
JavaScript. Pierwsze starcieJavaScript. Pierwsze starcie
JavaScript. Pierwsze starcie
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny trening
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktyk
 
Excel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktykExcel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktyk
 
Access 2007 PL. Seria praktyk
Access 2007 PL. Seria praktykAccess 2007 PL. Seria praktyk
Access 2007 PL. Seria praktyk
 
Word 2007 PL. Seria praktyk
Word 2007 PL. Seria praktykWord 2007 PL. Seria praktyk
Word 2007 PL. Seria praktyk
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacja
 
AutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PLAutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PL
 
Bazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcieBazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcie
 
Inventor. Pierwsze kroki
Inventor. Pierwsze krokiInventor. Pierwsze kroki
Inventor. Pierwsze kroki
 

UML. Inżynieria oprogramowania. Wydanie II

  • 1. UML. In¿ynieria oprogramowania. Wydanie II Autor: Perdita Stevens T³umaczenie: Ireneusz Jakóbik ISBN: 978-83-246-0805-8 Tytu³ orygina³u: Using UML: Software Engineering with Objects and Components (2nd Edition) Format: B5, stron: 304 Praktyczny podrêcznik do nauki jêzyka UML • Jak zaprojektowaæ dobry system? • Jak poprawnie tworzyæ i odczytywaæ modele? • Jak w praktyce stosowaæ UML i poprawiæ jakoœæ projektowanych produktów? W œwiecie informatyki dobry projekt to czêsto wiêcej ni¿ po³owa sukcesu, a wraz ze wzrostem popularnoœci obiektowych jêzyków programowania UML — ujednolicony jêzyk modelowania przeznaczony do reprezentacji elementów w analizie obiektowej i programowaniu obiektowym — sta³ siê podstawowym narzêdziem do tworzenia modeli. Dlatego te¿ trudno wyobraziæ sobie dobrego informatyka, który nie potrafi przygotowaæ poprawnego projektu w tym jêzyku lub odczytaæ modelu utworzonego przez kogoœ innego. „UML. In¿ynieria oprogramowania. Wydanie II” to przystêpny podrêcznik dla studentów i informatyków pragn¹cych nie tylko poznaæ ujednolicony jêzyk modelowania, ale przede wszystkim nauczyæ siê korzystaæ z niego w kontekœcie in¿ynierii oprogramowania. Czytaj¹c go, dowiesz siê, jak powinien wygl¹daæ dobry system, poznasz sk³adniê i funkcje jêzyka UML, a przedstawione studia przypadku pozwol¹ Ci zobaczyæ, jak u¿ywaæ go do projektowania praktycznych rozwi¹zañ. • Projektowanie systemów bazuj¹cych na komponentach • Wprowadzenie do obiektowoœci • Efektywny proces projektowania • Opracowywanie modeli klas • Przygotowywanie modeli przypadków u¿ycia • Tworzenie diagramów interakcji, stanów i aktywnoœci • Przygotowywanie diagramów struktury i wdro¿eñ Wydawnictwo Helion • Stosowanie komponentów i wzorców ul. Koœciuszki 1c • Dbanie o jakoœæ procesu i produktu 44-100 Gliwice • Praktyczne przyk³ady projektowania systemów tel. 032 230 98 63 Jeœli chcesz tworzyæ oprogramowanie najwy¿szej jakoœci, zacznij od dobrego projektu e-mail: helion@helion.pl
  • 2. X Wstęp ...................................................................................................... 13 Część I Tło koncepcyjne .................................................................. 19 Rozdział I Inżynieria oprogramowania z użyciem komponentów ......................... 21 1.1. Co to jest dobry system? ......................................................................................... 21 1.2. Czy istnieją dobre systemy? ..................................................................................... 22 1.2.1. Problemy… ............................................................................................... 22 1.2.2. …a nawet katastrofalne niepowodzenia .................................................... 24 1.2.3. Obietnice, obietnice .................................................................................. 25 1.3. Jakie są dobre systemy? ............................................................................................ 26 1.3.1. Hermetyzacja: słabe powiązania ................................................................ 27 1.3.2. Abstrakcja: wysoki stopień spójności ......................................................... 30 1.3.3. Architektura i komponenty ........................................................................ 31 1.3.4. Projektowanie oparte na komponentach: modularność ............................ 33 1.4. Jak są zbudowane dobre systemy? ........................................................................... 33 Rozdział 2 Koncepcje obiektów ............................................................................... 35 2.1. Czym jest obiekt? ..................................................................................................... 35 2.1.1. Przykład ..................................................................................................... 37 2.1.2. Komunikaty ................................................................................................ 37 2.1.3. Interfejsy .................................................................................................... 38 2.1.4. Klasy .......................................................................................................... 39 2.2. Jaki to ma związek z celami poprzedniego rozdziału? .............................................. 42 2.2.1. Co wspólnego z komponentami mają obiekty? ......................................... 43 2.3. Dziedziczenie ........................................................................................................... 44 2.4. Polimorfizm i wiązanie dynamiczne ......................................................................... 46 Rozdział 3 Wstępne studium przypadku ................................................................. 49 3.1. Problem ................................................................................................................... 49 3.1.1. Sprecyzowanie wymagań ........................................................................... 49 3.1.2. Model przypadków użycia ......................................................................... 51 3.2. Zakres oraz iteracje ................................................................................................. 53 3.3. Identyfikowanie klas ................................................................................................. 55 3.4. Relacje między klasami ............................................................................................. 57 3.5. System w akcji ......................................................................................................... 60 3.5.1. Zmiany w systemie: diagramy stanów ....................................................... 64 3.5.2. Dalsze prace .............................................................................................. 64
  • 3. 4 UML. Inżynieria oprogramowania Rozdział 4 Proces projektowania ............................................................................. 67 4.1. Definicje terminów .................................................................................................. 67 4.1.1. Modele i języki modelowania .................................................................... 68 4.1.2. Proces i jakość ........................................................................................... 70 4.2. Proces projektowania .............................................................................................. 70 4.2.1. Zunifikowana metodologia? ....................................................................... 72 4.2.2. Procesy stosowane w UML ....................................................................... 73 4.3. System, projekt, model, diagram ............................................................................. 75 4.3.1. Wykorzystanie modeli ............................................................................... 76 Część II UML ..................................................................................... 79 Rozdział 5 Podstawy modeli klas ............................................................................. 81 5.1. Identyfikowanie obiektów i klas ............................................................................... 81 5.1.1. Co sprawia, że model klasy jest dobry? ..................................................... 81 5.1.2. Jak zbudować dobry model klasy ............................................................... 82 5.1.3. Jakim rodzajem rzeczy są klasy? ................................................................. 85 5.1.4. Obiekty ze świata rzeczywistego a ich reprezentacje w systemie ............ 85 5.2. Powiązania ............................................................................................................... 86 5.2.1. Wielokrotności .......................................................................................... 88 5.3. Atrybuty i operacje .................................................................................................. 89 5.3.1. Operacje .................................................................................................... 89 5.3.2. Atrybuty ..................................................................................................... 89 5.4. Generalizacja ............................................................................................................ 90 5.4.1. Korzystanie z języka polskiego w celu sprawdzenia, czy zachodzi generalizacja ...................................................................................................... 93 5.4.2. Implementacja generalizacji: dziedziczenie ................................................ 93 5.5. Model klasy podczas opracowywania ...................................................................... 94 5.6. Karty CRC ............................................................................................................... 95 5.6.1. Tworzenie kart CRC ................................................................................. 95 5.6.2. Używanie kart CRC podczas opracowywania projektu ............................ 96 5.6.3. Przykład karty CRC ................................................................................... 97 5.6.4. Refaktoring ................................................................................................ 98 Rozdział 6 Więcej na temat modeli klas ................................................................ 101 6.1. Więcej na temat powiązań ..................................................................................... 101 6.1.1. Agregacja i kompozycja ........................................................................... 101 6.1.2. Role ......................................................................................................... 103 6.1.3. Możliwości nawigacji ............................................................................... 104 6.1.4. Powiązania kwalifikowane ....................................................................... 105 6.1.5. Powiązania pochodne .............................................................................. 107 6.1.6. Ograniczenia ............................................................................................ 108 6.1.7. Klasy powiązań ........................................................................................ 110 6.2. Więcej na temat klas .............................................................................................. 112 6.2.1. Interfejsy .................................................................................................. 113 6.2.2. Klasy abstrakcyjne .................................................................................... 115 6.3. Klasy sparametryzowane ....................................................................................... 117 6.4. Zależność ............................................................................................................... 118 6.5. Komponenty i pakiety ............................................................................................ 119 6.6. Widoczność i ochrona ........................................................................................... 119
  • 4. Spis treści 5 Rozdział 7 Najważniejsze informacje na temat modeli przypadków użycia ........ 121 7.1. Szczegóły dotyczące aktorów ................................................................................ 123 7.2. Przypadki użycia w szczegółach ............................................................................. 125 7.3. Granice systemu .................................................................................................... 126 7.4. Używanie przypadków użycia ............................................................................... 127 7.4.1. Przypadki użycia podczas gromadzenia wymagań ................................... 127 7.4.2. Przypadki użycia podczas projektowania ................................................ 128 7.5. Możliwe problemy z przypadkami użycia .............................................................. 130 Rozdział 8 Więcej informacji na temat modeli przypadków użycia ..................... 133 8.1. Relacje między przypadkami użycia ....................................................................... 133 8.1.1. Przypadki użycia do wielokrotnego użycia: <<include>> .................... 134 8.1.2. Komponenty i przypadki użycia ............................................................... 136 8.1.3. Rozdzielanie wariantów zachowania: <<extend>> ............................. 138 8.2. Generalizacje ......................................................................................................... 139 8.3. Aktorzy i klasy ........................................................................................................ 140 8.3.1. Notacja: aktorzy jako klasy ...................................................................... 141 Rozdział 9 Najważniejsze informacje na temat diagramów interakcji .................. 143 9.1. Współprace ............................................................................................................ 144 9.2. Diagramy komunikacji ........................................................................................... 145 9.3. Diagramy sekwencji ............................................................................................... 147 9.4. Więcej zaawansowanych funkcji ............................................................................ 150 9.4.1. Komunikaty z obiektu do samego siebie ................................................. 150 9.4.2. Zwracane wartości .................................................................................. 151 9.4.3. Tworzenie i usuwanie obiektów ............................................................. 152 9.5. Diagramy interakcji służące innym celom .............................................................. 154 9.5.1. Pokazywanie, jak klasa udostępnia operację ............................................ 154 9.5.2. Opisywanie, jak działa wzorzec projektowy ........................................... 154 9.5.3. Opisywanie, jak można użyć komponentu .............................................. 154 Rozdział 10 Więcej informacji na temat diagramów interakcji ............................... 155 10.1. Więcej niż tylko proste sekwencje komunikatów ................................................ 155 10.1.1. Zachowania warunkowe ....................................................................... 155 10.1.2. Iteracja ................................................................................................... 157 10.2. Współbieżność ..................................................................................................... 158 10.2.1. Modelowanie ścieżek kontroli ............................................................... 159 Rozdział 11 Najważniejsze informacje na temat diagramów stanów i aktywności ......165 11.1. Diagramy stanów ................................................................................................. 166 11.1.1. Niespodziewane komunikaty ................................................................ 167 11.1.2. Poziom abstrakcji ................................................................................... 168 11.1.3. Stany, zmiany stanu i zdarzenia .............................................................. 168 11.1.4. Akcje ...................................................................................................... 169 11.1.5. Dozór .................................................................................................... 171 11.2. Diagramy aktywności ........................................................................................... 174 Rozdział 12 Więcej informacji na temat diagramów stanów ................................... 179 12.1. Inne rodzaje zdarzeń ........................................................................................... 179 12.2. Inne rodzaje akcji ................................................................................................. 180 12.3. Zaglądanie do wnętrza stanów ............................................................................ 181 12.4. Współbieżność w obrębie stanów ....................................................................... 183
  • 5. 6 UML. Inżynieria oprogramowania Rozdział 13 Diagramy architektury i wdrożeń ....................................................... 185 13.1. Diagramy struktury komponentów ..................................................................... 185 13.2. Model wdrożeń ................................................................................................... 187 13.2.1. Warstwa fizyczna ................................................................................... 187 13.2.2. Wdrażanie oprogramowania na sprzęcie ............................................... 187 Rozdział 14 Pakiety i modele ................................................................................... 191 14.1. Pakiety ................................................................................................................. 191 14.1.1. Kontrolowanie przestrzeni nazw ........................................................... 192 14.2. Modele ................................................................................................................. 194 Część III Studia przypadków ........................................................... 197 Rozdział 15 Administrowanie I4 .............................................................................. 199 15.1. Studium przypadku .............................................................................................. 199 15.1.1. Model klas .............................................................................................. 203 15.1.2. Dynamika ............................................................................................... 204 15.1.3. Diagramy stanów ................................................................................... 204 15.1.4. Diagramy aktywności ............................................................................. 204 15.2. Dyskusja ............................................................................................................... 205 Rozdział 16 Gry planszowe ...................................................................................... 207 16.1. Zakres i wstępna analiza ...................................................................................... 208 16.1.1. „Kółko i krzyżyk” ................................................................................... 208 16.1.2. Szachy .................................................................................................... 209 16.2. Interakcja ............................................................................................................. 213 16.3. Z powrotem do szkieletu aplikacji ....................................................................... 215 16.4. Stany .................................................................................................................... 217 Rozdział 17 Symulacja metodą kolejnych zdarzeń ................................................. 219 17.1. Wymagania ........................................................................................................... 219 17.1.1. Bardziej szczegółowy opis ..................................................................... 220 17.2. Zarys modelu klasy .............................................................................................. 222 17.3. Przypadki użycia .................................................................................................. 224 17.3.1. Podsumowanie przypadku użycia tworzenie modelu ............................ 224 17.3.2. Podsumowanie przypadku użycia obserwowanie zachowania .............. 225 17.3.3. Podsumowanie przypadku użycia zbieranie danych statystycznych ...... 225 17.3.4. Podsumowanie przypadku użycia uruchomienie modelu ...................... 225 17.4. Standardowy mechanizm symulacji opartej na procesie ...................................... 226 17.5. Powiązania i możliwości nawigacji ....................................................................... 227 17.6. Klasy w szczegółach ............................................................................................. 230 17.6.1. Klasa Zarzadca ....................................................................................... 230 17.6.2. Klasa JednostkaAktywna ........................................................................ 231 17.6.3. Klasa JednostkaPasywna ........................................................................ 233 17.6.4. Klasa Zasob ............................................................................................ 233 17.7. Klasa Raport ......................................................................................................... 236 17.8. Klasa DaneStatystyczne ....................................................................................... 236 17.8.1. Klasa Srednia .......................................................................................... 236 17.9. Budowanie kompletnego modelu symulacji ......................................................... 237 17.10. Ucztujący filozofowie ......................................................................................... 238
  • 6. Spis treści 7 Część IV W stronę praktyki ............................................................. 241 Rozdział 18 Wielokrotne używanie: komponenty i wzorce .................................... 243 18.1. Praktyczne informacje na temat wielokrotnego używania ................................... 243 18.1.1. Co może być użyte wielokrotnie i w jaki sposób? ................................. 244 18.1.2. Dlaczego używać powtórnie? ................................................................ 246 18.1.3. Dlaczego używanie wielokrotne jest trudne? ........................................ 247 18.1.4. Które komponenty w naturalny sposób nadają się do powtórnego użycia? ........................................................................ 248 18.1.5. A co z budowaniem własnych komponentów? ...................................... 249 18.1.6. Jaką różnicę sprawia zorientowanie obiektowe? ................................... 250 18.2. Wzorce projektowe ............................................................................................. 251 18.2.1. Przykład: Fasada .................................................................................... 254 18.2.2. Język UML i wzorce .............................................................................. 254 18.3. Szkielety ............................................................................................................... 256 Rozdział 19 Jakość produktu: weryfikowanie, walidacja i testowanie .................... 257 19.1. Omówienie jakości .............................................................................................. 257 19.2. W jaki sposób można osiągnąć wysoką jakość? .................................................... 258 19.2.1. Nastawienie na produkt ........................................................................ 258 19.2.2. Nastawienie na proces .......................................................................... 258 19.2.3. Dalsza lektura ........................................................................................ 259 19.3. Weryfikacja .......................................................................................................... 259 19.4. Walidacja .............................................................................................................. 260 19.4.1. Użyteczność .......................................................................................... 261 19.5. Testowanie .......................................................................................................... 262 19.5.1. Wybieranie i przeprowadzanie testów .................................................. 263 19.5.2. Dodatkowe problemy związane ze zorientowaniem obiektowym ....... 265 19.5.3. Dlaczego testowanie jest często przeprowadzane źle? ......................... 267 19.6. Przeglądy i inspekcje ............................................................................................ 268 19.6.1. Problemy związane z przeglądami FTR ................................................. 269 Rozdział 20 Jakość procesu: zarządzanie, zespoły i kontrola jakości ...................... 271 20.1. Zarządzanie ......................................................................................................... 271 20.1.1. Zarządzanie projektem .......................................................................... 272 20.1.2. Szacowanie projektu iteracyjnego ......................................................... 273 20.1.3. Zarządzanie projektowaniem opartym na komponentach .................... 274 20.1.4. Zarządzanie ludźmi ................................................................................ 275 20.2. Zespoły ................................................................................................................ 276 20.3. Przywództwo ...................................................................................................... 277 20.3.1. Zmiana procesu projektowania ............................................................. 278 20.4. Kontrola jakości ................................................................................................... 279 20.4.1. Kontrola jakości w procesach iteracyjnych ............................................ 281 20.4.2. Kompleksowe zarządzanie jakością ....................................................... 281 20.5. Dalsza lektura ...................................................................................................... 283 Skorowidz ............................................................................................ 289
  • 7. W tym rozdziale będziemy kontynuować udzielanie odpowiedzi na pytanie „jakie są dobre systemy?”, opisując zorientowany obiektowo paradygmat, który zawdzięcza swoją popular- ność częściowo temu, że wspiera on projektowanie dobrych systemów. Korzystanie jednak ze zorientowania obiektowego nie jest ani niezbędne, ani wystarczające do budowania do- brych systemów. Udzielimy odpowiedzi na następujące pytania: · Czym jest obiekt? · W jaki sposób porozumiewają się obiekty? · Jak jest zdefiniowany interfejs obiektu? · Co obiekty mają wspólnego z komponentami? Pod koniec omówimy dziedziczenie, polimorfizm i wiązanie dynamiczne. Treści zawarte w tym rozdziale odnoszą się do standardowych, nowoczesnych, opartych na klasach, obiektowo zorientowanych języków, takich jak Java, C# i C++. Większość roz- działu można odnieść też do języków Smalltalk, Eiffel, CLOS, Perl5 i innych obiektowo zo- rientowanych języków, z którymi można się spotkać, jednak dokładne ich porównywanie wykracza poza zakres tej książki. W niniejszym rozdziale są zawarte pytania na temat sposobów, w jaki języki programo- wania używane przez Czytelnika udostępniają omawiane obiektowo zorientowane funkcje. Jeśli Czytelnik zna już jakiś język programowania, powinien być w stanie udzielić odpowie- dzi na te pytania. Jeśli nie, warto aby przeczytał ten rozdział do końca, poznał podstawy wy- branego języka, a następnie powrócił do pytań w celu sprawdzenia swojej wiedzy na temat sposobów realizowania przez język zorientowania obiektowego. W pytaniach język progra- mowania używany przez Czytelnika będziemy w skrócie nazywać „Twoim językiem”. 2.1. Czym jest obiekt? Pojęciowo obiekt jest elementem, z którym można wchodzić w interakcje: można wysyłać do niego różne komunikaty, a on będzie reagował. Zachowania obiektu zależą od jego bie- żącego stanu wewnętrznego, który może ulegać zmianie, na przykład na skutek reakcji na
  • 8. 36 Część I ¨ Tło koncepcyjne otrzymany komunikat. Ważne jest, z którym obiektem zachodzi interakcja, i dlatego odnie- sienie do obiektu następuje za pośrednictwem jego nazwy. Obiekt ma zatem swoją tożsa- mość, która odróżnia go od wszystkich innych obiektów. Obiekt jest więc elementem posia- dającym swoje zachowanie, stan i tożsamość; w taki sposób charakteryzuje go Grady Booch [7]. Rozważymy te aspekty bardziej szczegółowo. Przedmiot Pojęcie przedmiotu jest bardziej interesujące, niż może się to początkowo wydawać. Obiekt nie jest tylko elementem systemu; reprezentuje on w systemie koncepcję przedmiotu. Obiekt może być na przykład reprezentacją prawdziwego przedmiotu, takiego jak zegar, tablica rozdzielcza albo klient. W rzeczywistości obiekty pojawiły się jawnie po raz pierwszy w ję- zyku Simula, w którym reprezentowały obiekty z realnego świata — te, które były symulo- wane. Oczywiście, aby systemy programistyczne ogólnego przeznaczenia mogły być two- rzone w oparciu o obiekty, obiekty nie muszą reprezentować fizycznie istniejących rzeczy. Do kwestii sposobu rozpoznawania obiektów powrócimy w rozdziale 5. P: Które z elementów następującej listy mogą być obiektami: młotek, kula, proces chemiczny, miłość, mgła, rzeka, złość, kot, szarość, szary kot? Stan Stan obiektu to wszystkie dane aktualnie w nim zapisane. Zwykle obiekt ma wiele nazwa- nych atrybutów (zmiennych obiektu, danych składowych), z których każdy ma określoną wartość. Niektóre z atrybutów mogą podlegać zmianom, to znaczy ich wartości mogą się zmie- niać. Obiekt reprezentujący na przykład klienta może mieć atrybut o nazwie adres, którego wartość ulegnie modyfikacji po przeprowadzce klienta. Inne atrybuty mogą być niezmienne, czyli stałe. Obiekt reprezentujący klienta może mieć atrybut, którego wartością będzie numer identyfikacyjny klienta, pozostający bez zmian przez cały czas trwania życia obiektu. W większo- ści współczesnych obiektowo zorientowanych języków programowania zestaw atrybutów przypisanych obiektowi nie może ulec zmianie podczas trwania życia tego obiektu, chociaż wartości atrybutów mogą się zmieniać. Zachowanie Zachowanie oznacza sposób, w jaki obiekt działa i reaguje w sensie zmian swojego stanu i przekazywania komunikatów. Obiekt rozumie niektóre komunikaty, co znaczy, że może je odbierać i zgodnie z nimi postępować. Zestaw komunikatów rozumianych przez obiekt, po- dobnie jak i zestaw atrybutów, jest zwykle stały. Sposób, w jaki obiekt reaguje na komunikat, może zależeć od aktualnych wartości jego atrybutów. Dzięki temu, nawet jeśli świat zewnętrzny nie ma zagwarantowanego bezpośredniego dostępu do atrybutów (a zazwyczaj właśnie tak jest), może pośrednio wpływać na ich wartości. W taki sposób wartości atrybutów decydują o stanie obiektu.
  • 9. Rozdział 2. ¨ Koncepcje obiektów 37 Tożsamość To zagadnienie może być trochę trudne. Idea jest taka, że obiekty są definiowane nie tylko przez bieżące wartości swoich atrybutów. Istnienie obiektu jest ciągłe. Wartości atrybutów mogą na przykład ulec zmianie, zwykle w odpowiedzi na komunikat, ale to będzie ciągle ten sam obiekt. Odniesienie do obiektu następuje zazwyczaj przez jego nazwę (wartość zmien- nej w programie-kliencie, na przykład Klient), ale nazwa obiektu to nie to samo, co sam obiekt, ponieważ obiektowi można nadać kilka różnych nazw (co może być zaskakujące dla programistów funkcyjnych, a niektórzy z nich twierdzą, że zorientowanie obiektowe można zrealizować w czysto funkcyjny sposób; jednak tego zagadnienia nie będziemy poruszać w niniejszej książce). 2.1.1. Przykład Rozważmy obiekt o nazwie mojZegar, który rozumie komunikaty podajCzas i ustawCzasNa(07:43), i w ogólności ustawCzasNa(nowyCzas) dla sensownych wartości parametru nowyCzas. Można to zrealizować, tworząc interfejs, który ogłosi, że przyjmuje komunikaty w postaci podajCzas i ustawCzasNa(nowyCzas: Czas), gdzie Czas jest typem1, którego elementy są sensownymi wartościami wspomnianego parametru nowyCzas. W jaki sposób zaimplementować taką funkcję? Świat zewnętrzny nie musi tego wiedzieć (informacja powinna być ukryta), ale być może obiekt ma atrybut Czas, którego wartość zwraca w odpowiedzi na komunikat podajCzas i który jest ustawiany na wartość nowyCzas po otrzymaniu przez obiekt komunikatu ustawCzasNa(nowyCzas). Jest też możliwe, że komuni- kat jest przekazywany do innego obiektu, znanego obiektowi mójZegar, i że to właśnie ten inny obiekt pracuje z komunikatami. 2.1.2. Komunikaty Z poprzedniego przykładu można wysnuć kilka wniosków na temat komunikatów. W skład komunikatu wchodzi słowo kluczowe nazywane selektorem. W przykładzie selektorami są podajCzas i ustawCzasNa. Komunikat może, ale nie musi, zawierać jeden lub więcej argu- mentów, które są wartościami przekazywanymi obiektowi, podobnie jak są przekazywane wartości w przypadku wywoływania funkcji. W powyższym przykładzie 07:43 jest argu- mentem, stanowiącym część komunikatu ustawCzasNa(07:43). Zazwyczaj dla danego selektora istnieje pojedyncza „prawidłowa” liczba argumentów, które powinny znajdować się w ko- munikacie rozpoczynającym się tym od tego selektora. Nie można oczekiwać, że obiekt mojZegar zrozumie komunikat ustawCzasNa bez żadnego argumentu lub w postaci ustawCzasNa(4, 12:30) i tak dalej. Akceptowalne wartości argumentów również są ustalane w interfejsie obiektu2. 1 Albo klasą; klasy omówimy w podrozdziale 2.1.4. 2 Podając klasę (patrz podrozdział 2.1.4) lub niekiedy tylko interfejs, do których powinien należeć obiekt przekazywany jako argument, lub jego typ, jeśli należy do typu podstawowego, takiego jak int albo bool — szczegóły zależą od konkretnego języka.
  • 10. 38 Część I ¨ Tło koncepcyjne P: Jaka jest składnia przesyłania komunikatów w Twoim języku? Warto zauważyć, że wartości, na przykład wartości atrybutów obiektu albo wartości ar- gumentów przesyłane w komunikatach, nie muszą należeć do typu podstawowego (takiego jak znaki, liczby całkowite i tak dalej. Rodzaje typów podstawowych zależą od konkretnego języka). Mogą to być również obiekty. P: Jakie są podstawowe typy w Twoim języku? Jedną z czynności, którą może wykonać obiekt w odpowiedzi na komunikat, jest wysła- nie komunikatu do innego obiektu. Jeśli tak ma się stać, to powinien on w jakiś sposób po- znać nazwę tego obiektu. Prawdopodobnie wartością jednego z jego atrybutów mógłby być na przykład obiekt, którego nazwa byłaby wykorzystywana podczas wysyłania komunikatu. P: Niech o będzie obiektem. Do jakich innych obiektów może wysyłać komunikaty obiekt o, oprócz obiektów, dla których może być wartością ich atrybutów? Warto zwrócić uwagę na to, że podczas wysyłania komunikatu do obiektu nie wiadomo, jaki kod zostanie w wyniku wykonany, gdyż informacja o tym jest hermetyzowana. Będzie to istotne pod koniec niniejszego rozdziału, kiedy omówimy wiązanie dynamiczne. 2.1.3. Interfejsy Publiczny interfejs definiuje komunikaty, które będą przyjmowanie przez obiekt niezależnie od miejsca ich pochodzenia. Zazwyczaj interfejs zapisuje selektory tych komunikatów, łącznie z niektórymi informacjami na temat wymaganych argumentów oraz wartości, która ewentu- alnie mogłaby być zwrócona. Jak wspomnieliśmy w rozdziale 1., korzystne byłoby, gdyby interfejs zawierał jakiś rodzaj specyfikacji dotyczącej skutków wysłania komunikatu do obiektu. Informacje tego typu są jednak podawane jedynie w komentarzach i dokumentacji. W więk- szości języków programowania atrybuty mogą być zawarte również w publicznym interfejsie obiektu. Umieszczenie atrybutu x w interfejsie jest równoważne z zadeklarowaniem, że fragment danych tego obiektu, x, może być widziany i zmieniany z zewnątrz. Zagadnienie do przedyskutowania 9 Jeśli korzystasz z języka, który nie zezwala na umieszczanie atrybutów w interfejsie publicz- nym, to w jaki sposób możesz osiągnąć taki sam efekt, używając komunikatów w celu uzyska- nia dostępu do danych? Czy są jakieś zalety stosowania takiego rozwiązania nawet w językach, które dopuszczają używanie atrybutów w interfejsie? A wady? Często jest tak, że nie każdy element systemu powinien mieć możliwość wysyłania do obiektu wszystkich komunikatów, które dany obiekt mógłby zrozumieć. Dlatego też obiekt może zwykle zrozumieć pewne komunikaty, które nie są częścią jego publicznego interfejsu. Jak już na przykład wyjaśniliśmy w rozdziale 1., struktura danych używana przez moduł po- winna być hermetyzowana, co jest zgodne z założeniem, że interfejs publiczny obiektu nie powinien zazwyczaj zawierać atrybutów. Obiekt zawsze może wysłać sam do siebie komunikat, który będzie w stanie zrozumieć. Wysyłanie komunikatów samemu sobie może wydawać się dziwne lub zbyt skomplikowane,
  • 11. Rozdział 2. ¨ Koncepcje obiektów 39 jednak powód takiego postępowanie wyjaśnimy w dalszej części niniejszego rozdziału przy okazji omawiania wiązania dynamicznego. Zazwyczaj obiekt ma przynajmniej dwa interfejsy: publiczny, z którego może korzystać dowolny element systemu, oraz obszerniejszy interfejs prywatny, z którego może korzystać zarówno sam obiekt, jak i inne uprzywilejowane elementy systemu. Czasami może być jesz- cze przydatny interfejs pośredni, udostępniający więcej możliwości niż interfejs publiczny, ale mniej niż interfejs prywatny. Czasami w danym kontekście jest potrzebna tylko część publicznego interfejsu obiektu, co powoduje wzrost liczby obiektów, które potencjalnie mo- głyby być używane zastępczo. Może być zatem przydatne zapisywanie naprawdę potrzeb- nych funkcji w mniejszym interfejsie, zamiast umieszczania ich w całym interfejsie publicz- nym obiektu. Z tego względu obiekt może mieć (lub realizować) więcej niż tylko jeden interfejs. I odwrotnie — wiele różnych obiektów może realizować taki sam interfejs. W tej książce określenie „interfejs” zawsze będzie oznaczać interfejs publiczny. Jeśli bę- dzie inaczej, zostanie to wyraźnie określone. 2.1.4. Klasy Do tej pory omawialiśmy obiekty, jak gdyby każdy z nich był osobno definiowany, każdy miał swój własny interfejs i sposób sprawdzania, który inny obiekt może wysyłać do niego komu- nikaty. Oczywiście taki sposób tworzenia typowego systemu nie jest rozsądny, ponieważ obiekty mają ze sobą wiele wspólnego. Jeśli przedsiębiorstwo ma 10 000 klientów i potrzeb- ne jest zbudowanie systemu z obiektami reprezentującymi każdą z tych osób, to wszystkie obiekty reprezentujące klientów będą posiadały wiele wspólnych cech. Ich zachowania po- winny być spójne, aby programiści i osoby opiekujące się systemem mogły je zrozumieć. Potrzebna będzie klasa obiektów reprezentująca klientów. Klasa opisuje zestaw obiektów pełniących w systemie takie same funkcje. W opartych na klasach, zorientowanych obiektowo językach programowania każdy obiekt należy do klasy, a klasa obiektu determinuje jego interfejs3. Obiekt mojZegar może należeć do klasy Zegar, której interfejs publiczny określa, że każdy obiekt klasy Zegar będzie udostępniał operację ustawCzasNa(nowyCzas: Czas). Znaczy to, że będzie rozumiał komunikaty z selekto- rem ustawCzasNa i pojedynczym argumentem, który jest obiektem klasy (typu) Czas. W rzeczywistości nawet sposób, w jaki obiekt reaguje na komunikaty, jest zdeterminowany przez jego klasę, łącznie z wartościami atrybutów obiektu. Metoda jest określonym frag- mentem kodu, w którym są zaimplementowane operacje. W interfejsie obiektu widoczne jest jedynie to, że obiekt wykonuje operację; metoda, w której jest zaimplementowana funk- cja, jest ukryta. Podobnie zestaw atrybutów posiadanych przez obiekt jest zdeterminowany przez klasę, chociaż oczywiście wartości przyjmowane przez atrybuty obiektu nie są określone w klasie i mogą ulegać zmianom. Być może na przykład obiekty należące do klasy Zegar mają pry- watny atrybut o nazwie czas. Jeśli taki sam komunikat zostanie wysłany do dwóch obiektów tej samej klasy, w obu przypadkach zostanie wykonana ta sama metoda, chociaż efekt jej wykonania może być znacząco różny, gdy atrybuty obiektów będą mieć inne wartości. 3 W rzeczywistości obiekt może należeć do więcej niż jednej klasy, z których klasa najbardziej szczególna decyduje o jego interfejsie.
  • 12. 40 Część I ¨ Tło koncepcyjne Podsumowując, obiekty tej samej klasy mają takie same interfejsy. Publiczne i prywatne interfejsy klasy Zegar mogłyby być opisane następująco: - czas : Czas + podajCzas() : Czas + ustawCzasNa (nowyCzas: Czas) W skład interfejsu publicznego wchodzą wiersze oznaczone znakiem +, a w skład inter- fejsu prywatnego także wiersz ze znakiem –. P: W jaki sposób definiuje się klasę, taką jak Zegar w Twoim języku? Czy interfejs i implementacja są definiowane oddzielnie? Jak jest nazywany interfejs publiczny, a jak prywatny (może właśnie: pu- bliczny i prywatny)? Czy są może jeszcze jakieś inne możliwości? Co one oznaczają? Proces tworzenia nowego obiektu należącego do klasy Zegar jest nazywany tworzeniem egzemplarza klasy Zegar, a powstały w wyniku obiekt egzemplarzem klasy Zegar. To właśnie dlatego zmienne, których wartości należą do obiektu i które mogą ulegać zmianie w czasie życia obiektu, są nazywane zmiennymi egzemplarza. Utworzenie obiektu oznacza utworze- nie nowego egzemplarza klasy posiadającego własny stan i tożsamość, które będą pozosta- wać spójne w obrębie wszystkich obiektów klasy. Proces tworzenia zazwyczaj obejmuje także nadanie wartości atrybutom. Wartości mogą zostać określone w zleceniu utworzenia lub na- dane przez klasę obiektu jako domyślne wartości początkowe. W językach takich jak C++ i Java klasa odgrywa bezpośrednią rolę podczas tworzenia nowych obiektów — w rzeczy- wistości wykonuje całą pracę, nie ograniczając się jedynie do roli szablonu. Dlatego klasa może być często uważana za fabrykę obiektów. P: W jaki sposób jest tworzony w Twoim języku nowy obiekt danej klasy? W wielu językach klasy mogą zachowywać się, jak gdyby same były obiektami. Klasa Klient mogłaby mieć atrybut liczbaEgzemplarzy, który byłby liczbą całkowitą zwiększaną za każdym razem, gdy tworzony jest nowy obiekt typu Klient. Takie rozwiązanie konsekwentnie przyjęto w języku Smalltalk, a w językach C++ i Java można odnaleźć jego ślady. W Smalltalk na przykład nowy obiekt typu Klient zostałby utworzony przez wysłanie komunikatu (przy- kładowo new) do klasy Klient. Reakcją klasy byłoby utworzenie nowego obiektu i zwrócenie go do metody wywołującej. Zagadnienie do przedyskutowania 10 Zastanów się, co by było, gdyby konsekwentnie stosować takie rozwiązanie. Stwierdziliśmy już, że każdy obiekt ma swoją klasę. Jeśli więc klasa k zostanie uznana za obiekt, to co będzie klasą dla k? I co będzie klasą tej klasy? P: Czy Twój język posiada takie funkcje? Jakie dokładnie? Dygresja: po co istnieją klasy? Dlaczego nie wystarczą obiekty, które posiadają wymagany stan, zachowanie i tożsamość? Klasy w zorientowanych obiektowo językach programowania służą dwóm celom. Po pierw- sze, są wygodnym sposobem na opisanie zbioru (klasy) obiektów posiadających takie same właściwości. W językach zorientowanych obiektowo klasy są używane przede wszystkim dla
  • 13. Rozdział 2. ¨ Koncepcje obiektów 41 wygody. Nie ma na przykład potrzeby przechowywania kopii kodu opisującego zachowania obiektu w każdym obiekcie, chociaż można wyobrażać sobie, że w każdym obiekcie znajduje się jego kod. Zamiast tego programista może jednorazowo napisać definicję klasy, a kompi- lator utworzy pojedynczą reprezentację klasy i pozwoli obiektom na uzyskiwanie dostępu do reprezentacji klasy w celu pobierania potrzebnego kodu. Należy pamiętać, że taka wygoda wcale nie jest czymś błahym. Zasadniczym celem jest przecież uczynienie systemów łatwiejszymi do zrozumienia, aby ich projektowanie i pielę- gnacja były jak najbardziej tanie, łatwe i niezawodne. Sprawienie, że podobne obiekty dzielą ten sam projekt oraz implementację, jest ważnym krokiem w tym kierunku. W taki sposób przejawia się zasada4, która jest tak ważna w inżynierii oprogramowania — nie tylko w odniesieniu do kodu — że ją wykrzyczymy: PISZ TYLKO RAZ! Oznacza to, że jeśli dwie kopie jakiegoś produktu inżynierii oprogramowania, na przy- kład fragment kodu, fragment diagramu czy fragment tekstu pochodzący z dokumentu, po- winny być spójne, to nie powinny istnieć w dwóch egzemplarzach. Za każdym razem, gdy ta sama informacja jest zapisywana w więcej niż jednym miejscu, nie tylko marnuje się wysiłek na powtórne robienie tego samego, zamiast zrobienia czegoś nowego, ale też naraża się na kłopoty związane z pielęgnacją, ponieważ dwie wersje nigdy nie będą zsynchronizowane bez żadnych starań. Sztuka stosowania tej zasady polega na stwierdzeniu, czy dwie kopie infor- macji są rzeczywiście takie same, czy też zdarzyło się, że potencjalnie różne informacje są akurat w danym momencie identyczne. W tym drugim przypadku skopiowanie i wklejenie odpowiedniego fragmentu jest jak najbardziej prawidłowe. W pierwszym przypadku niechęć do powielania informacji w więcej niż jednym miejscu jest zaletą. Należy tak postąpić wy- łącznie wtedy, gdy istnieją ku temu dobre powody. Zagadnienie do przedyskutowania 11 Czy ta zasada oznacza, że powielanie danych w rozproszonych bazach danych jest złym pomy- słem? Dlaczego? Zauważmy, że istnieją inne sposoby na tworzenie wielu podobnych obiektów, pisząc ich kod tylko raz. Można na przykład zdefiniować prototyp obiektu, a następnie definiować ko- lejne obiekty jako będące „takie jak tamten, ale z następującymi różnicami”. W takim przy- padku również wystarczyłoby przechowywanie tylko jednej kopii kodu. Mniej więcej w taki sposób postępuje się, programując w eleganckim, opartym na prototypach, języku Self. Ję- zyki programowania oparte na klasach zdominowały jednak obecnie zorientowanie obiekto- we i zapewne tak już pozostanie. Po drugie, w większości zorientowanych obiektowo językach programowania klasy są używane w taki sam sposób, jak w wielu innych językach są wykorzystywane typy — w celu określenia, jakie wartości są dopuszczalne w określonych kontekstach, umożliwiając tym samym kompilatorowi (oraz, co jest równie ważne, osobie czytającej kod) zrozumienie in- tencji programisty i sprawdzenie, czy pewne rodzaje błędów nie wystąpią w programie. 4 Na którą kładzie nacisk zwłaszcza Kent Beck.
  • 14. 42 Część I ¨ Tło koncepcyjne Wiele osób uważa, że klasy i typy oznaczają tę samą rzecz. Rzeczywiście, jest to wygod- ne i często nie prowadzi do żadnych nieporozumień, niemniej taki sposób myślenia jest błędny. Należy pamiętać, że klasa definiuje nie tylko to, jakie komunikaty zrozumie obiekt, co tak naprawdę wystarcza, aby sprawdzać, czy jest on akceptowalny w danym kontekście. Określa również czynności obiektu wykonywane w odpowiedzi na komunikaty. 2.2. Jaki to ma związek z celami poprzedniego rozdziału? Szukamy modułów, najlepiej nadających się do wielokrotnego używania wymiennych mo- dułów, które mogłyby być dobrymi komponentami. Gdzie można je znaleźć w systemie obiektowo zorientowanym? Poszczególne obiekty mogłyby być uważane za moduły, ale nie byłyby one dobre. W syste- mie znajduje się bowiem zazwyczaj wiele różnych modułów, które są blisko spokrewnione pojęciowo. Gdyby każdy obiekt był uważany za odrębny moduł, to albo istniałyby wprowa- dzające w błąd nieścisłości między pojęciowo powiązanymi modułami, albo potrzeba za- chowania spójności powodowałaby tworzenie silnych skojarzeń. Klasy powinny być słabo skojarzonymi, wysoce spójnymi modułami. Można zatem mieć nadzieję (być może na próżno, co przedyskutujemy w następnym podrozdziale), że będzie realne uzyskanie korzyści przedstawionych w rozdziale 1., a mianowicie niskiego kosztu i krótkiego czasu opracowywania, łatwości pielęgnacji i wysokiej niezawodności. Zalety te nie są cechą charakterystyczną zorientowania obiektowego, chociaż jest ono obecnie najle- piej poznaną ścieżką do nich prowadzącą. Kolejna uznana zaleta zorientowania obiektowego należy do innej kategorii. Naturalne jest postrzeganie otaczającego świata w kategoriach obiektów. Warto przypomnieć sobie, że głównym wymogiem stawianym przed dobrym systemem jest spełnianie oczekiwań użyt- kowników i że prawidłowe uchwycenie tych oczekiwań oraz śledzenie ich zmian należą do najtrudniejszych zadań związanych z tworzeniem systemów. Ważne jest, aby model systemu (model domeny problemu i zachodzących procesów) był zgodny z modelem użytkownika. Wydaje się, że obiekty z domeny problemu rzadziej ulegają zmianom, a same zmiany są mniej dramatyczne, niż jest to w przypadku działania systemu wymaganego przez użytkow- nika. Jeśli zatem system jest zbudowany w oparciu o te obiekty, to zmiany w systemie praw- dopodobnie będą mniej rewolucyjne, niż gdyby system powstał w oparciu o bardziej ulotne aspekty funkcjonalne. Podsumowując, należy mieć nadzieję, że system będzie zgodny z mo- delem świata użytkownika, dzięki czemu będzie możliwe: · łatwiejsze i dokładniejsze uchwycenie wymagań; · lepsze nadążanie za zmianami wymagań użytkownika; · tworzenie systemów, które prowadzą interakcje w bardziej naturalny sposób. Łatwiejsze jest zaimplementowanie na przykład interfejsu użytkownika, który pozwala użytkowni- kowi na interakcję z plikiem, zegarem albo drukarką jako całością (co ma sens z punktu widzenia użytkownika, ponieważ te przedmioty są podobne do obiektów z rzeczywistego świata), jeśli są one spójnymi obiektami także z punktu widzenia systemu. Z tego powo- du interfejsy użytkownika były jednymi z pierwszych głównych obszarów, w których zo- rientowanie obiektowe stało się popularne.
  • 15. Rozdział 2. ¨ Koncepcje obiektów 43 Należy jednak zaznaczyć, że te argumenty nie są bezdyskusyjne. W niektórych przypad- kach, takich jak na przykład systemy obsługi zamówień, podejście zorientowane obiektowo wydaje się bardzo naturalne, w innych (na przykład kompilatory) taka argumentacja jest mniej przekonująca. W każdym jednak przypadku gdy zorientowanie obiektowe osiąga swój cel, zwykle nie jest tak z powodu charakterystycznych cech zorientowania obiektowego. Jest tak, ponieważ: · podstawami zorientowania obiektowego są modularność, hermetyzacja i abstrakcja, · zorientowane obiektowo języki programowania sprawiają, że osiąganie celów staje się względnie proste, ponieważ istnieje uzasadnione prawdopodobieństwo, że oczywisty sposób zrobienia czegoś jest również dobrym sposobem na zrobienie tego. Zorientowanie obiektowe jest religią: to ludzie zostają zorientowani w stronę obiektów. Zagadnienie do przedyskutowania 12 Istnienie jakich konsekwencji, dobrych i złych, może sugerować stwierdzenie, że „zorientowanie obiektowe jest religią”? 2.2.1. Co wspólnego z komponentami mają obiekty? Euforia towarzysząca zorientowaniu obiektowemu mogłaby czasami sugerować, że każda klasa jest automatycznie komponentem, nadającym się do wielokrotnego używania. Oczywi- ście nie jest to prawdą. W rozdziale 1. omówiliśmy powody, dla których możliwość wielo- krotnego używania komponentu nie jest po prostu faktem o komponencie jako takim, ale zależy od kontekstu projektu i proponowanego sposobu jego powtórnego użycia. Innym ważnym czynnikiem jest to, że struktura klasy może być zbyt szczegółowa, aby mogła być efektywnie wielokrotnie wykorzystywana. Aby na przykład można było wielokrotnie korzystać z poje- dynczej klasy w sposób praktyczny i łatwy, należałoby pisać programy w tym samym języku i sięgać do zgodnej architektury. Nie zawsze jest to niewykonalne. Istnieją powszechnie używa- ne biblioteki klas, które odniosły sukces, i ich biblioteki mogą być uważane za komponenty do wielokrotnego używania. Często jednak określenie komponentu odnosi się do grupy po- wiązanych klas. Im więcej wysiłku włoży się w dostosowanie komponentu do kontekstu, tym więcej korzyści powinien przynieść dany komponent, jeśli ten wysiłek ma być opłacalny. Celowo rozmyliśmy kwestię tego, czy komponenty są zbudowane z obiektów, czy z klas; nie dokonaliśmy jeszcze wyraźnego rozróżnienia między typem a egzemplarzem. Powód jest taki, że wziąwszy pod uwagę szeroką definicję komponentu, oba te przypadki mogą być prawdziwe. Klasa albo zbiór klas może być komponentem na poziomie kodu źródłowego. Kontekst, w którym jest używany komponent, korzysta z udogodnień danego języka w celu tworzenia obiektów klasy. W innych przypadkach komponent może realizować dostęp do określonego, gotowego obiektu jakiejś klasy, realizując również dostęp do funkcji związa- nych z tworzeniem kolejnych obiektów tej klasy. Należy pamiętać, że sam komponent ma dobrze zdefiniowany interfejs. Jeśli komponent składa się z obiektów i (lub) klas, to interfejs komponentu zwykle nie pozwala na dostęp do wszystkiego, co znajduje się w interfejsach obiektu i wewnątrz klas. Komponent sam stara się być hermetyzowaną abstrakcją i prawdo- podobnie jest właściwe, że ukrywa część lub całość swojej wewnętrznej struktury — na przykład czy i jak składa się z obiektów i klas.
  • 16. 44 Część I ¨ Tło koncepcyjne Zagadnienie do przedyskutowania 13 Skorzystaj z sieci Web i innych dostępnych zasobów w celu odszukania popularnych kompo- nentów architektury, takich jak JavaBeans, CORBA albo .NET. Co to jest architektura? Jaką wewnętrzną strukturę może mieć komponent i jak jest zdefiniowany interfejs komponentu? 2.3. Dziedziczenie Do tej pory omówiliśmy jedynie pojęciowe podstawy tego, co czasami jest nazywane pro- jektem opartym na obiektach. W tym podrozdziale weźmiemy pod uwagę dziedziczenie, które będąc pojęciowym elementem leżącym u podstaw obiektowo zorientowanego pro- jektu, jest niczym lukier dla pączka. Jak wskazuje metafora, pojęcie to jest uważane za atrak- cyjne i ważne, ale tak naprawdę jest mniej treściwe niż to, co do tej pory opisaliśmy w książce. W niniejszym podrozdziale rozpatrzymy dziedziczenie jako techniczną właściwość języ- ków zorientowanych obiektowo, użyteczną (w ograniczonym zakresie) podczas niskopozio- mowego wielokrotnego wykorzystywania. W rozdziale 5. omówimy korzystanie z dziedzi- czenia w modelowaniu. Poniższy przykład został zaczerpnięty ze studium przypadku z rozdziału 15. W rozważa- nym systemie istnieje klasa, której obiekty reprezentują wykładowców, oraz klasa, której obiekty reprezentują opiekunów studiów. Opiekun studiów jest kimś w rodzaju wykładowcy, a dokładniej jest wykładowcą, który oprócz pełnienia zwykłych obowiązków jest odpowiedzialny także za nadzorowanie postępów poszczególnych studentów. W systemie OpiekunStudiow powinien rozumieć takie same komunikaty jak Wykladowca i dodatkowo powinien być w sta- nie odpowiedzieć na komunikat podopieczni, zwracając zbiór obiektów typu Student. Załóżmy, że klasa Wykladowca została już zaimplementowana i teraz należy zaprojektować klasę OpiekunStudiow. Załóżmy też (wyłącznie dla skonkretyzowania przykładu), że używany jest język podobny do C++, w którym interfejs klasy i jego implementacja są przechowywane w oddzielnych plikach. Co jest potrzebne do zaimplementowania nowej klasy tak szybko jak to tylko możliwe? Można skopiować i wkleić kod definiujący interfejs klasy Wykladowca do nowego pliku z interfejsem i dodać u dołu opis dodatkowego komunikatu. Podobnie można skopiować do pliku z implementacją nowej klasy kod, w którym zaimplementowano reakcję obiektów klasy Wykladowca na komunikat, a następnie dokonać niezbędnych zmian. Jak już jednak wspomnieliśmy, wielokrotne używanie kodu przez jego kopiowanie ma wady. Naj- ważniejsza z nich jest taka, że w przypadku konieczności dokonania zmian w zduplikowa- nym kodzie (na przykład wykryto błąd w programie) należy wprowadzić zmiany w dwóch miejscach zamiast w jednym. Jest to uciążliwe i prawdopodobnie doprowadzi do błędów. Zamiast tego obiektowo zorientowane języki programowania dopuszczają utworzenie nowej klasy OpiekunStudiow na podstawie istniejącej klasy Wykladowca. Wystarczy zadekla- rować, że klasa OpiekunStudiow jest podklasą klasy Wykladowca, a następnie dopisać jedynie to, co ma związek z dodatkowymi atrybutami lub operacjami klasy OpiekunStudiow 5. Co więcej, ponieważ w zorientowaniu obiektowym wiedza na temat kodu, jaki zostanie wykonany przez obiekt po tym, gdy otrzyma on komunikat, jest hermetyzowana, istnieje 5 W niektórych językach, a zwłaszcza w języku Eiffel, można w podklasach usuwać atrybuty i operacje nadklas, jednak takie postępowanie nie jest zazwyczaj uważane za dobry zwyczaj.
  • 17. Rozdział 2. ¨ Koncepcje obiektów 45 możliwość, aby w klasie OpiekunStudiow zaimplementować w odpowiedzi na komunikat inne zachowania niż te, które są zaimplementowane w klasie Wykladowca. Oznacza to, że w klasie OpiekunStudiow można przesłonić niektóre z metod klasy Wykladowca. Oprócz dziedziczenia metod po klasie Wykladowca, klasa OpiekunStudiow może zawierać nową metodę implemen- tującą taką samą operację, dla której klasa Wykladowca miała już metodę. Kiedy obiekt klasy OpiekunStudiow otrzyma komunikat z żądaniem wykonania operacji, wywołana metoda bę- dzie wyspecjalizowaną wersją metody udostępnianej przez klasę OpiekunStudiow. Podklasa jest rozszerzoną, wyspecjalizowaną wersją swojej nadklasy. Zawiera operacje oraz atrybuty nadklasy i możliwie jeszcze inne, dodatkowe elementy. P: W jaki sposób jest definiowana podklasa w Twoim języku? Czy klasa może być bezpośrednią podklasą kilku klas (dziedziczenie wielokrotne), czy nie? Terminologia Mówi się, że: · klasa OpiekunStudiow dziedziczy po klasie Wykladowca, · klasa OpiekunStudiow jest podklasą (lub klasą pochodną) klasy Wykladowca, · klasa OpiekunStudiow jest specjalizacją klasy Wykladowca, · klasa OpiekunStudiow jest bardziej wyspecjalizowana niż klasa Wykladowca, · klasa Wykladowca jest nadklasą (lub klasą bazową) klasy OpiekunStudiow, · klasa Wykladowca jest generalizacją klasy OpiekunStudiow. Wszystkie powyższe określenia mają niemal to samo znaczenie. Często pojęcia podklasy i nad- klasy są używane przy opisie konkretnych relacji pomiędzy pojęciami reprezentowanymi w klasach. Zazwyczaj zachodzi między nimi związek. Związki pojęciowe jednak niekoniecz- nie muszą być widoczne w strukturze klasy. Przeciwnie, niektórzy programiści używają dziedziczenia w strukturze klasy w przypadkach, w których nie ma pojęciowego związku dziedziczenia pomiędzy klasami (nie zawsze można polecać takie rozwiązanie. Może być ono wygodne w krótszym okresie czasu, jednak niemal zawsze spowoduje nieporozumienia po upływie dłuższego czasu). Czy można powiedzieć, że klasa OpiekunStudiow należy do klasy Wykladowca? Można, jeśli myśli się o klasach jak o zbiorach obiektów. Gdy mówi się o obiektach klasy Wykladowca, z pewnością chce się uwzględnić także obiekty klasy OpiekunStudiow — po prostu ciągłe pi- sanie o „klasie Wykladowca i dowolnych podklasach” jest zbyt niewygodne. Co więcej, zasa- da, że obiekt podklasy powinien być zastępowalny obiektem nadklasy, jest fundamentalna. Za każdym razem więc, gdy będzie mowa o obiektach należących do klasy, będzie to ozna- czać także obiekty należące do podklas. Z drugiej strony bardzo wygodna byłaby możliwość mówienia o „klasie tego obiektu”, jak gdyby należał on wyłącznie do jednej klasy. Przez określenie „klasa” obiektu będziemy więc rozumieć najbardziej wyspecjalizowaną klasę, do której należy dany obiekt. Oznacza to, że twierdzenie, iż zachowanie obiektu jest określone przez jego klasę, pozostaje prawdziwe.
  • 18. 46 Część I ¨ Tło koncepcyjne 2.4. Polimorfizm i wiązanie dynamiczne Te dwa określenia są często w środowisku zorientowanym obiektowo używane zamiennie. W rzeczywistości oznaczają one całkiem różne koncepcje. Ogólnie w językach programowa- nia jedno pojęcie może istnieć bez drugiego, chociaż w językach zorientowanych obiektowo są one spokrewnione i mają związek z dziedziczeniem. Przede wszystkim należy zauważyć, że sam fakt, iż jedną klasę można definiować na podstawie innej klasy, korzystając ponownie z jej kodu, nie musi mieć żadnego wpływu na to, w jaki sposób kod-klient będzie traktował obiekty tych klas. Możliwy byłby język, w którym dziedziczenie byłoby tylko sposobem na wielokrotne wykorzystywanie kodu. Można by zdefi- niować klasę OpiekunStudiow na podstawie klasy Wykladowca, lecz cały kod klienta (a także kompilator) musiałby dokładnie znać klasę każdego obiektu, z którym by wchodził w inte- rakcję. Technicznie rzecz biorąc oznacza to, że można by utworzyć język z takim rodzajem dziedziczenia, w którym występowałyby wyłącznie typy monomorficzne. Języki zoriento- wane obiektowo radzą sobie jednak lepiej. Polimorfizm Określenie to, wywodzące się z języka greckiego, oznacza mający wiele kształtów. W języ- kach obiektowo zorientowanych odnosi się do sytuacji, w której obiekt może należeć do jednego z kilku typów. W obiektowo zorientowanej sytuacji zmienna polimorficzna mogłaby odnosić się (w różnych przypadkach) do obiektów kilku różnych klas. Funkcja polimorficzna może pobierać argumenty różnych typów. Powiedzieliśmy już, że obiekt podklasy powinien być stosowany w każdej sytuacji, w której mógłby zostać użyty obiekt nadklasy. Powinno to oznaczać w szczególności, że obiekt podklasy powinien być akceptowany jako wartość zmiennej, jeśli jest akceptowany jako obiekt klasy bazowej. Innymi słowy, w obiektowo zorientowanym ję- zyku każda zmienna jest polimorficzna — przynajmniej w tym ograniczonym znaczeniu. Podobnie, jeśli jakaś funkcja (na przykład metoda) może pobierać argument klasy B, powin- na być w stanie pobrać argument dowolnej klasy C, która jest podklasą klasy B; tak więc również każda funkcja jest polimorficzna w tym ograniczonym sensie. Funkcja, która na przykład oczekuje jako argumentu obiektu Wykladowca, nie powinna zgłosić błędu, jeśli jako argument otrzyma obiekt OpiekunStudiow. Zagadnienie do przedyskutowania 14 Czy w Twoim języku (w C albo w typologicznie funkcjonalnym języku programowania) jest re- alizowany polimorfizm? Czy na polimorfizm są nałożone większe, czy mniejsze ograniczenia niż w polimorfizmie obiektowo zorientowanym, który został tu opisany? Czy jest on przydatny? W jaki sposób? Polimorfizm pozwala na znaczne ograniczenie duplikacji kodu. Swoje prawdziwe możli- wości pokazuje jednak w powiązaniu z związaniem dynamicznym.
  • 19. Rozdział 2. ¨ Koncepcje obiektów 47 Wiązanie dynamiczne Słowo „wiązanie” w określeniu wiązanie dynamiczne (albo też późne wiązanie — oba te określenia są używane zamiennie) odnosi się do procesu identyfikowania kodu, który powi- nien zostać wykonany na skutek otrzymanego komunikatu. Zrozumienie tego będzie łatwiej- sze po rozważeniu kilku przykładów. Załóżmy, że interfejs obiektu Wykladowca zawiera funkcję mozeWykonac (obowiazek: Obowia- zek), która jako argument pobiera obiekt reprezentujący obowiązek administracyjny, a w wyniku zwraca wartość logiczną, której wartością jest prawda, jeśli wykładowca może wypełnić dany obowiązek. Przyjmijmy też założenie (trochę nierealne), że OpiekunStudiow jest w stanie zrobić wszystko, a tym samym że zawsze powinien zwracać wartość prawda. Znaczy to, że podklasa OpiekunStudiow przeimplementowała (przesłoniła) funkcję mozeWykonac, prawdopodobnie za- stępując skomplikowany kod sprawdzający informacje na temat zainteresowań lub doświad- czenia wykładowcy prostym kodem, który zawsze zwraca wartość prawda. Załóżmy teraz, że wykladowcy są zmienną odnoszącą się do zbioru obiektów klasy Wykladowca. W tym zbiorze mogą być oczywiście zawarte także obiekty typu OpiekunStudiow, ponieważ jeśli do zmiennej wykladowcy można dodawać obiekty klasy Wykladowca, to można do niej do- dawać również obiekty klasy OpiekunStudiow. Przypuśćmy, że klient-zadanie próbujące znaleźć kogoś do zorganizowania seminarium wykonuje kod w rodzaju poniższego pseudokodu: dla kazdy o w wykladowca o.mozeWykonac(organizacjaSeminarium) Warto zwrócić uwagę na zapis z kropką w wierszu z wysyłanym komunikatem, który jest wspólny dla wielu języków programowania. Wyrażenie o.mozeWykonac(organizacjaSeminarium) oznacza wysłanie komunikatu mozeWykonac(organizacjaSeminarium)do obiektu o. Może ono być również używane w celu reprezentowania wartości, którą obiekt o zwróci klientowi po przetworzeniu komunikatu. Przyglądając się kodowi można przypuszczać, że obiekt o należy do klasy Wykladowca. Warto przypomnieć ideę, że w obiekcie hermetyzowane jest jego zachowanie, a klasy wprowadzo- no jedynie z potrzeby zwięzłości zapisu. Jeśli obiekt o znajduje się wyłącznie w klasie Wykla- dowca, to powinien zostać wykonany kod obiektu Wykladowca dla komunikatu mozeWykonac, czyli jego zachowanie w reakcji na komunikat. Co powinno się stać, gdy pętla dla osiągnie obiekt o, który w rzeczywistości należy do klasy OpiekunStudiow? Oczywiście w takim przy- padku powinien wykonać się kod klasy OpiekunStudiow (gdyby obiekt o rzeczywiście zabierał ze sobą swój kod, działoby się tak automatycznie; fakt, że tak nie jest, wynika po prostu z optymalizacji). Znaczy to, że ten sam fragment składni powinien spowodować wykonanie dwóch różnych fragmentów kodu w różnych sytuacjach. Wysyłany komunikat jest dyna- micznie wiązany z odpowiednim kodem6. Na koniec rozważmy inny bardzo prosty przykład wiązania dynamicznego, który ilu- struje także przypadek wysyłania przez obiekt komunikatu do samego siebie. 6 W najprostszy sposób można to zrobić, sprawdzając typ obiektu podczas wykonywania się programu. W nowoczesnych językach jednak większość pracy bierze na siebie kompilator, co pozwala na większą wydajność.
  • 20. 48 Część I ¨ Tło koncepcyjne Przypuśćmy, że interfejs klasy Wykladowca zawiera komunikat mozliwosci; w odpowiedzi na niego obiekt klasy Wykladowca powinien zwrócić zbiór czynności, które wykładowca może wykonać. Być może kod klasy Wykladowca jest zaimplementowany w podobny sposób jak w poniższym pseudokodzie (w którym instrukcja sam.mozeWykonac(obowiazek) oznacza wy- nik zwracany po wysłaniu do tego obiektu komunikatu z selektorem mozeWykonac i argu- mentem obowiazek): coMogeWykonac := pustyZbior dla kazdy obowiazek w listaWszystkichObowiazkow jesli (sam.mozeWykonac(obowiazek)) wtedy dodaj obowiazek do coMogeWykonac inaczej zrob nic zwroc coMogeWykonac Oczywiście tę operację można przesłonić w nowej klasie OpiekunStudiow, tylko po co tak robić (wydajność raczej nie będzie ważna)? Załóżmy, że kod pozostanie na swoim miejscu, dzięki czemu zostanie bez zmian odziedziczony przez obiekty klasy OpiekunStudiow. Przy- pomnijmy jednak, że w klasie OpiekunStudiow została przesłonięta operacja mozeWykonac. Co się stanie, gdy obiekt klasy OpiekunStudiow otrzyma komunikat mozliwosci? Zostanie wyko- nany powyższy kod — w czym nie ma nic szczególnego — co spowoduje wysłanie komuni- katu mozeWykonac do siebie samego. Jest to obiekt klasy OpiekunStudiow, tak więc po otrzy- maniu komunikatu mozeWykonac zostanie wykonana wyspecjalizowana wersja kodu zdefiniowana w klasie OpiekunStudiow. W przypadku używania czystego języka obiektowo zorientowanego takie zachowanie szybko powinno stać się drugą naturą. Ostrożność należy zachować w przypadku języka C++: takie zachowanie wykazują tylko metody wirtualne. Niektóre osoby, łącznie ze mną7, są głęboko przekonane, że zaczynając programowanie obiektowo zorientowane w języku C++ powin- no się początkowo tworzyć wyłącznie metody wirtualne8, a dopiero potem nauczyć się two- rzenia metod niewirtualnych. PODSUMOWANIE Ten rozdział był krótkim wprowadzeniem do zorientowania obiektowego. Opisaliśmy, czym jest obiekt i jak między obiektami są przesyłane komunikaty. Pokazaliśmy, że obiekty w systemie można z pożytkiem podzielić na klasy, zamiast rozpatrywać je indywidualnie, oraz rozpo- częliśmy rozpatrywanie powiązań między obiektami i komponentami. Omówiliśmy, jak za pomocą dziedziczenia klasa może zostać zdefiniowana z wykorzystaniem definicji innej kla- sy. Na koniec przedstawiliśmy inną cechę dziedziczenia w językach zorientowanych obiek- towo — możliwość udostępniania polimorfizmu i wiązania dynamicznego. W następnym rozdziale dokonamy wprowadzenia do głównego tematu tej książki — Ujed- noliconego Języka Modelowania, który może być używany do określania specyfikacji i pro- jektowania systemów korzystających z przewagi, jaką zapewnia zorientowanie obiektowe. 7 Stevens. 8 Łącznie (zwłaszcza) z destruktorami, ale nigdy z konstruktorami. Dlaczego?