niedziela, 11 stycznia 2009

Dystans

W życiu trzeba mieć dystans - to podstawa. W programowaniu też - szczególnie do tego co mówi klient:)

Dalsze me dywagacje pierwej podeprę takim oto małym przykładzikiem z frontu (projektu w jakim do niedawna jeszcze brałem udział):

Emulując analityka radośnie przeprowadzałem analizę małego modułu do zarządzania drukami ścisłego zarachowania. Z analizy biznesowej wynikało jakoby:

W jednym dziale panie pracują z DPDANPB_1 (Drukiem Potrzebnym Do Arcy Nudnego Procesu Biznesowego 1); druki przychodzą z drukarni do działu w paczkach po parę tysięcy sztuk; użytkownicy dzielą paczki na bloczki po kilkadziesiąt sztuk.

W innym dziale panie pracują z DPDANPB_2, które to przychodzą z drukarni również w paczkach - tym razem po kilkaset sztuk. Użytkownicy w tym dziale nie dzielą sobie druczków na bloczki - po prostu radośnie wykonują swą jakże smutną pracę używając druczków DPDANPB_2.

W obu przypadkach system musi ogólnie rzecz ujmując nadzorować druczki (zliczać, kontrolować kto komu ile po co wydał itp) z uwagi na to iż są one jak już wspomniałem "ściśle zarachowane" - cóż za małostkowość swoją szosą;)


Zatem na tak zwany rzut tak zwanego oka widać, że mamy do czynienia z taką oto strukturą (wybaczcie ASCII art, ale w niedzielny poranek nie chce mi się odpalać kombajnu - do UMLa):

Paczka1 ------* Bloczek1 -------* DPDANPB_1
Paczka2 ------* DPDANPB_2

Wszystko jasne i oczywiste, odpalamy Eclipse, tworzymy 5 klasek, adnotujemy @Entity, radośnie klepiemy atrybuty i gotowe.

Za parę miesięcy ktoś będzie się martwić o zmiany bo na przykład: nowa kierowniczka działu 2 nie będzie chciała być gorsza i wprowadzi u siebie również dwustopniowy podział. Następnego dnia kierowniczka działu 1 chcąc pozostać lepszą (od tej ździry z dwójki) wprowadzi trójstopniowy podział. Albo - o zgrozo - będąc w fazie cyklu gdy w jej ustroju dominują męskie hormony wprowadzi 8 stopniowy podział - BO TAK!!!

Możemy oczywiście założyć, że nie zależy nam na przygotowaniu giętkiego systemu otwartego na nowe wymagania, np: atak kosmitów lub co gorsza nierokendrolowe dni kierowniczek. Nie chcemy wydawać kasy na dobry projekt, odwalamy chałę, wdrażamy metodykę RÓB! Takie założenie biznesowe jest w sumie fajne, bo zwalnia mózg developerów od myślenia a co za tym idzie chroni go przed śmiertelnym przegrzaniem - hehe krótkowzroczni biedacy nie widzą, że do czasu...

Jak się jednak okazało (zresztą nie tylko w tym przypadku), że chwila zastanowienia nic nie kosztuje i jest inwestycją pozwalającą zaoszczędzić niemałe pieniądze już w niedalekiej przyszłości.

Wystarczy się nieco wnikliwej przyjrzeć zachowaniu klienta - dokonać rzetelnej analizy. Użytkownicy z działu 1 wiedzeni wrodzonym instynktem niemal intuicyjnie podsuwają nam rozwiązanie: stary dobry model "plików w katalogu".

Uogólniając mamy po prostu jakieś dokumenty pogrupowane w drzewiaste struktury katalogów: katalog zawiera inne katalogi oraz dokumenty:

Katalog -------* Dokument
 |      *
 |----|

Jeszcze 2 kwestie z perspektywy projektanta OO:

W razie potrzeby konkretne druczki (DPDANPB_1, DPDANPB_2,...) mogą dziedziczyć po dokumencie jeżeli chcemy dodać im specyficzną odpowiedzialność biznesową - anemicznemu modelowi mówimy stanowcze NIE. Dziedziczenie jest akurat w tym wypadku usprawiedliwione ponieważ dokumenty będą traktowane polimorficzne na przykład w logice nadzorowania - zatem jesteśmy zgodni z zasadą podstawienia Liskov - możesz używać dziedziczenia tylko wówczas gdy spodziewasz się polimorfizmu.
A co do technicznych aspektów persystencji naszych dokumentów polecam artykuł Dawida Walczaka: JPA - modelowanie dziedziczenia.


Co natomiast ze szczególnymi typami katalogów (węzłów drzewa)? Tu akurat dziedziczenie niezbyt mi się podoba - nie wiem dlaczego.
Zamiast dziedziczenia zalecałbym przede wszystkim podpinanie pod nie strategii.
Czyli nasz katalog mógłby mieć np metodę validate(), która to deleguje proces walidacji do konkretnego walidatora - oczywiście stojącego za interfejsem strategii.

Oczywiście w razie gdy pewien rodzaj katalogu ma specyficzną odpowiedzialność, której nie mają inne to nie możemy pozwolić na "brudzenie" klasy katalogu jakąś ezoteryczną metodą. Drugim (nie wykluczającym rozwiązaniem) pozwalającym na "dodanie" nowych odpowiedzialności do klasy Katalogu jest wzorzec wizytatora. Czyli w tym przypadku katalog miałby metodę pozwolSieZwintestygowac(Visitor v).

//=============================
To był bardzo szczególny przykład - natomiast ogólna idea jest taka: klient zazwyczaj mówi do nas obiektami (instancjami) biznesowymi. Rola analizy jest między innymi taka aby odkryć klasy tych obiektów. W naszym przykładzie klient posługiwał się pojęciami paczka1, paczka2, bloczek. Naiwna analiza przekłada je na klasy. Natomiast w rzeczywistości są to pewne szczególne obiekty klasy Katalog.

W sumie to nie bez powodu w UML istnieje diagram obiektów.


Jeszcze bardziej ogólną analizę problemów analizy przedstawił Michał Bartyzel w swym poście "Metaprogramy w tworzeniu oprogramowania" (wytłuszczenia są moje):

[Klienci] Opisują to jednak w postaci procesów, natomiast analityk widzi system jako strukturę. Podążając za procesem łatwiej dokonywać w nim zmian. Z kolei zmiany wprowadzane w strukturze wymagają przeanalizowania całej koncepcji od nowa. Podczas zbierania wymagań klient często zastanawia się nad pożądanym sposobem pracy. Próbuje różnych alternatywnych przebiegów tego samego procesu i oczekuje od analityka pomocy w wyborze najlepszego rozwiązania. Jeśli analityk nie podąża w procesie za klientem, lecz percypuje system jako strukturę, to ma nie lada kłopot. Alternatywne ścieżki procesu klienta zazwyczaj mają istotny wpływ na domniemaną strukturę systemu i/lub implementację.


Polecam lekturę całego posta - jest arcy ciekawy, bo zanurzony w kontekście Metaprogramów myślenia, o których wspomniałem już 2 krotnie:
- The Unforgiven
- Twoja rola w zespole

Polecam też oczywiście całego bloga Michała Bartyzela - jest zanurzony w różnych innych ciekawych kontekstach.

Brak komentarzy: