Obecnie w branży IT istnieje ogromny przekrój dostępnych rozwiązań dla szkieletów aplikacji biznesowych. Mowa tutaj oczywiście o architekturze. Możemy wybierać pomiędzy koncepcją systemów rozproszonych czy np. programowania reaktywnego. Jednak czy wybór architektury dla naszego projektu powinien być uzależniony od panujących aktualnie trendów? Moim zdaniem zdecydowanie nie. Nasza aplikacja powinna ewoluować. Wraz z jej rozwojem należy podejmować decyzje o tym czy warto przejść na inne rozwiązanie czy też nie. Początkowo można wybrać najprostszą architekturę i co jakiś czas zastanowić się, w którym kierunku zmierzamy, co warto zmienić.
Z tego powodu postanowiłem napisać tą krótką serię artykułów, w których przyjrzę się bliżej sześciu wybranym architekturom: architekturze warstwowej, architekturze DDD, architekturze heksagonalnej, architekturze mikroserwisowej, architekturze reaktywnej oraz serverless. Niestety na co dzień nie mam styczności z większością z nich w kodzie produkcyjnym. Ubolewam nad tym, ale nie poddaję się. Cały czas edukuję się w tym kierunku i staram się tworzyć aplikacje w oparciu o wyżej wymienione rozwiązania. No dobrze, ale przejdźmy do sedna dzisiejszego artykułu.
Czym jest architektura warstwowa?
Każdy złożony system chcąc nie chcą posiada jakąś architekturę, nawet jak nie jest ona określona wprost (pięknym określeniem na to jest “Big Ball of mud”). Czym więc jest architektura? Można ją określić jako strukturę systemu, dzięki której wiadomo w jakim kierunku zmierzamy z naszym rozwiązaniem. Jest drogowskazem mającym na celu zachowanie spójności w obrębie całej aplikacji oraz pilnowanie, aby jej rozwój przebiegał w sposób przewidywalny. Następstwem takiego biegu rzeczy jest podjęcie decyzji o tym z jakich narzędzi oraz technologii będzie korzystał zespół programistyczny tworzący aplikację.
Jedną z możliwych opcji jest tworzenie oprogramowania w taki sposób, aby była to jednolita całość. Aplikacja będzie miała wtedy postać monolitu. Przykładem takiego rozwiązania może być właśnie architektura warstwowa. Często ucząc się nowego frameworka (jakim jest np. Spring) kursy internetowe świadomie lub nieświadomie przeprowadzają nas przez tego typu strukturę oprogramowania. Aplikacja zostaje podzielona według swoich technicznych odpowiedzialności. W ten sposób powstają trzy warstwy: prezentacji, serwisów biznesowych oraz dostępu do danych.
Charakterystyka architektury warstwowej
Architekturze warstwowej najczęściej towarzyszy tak zwany model anemiczny. Co się na niego składa? Klasy, których nazwy przedstawiają pojęcia dziedzinowe, służą tylko i wyłącznie jako nośniki danych. Nie posiadają one logiki biznesowej zmieniającej ich stan. Za to wszystkie reguły dziedzinowe znajdują się w klasach będących częścią warstwy serwisowej. Ten aspekt sprawia, że architektura warstwowa łamie wszelkie zasady OOP chociaż głównie korzysta się z niej w językach obiektowych. Istnieje spore ryzyko, że aspekty biznesowe zostaną rozsiane po całej aplikacji i będą się duplikowały. Na pewno przyprawi to o ból głowy nie jednego programistę, który będzie musiał wykonać małą poprawkę w implementacji takiego reguły.
Najczęściej systemy oparte o architekturę warstwową powstają według następującego schematu. Na początku kształtuje się projekt bazy danych z ogromną ilością tabel, a na jej podstawie zespół deweloperski tworzy aplikację.
Za i przeciw
Na pewno ogromną zaletą architektury warstwowej jest jej prostota co potwierdza fakt, że wiele systemów rozwijanych od lat ma właśnie taką strukturę. Mało doświadczeni programiści z łatwością przyswajają taką architekturę, gdzie podział aplikacji odbywa się pod względem odpowiedzialności technicznych.
Programowana aplikacja monolityczna kompiluje się najczęściej do jednego artefaktu. Na plus takiego rozwiązania można powiedzieć, że nie ma problemów z jego wdrożeniem. Struktura jest prosta, trzeba jedynie wgrać daną paczkę i uruchomić na środowisku produkcyjnym. Jak każde rozwiązanie to także ma swoje minusy. Skompilowany artefakt potrafi po prostu osiągnąć wielkie rozmiary.
Decydując się na architekturę warstwową trzeba wziąć pod uwagę fakt, że przez monolityczny model danych aplikacja bardzo szybko stanie się skomplikowana. Brak jest jakichkolwiek granic przez co wszystko jest ze sobą wymieszane. Dodatkowo jak już wcześniej wspomniałem reguły biznesowe są rozsiane po klasach serwisowych przez co bardzo łatwo jest o powtórzenia w kodzie. Ciężko jest po prostu zapanować nad tak ogromną aplikacją i pamiętać o każdej funkcjonalności.
Poważnym argumentem przemawiającym na niekorzyść architektury warstwowej jest brak skalowalności. System pracuje jako jeden organizm. Z tego powodu, gdy jedna jego część szwankuje wydajnościowo odbija się to na innych częściach. Praktycznie nie możliwe jest wyodrębnienie kawałka oprogramowania, który można by skalować. Właśnie z tego powodu skalowana jest cała aplikacja chociaż nie jest to konieczne. Powoduje to duży narzut sprzętowy co sprowadza się oczywiście do dodatkowych kosztów.
Podsumowanie
W tym artykule chciałem przedstawić najczęściej spotykany scenariusz architektury warstwowej. Oczywiście nie każdy system napisany w oparciu o taki szkielet musi mieć tego typu problemy. Na pewno można spotkać aplikacje w architekturze warstwowej, które nie posiadają monolitycznego modelu danych. Zakładam, że jednak jest to rzadkość.
Mam nadzieję, że ta seria architektoniczna przyda się Ci jako forma powtórzenia teorii dotyczącej najczęściej spotykanych rozwiązań. Muszę przyznać, że sam cały czas uczę się nowych rzeczy w dziedzinach, które wydaje mi się, że znam bardzo dobrze. W następnym artykule chciałbym przedstawić architekturę w oparciu o Domain-Driven Design.
Na razie i cześć!