Archiwa tagu: klasa

Klasy i obiekty – trochę teorii

Rodzaje relacji pomiędzy obiektami:

  • powiązanie – luźna relacja, mówiąca tylko o współdziałaniu obiektów
  • agregacja – silna forma powiązania obiektów.
  • skojarzenie
  • generalizacja – służy do wyrażania podobieństwa pomiędzy obiektami
  • dziedziczenie – doskonale znane z programowania. Pozwala elementom bardziej szczegółowym wykorzystywać strukturę obiektów bardziej ogólnych.

Własności obiektów:

  • atrybut – struktura danych, która opisuje jakąś cechę obiektu (np. string backgroundColor = '#FF00FF';).
    Przyjmowane wartości są ściśle określone poprzez typ danych (np. integer).
    Jeżeli mamy sytuację, że wartością miałby być inny obiekt, to wtedy wartością atrybutu nie jest ten obiekt, lecz wskazanie na obiekt (powiązanie). Dobrze widać to na przykładzie języka C++. Atrybutami są typy proste (int, float itd.), natomiast chcąc mieć w klasie bardziej rozbudowany obiekt, umieszczamy de facto wskaźnik do niego.
  • usługa – (abstrakcyjne pojęcie) zachowanie obiektu, funkcjonalność jaką musi dostarczyć obiekt (powiedziałabym, że interfejs definiuje nam usługi, a klasa będzie je implementować w metodach). Jest opisywana przez sygnaturę – ilość raz typy parametrów, zwracany wynik.
  • metoda – implementacja usługi. Wiązanie metod do usług może być realizowane na różne sposoby (np. dziedzicząca klasa może nadpisywać metodę zdefiniowaną w klasie wyżej itp.)
  • stan – stan obiektu w danej chwili, zapisane w atrybutach wartości, które wpływają  na sposób zachowania się obiektu. Zmienia się na skutek wywołania metod (np. ustawienie atrybutu albo wykonanie na nim jakiś obliczeń) lub samoistnej zmiany.
  • komunikat – zlecenie wykonania usługi + parametry (czyli de facto wywołanie metody).

UML

UML to pojęcie, z którym zetknął się pewnie każdy student informatyki;) Rozwinięcie skrótu to czyli Unified Modeling Language – „zunifikowany język modelowania”. Co więcej – język graficzny, służący do przedstawiania w przystępnej formie projektu systemów informatycznych. W UML występują bowiem głównie różnorakie schematy i bloczki.

Wyróżniamy m.in następujące rodzaje diagramów UML:

  • diagram przypadków użycia – służy do przedstawienia wymagań. Występują aktorzy (np. administrator, redaktor, czytelnik…) oraz akcje, jakie mogą wykonywać (dodawanie artykułu, usuwanie komentarza…)
  • diagram klas – ukazuje strukturę: wykorzystywane w projekcie klasy wraz z ich atrybutami, metodami i relacjami jakie tworzą z innymi klasami. Podczas projektowania diagramu klas należy uważać, aby nie pokusić się o drogę na skróty i „przerzutowanie” struktury… bazy danych. To zadanie należy raczej do ORM (bibliotek/frameworków do mapowania obiektowo-relacyjnego, np. Hibernate, Doctrine)! Jedna z technik projektowania mówi o przeczytaniu wymagań projektu i podkreśleniu rzeczowników – najprawdopodobniej każdy z nich powinien zostać osobną klasą (więc stworzymy ogólny interfejs użytkownik, z którego dziedziczyć będzie redaktor i czytelnik. Tymczasem w bazie danych wszyscy użytkownicy mogą zostać umieszczeni w jednej tabeli users, gdzie jedynym rozróżnieniem między nimi będą np. prawa dostępu lub flagi określające kto jest kim).
  • diagram sekwencji – ukazuje zachowania obiektów. Występuje aktor, jego akcje oraz obiekty, na których owe akcje będą wykonywane, np. czytelnik, dodanie komentarza, komentowany artykuł.
  • diagram komunikacji – ukazuje komunikację między obiektami. Podobny do diagramu sekwencji, lecz inaczej przedstawiony.

Definicje – projektowanie obiektowe

Przy okazji sprzątania biurka ze szpargałów ze studiów, wpadły mi w ręce całkiem zgrabne wykłady na temat projektowania obiektowego (czyli – planowania jak wykonać i zaprogramować projekt, np. za pomocą diagramów UML). Może przyda się – jako szybka powtórka pojęć, które każdy programista „obiektowy” znać powinien.

(Podejście momentami niestety dość suche i akademickie, wpis chciałabym więc sukcesywnie uzupełniać o bardziej „ludzkie” definicje.)

Interfejs – klasa bez atrybutów, nie opisująca implementacji metod, posiadająca wyłącznie usługi i operacje abstrakcyjne.

Abstrakcja – pomijanie nieistotnych szczegółów w celu ukazania tych informacji, które są w danym przypadku istotne. W połączeniu ze skalą (czyli „taką organizacją, aby dowolnie duża wartość była przejrzysta dla obserwatora”) można sobie wyobrazić to jako schemat blokowy (lub UML) – ogólny gdy jest „oddalony”, a w miarę zwiększania skali – bardziej szczegółowy. Zgodnie z zasadą skali, logicznie powiązane klasy powinny znajdywać się w jednym pakiecie.

Hermetyzacja – ukrywanie szczegółów implementacji za interfejsami, aby dana „struktura” (klasa, moduł, pakiet, biblioteka…) zamykała w sobie możliwie jedną funkcjonalność.
Interfejsy powinny ukrywać jak najwięcej szczegółów implementacyjnych (czyli lepiej, aby posiadały jedną metodę typu „rób to”, niż kilka metod, konfiguracji, kilka metod wykonania danej czynności – programista implementujący taki interfejs w swojej klasie poczuje się zdezorientowany).
Dane oraz operujące na nich algorytmy powinno zostać umieszczone w jednym obiekcie.
Wartości atrybutów powinny zostać udostępniane tylko przez usługi (gettery, settery albo bardziej rozbudowane metody), dzięki czemu można go z zewnątrz pobrać, a niekoniecznie można go modyfikować.
Hermetyzacja powoduje duże rozdrobnienie struktury, ponieważ każda klasa zajmuje się jedną rzeczą.

Czytaj dalej