Wybór architektury

Z reguły gdy tworzymy jakąś aplikację jest to jedna wielka aplikacja albo zbiór małych aplikacji, które w mniejszym lub większym stopniu się ze sobą komunikują. Ponadto często jest tak, że architektura większości z nich jest dokładnie taka sama. Czy to aby na pewno dobre podejście?

Gdy próbuję dopytywać czemu w firmie wszystkie aplikacje mają taką samą architekturę, to najczęstszym argumentem, z jakim się spotykam jest: „chcemy mieć wszystko tak samo, aby łatwo się odnaleźć, gdy ktoś zmieni projekt”. Czasem nawet zdarza się, że w firmie jest jakiś „architekt”, który ma wpływ na to jak wygląda architektura. Bardzo często niestety jego praca wygląda tak, że wymyśli jedną architekturę i musi być ona zastosowana w każdej aplikacji. Ciężko mu się dziwić – jeśli dana architektura sprawdziła mu się w jednym projekcie, to liczy na to, że sprawdzi się też w innym. To trochę jak w tym powiedzeniu: „gdy twoim jedynym narzędziem jest młotek, wszystko zaczyna ci przypominać gwoździe”. Takie podejście sprawia, że mamy nieodpowiednio dobraną architekturę do danej aplikacji. Każda aplikacja powstaje po to, aby rozwiązać jakiś problem. Niestety nie każdy problem, da się rozwiązać tak samo. Niektóre problemy są proste, a niektóre skomplikowane. W rezultacie często w projektach mamy albo nadmierne skomplikowanie, albo wręcz przeciwnie – próbujemy zastosować proste rozwiązanie do złożonego problemu. W obu przypadkach mocno się męczymy i finalnie projekt powstaje dużo dłużej, niż by mógł.

Wielokrotnie spotkałem się z takimi architekturami przy różnych projektach. Co gorsza, czasem nawet sam je proponowałem. Myślałem wtedy, że tak będzie dobrze, że to słuszna droga. Nie trzeba chyba jednak nikomu mówić jak to się kończyło. Jednakże nauczyło mnie to, że część problemów jest podobna, a część zupełnie inna. W związku z tym do niektórych z nich możemy zastosować podobne architektury, jakie mamy w innych projektach, ale są też takie, do których powinniśmy spróbować czegoś innego.

Projekty proste

Czasem, gdy słyszymy o tym, co dana aplikacja ma robić, to od razu widzimy, że nie ma w tym skomplikowanego. Jest to na przykład proste zapisanie danych z interfejsu użytkownika w bazie danych – czyli aplikacja, dla którego świetnie sprawdzi się architektura typu CRUD. Innym przykładem może być stworzenie aplikacji, która będzie działać jako proxy lub fasada do jakiegoś innego systemu.

W tego typu projektach nie musimy tworzyć zaawansowanej architektury. Często wystarczą nam 1-2 warstwy. Nie potrzebujemy ich dużej ilości, ponieważ każda z nich będzie miała taką samą złożoność – z reguły będzie to wywołanie operacji z warstwy niższej.

Przykładem takiej aplikacji może być blog, czyli zbiór postów i komentarzy.

Projekty skomplikowane

Z drugiej strony czasem trafiają nam się projekty, gdzie jak słyszymy co będą one miały robić, to przychodzi nam do głowy jedna myśl: „będzie grubo”. Oczywiście nie dla każdej aplikacji to skomplikowanie wynika z tego samego powodu. Czasem wynika ono z tego, że aplikacja ma być mocno konfigurowalna. Czasem ma mieć bardzo złożoną/rozbudowaną logikę biznesową. A jeszcze inny przykład to taki, że może zawierać skomplikowane przetwarzanie albo algorytmy. Jednak zawsze te aplikacje są dość mocno skomplikowane i dlatego powinniśmy poświęcić trochę czasu na odpowiednie dobranie architektury. Często może się wtedy okazać, że będziemy chcieli zastosować inną.

Przykładami takich mniej oczywistych architektur może być:

  • Architektura portów i adapterów (ports and adapters),
  • Architektura potoków i filtrów (pipes and filters),
  • Architektura mikrojądro (microkernel).

Zastanawiając się nad architekturą do tego typu projektów, jedno z pytań jakie powinniśmy sobie zadać jest co w naszej aplikacji może się zmienić, a co nie. Najlepiej byłoby porozmawiać o tym z biznesem, ale nie zawsze istnieje taka możliwość. Niemniej jednak w miejscach, które mogą ulec zmianie, powinniśmy zastosować wzorce, które nam te zmiany ułatwią. Z drugiej strony w miejscach, gdzie takie zmiany są mało prawdopodobne, nie powinniśmy zbytnio komplikować, tylko napisać najprostszy kod jaki się da.

Myśląc o architekturze czasem warto też zastanowić się nad prawdopodobieństwem wymiany jednej biblioteki na inną albo chociaż nawet nad podniesieniem wersji używanych bibliotek. Czy takie zmiany mogą wystąpić i jeśli tak, to warto też być na nie przygotowanym.

Przykład – skomplikowany zapis

Jednym z przykładów projektów skomplikowanych mogą być systemy do składania zamówień albo systemy księgowe. Charakteryzują się one skomplikowanym zapisem danych, ponieważ w momencie dodania nowego dokumentu, dzieje się wiele skomplikowanych operacji. Często najpierw musimy sprawdzić, czy w ogóle taka operacja jest możliwa albo musimy coś przeliczyć. Dodatkowo w tego typu systemach mamy też dużo integracji z innymi systemami.

Kolejnym charakterystycznym elementem takich projektów jest to, że „zapisów” robimy bardzo dużo i chcemy, aby to była operacja szybka i bezproblemowa. Często nawet jest to dla nas operacja dużo ważniejsza niż późniejszy odczyt takiego zapisanego obiektu. W tego typu aplikacjach kluczowe może być wydzielenie odpowiednich warstw i abstrakcji.

Przykład – skomplikowany odczyt

Innym przykładem skomplikowanego projektu może być wyszukiwarka albo aplikacja do raportów. W tego typu systemach dużo częściej jest używana opcja odczytu danych niż ich zapisu. Możemy sobie pozwolić na to, aby czas zapisu obiektu był długi, ale nie możemy sobie pozwolić, aby użytkownicy długo czekali na wyniki wyszukiwań. Odczyt danych jest tu dużo ważniejszy niż ich zapis.

Przykładem takiej aplikacji może być allegro – nowo dodana akcja sprzedaży jakiegoś przedmiotu nie musi być automatycznie widoczna u wszystkich użytkowników. Z drugiej strony gdy, ktoś jest zainteresowany kupnem jakiegoś przedmiotu, to po wpisaniu jego nazwy w wyszukiwarkę, wyniki powinny pojawić się jak najszybciej.

W tego typu aplikacjach często powinniśmy zastosować operacje, które spowodują, że odczyt będzie bardzo szybki. Może to być na przykład odpowiednie przetworzenie danych podczas ich zapisu, aby podczas odczytu nie musiały być w ogóle przetwarzane. Zastosowana przez nas architektura powinna nam to ułatwiać.

Podsumowanie

W naszej pracy natrafiamy na problemy proste i skomplikowane. Powinniśmy zdawać sobie sprawę z tego, że nie każdy problem jest taki sami i nie każdy da się rozwiązać tak samo. Dlatego ważne jest, aby nie używać zawsze tej samej architektury, tylko dobierać architekturę do problemu, który dana aplikacja ma rozwiązać. Nawet jeśli jakiś problem wydaje się dla nas oczywisty, to warto nad nim chwilę posiedzieć i zastanowić się, czy wybrane przez nas rozwiązanie, będzie ułatwiało poradzenie sobie z najbardziej prawdopodobnymi przypadkami.

1 myśl na “Wybór architektury”

  1. Pingback: dotnetomaniak.pl

Dodaj komentarz