For every complex problem there is a simple solution – that won’t work.
Złożoność współczesnych systemów informatycznych wymaga ich budowy zgodnie ze strukturami architektonicznymi, które są utrzymywalne i skalowalne. Prezentowana praca proponuje taką konstrukcję architektoniczną nazwaną PCMEF. PCMEF jest hierarchiczną strukturą oprogramowania minimalizującą zależności między obiektami. Przy pomocy narzędzia DQ (Design Quantifier), zależności te mogą być automatycznie obliczane w istniejącym oprogramowaniu w Javie i prezentowane w diagramach klas UML
1. Złożoność oprogramowania#
Systemy informatyczne są złożone. W przeszłości oprogramowanie było monolityczne i proceduralne. Typowy program w Cobolu był monolitem z podprogramami wywoływanymi w razie potrzeby. Logika wykonawcza takiego programu była sekwencyjna i przewidywalna. Złożoność takiego systemu była konsekwencją jego rozmiaru wyrażonego w liniach kodowych.Współczesne obiektowe oprogramowanie jest rozproszone, a jego logika wykonawcza jest losowa i nieprzewidywalna. Rozmiar takiego systemu jest sumą rozmiarów jego elementów składowych – komponentów (components). Komponenty są projektowane tak, żeby ich rozmiary były małe, i tak, żeby można było zarządzać nimi indywidualnie. W rezultacie, rozmiar nie jest głównym czynnikiem złożoności nowoczesnych systemów.
Złożoność nowoczesnego oprogramowania jest w „drutach” – w połączeniach i ścieżkach komunikacyjnych między komponentami. Połączenia między rozproszonymi komponentami tworzą zależności, które są trudne do zrozumienia i kontroli. Trudności są spotęgowane przez fakt że wiele komponentów pochodzi z zewnątrz (z bibliotek, itp.) i nie podlega kontroli zespołu projektowo-programowego.
Rysunek 1. przedstawia system obiektowy, w którym obiekty (klasy) w różnych pakietach (komponentach) komunikują się w sposób nieograniczony. Tworzy to sieć komunikujących się obiektów. Złożoność wewnątrz pakietów jest wciąż kontrolowalna ze względu na ograniczone rozmiary pakietów. Natomiast zależności powodowane przez ścieżki komunikacyjne między pakietami mają tendencje wzrostu wykładniczego wraz z dodawaniem do systemu nowych pakietów.
Sytuacja, w której obiekty w jednym pakiecie mogą komunikować się z dowolnymi obiektami w innych pakietach tworzy zależności potencjalne między wszystkimi obiektami w systemie. Oznacza to, że jakakolwiek modyfikacja obiektu może miećskutek rozrywający (ripple effect) na pozostałe obiekty w systemie. Takie systemy określa się mianem nieutrzymywalnych i nieskalowalnych (unsupportable, unscalable).
Rysunek 2. pokazuje redukcję złożoności systemu poprzez proste ustanowienie pojedynczych połączeń między pakietami. Takie rozwiązanie wymaga zdefiniowania interfejsu (interface) dla każdego pakietu i wymuszenie komunikacji z użyciem tych interfejsów (interfejs jest rozumiany w znaczeniu Java interface albo w znaczeniu klasy dominującej (dominant class)). Mimo wprowadzenia trzech dodatkowych obiektów (trzech interfejsów), złożoność systemu na rysunku 2. jest mniejsza niż na rysunku 1.
2. Architektura PCMEF#
Rysunek 2. nie stanowi jeszcze rozwiązania problemu. Rozwiazanie wymaga zastąpienia sieci obiektów przez hierarchię obiektów. Wszystkie utrzymywalne i skalowalne systemy, w tym systemy naturalne, przyjmują formę hierarchiczną.Architektoniczny project systemu jest odpowiedzialny za dostarczenie struktury hierarchicznej z utrzymywalnymi i skalowalnymi zależnościami między obiektami.Obiekt A zależy od obiektu B jeżeli zmiany w obiekcie B wymuszają zmiany w obiekcie A. Zależności te nie mogą przerywać zapór przeciwogniowych (dependency firewalls). W szczególności, zależności nie mogą łączyć obiektów z nie sąsiadujących poziomów (non–neighboring layers) w hierarchii i nie mogą tworzyć cykli zależności (dependency cycles). Zależności są klasyfikowane w cztery grupy: (1) zależności klas (class dependencies), (2) zależności wiadomości (message dependencies), (3) zależności zdarzeń (event dependencies), i (4) zależności dziedziczenia (inheritance dependencies).
Rysunek 3. przedstawia konstrukcję (framework) pięcio-poziomowego projektu architektonicznego PCMEF (Presentation – Control – Mediator – Entity – Foundation) [MACI2001; MACI2003; MACI2004]. Architektura PCMEF jest zbliżona do innych popularnych konstrukcji architektonicznych, takich jak J2EE [ALUR 2003].
PCMEF jest zorganizowany w pionową strukturę hierarchiczną. Każdy z pięciu poziomów jest pakietem, który może zawierać inne pakiety. Zależności między pakietami są jednokierunkowe w dół (klasy w poziomie presentation zależą od klas w poziomie control, ale nie odwrotnie, itd.). Zależności w górę mają charakter wolnych związków (loose coupling) realizowanych przy pomocy interfejsów, przetwarzania zdarzeń (event processing), pakietów znajomości (acquaintance packages) i podobnych technik. Bezpośrednie zależności są dozwolone tylko między sąsiednimi poziomami. Technika delegacji (delegation) jest używana do wykonywania zadań na niesąsiadujących obiektach.
W języku Java zależności między pakietami takimi jak na rysunku 2., są wyrażane przy pomocy instrukcji import, tak jak w tabeli 1.Poziom presentation zawiera klasy defininujące obiekty UI (User Interface). W otoczeniu Java wiele klas w pakiecie presentation bazuje na klasach i interfejsach z biblioteki Java Swing. Użytkownik komunikuje się z systemem za pośrednictwem klas presentation. Także klasa zawierająca funkcję main programu jest najczęściej umieszczana w pakiecie presentation.
package presentation; import control.*; package control; import domain.entity.*; import domain.mediator.*; package entity; package mediator; import entity.*; import foundation.*; package foundation;
Poziom control spełnia wymagania nadchodzące z poziomu presentation. Zawiera on klasy odpowiedzialne za przetwarzanie interakcji użytkownika z systemem; interakcji delegowanych do control przez obiekty presentation. W efekcie controljest odpowiedzialna za większość zadań związanych z logiką programu, rozwiązaniami algorytmicznymi, głównymi obliczeniami i utrzymywaniem stanów sesji (session states) dla każdego użytkownika.Pakiet entity w ramach poziomu domain spełnia wymagania nadchodzące z poziomu control. Pakiet ten zawiera klasy reprezentujące obiekty biznesowe (business objects). Klasy te zapamiętują (w pamięci wewnętrznej programu) obiekty wyszukane z bazy danych jak również nowe obiekty utworzone przez program w celu zapamiętania ich w bazie danych.
Pakiet mediator w ramach poziomu domain stanowi kanał komunikacyjny, który pośredniczy między klasami entity i foundation. To pośrednictwo służy dwóm celom. Po pierwsze do rozdzielenia tych dwóch pakietów tak żeby zmiany w jednym z nich nie powodowały zmian w drugim pakiecie. Po drugie do wyeliminowania potrzeby żeby klasy control komunikowały się bezpośrednio z klasami foundation gdy presentation żąda wyszukania kolejnych obiektów biznesowych z bazy danych (takie żądania są kierowane do klas mediator).
Poziom foundation jest odpowiedzialny za komunikację z bazą danych i z usługami web (web services). Klasy tego poziomu ustanawiają połączenie z serwerami baz danych i z serwerami web, konstruują zapytania do trwałych danych (persistentdata) i zarządzają transakcjami.
3. Zasady i wzorce PCMEF#
Oprócz struktury poziomowej, architektura PCMEF definiuje zasady (principles) i wzorce (patterns) konieczne do zarządzania zależnościami między obiektami i do wspomagania rozwiązań, które będą zrozumiałe, utrzymywalne i skalowalne. Główne zasady PCMEF to [MACI2004]:
- zasada zależności w dół – Downward Dependency Principle (DDP)
- zasada zawiadamiania w górę – Upward Notification Principle (UNP)
- zasada komunikacji między sąsiadami – Neighbor Communication Principle (NCP)
- zasada wyraźnych powiązań – Explicit Association Principle (EAP)
- zasada eliminacji cykli – Cycle Elimination Principle (CEP)
- zasada nazywania klas – Class Naming Principle (CNP)
- zasada pakietu znajomości – Acquaintance Package Principle (APP)
Zasada DDP wymaga, żeby główna struktura zależności była z góry na dół. Obiekty na wyższych poziomach zależą od obiektów na niższych poziomach, ale nie odwrotnie. W efekcie obiekty na niższych poziomach są bardziej stabilne – jest je trudno zmienić (co nie oznacza że jest je trudno rozszerzyć przez dodanie nowych funkcji).
Zasada UNP lansuje „low coupling” między poziomami (pakietami) w komunikacji z dołu w górę. Uzyskuje się to poprzez asynchroniczną komunikację bazowaną na przetwarzaniu zdarzeń (event processing). Obiekty na wyższych poziomach są obserwatorami (observers, subscribers) zmian stanów na niższych poziomach. Gdy obiekt obserwowany (publisher) zmienia swój stan, wysyła zawiadomienie (notification) do wszystkich swoich obserwatorów. W odpowiedzi obiekty obserwujące podejmują normalną komunikację z obiektami obserwowanymi przez wysyłanie do nich wiadomości (teraz już z góry na dół).
Zasada NCP umożliwia bezpośrednią komunikację tylko między pakietami, które sąsiadują w strukturze PCMEF. Zasada ta ustala hierarchiczną komunikację i nie pozwala na jej dezintegrację do niezrozumiałej sieci interkomunikacji między-obiektowej. W celu spełnienia tej zasady, wysyłanie wiadomości bazuje na technice delegacji (delegation), tj. łańcucha delegujących obiekty między obiektem klientem (client object) i obiektem dostarczającym usługę (supplier object).
Zasada EAP dokumentuje w sposób wyraźny dozwolone sposoby wysyłania wiadomości między klasami. Zasadę tę stosuje się głównie do klas z zależnościami w dół (zasada DDP) i do klas, które z sobą często współpracują. Powiązania (associations), które są rezultatem tej zasady w ramach DDP, są jednokierunkowe. Powiązania dwukierunkowe są dozwolone w innych sytuacjach, szczególnie między obiektami biznesowymi w pakiecie entity.
Zasada CEP wymaga eliminacji zależności cyklicznych między poziomami, między pakietami i między klasami w ramach pakietów. Zależności cykliczne mogą być eliminowane poprzez tworzenie nowych pakietów specjalnie w tym celu lub przez przekierowywanie jednej ze ścieżek komunikacyjnych w cyklu tak, żeby komunikacja odbywała się z użyciem interfejsu.
Zasada CNP umożliwia rozpoznanie w nazwie klasy pakietu, do którego ta klasa należy. Rekomendacja PCMEF to użycie jednej litery identyfikującej pakiet jako przedrostka w nazwie klasy (np. EFaktura to klasa w pakiecie entity). Inerfejsy są dodatkowo identyfikowane literą I (np. IMFaktura to interfejs w pakiecie mediator).
Zasada APP jest konsekwencją zasady NCP. Pakiet acquaintance składa się z interfejsów, które obiekt przesyła, zamiast konkretnych obiektów, w parametrach do wywołań metod (method calls). Te interfejsy mogą być implementowane w dowolnym pakiecie. Umożliwia to komunikację między nie-sąsiadującymi pakietami, a jednocześnie ograniczenie zależności tego typu do jednego pakietu, tj. do pakietu acquaintance.
Architektura PCMEF bazuje na znanych wzorcach dobrego projektowania i programowania i na kilku nowych wzorcach specjalnie opracowanych dla PCMEF. Głównym źródłem wzorców PCMEF są wzorce GoF (Gang of Four – [GAMM1995]), PEAA (Patterns of Enterprise Application Architecture – [FOWL2003]) i Core J2EE [ALUR2003]. Wzorce o szczególnej przydatności dla PCMEF to MVC, Façade, Abstract Factory, Chain of Responsibility, Observer, Mediator, Identity Map, Data Mapper, Lazy Load, OID Proxy.
4. Weryfikacja zgodności oprogramowania z architekturą#
Architektura PCMEF prowadzi do produkcji utrzymywalnego i skalowalnego oprogramowania pod warunkiem że zasady tej architektury zostaną zachowane w oprogramowaniu. Oznacza to potrzebę obliczania i weryfikowania czterech rodzajów zależności wymienionych wcześniej.Podejście PCMEF do obliczania zależności jest dwu-aspektowe: proaktywne i reaktywne. Podejście proaktywne to przede wszystkim sama propozycja architektury PCMEF prowadząca do minimalizacji zależności. Jest to podejście inżynierii bezpośredniej (forward–engineering) – z projektu do implementacji. Celem jest minimalizacja zależności przez wymuszenie rozwiązania architektonicznego na zespole programistycznym.
Podejście reaktywne polega na mierzeniu zależności w zaimplementowanym oprogramowaniu. Jest to podejście inżynierii wstecznej (reverse–engineering) – z implementacji do projektu. Implementacja może nie zastosować się do projektu architektonicznego. Celem obliczeń jest pokazanie w liczbach o ile taka zaimplementowana struktura jest gorsza od struktury PCMEF (albo innej konstrukcji architektonicznej minimalizującej zależności). Celem podejścia reaktywnego jest także wskazanie zależności, które zaprzeczają zasadom architektonicznym.
Obliczanie zależności jest wielo-wymiarowe i bazowane na czterech podstawowych miarach (metrics): CCD (cumulative class dependency), CMD (cumulative message dependency), CED (cumulative event dependency) i CID (cumulativeinheritance dependency) [MACI2003]. W celach ilustracyjnych, pierwsza z tych miar, nawiązująca do ogólnej liczby zależności między klasami w systemie, jest zaprezentowana poniżej.
DEFINICJA: Cumulative Class Dependency (CCD) jest to ogólny koszt utrzymywalności i skalowalności systemu mierzony na wszystkich klasach w systemie Ci{i=1,…,n) i uwzględniający wszystkie inne klasy w systemie Cj(j<=1,…,n), które potencjalnie mogą wymagać zmian wskutek zmian na klasach Ci.
Jak każda praktyczna miara, definicja CCD jest celowo nieskomplikowana. W szczególności miara ta, sama w sobie, nie tworzy opinii na temat jakości systemu. Wartością tej miary jest możliwość użycia jej do porównań różnych wersji projektów tego samego systemu. W tym celu, obliczanie CCD ma między innymi za zadanie weryfikację, czy dany projekt stosuje się do założeń architektonicznych (takich jak PCMEF). Odkrycie, że tak nie jest, oznacza istnienie zależności potencjalnychdyskutowanych w podrozdziale 1.
Obliczanie CCD dla określonego projektu zaczyna się założeniem, że projekt stosuje się do zasad i wzorców architektury (podrozdział 3). Jeżeli okaże się, że system łamie jakieś zasady lub wzorce, to obliczanie CCD jest kontynuowane tak jakby każda klasa zależała (potencjalnie) od wszystkich pozostałych klas. Obliczanie CCD postępuje wówczas z użyciem metody teorii prawdopodobieństwa znanej jako combinations counting rule. Wartość CCD jest wówczas liczbą różnych kombinacji par klas zależnych, które mogą być utworzone z ogólnej liczby klas w systemie. Wartość ta jest pomnożona przez dwa, żeby odzwierciedlić potencjalne cykliczne zależności.
Powyższa formuła oblicza najgorsze możliwe CCD dla projektu lub systemu. Taki projekt lub system jest uważany za nieutrzymywalny i nieskalowalny. Porównanie najgorszego CCD z CCD projektu/systemu stosującego się do założeń architektonicznych prowadzi do tzw. Unsupportability Factor (UF).
DEFINICJA: Unsupportability Factor (UF) jest wskaźnikiem uzyskanym z podzielenia najgorszego potencjalnego CCD przez CCD projektu/systemu stosującego się do założeń architektonicznych (np. założeń PCMEF).
Wskaźnik UF służy jako modyfikator bardziej szczegółowych miar liczonych dla projektów lub systemów, które okazały się nieutrzymywalne i nieskalowalne. Miary te to między innymi CMD, CED i CID.
Proponowane podejście wymaga ukierunkowanego zarządzania projektem i wymaga wspomagających narzędzi inżynierii wahadłowej (roundtrip–engineering). W ramach badań nad PCMEF zostało zaimplementowane narzędzie DQ (DesignQuantifier) [MACI2003]. DQ umożliwia analizę programów w Javie, potwierdzenie (albo nie) zgodności programu z PCMEF (albo inną konstrukcją architektoniczną zdefiniowaną w DQ), obliczenie pełnego zestawu miar zależności, jak też wizualną prezentację tych miar w diagramach klas UML.
5. Podsumowanie#
Badania nad modelem roundtrip–engineering do produkcji utrzymywalnego i skalowalnego oprogramowania bazującego na architekturze PCMEF są wciąż w toku. Zaproponowany model został częściowo zweryfikowany w jednym dużym projekcie przemysłowym i w kilku dużych projektach studenckich z ogólną liczbą zaangażowanych studentów sięgającą tysiąca osób. Projekty te są przedmiotem studiów przypadków (case studies), ćwiczeń i przykładów w [MACI2004]. Niektóre z tych projektów zostały następnie zweryfikowane przy pomocy narzędzia DQ.Trwają prace nad formalizacją modelu z użyciem teorii zbiorów rozmytych. W ogólności, teoria zbiorów rozmytych pozwala uzyskiwać jedną miarę stanowiącą ocenę syntetyczną modelu w drodze stopniowego syntetyzowania zbioru pojedynczych miar. Wydaje się, że w drodze obliczeń rozmytych można dokonać syntetycznej oceny stanu utrzymywalności i skalowalności dowolnego systemu pod warunkiem, że elementarne miary dla takiego systemu mogą być zdefiniowane.
Bibliografia#
[ALUR2003] | D. Alur, J. Crupi i D. Malks, Core J2EE Patterns: Best Practices and Design Strategies, Prentice Hall, 2/e, 2003, 528p. |
[FOWL2003] | M. Flower, Patterns of Enterprise Application Architecture, Addison-Wesley, 2003, 531p. |
[GAMM1995] | E. Gamma, R. Helm, R. Johnson i J. Vlissides, Design Patterns. Elements of Reusable Object-Oriented Software, Addison-Wesley, 1995, 395p. |
[MACI2001] | L.A. Maciaszek, Requirements Analysis and System Design. Developing Information Systems with UML, Addison-Wesley, 2001, 378p. |
[MACI2003] | L.A. Maciaszek i B.L. Liong, Designing Measurably-Supportable Systems, Nowoczesne Technologie Informatyczne w Zarządzaniu NTIZ’2003, Research Papers Wroclaw University of Economics, 986, 2003, 26p. |
[MACI2004] | L.A. Maciaszek, B.L. Liong i S. Bills, Practical Software Engineering, A Case-Study Approach, Addison-Wesley, 2004, 600p. |
[#1] Tekst został przygotowany podczas urlopu sabatykalnego na Akademii Ekonomicznej we Wrocławiu