Konstrukcje na diagramach klas, których NIE należy używać
Na diagramach klas UML są dostępne m. in. dwie konstrukcje których uzywanie - moim zdaniem - powinno być zabronione. Chodzi o: dziedziczenie z częścią wspólną (ang. overlapping) oraz dziedziczenie wieloaspektowe (ang. multi-aspect). Dziedziczenie z częścią wspólną polega na tym, że zbiory definiowane przez podklasy nie są rozłączne (mają część wspólną). W przykładzie z rys. 1. niektórzy kontrahenci mogą być jednocześnie dostawcami, jak i klientami. Natomiast dziedziczenie wieloaspektowe polega na określeniu kilku hierarchii dziedziczenia, każdej wg innego kryterium, tak jak na rys. 2.

Rys. 1. Dziedziczenie z częścią wspólną
Rys. 2. Dziedziczenie wieloaspektowe
Efekt stosowania tych konstrukcji jest taki, że niektóre obiekty mają przypisane kilka klas jednocześnie (np. firma będąca dostawcą i klientem jest obiektem klasy Dostawca i jednocześnie klasy Klient; leasingowany samochód osobowy jest obiektem klasy SamochódOsobowy i jednocześnie obiektem klasy SamochódWLeasingu). Taka sytuacja nie jest zrozumiała z punktu widzenia analizy i projektowania obiektowego. Nie da się jej także zaimplementować w obiektowych językach programowania, gdzie obiekt nie może mieć przypisanych kilku klas.
Na szczęście takie konstrukcje można łatwo zastąpić znacznie prostszymi modelami, opartymi na kompozycji. Na rys. 3. i 4. są pokazane zmodyfikowane diagramy dla naszych dwóch przykładów. Opierają się one na spostrzeżeniu, że dostawca i klient nie są specjalizacjami kontrahenta, lecz rolami granymi przez kontrahenta. Analogicznie, samochód osobowy, samochód ciężarowy, samochód - własność oraz samochód w leasingu nie są specjalizacjami samochodu, lecz jego cechami. Zauważmy, że diagramy z rys. 3. i 4. wcale nie są mniej czytelne od diagramów z rys. 1. i 2. Wręcz przeciwnie - jasno i czytelnie pokazują zasadnicze cechy obu modelowanych sytuacji.
Rys. 3. Równoważny model nie wykorzystujący dziedziczenia z częścią wspólną
Rys. 4. Równoważny model nie wykorzystujący dziedziczenia wieloaspektowego
W zasadzie każdy diagram klas można narysować korzystając wyłącznie z następujących konstrukcji:
-
klas, atrybutów i metod,
-
relacji między klasami (w tym agregacji i kompozycji),
-
zwykłego dziedziczenia (określanego w specyfikacji UML jako "disjoint").
Takie ograniczenie się do podstawowych konstrukcji powoduje, że model staje się prosty i czytelny. Taki model można bezpośrednio (bez dodatkowych przekształceń) zaimplementować w obiektowych językach programowania. Natomiast modele z rys. 1. i 2. nie nadają się do implementacji, ponieważ dziedziczenie z częścią wspólną i dziedziczenie wieloaspektowe nie są wspierane przez obiektowe języki programowania.
Ograniczenie się do podstawowego podzbioru notacji ma jeszcze jedną zaletę: zwiększa szanse, że wszyscy udziałowcy projektu (programiści, inni analitycy, a nawet klient) zrozumieją nasze diagramy. Użycie skomplikowanych i rzadko używanych elementów notacji oznacza ryzyko, że nasz model będzie tylko "sztuką dla sztuki" i zwyczajnie nie zostanie zrozumiany (lub zostanie zrozumiany niezgodnie z naszymi intencjami).