Zacznijmy od czegoś prostego. Według słownika abstrakcja to:

“a general concept formed by extracting common features from specific examples”

“the action of removing something from something else”

“the situation in which a subject is very general and not based on real situations”

Wiemy zatem, że abstrakcja to pojęcie ogólne, którego opracowanie może polegać na wyodrębnianiu pewnych właściwości z jakiegoś obiektu. Abstrakcja może też polegać na usuwaniu ‘czegoś z czegoś’. Weźmy pod uwagę słowo abstrakt, które oznacza streszczenie jakiejś publikacji. W streszczeniu lektury szkolnej ujęci zostaną kluczowi bohaterowie oraz wydarzenia, a te mniej istotne zostaną ukryte.

Posłużmy się jeszcze innym przykładem. Trochę kultury nigdy nikomu nie zaszkodziło.

Widziałeś na pewno kiedyś obraz, który przedstawiał, ogólnie mówiąc, abstrakcję. Myśląc o nurcie jakim jest abstrakcjonizm wyobrażam sobie figury geometryczne, nieregularne, kolorowe kształty i trudną do zrozumienia symbolikę obrazu. Można domniemywać, że w nurcie tym ważna jest niejednoznaczność i subiektywizm odbioru. Jednak w sztuce, w przeciwieństwie do programowania autor może pozwolić sobie, aby być rozumianym na wiele sposobów. Artysta malując obraz abstrakcyjny może usunąć (i jest to zgodne z definicją słownikową) na tyle dużo atrybutów, właściwości przedmiotu, że staje się on albo nie do rozpoznania przez obserwatora albo nabiera wieloznaczności. Każdy może interpretować taki obraz na swój sposób. Malarz tworząc obraz uogólnia i upraszcza. Podobne zabiegi będziemy stosować w programowaniu.

Abstrakcja obiektu

Wyobraź sobie, że tworzysz aplikację pt.: “Sklep internetowy” dla firmy ProsteSłowa z o.o. Jak to każdy sklep internetowy, ten również obsługuje masę zamówień. Zamówienie jest słowem, które krąży po wszystkich działach firmy ProsteSłowa z o.o., na przykład w księgowości oraz w magazynie. Jednak patrząc z perspektywy każdego z działów firmy, to słowo może być rozumiane w inny sposób. Słowo zamówienie w codziennym życiu zawodowym księgowej ma inną charakterystykę niż pracownika magazynu. Księgową będzie interesować m.in.: cena zamówienia, aby móc wystawić fakturę, a pracownika magazynu będzie interesował np.: status zamówienia.

Jak w takim razie stworzyć model takiego zamówienia? Intuicja podpowiada, że stworzenie jednego, wspólnego modelu nie jest najlepszym pomysłem. Skończyłoby się to bardzo źle. Zmiana dotycząca kodu magazynu, mogłaby spowodować że popsuliśmy działające wcześniej funkcje księgowości. No dramat. Łamiemy wówczas mnóstwo zasad dobrego programowania. Gdyby kilka osób popatrzyło na taki model mogłyby one zinterpretować go na kilka różnych sposobów. Bylibyśmy jak malarz abstrakcyjny, który swoje barwne uniesienia przedstawił w, delikatnie mówiąc, fikuśny sposób, przy czym dla mnie obraz przedstawiałby kotka na parapecie, a dla Ciebie byłby to nie kotek, na nie parapecie.

Skoro nie jeden model, to może kilka modeli o tej samej nazwie i podzielenie naszej aplikacji na, w miarę możliwości, jak najmocniej niezależne moduły. Mówiąc moduł mam na myśli jednostkę kodu, która realizuje jakieś funkcje biznesowe. Niech to będzie u nas pakiet znany z języka Java. Zatem w pakiecie accounting (księgowość) w modelu Order niektóre atrybuty zamówienia, takie jak np.: status zamówienia zostaną ukryte, tzn.: po prostu ich tam nie będzie, a niektóre wyodrębnione jako te istotne np.: cena zamówienia. Podobnie stanie się w pakiecie warehouse (magazyn) gdzie status zamówienia będzie obecny, a cena zostanie ukryta, ponieważ w trakcie analizy projektu okazało się, że pracownik magazynu w żaden sposób nie wchodzi w interakcję z ceną zamówienia. To co będzie łączyć te zamówienia, to unikalny identyfikator np.: numer zamówienia, który pozwoli na realizację pełnego procesu.

Podsumowując, opracowanie abstrakcji zamówienie polegało u nas na:

  • identyfikacji pojęcia zamówienie
  • wyodrębnieniu tego, co z punktu widzenia każdego z działów jest istotne do realizacji ich pracy
  • ukryciu nieistotnych atrybutów modelu zamówienie z punktu widzenia każdego z działów

Dzięki temu, nasz pierwotny pomysł dużego, wspólnego modelu zamówienie odszedł w niepamięć poprzez podzielenie go na kilka odrębnych abstrakcji.

Abstrakcja procesu

opisie przebiegu procesu obliczania podatku przez księgową wyłuskaliśmy istotne informacje na temat procesu rozkładając go tym samym na czynniki pierwsze. Można wysnuć wniosek, że opracowanie abstrakcji pozwala rozbić złożony problem biznesowy na mniejsze części.

Krótkie przypomnienie. Pierwsza abstrakcja, którą wyodrębniliśmy i ubraliśmy w interfejs Javowy to pobranie danych klienta (ClientDataRetrieval). W realnym przebiegu tego procesu, bez użycia komputera, księgowa zapewne otworzyłaby teczkę i wyjęła fakturę z danymi klienta takimi jak.: NIP, nazwa firmy oraz kwota, na którą klient wystawił fakturę czy rachunek.

Jeśli Ty, jako programista rozmawiałbyś z księgową na temat aplikacji do obliczania podatku dochodowego, to nie będziecie mieli problemu, aby porozumieć się w kwestii pobrania danych klienta. Takie zdarzenie występuje niezaprzeczalnie i w tej kwestii świetnie się rozumiecie. Co prawda Twoja księgowa nie będzie wiedziała czy dane klienta pobrane zostały z relacyjnej bazy danych czy z jakiegoś zewnętrznego systemu. W końcu ona naciśnie tylko przycisk Pobierz dane klienta John Doe. Grunt, że jesteście w stanie się porozumieć dzięki identyfikacji abstrakcyjnego terminu o jasno brzmiącej nazwie. Na przykład stwierdzenie zaciągnąłem selectem informacje o customerze niekoniecznie będzie zrozumiałe dla księgowej. Księgowa może i zaciąga pośrednio selectem dane przy pomocy przycisku, ale w jej języku nie jest to customer tylko klient, a o żadnym słowie select w życiu nie słyszała. Po co więc utrudniać sobie i innym życie. Warto mówić wspólnym językiem za pomocą umownych terminów. Oczywiście sztuką jest je zidentyfikować.

Podobnie jest z abstrakcją obliczanie podatku dochodowego (interface TaxCalculator). Zarówno Ty – programista, Twój nietechniczny przełożony czy księgowa, niezależnie od kraju pochodzenia, przynajmniej słyszeli termin obliczenie podatku dochodowego. Czyli wyodrębniliśmy ponownie ważny aspekt procesu biznesowego, pomijając w tej chwili jakiekolwiek szczegóły dotyczące implementacji. W realnym przebiegu procesu, jak już księgowa otworzyłaby teczkę i wyjęła fakturę z wszystkimi niezbędnymi danymi, chwyciłaby następnie za kalkulator, kawałek papieru i długopis. Detalem natomiast jest to, co by na tej kartce zostało napisane.

Przykłady przykładziki

Klasy (abstrakcyjne i nieabstrakcyjne) oraz interfejsy są elementami języka programowania, które pozwalają upraszczać problem biznesowy poprzez dzielenie go na mniejsze części. To już pi razy oko wiemy. Spróbujmy jeszcze kilka, może nieco bardziej namacalnych przykładów,

Abstrakcja opracowana za pomocą nieabstrakcyjnej klasy

Stworzyliśmy klasę OrderService w pakiecie com.order. Klasa ta stanowi punkt dostępowy do procesu realizacji zamówienia w naszym systemie. To znaczy, że klasy z innych modułów (np.: z innego pakietu) mogą skomunikować się z pakietem com.order wyłącznie poprzez OrderService, będącą publicznym API. Stworzyłeś tym samym pewną abstrakcję poprzez wyodrębnienie istotnych, dostępnych na zewnątrz modułu zachowań. To co nie jest istotne w API (z punktu widzenia innych modułów) jest ukryte oraz niedostępne dla klienta.

Abstrakcja opracowana za pomocą abstrakcyjnej klasy

Jeśli stworzysz abstrakcyjną klasę zamówienie (abstract Order) i stanie się ona klasą bazową dla klas pochodnych np.: VipOrder oraz NonVipOrder to w tym przypadku abstract Order stanowi uogólnienie bytu jakim jest zamówienie. Wyodrębnimy w niej wspólne atrybuty i zachowania dla klas pochodnych. Natomiast klasy VipOrder oraz NonVipOrder będą kolejnym poziomem abstrakcji. Go deeper and deeper.

Abstrakcja opracowana za pomocą interfejsu

Tworząc interfejs Javowy TaxCalculator tworzysz uogólniony byt z wyodrębnionymi zadaniami, które będą następnie realizowane przez klasy implementujące ten interfejs. Za pomocą interfejsu mówimy jedynie co a nie jak możemy zrobić. Abstrakcja będzie dobra, jeśli nie będziemy musieli czytać implementacji, żeby dowiedzieć się co możemy osiągnąć wywołując metodę interfejsu. Nie chcemy być jak malarz, który pozostawia nam dowolną liczbę możliwości interpretacji swojej pracy. Owszem, tak jak on ukrywamy jedne aspekty i wyodrębniamy inne, pamiętając jednak przy tym, że nasze intencje oraz słownictwo użyte w kodzie powinny być dla wszystkich zrozumiałe i, w miarę możliwości, jak najlepiej opisywać swoje przeznaczenie.

Gdy skończyłem ten wpis trafiłem na bardzo fajny artykuł. Warto przeczytać. Autor również skupił się na semantyce i również odnosi się do abstrakcji w sztuce. Porusza też kilka innych ciekawych tematów.

Leave a Reply

Your email address will not be published. Required fields are marked *