How to describe software architecture

23 june 2022
Jakub Rojek Jakub Rojek
Photo by Alexa Wonga on Unsplash (https://unsplash.com/photos/l5Tzv1alcps)
Categories: IT analysis, Programming, Methodologies

Wstęp

Dokumentacja projektów informatycznych to temat rzeka i można go rozpatrywać pod wieloma aspektami. Co do tego, że dobrze przygotowane i opisane wytyczne często wręcz ratują przedsięwzięcia cyfrowe, nikt raczej nie ma wątpliwości. Kwestią sporną jest natomiast zakres przygotowywanej dokumentacji oraz jej szczegółowość. Należy bowiem pamiętać, że proces wytwarzania specyfikacji czy innego konspektu nie powinien trwać zbyt długo z uwagi na to, że w pewnym momencie i w odpowiednich warunkach staje się to nieopłacalne. Oczywiście, trudno zdefiniować regułę, która jednoznacznie by to określała, a nawet pokuszę się o stwierdzenie, że jest to niemożliwe. Cały proces, a także moment tworzenia dokumentacji to kwestia wyczucia i doświadczenia, natomiast nie bez powodu jeden z punktów manifestu agile mówi o tym, że "działające oprogramowanie jest ważniejsze od szczegółowej dokumentacji". Z drugiej strony, z doświadczenia wiemy, że brak opisu w jakiejkolwiek formie jest jeszcze gorszy.

Dlatego najpierw warto skupić się na wyróżnieniu aspektów, które powinny być dokumentowane i wysiłek poświęcony na ten proces rzeczywiście zwróci się w przyszłości. W tym momencie większości z Was zapali się w głowie lampka podpisana "specyfikacja wymagań" i to bardzo dobry trop - to podstawowy zbiór informacji, który jest opracowywany w formie pliku tekstowego i jedna z metod tworzenia takowego została bardzo dobrze opisana na naszym blogu przez Piotra Miklosika (metoda HANSA). Natomiast istnieją projekty IT, w których spisanie jedynie wymagań nie wystarczy - konieczne jest zajęcie się również innymi obszarami oprogramowania, a jednym z nich jest architektura. Niestety, o ile wiele osób umie (przynajmniej mniej więcej) przygotować specyfikację wymagań, a na kodzie zna się równie wielka gromada specjalistów, tak wiedza o dokumentowaniu bardziej technicznej strony nie jest już tak powszechna.

W dzisiejszym artykule pokażemy sobie jedno z podejść do specyfikowania architektury - opiszemy sposób wykorzystywany u nas, w Wilda Software i który sprawdził się w kilku projektach oraz na różnych poziomach abstrakcji. Jest też cały czas dopracowywany, aby w przyszłości jeszcze lepiej pozwalał osiągać to, co już i tak jest możliwe w momencie, kiedy piszę te słowa. A na deser (lub od razu, jeśli jesteście niecierpliwi) zapraszam Was od razu do pobrania wzoru dokumentu, który podsumowuje wiedzę opisaną w tym tekście.

Czym jest architektura oprogramowania?

Architektura dużego miasta (źródło: https://www.pexels.com/pl-pl/zdjecie/miasto-panorama-budynki-wybrzeze-8412697/)

Na początku jednak zdefiniujmy w ogóle termin, który dzisiaj będzie pojawiał się bardzo często, a więc architektura oprogramowania - czym ona właściwie jest? Na to pytanie spróbował odpowiedzieć Robert C. Martin w jednej ze swoich najsłynniejszych książek pod tytułem "Czysta architektura", w której stwierdził, że architektura niczym nie różni się od projektu. Dodatkowo:

Celem architektury oprogramowania jest zminimalizowanie liczby ludzi wymaganych do zbudowania i utrzymywania danego systemu.

W ogólności jest to prawda - im lepsza architektura, tym mniejszy wysiłek jest potrzebny do tego, aby utrzymywać ją w porządku i skupić się na funkcjonalnym rozwijaniu systemu. Natomiast mam wrażenie, że osoba, która wcześniej nie do końca wiedziała, co się kryje pod tym pojęciem, po przeczytaniu tego cytatu też się nie dowie. Dlatego spróbuję wyjaśnić to własnymi słowami.

Na pewno architektura oprogramowania nie jest tylko schematem bazy danych, jak czasem myślą niektórzy studenci początkowych lat kierunków informatycznych. To projekt podzielenia systemu informatycznego na części składowe oraz sposobu komunikacji pomiędzy nimi. Należy zwrócić uwagę, że te "części składowe" mogą być rozumiane w różny sposób - mogą to być aplikacje, mikroserwisy, moduły, a nawet pojedyncze klasy. To od projektanta i danego etapu zależy, na jakich poziomach ogólności stworzy wytyczne - zazwyczaj zaczyna się od dosyć wysokiego (i na takim poprzestaniemy w naszych rozważaniach), a w zależności od sytuacji może zejść trochę niżej, aż do szczegółów programistycznych. Do architektury zalicza się praktycznie każdy techniczny aspekt systemu - wydzielenie poszczególnych aplikacji, protokołów komunikacyjnych, struktur danych, wzorców projektowych, schematu baz(y) danych, założenia dotyczące interfejsu oraz oczekiwanego sprzętu i wiele, wiele innych. Jest to zatem dość szerokie pojęcie, które można określić skrótowo jako techniczny plan wykonania i utrzymywania aplikacji.

Dlaczego powinno opisywać się architekturę?

Po przeczytaniu powyższej sekcji zapewne domyślacie się już odpowiedzi - chodzi głównie o to, aby uniknąć spontanicznego tworzenia aplikacji i tym samym zminimalizować błędy, które potem mogą być kosztowne w naprawie. Oczywiście, w przypadku małych aplikacji lub bardzo oczywistych rozwiązań, wcześniejszy etap planistyczny może nie być potrzebny, ale w większych lub mniej standardowych systemach bardzo rekomendowane jest wcześniejsze zaprojektowanie oraz spisanie założeń. Zresztą, powodów ku temu jest więcej.

Po pierwsze, opisując architekturę i spisując kolejne punkty, tak naprawdę nad nimi myślimy, rozważamy różne opcje i cały czas weryfikujemy nasze pomysły. Dzięki temu cały proces werbalizowania myśli w słowa pozwala nam nie tylko trwale zachować ważne refleksje, ale też poprawić potencjalne niedociągnięcia i odkryć luki w rozumowaniu. Może się również zdarzyć, że podczas projektowania okaże się, że liczba powstałych aplikacji będzie większa niż początkowo zakładaliśmy lub odwrotnie - pewien komponent przestanie być potrzebny, upraszczając architekturę. Zawsze lepiej dowiedzieć się tego zanim zaczniemy pisać faktyczny kod.

Po drugie, stanowi możliwość udokumentowania wytycznych, które nie są wymaganiami funkcjonalnymi (a zatem nie można ich wprost opisać w backlogu), ale są równie istotne i należy o nich pamiętać. Oczywiście, mowa o wymaganiach pozafunkcjonalnych (NFR), które opisują nam, jak system powinien działać, wyglądać lub zachowywać się w różnych sytuacjach. Nieco bagatelizując można je nazwać kryteriami jakościowymi i w wielu przypadkach wpływają właśnie na architekturę oprogramowania (oraz makiety), nadając różne ograniczenia.

Po trzecie, osoby będące aktywnymi programistami w software house'ach (i nie tylko) z pewnością znają sytuacje, w których muszą wprowadzić nową osobę do projektu, ale nie mają czasu tłumaczyć wszystkich aspektów. W związku z tym zazwyczaj kończą na poradniku pozwalającym skonfigurować projekt na komputerze (który też powinien być zawczasu spisany), natomiast pomijają etap wprowadzenia osoby do założeń projektu. I właśnie tutaj wchodzi dokumentacja, która odpowiednio spisana wprowadzi nowego członka zespołu bez angażowania innych uczestników. Dodatkowo, może być drogowskazem nawet dla osób aktywnie partycypujących w realizacji oprogramowania, którzy zastanawiają się, dlaczego coś zostało wykonane w pewien sposób - specyfikacja architektury może to wyjaśnić i przypomnieć ograniczenia, przy których pracowali architekci.

Dlaczego nie warto dokładnie opisywać architektury?

Wcześniej wspomniałem, że zatrzymamy się na dość wysokim poziomie abstrakcji architektury i uczyniłem to nie bez powodu - tak najczęściej się robi, nie licząc bardzo specyficznych projektów lub dużych zespołów z ogromnymi budżetami. Dlaczego? Ponownie - można tutaj wyróżnić kilka powodów.

Musimy pamiętać o tym, że dokumentacja architektury często powstaje na bardzo wczesnym etapie projektu, zaraz po specyfikacji wymagań. Oczywiście, nie jest to regułą w każdej firmie, ale przygotowanie takiej specyfikacji w tym momencie jest bardzo pomocne z wielu względów, także biznesowych. Natomiast nie ma co ukrywać, że w takim wypadku architekt nie jest w stanie przewidzieć wszystkich zmian oraz trudności, które zostaną napotkane po drodze. Co więcej, próba przewidzenia wszystkiego najczęściej wymaga ogromnej ilości czasu, a i tak łatwo sobie wyobrazić, że niektóre aspekty nawet nie pojawią się na myślowym horyzoncie i zaskoczą zespół w praktyce dopiero w przyszłości. Krótko mówiąc - przy opracowywaniu wstępnej dokumentacji należy poświęcić tyle czasu, ile jest potrzebne (na przykład ze względu na prośby klienta), ale nie zwiększać tego czasu sztucznie, starając się rozpatrywać sytuacje, które z dużym prawdopodobieństwem i tak nie pojawią się lub ulegną zmianie w przyszłości.

Co więcej, zauważmy, że najczęściej tworzymy specyfikację dla klienta, który nie jest techniczny w takim stopniu, jak my. To oznacza, że opis architektury będzie dla niego bardziej ciekawostką, ewentualne materiałem przekazywanym do analizy i weryfikacji jeszcze innej jednostce. Z tego płynie wniosek, że dokumentacja na tym etapie jest bardziej przydatna dla zespołu IT, który projektując architekturę może lepiej ocenić nakład pracy wymagany do realizacji projektu, a jednocześnie pokazać, że zna się na rzeczy. Dlatego poziom powinien być odpowiedni według uznania programistów i innych specjalistów, o ile zleceniodawca nie określił inaczej.

Na koniec warto pamiętać, że architektura nie jest stała - ona cały czas żyje. Oczywiście, pewne ramy pozostają zwykle niezmienne i od nich zaczyna się projekt. Jednakże, podczas realizacji projektów IT zachodzi tyle zmian, że prawdopodobnie pierwotne założenia techniczne będą niewystarczające i często będzie trzeba przeprojektowywać pewne fragmenty oraz refaktoryzować kod (oczywiście, architektura dobra u podstaw pozwala ograniczyć ten proceder i tym samym brzydkie zapachy). Nie bez powodu w prowadzeniu przedsięwzięcia dominują metodyki zwinne i można też śmiało powiedzieć, że pewną zwinność należy założyć również w sferze technicznej. Nie warto zatem tracić czasu na szczegółowe projektowanie pojedynczych klas - lepiej poświęcić go na dopracowywanie istniejących rozwiązań i zbudowanie dobrej ramy architektonicznej.

Co powinna zawierać dokumentacja?

Spotkanie inżynierów oprogramowania (źródło: https://unsplash.com/photos/mpN7xjKQ_Ns)

Najpierw zastanówmy się, dla kogo tworzony jest opis architektury. Jest to kilka grup ludzi:

  • programiści - oczywista grupa, która będzie realizowała projekt od strony technicznej i tym samym musi wiedzieć, jak to robić,
  • klient - osoba lub firma, mogąca potwierdzić poprawność przyjętych założeń i akceptująca rozwiązanie,
  • wdrożeniowcy i administratorzy - osoby zainteresowane późniejszym wdrożeniem systemu oraz jego utrzymaniem.

Jak widać, dokumentacja powinna zadowolić różnych udziałowców projektu (ang. stakeholders). Możemy zatem spokojnie przyjąć, że opis architektury powinien zawierać:

  • wymagania pozafunkcjonalne (NFR) - co prawda, są one zbierane raczej w specyfikacji wymagań oprogramowania, ale opis architektury jak najbardziej do nich nawiązuje,
  • założenia powstałe za sprawą NFR-ów oraz innych informacji, które następnie będą stanowiły bazę do projektu architektury,
  • decyzje architektoniczne oraz ich uzasadnienie,
  • diagramy przedstawiające opisywaną architekturę, przynajmniej na dużym poziomie ogólności (pamiętajcie, że jeden obrazek jest wart tysiąca słów, a w przypadku technicznego opisu to szczególnie istotne),
  • proponowany proces realizacji i miejsce przechowywania kodu (dla programistów jest to oczywiste, ale dla klienta niekoniecznie.

Dodatkiem do opisu architektury może być opis procedur związanych z samym wdrożeniem - mam tutaj na myśli instrukcję instalacji i aktualizacji systemu. Tym niemniej, z uwagi na fakt, że wybór serwera zazwyczaj zachodzi na dużo późniejszym etapie, a sama architektura - jak już wspomniałem - jest dość płynna, tego typu dokumenty powstają zwykle później i osobno.

Oczywiście, w zależności od sytuacji, opis architektury może zawierać również inne elementy, jednak skupimy się na tych, które zostały wymienione powyżej.

Metodyki opisu architektury

Zanim przedstawimy najpopularniejsze sposoby na eksplorowanie i opisywanie architektury, to warto wspomnieć o tym, że mamy tutaj trochę inną sytuację niż w przypadku zarządzania projektami. Nie musimy ograniczać się do jednej metodyki - możemy łączyć różne podejścia, korzystając z tego, że wszystkie pozwalają dotrzeć do rozwiązania od trochę innej strony. Oczywiście, nie oznacza to, że te same fragmenty architektury trzeba opisać kilkukrotnie, różnymi sposobami - bardziej chodzi o pokazywanie projektu z różnych stron, nie ograniczając się do jednej techniki we wszystkich.

Przykładowy diagram kontekstu

A jakie są w ogóle najpopularniejsze metody opisu architektury? Zapraszam na krótki przewodnik:

Model C4

Po dłuższym czasie szukania odpowiedniej formy mogę stwierdzić, że jest to jedna z bardziej przystępnych, a jednocześnie dających największe możliwości. Nazwa modelu C4 pochodzi od kolejnych warstw, które są opisywane w następujący sposób:

  • Context - jest to nic innego jak diagram kontekstu, a więc tworząc tę grafikę na potrzeby specyfikacji wymagań tak naprawdę już przygotowujemy sobie fundament do tworzenia architektury. Pokazuje projekt z bardzo szerokiej perspektywy, koncentrując się na aktorach (personach) i ich powiązaniach z poszczególnymi częściami systemu. Pod "częściami" rozumiemy tutaj zazwyczaj grupy aplikacji składające się na całe oprogramowanie oraz systemy zewnętrzne.
  • Container - diagram kontenerów wchodzi trochę głębiej, gdyż wydzielamy tutaj konkretne aplikacje, a nawet ich części, pokazując przy tym typ oprogramowania (webowe, mobilne itd.), a także biorąc pod uwagę wybrane technologie. To już bardziej techniczny poziom.
  • Component - każdy kontener (lub przynajmniej te bardziej rozbudowane) są tutaj ukazane w jeszcze większych detalach i prezentowana jest wewnętrzna struktura. Na tym poziomie możemy np. dowiedzieć się, że oprogramowanie składa się z modułów, z których każdy zorganizowany jest zgodnie z modelem MVC oraz jakie są powiązania między tymi modułami.
  • Code - najniższy poziom przewidywany przez tą metodykę, który de facto opisuje już kod. A dokładniej model obiektowy i konkretne klasy, zgodnie z notacją UML, o której dzisiaj jeszcze wspomnimy.

Jak widać, mamy cztery razy "C" i stąd nazwa tego podejścia. Widzimy też, że opisując architekturę, stopniowo schodzimy w dół, coraz bardziej zaglądając do zakamarków poszczególnych części i dlatego niektórym nazwa "C4" bardziej kojarzy się z materiałem wybuchowym i stopniową "eksplozją" poszczególnych fragmentów na mniejsze części.

Tutaj warto wspomnieć, że na tym ta metodyka się nie kończy - jak najbardziej przewiduje dodatkowe, pomocnicze diagramy, a także podaje wytyczne dotyczące opisywania każdej części. Natomiast to, co jest w niej (jak i w wielu innych metodykach) świetne to dość duża elastyczność - architekt wcale nie jest zobowiązany do korzystania ze wszystkich dobrodziejstw C4 i nawet czytając opisy diagramów na podlinkowanej wyżej stronie można zobaczyć, że nie wszystkie są polecane w każdej sytuacji. A jeśli nie macie czasu czytać oficjalnej dokumentacji, to skrót znajduje się tutaj.

Korzystajcie z modelu C4, gdy:

  • szukacie konkretnego, “gotowego” rozwiązania, które nadaje Wam pewien szablon, ale jednocześnie jest elastyczne,
  • pracujecie nad architekturą w podejściu top-down, a więc zaczynając od najbardziej ogólnych założeń,
  • chcecie szybko zacząć pracę nad architekturą.

4+1

To bardzo podobne podejście, w którym na architekturę patrzy się z czterech punktów widzenia, docierając stopniowo do przecięcia się tych perspektyw. Ta magiczna czwórka to:

  • Perspektywa logiczna - interesuje nas to, co system udostępnia końcowym użytkownikom, a więc opisuje komponenty udostępniane użytkownikom.
  • Perspektywa procesowa - w tym miejscu patrzymy na system nie pod kątem jego kształtu, ale dynamiki, opisując sekwencję zdarzeń, jakie mają miejsce przy wykonywaniu poszczególnych operacji przez użytkownika.
  • Perspektywa developerska - to z kolei punkt widzenia programisty, a więc tutaj komponenty są prezentowane dokładniej, jako oprogramowanie podzielone na moduły i zawierające kod.
  • Perspektywa fizyczna - widok prezentujący obraz systemu od strony fizycznej, czyli konkretnych połączeń pomiędzy podsystemami i dostępem do nich (może się wiązać np. z cyberbezpieczeństwem).
  • Scenariusze - to jest właśnie to "+1", które stanowi zbiór czynności, które użytkownik może wykonywać w systemie. Jest to nic innego, jak diagram przedstawiający wymagania funkcjonalne, który może posłużyć do dalszego eksplorowania możliwych zagrożeń i modyfikacji.

To podejście, które ciągle jest elastyczne, wydaje się już pełniejsze niż C4, ale jest też bardziej czasochłonne i tak naprawdę często ograniczane do paru perspektyw. Może mieć sens w przypadku bardzo rozbudowanych systemów, w których występują liczne grupy użytkowników, gdzie proces biznesowy jest wyjątkowo długi i obejmuje integrację pomiędzy systemami, a część oprogramowania jest osadzona w obszarze zabezpieczonym przed niepowołanym dostępem.

Korzystajcie z metody 4+1, gdy:

  • umiecie przyjmować punkty widzenia różnych ról,
  • system jest bardzo rozbudowany i będzie składał się z wielu komponentów,
  • system będzie musiał integrować się z innymi w celu przeprowadzenia użytkownika przez dany proces.

ATAM

To z kolei podejście nie tyle do opisu architektury, co przeglądania jej i szukania luk. Metoda ATAM polega na przygotowaniu spotkania (lub serii spotkań), podczas których pomysły na poszczególne fragmenty architektury są omawiane i konfrontowane z różnymi osobami - zarówno technicznymi, jak i reprezentującymi stronę biznesową. Celem jest wytłumaczenie pewnych rozwiązań i przekonanie się, czy ktoś nie ma lepszego pomysły lub zastrzeżeń, które zmienią warunki, przy których działają architekci. Może to być bardzo obiecujące podejście, gdyż pozwala wyjść ze swojej technicznej strefy komfortu i zapalić w mózgu lampkę, pokazując inne możliwości. Niektórzy znajdą tutaj analogię do słynnej metody gumowej kaczuszki, która opiera się o założenie, że wypowiadając swoje “tłumaczenie” na głos uruchamiamy w szarych komórkach mechanizmy, pozwalające bardziej kreatywnie myśleć i szukać rozwiązania - dlatego ma to formę spotkania, gdzie trzeba mówić i słuchać, a nie dokumentu (ten jest dopiero wynikiem procesu). Jednocześnie ATAM w swojej specyfikacji narzuca pewien porządek opisu, ale trzeba pamiętać, że ta metoda skupia się przede wszystkim na procesie weryfikacji swoich idei.

Korzystajcie z podejścia ATAM, gdy:

  • macie już zalążki architektury i chcecie ją omówić z innymi osobami o różnych specjalnościach,
  • chcecie drobiazgowo przedyskutować każdy punkt architektury,
  • macie dość dużo czasu, za to system będzie długo “żył”.

ADR (Architecture Decision Records)

Znacie to uczucie, kiedy po wielu miesiącach walki z systemem zadajecie sobie pytanie "dlaczego w ogóle przyjęliśmy takie rozwiązanie, skoro alternatywa była łatwiejsza"? Czasami wynika to z braku wiedzy w momencie rozpoczynania projektu, czasami po prostu z błędu, ale istnieją również sytuacje, w których alternatywa nie była tak dobra, jak to się wydaje. Niestety, po wielu miesiącach łatwo zapomnieć właściwe argumenty w celu wyjaśnienia sytuacji kolegom i koleżankom w zespole. Dlatego powstało podejście ADR, które wprowadza szereg artefaktów (w uproszczeniu - dokumentów), ale najważniejszym z nich jest zestawienie podjętych decyzji architektonicznych (o różnym poziomie istotności), ich historii, konsekwencji oraz innych możliwych opcji. Najważniejszą zasadą jest spisywanie tych decyzji w momencie ich podejmowania, gdyż wówczas nie tylko na świeżo możemy wyrazić, jakie były powody takiego działania, ale także, nie będąc jeszcze tak przywiązanymi do swojej koncepcji i wypisując inne opcje, możemy jeszcze raz zweryfikować swoje wybory.

Poniżej, przy okazji omawiania wzoru, będziecie mogli przeczytać więcej szczegółów dotyczących tej techniki i konstrukcji odpowiednich rekordów.

Z ADR warto korzystać, gdy:

  • macie dużo decyzji do podjęcia i dróg technologicznych do wybrania,
  • współpracownicy często przychodzą do pracy nad projektem lub zadają pytania dotyczące architektury,
  • klient konsultuje Waszą specyfikację ze swoim pionem technicznym.

UML

Przy okazji omawiania opisu architektury nie można pominąć wysłużonego UML-a, któremu poświęciliśmy już dwa artykuły - o diagramach klas oraz stanów. Nie jest to osobna metodyka pracy, ale notacja, pozwalająca urzeczywistnić większość diagramów omawianych w tym artykule oraz poza nim.

Jeśli chcecie poczytać więcej o podejściach architektonicznych, to bardzo polecam artykuł Herberto Graçy, który przy okazji opisuje jeszcze podejścia związane z prezentowaniem zależności pomiędzy poszczególnymi elementami (np. tabel w bazie danych).

Propozycja dokumentu opisu architektury

Przykładowy diagram kontenerów

Mając w pamięci to, o czym opowiedzieliśmy sobie powyżej, chcielibyśmy przedstawić nasz wzór na opis architektury, podobnie jak poprzednio zrobiliśmy to ze specyfikacją wymagań. Jest to dokument, który zazwyczaj przygotowujemy klientom na wczesnych etapach projektu, po analizie ich potrzeb, kiedy już mniej więcej wiadomo, z czym się mierzymy, ale jeszcze musimy przeanalizować temat w celu lepszego oszacowania pracochłonności realizacji. Oczywiście, to tylko wzór i przykład - w zależności od sytuacji dodajemy lub odejmujemy poszczególne rozdziały, tworzymy dodatkowe dokumenty lub zmieniamy strukturę. Tym niemniej, szablon, którzy przedstawiamy Wam poniżej w sekcji załączników jest czymś, co stanowi fundament dla dalszy prac.

Sam wzór bazuje na dwóch z wyżej wymienionych technik - jest to ADR oraz model C4, jednak ten drugi został przez nas uproszczony i trochę przekształcony. Po pierwsze, omijamy ostatnie "C", a więc diagram kodu, ponieważ na tak wczesnym etapie projektu nie ma on większego sensu. Co więcej - później też ma mniejszy, gdyż przy odpowiednio doświadczonym zespole, który działa w obrębie małych obszarów (np. poszczególnych modułów), powstający kod jest od początku niezłej jakości i lepiej wykorzystać czas na jego poprawianie. Ale zastrzegam - to nie zawsze tak działa i niekiedy rzeczywiście schodzimy do niższego poziomu diagramów, aby przemyśleć pewne kluczowe elementy systemu. To ważna uwaga i ogólnie polecam rozmyślania nad poszczególnymi konstrukcjami w kodzie, natomiast trzeba wziąć pod uwagę czas. Druga modyfikacja modelu to C4 to fakt, poszczególne aplikacje zazwyczaj widoczne są u nas już na diagramie kontekstu, a przy opisie kontenerów schodzimy już trochę na poziom komponentów. Tak jest dla nas wygodniej, szczególnie przy wielomodułowych aplikacjach.

Prześledźmy teraz po kolei rozdziały zawarte we wzorze.

1. Cel dokumentu

W dobrym tonie jest zacząć dokument od powtórzenia krótkiego opisu projektu (nie każdy musiał czytać specyfikację wymagań) oraz informacji, dla kogo jest to tekst. Zauważcie bowiem, że w tej fazie powstaje zwykle więcej wszelkiego rodzaju opisów (nazwanych już wcześniej artefaktami) i klient zwyczajnie może się pogubić w tym, co sam powinien uważnie przeczytać, a co wystarczy przejrzeć przy asyście osoby technicznej. Dodatkowo, jeśli nasz dokument zawiera specyficzne notacje, to warte je tutaj wyjaśnić.

2. Ogólne założenia

Tutaj również przypominamy, ale już bardziej konkretne rzeczy. W tym rozdziale możemy zawrzeć odniesienia do NFR-ów (niekoniecznie je przeklejać, gdyż lista wymagań również “żyje”) oraz wypisać jak najwięcej założeń oraz ograniczeń, które znamy przed startem projektu. Przykładowo, klient może wymóc korzystanie z pewnej infrastruktury (co nakłada limity technologiczne) lub wiadomo, że duży procent użytkowników będą stanowiły osoby z niepełnosprawnościami. Przypomina to trochę zbieranie luźnych tropów w śledztwie, które następnie doprowadzą do rozwiązania, a więc w naszym przypadku kształtu architektury.

Jeśli ograniczeń technicznych nałożonych przez klienta jest dość dużo, można wydzielić je jako osobny podrozdział i skupić się na tym fragmencie, korzystając z naszych porad w odpowiednim artykule.

3. Rejestr decyzji architektonicznych (ADR)

Ten rozdział z kolei dokumentuje nasze przemyślenia (zwykle warto to robić w kilka osób) dotyczące wybranych technologii i innych rozwiązań (np. komunikacyjnych). Zgodnie z metodyką ADR, decyzja nie jest zapisywana po prostu jako krótkie sformułowanie (np. "wybrano framework Angular 13"), tylko dodatkowo musi nastąpić uzasadnienie oraz wymienienie wad innych opcji. Bywały już sytuacje, w których klient doceniał tak opisane punkty oraz bardziej rozważnie debatował nad (tańszą) alternatywą, a także w których wewnątrz samego zespołu mogliśmy przypomnieć sobie, dlaczego właściwie męczymy się z daną technologią.

Co powinien zawierać wpis w ADR? Poniżej jedna z koncepcji, którą wykorzystamy też we wzorze - zakłada ona następujące atrybuty:

  • Identyfikator - unikalna etykieta ułatwiająca późniejsze odnoszenie się do danego rekordu.
  • Decyzja - krótki opis samej decyzji, np. "Przesyłanie danych w formie JSON przez usługi sieciowe".
  • Część architektury - fragment systemu, do którego dany rekord się odnosi. Czasami jest to oczywiste, ale ponieważ istnieją technologie, które pasują do wielu komponentów, to warto je tutaj wyróżnić. Może się okazać, że decyzji jest tak dużo, że warto będzie ten atrybut zamienić na podrozdziały zawierające decyzje odnoszące się do konkretnej części architektury.
  • Uzasadnienie - jeden z ważniejszych punktów, w którym faktycznie opisujemy powody stojące za wyborem danego rozwiązania. Jeśli podczas spisywania okaże się, że nie mamy tutaj za wiele do wpisania, to może oznaczać jedną z dwóch rzeczy: albo wybór jest tak oczywisty, albo niedostatecznie przemyśleliśmy dane zagadnienie.
  • Czynniki ryzyka - za wyborami i korzyściami z nich płynącymi stoją też konsekwencje, które mogą przerodzić się w słabości technologiczne. Nie należy zapominać o czynnikach ryzyka i warto sumiennie je podać, aby zespół IT był świadomy potencjalnych skutków ubocznych.
  • Inne opcje i konsekwencje - zazwyczaj mamy do wyboru kilka dróg i mimo zdecydowania się na jedną z nich, warto opisać również te, z których zrezygnowaliśmy. Być może osoby weryfikujące nasze podejście będą mogły rzucić nam nowe światło, przychylając się do jednego z uprzednio odrzuconych rozwiązań.

Jeśli martwi Was to, że przy uzasadnieniu zazwyczaj moglibyście wpisywać "bo jesteśmy przyzwyczajeni do danego języka", to uspokajam, że nie ma w tym niczego złego. Nie każda aplikacja jest innowacyjna lub wymaga specjalnej technologii - bardzo często warto nie być "pistoletem" i korzystać z tego, co się zna najlepiej. Warto również w takiej sytuacji mieć przygotowane uzasadnienie, które umieszczamy w większości tego typu dokumentów. Warto pamiętać, że klient ufa naszemu doświadczeniu oraz cieszy się, że nie chcemy na nim "eksperymentować" (chyba że jest to jakoś umotywowane lub zgodził się na to).

4. Diagram kontekstu, 5. Diagram kontenerów, 6. Diagram komponentów

Przykładowy diagram komponentów

Te rozdziały potraktujemy zbiorczo, gdyż ilustrują warstwy wcześniej opisane przy okazji omawiania modelu C4 (teraz już właściwie C3). Są to sekcje zawierające diagramy (czasami więcej niż jeden na dany rozdział), ukazujące poszczególne warstwy i pomysły przedstawione z pewnej perspektywy. Jednak mimo że obraz już mówi dużo odbiorcy, to warto dopełnić go opisem - musimy mieć świadomość, że zwłaszcza w przypadku tekstów technicznych należy zadbać o to, aby interpretowano je wyłącznie w jeden sposób, nawet przez osoby nieznające danej notacji. Dlatego tacy czytelnicy potrzebują opisu słownego. Oczywiście, jego przygotowanie pozwala nam w myślach jeszcze raz zweryfikować postać graficzną.

Same diagramy można przygotować różnymi narzędziami - osobiście korzystam najczęściej ze wspominanego już na naszym blogu serwisu diagrams.net, który zawiera bardzo dużo gotowych obiektów do wstawienia na grafikę, a które mogą reprezentować poszczególne części składowe systemów. Możliwe w nim jest także zastosowanie notacji UML, jeśli jest ona potrzebna.

Czasem przydatne może być również dodanie diagramów przepływów poszczególnych akcji w systemie, jeśli np. użytkownik korzystający z oprogramowania przechodzi bardzo długi proces, podczas którego jest przenoszony pomiędzy wieloma usługami - najczęściej oznacza to konieczność odpowiedniego przygotowania szeregu usług sieciowych. Jest to ważne szczególnie w systemach, które mocno się ze sobą integrują. Stanowi to bezpośrednie odwołanie do perspektywy procesowej w podejściu 4+1.

7. Zarządzanie wersjami oprogramowania

Niekiedy spotykamy się z pytaniami klienta dotyczącymi sposobu pracy programistów. Zazwyczaj odpowiedź zaczyna się od "korzystamy z Gita", jednak to niepełny opis związany z tym punktem. Ze strony zleceniodawcy może powstać wątpliwość, czy korzystamy z własnych repozytoriów, czy klient musi wykupić jakąś usługę oraz czy na pewno potrafimy oddzielić wersje produkcyjne od testowych oraz w jaki sposób to robimy.

Na te i inne wątpliwości można odpowiedzieć w tym punkcie, uspokajając klienta oraz pokazując przebieg naszej pracy. Natomiast ten rozdział zyskuje na znaczeniu, jeśli repozytoriów jest kilka i konieczna jest opracowanie ich współpracy ze sobą.

8. Uwagi końcowe

Standardowo, czasami istnieją kwestie, które nie zmieściły się w żadnym rozdziale lub pojawiły się na samym końcu. Mogą też wynikać z bardzo specyficznych warunków powstawania projektu. W takim wypadku miejsce na takie uwagi jest właśnie w tym rozdziale.

Tak, jak wspomniałem, dokument może być (i zwykle jest) rozszerzany o rozdziały, które są potrzebne w danym projekcie. Jedną z takich sekcji może być odpowiednik perspektywy fizycznej z modelu 4+1, w którym zostanie nakreślony plan procedury późniejszych wdrożeń, co ma znaczenie przy bardzo skomplikowanych architekturach lub konkretnych konfiguracjach serwerowych. Przykładowo, jeśli klient zapewnia infrastrukturę dostępową dla swoich usług, z których należy korzystać, to najpewniej wiąże się ona z limitowanym dostępem i konkretnymi wytycznymi, mającymi przełożenie także m.in. na biblioteki wykorzystywane w aplikacji.

Co jeszcze pomaga w dokumentowaniu architektury?

Sam dokument lub nawet dokumenty to nie wszystko, co może pomóc w utrzymaniu odpowiedniej architektury kodu oraz wspomagać programistów w zorientowaniu się w projekcie. Jest jeszcze kilka (z wielu) technik, które mogą pomóc w dokumentowaniu i to bez pisania "wolnego słowa".

Pierwszą z nich są systemy komentowania kodu, które tak naprawdę są jedyną obecnie rekomendowaną formą komentowania linijek pisanych przez programistę. Mowa o specjalnych instrukcjach, które opisują poszczególne klasy, metody i pola, a następnie - za pomocą odpowiedniego narzędzia typu Javadoc czy PHPDoc - mogą posłużyć do wygenerowania estetycznej dokumentacji w formie strony HTML. W ten sposób jednocześnie informujemy innych programistów o tym, jak mają korzystać z naszego kodu, a także zyskujemy specyfikację, którą można potem wyeksportować dla naszych partnerów.

Drugą jest wiążące się z tym odpowiednie nazewnictwo stosowane w kodzie, które w dobie podpowiadających edytorów sprawia, że czasami warto nieco dłużej pomyśleć nad odpowiednim nazwaniem zmiennej czy metody, ale potem zyskać na natychmiastowym odgadywaniu (nawet po paru miesiącach), co się pod nią kryje oraz jak z niej skorzystać. Fachowo nazywa się to samodokumentującym się kodem. W ten sposób możemy całkowicie pozbyć się komentarzy z programu (za wyjątkiem tych opisywanych wyżej), które są przydatne i w pewnych miejscach nadal nieodzowne, ale ich wadą jest to, że często nie nadążają za zmianami w samym kodzie, przez co powodują zamieszanie.

Trzecim sposobem są testy jednostkowe i inne formy automatycznej weryfikacji, które same w sobie pomagają w zachowaniu jakości kodu, ale jednocześnie dokumentują go. Dzieje się tak, ponieważ z natury metody testujące sprawdzają różne, często skrajne przypadki, a to przy okazji opis i specyfikacja działania poszczególnych miejsc w kodzie. Dodatkowo, wymuszająca reakcję na zmiany, gdyż modyfikacje oryginalnego programu często wymagają zmiany testów lub dopisanie nowych przypadków, przez co aktualizacje są ze sobą związane. Idąc dalej, techniki takie jak TDD (Test Driven Development) pozwalają nie tylko dokumentować kod, ale też “przypadkiem” opracowywać odpowiednią architekturę na niskim poziomie, pokazując, jak najlepiej z poszczególnych klas i metod korzystałby prawdziwy programista. Jednak to oraz same zalety i wady korzystania z testów automatycznych to miejsce na osobny artykuł.

Takich technik warto szukać nie tylko w samym kodzie. Scrum zakłada etap retrospekcji pod koniec każdego sprintu, podczas którego zespół omawia dobre i złe strony tego, co się działo, w tym także w aspekcie technicznym. Tego typu inicjatywy wraz z przeglądami kodu oraz wewnętrznymi dyskusjami mogą pomóc zarówno w pracy nad samą architekturą, jak i po prostu samorozwojem programistów.

Podsumowanie

Mam nadzieję, że udało przekonać się Was do tego, że dokumentowanie architektury, co najmniej na wysokim poziomie ogólności, jest bardzo przydatnym krokiem w procesie realizacji oprogramowania o choćby średnim rozmiarze. Oczywiście, są przypadki, w których taki opis nie wniesie niczego odkrywczego, jednak warto pamiętać o jego istnieniu, gdyż jego przygotowywanie pozwala usystematyzować pracę i myślenie programistów o oprogramowaniu, przygotowując ich mentalnie do realizacji oraz przewidując pewne rzeczy.

Poniżej przedstawiliśmy wzór dokumentu, którym posługujemy się w Wilda Software do opisu architektury naszych projektów. Cały czas nad nim pracujemy - wraz z każdym klientem i przedsięwzięciem zyskujemy nowe spojrzenie i doświadczenie, które następnie wykorzystujemy do samodoskonalenia naszych technik. Tak powinno być w przypadku każdego software house'u, a także po prostu pojedynczych programistów, gdyż z każdego etapu planowania i realizacji można wynieść coś, co pomoże w przyszłych projektach.

Życzę Wam samych dobrych architektur!

Pozdrawiam i dziękuję - Jakub Rojek.

We can do quite a bit and what is more, our skills and resources are at your disposal. Take a peek at what we can offer you.

About author

Jakub Rojek

Lead programmer and co-owner of Wilda Software, with many years of experience in software creation and development, but also in writing texts for various blogs. A trained analyst and IT systems architect. At the same time he is a graduate of Poznan University of Technology and occasionally teaches at this university. In his free time, he enjoys playing video games (mainly card games), reading books, watching american football and e-sport, discovering heavier music, and pointing out other people's language mistakes.

Jakub Rojek