Nasza strona używa cookies. Korzystając ze strony, wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki. Rozumiem

Najważniejsze wzorce architektoniczne

Trung Anh Dang Leader of RnD Group / Viettel Business Solutions
Poznaj specyfikę oraz plusy i minusy kilku ważnych wzorców architektonicznych w tworzeniu oprogramowania.
Najważniejsze wzorce architektoniczne

Wzorzec architektoniczny to rozwiązanie wielokrotnego użytku dla powszechnie występującego problemu w architekturze oprogramowania, w określonym kontekście. A więc wzorzec jest rozwiązaniem problemu, ale w kontekście. Wielu programistów nadal do końca nie rozumie różnic między tymi wzorcami. Bywa też tak, że niewiele o nich w ogóle wiedzą. W tym artykule pewne rzeczy sobie zatem wyjaśnimy.

Oto najważniejsze wzorce architektoniczne:

  • Architektura warstwowa
  • Potoki i filtry
  • Klient-Serwer
  • Model View Controller
  • Event Driven Architecture
  • Mikroserwisy


Architektura warstwowa

Najpopularniejszym wzorcem architektonicznym jest architektura warstwowa (znana też jako architektura n-warstwowa). Jest ona dobrze znana większości architektów oprogramowania. Dobrze znają ją też projektanci i programiści. Chociaż nie ma określonych ograniczeń co do liczby i typu warstw, które powinny istnieć, to większość tej architektury składa się z następujących warstw: biznesowej, persystencji i bazy danych. Wygląda to następująco:

Popularny przykład architektury warstwowej


Kontekst

Wszystkie systemy muszą niezależnie rozwijać jakieś jego części. To dlatego programiści systemów potrzebują zrozumiałego i dobrze udokumentowanego podziału zadań, tak aby moduły systemu były rozwijane i utrzymywane niezależnie od siebie. 


Problem

Software musi zostać podzielony na części w taki sposób, aby moduły mogły być rozwijane oddzielnie, utrzymując jednocześnie minimalną interakcję między poszczególnymi częściami. Powinny one też wspierać przenośność, dawać możliwość modyfikacji czy ponownego wykorzystania komponentów. 


Rozwiązanie

Aby uzyskać taki podział obowiązków, wzorzec warstwowy dzieli soft na jednostki, które nazywamy warstwami. Każda warstwa stanowi grupę modułów i oferuje spójny zestaw usług. Użycie musi być jednokierunkowe. Warstwy dokonują podziału oprogramowania na części, z których każda wystawia publiczny interfejs. 

  • Po pierwsze, każda warstwa ma swoją rolę i za coś odpowiada. Na przykład, warstwa prezentacji będzie się zajmować wszystkim, co związane z UI. A to dlatego, że podział obowiązków wewnątrz architektury warstwowej ułatwia efektywny podział ról. 
  • Po drugie, architektura warstwowa jest podzielona technicznie, w przeciwieństwie do architektury domenowej. Tutaj mamy grupy komponentów, a tam grupy domen. 
  • Ostatnią rzeczą jest to, że każda z warstw jest oznaczona jako zamknięta lub otwarta. Zamknięta warstwa oznacza, że żądanie przechodzi z warstwy na warstwę. Musi też przejść przez warstwę znajdującą się bezpośrednio pod nią, aby dostać się do kolejnej warstwy, która jest poniżej. Żądanie nie może pominąć żadnych warstw.


Zamknięte warstwy i żądanie dostępu


Minusy

Warstwy powodują pogorszenie wydajności. Nie poleca się używania tego wzorca w aplikacjach wysokowydajnych - przechodzenie przez wiele warstw architektonicznych, aby spełnić żądanie biznesowe, nie jest efektywne. Warstwy powodują też zwiększenie nakładów na początkowe ich stworzenie i zwiększają złożoność systemu. 


Użycie

Wzorzec ten jest zalecany przy małych i prostych apkach, czy stronach internetowych. Przydaje się on w sytuacjach, gdy budżet nie jest za wysoki, a czasu mało. 


Wzorzec wielowarstwowy


Kontekst

W rozproszonym deploymencie często istnieje potrzeba dystrybucji infrastruktury w oddzielne podzbiory. 


Problem

Jak możemy podzielić system na obliczeniowo niezależne struktury wykonawcze, czyli grupy oprogramowania i sprzęt, połączone przez media komunikacyjne? 


Rozwiązanie

przykład wielowarstwowy - witryna konsumencka J2EE


Struktury wykonawcze wielu systemów są zorganizowane jako zbiór logicznych grup komponentów. Każdą z tych grup określamy mianem warstwy.


Minusy

Duży nakład na stworzenie takiej architektury i wzrost złożoności.


Użycie

Tego wzorca używamy zazwyczaj w rozproszonych systemach. 


Potoki i filtry

Jednym z bardziej powszechnych wzorców architektonicznych są potoki i filtry.

Potoki i filtry


Kontekst

Od wielu systemów wymaga się, aby przekształcały grupy oddzielnych elementów danych od wejścia do wyjścia. Wiele transformacji odbywa się wielokrotnie, a zatem warto je tworzyć jak niezależne części wielokrotnego użytku. 


Problem

Takie systemy trzeba podzielić na luźno połączone komponenty wielokrotnego użytku, które mają proste i powszechne mechanizmy do interakcji. W ten sposób można je ze sobą łączyć w sposób elastyczny. Takie komponenty też można łatwo później wykorzystać, ze względu na ich powszechność i luźne połączenia. A ich niezależność sprawia, że można je wykonywać równolegle. 


Rozwiązanie

Potoki w tej architekturze tworzą kanał komunikacji pomiędzy filtrami. Po pierwsze, żaden potok nie ma określonego kierunku i każdy z nich jest łączony od punktu do innego punktu ze względu na wydajność. Akceptuje on dane wejściowe z jednego źródła i zawsze przekierowuje dane wyjściowe do innego źródła. 

Mamy 4 rodzaje filtrów:

  • producent (źródło): początek procesu
  • transformator (mapa): transformuje dane 
  • tester (redukcja): testuje jedno lub więcej kryteriów
  • konsument (absorber): zakończenie.


Minusy

Wzorca tego nie powinno się używać przy systemach interaktywnych, a to ze względu na ich transformacyjny charakter. Nadmierne parsowanie prowadzi do utraty wydajności i zwiększonej złożoności przy samym tworzeniu filtrów. 


Użycie

Potoki i filtry można wykorzystać w wielu aplikacjach - szczególnie w takich, gdzie wykonuje się proste i jednokierunkowe procesowanie, np. narzędzia EDI, czy ETL. Kompilatory: następujące po sobie filtry wykonują analizę leksykalną, semantyczną, parsing i generują kod. 


Klient-serwer


Kontekst

Istnieją pewne wspólne zasoby i usługi, do których dostęp chce mieć spora liczba rozproszonych klientów. Chcemy więc kontrolować warunki dostępu, czy jakość tej usługi. 


Problem

Zarządzając zestawem współdzielonych zasobów i usług, możemy wykonywać modyfikacje i używać czegoś ponownie przez wyciąganie wspólnych usług i modyfikacje ich w jednym miejscu lub w niewielkiej liczbie lokalizacji. Chcemy też poprawić skalowalność i dostępność poprzez scentralizowanie kontroli nad zasobami i usługami przy jednoczesnej dystrybucji samych zasobów na wielu serwerach fizycznych.


Rozwiązanie

Komponenty i łączniki mają tutaj swoje określone zachowanie. 

  • Komponenty, zwane „klientami”, wysyłają żądania do komponentu zwanego „serwerem” i czekają na odpowiedź.
  • Komponent serwera otrzymuje żądanie od klienta i wysyła mu odpowiedź.


Minusy

Serwer może stanowić wąskie gardło wydajności i być powodem awarii. Zmiany decyzji dotyczących lokalizowania funkcji (w kliencie lub na serwerze) po zbudowaniu systemu są często złożone i kosztowne.


Użycie

Wzorzec ten można wykorzystać do modelowania części systemu, która ma wiele komponentów wysyłających żądania (klient) do innego komponentu (serwer) oferującego jakieś usługi. Przykładem takich aplikacji mogą być email, udostępnianie dokumentów, czy aplikacje w bankowości.


Model View Controller


Kontekst

UI jest najczęściej modyfikowaną częścią aplikacji interaktywnej. Użytkownicy chcą oglądać dane z różnych perspektyw (np. na wykresie słupkowym, czy kołowym). Każda reprezentacja danych ma wpływ na obecny ich stan.  


Problem

W jaki sposób oddzielić funkcje interfejsu użytkownika od funkcji aplikacji i nadal odpowiadać na dane wejściowe użytkownika lub zmiany w danych aplikacji bazowej? Jak można tworzyć, utrzymywać i koordynować wiele widoków interfejsu użytkownika, gdy zmieniają się dane aplikacji?


Rozwiązanie

Wzorzec Model View Controller (MVC) dzieli funkcje aplikacji na 3 rodzaje komponentów:

  • Model, zawierający dane aplikacji
  • Widok, który wyświetla część podstawowych danych i komunikuje się z użytkownikiem.
  • Kontroler, który pośredniczy między modelem a widokiem i zarządza powiadomieniami o zmianach stanu.


Minusy

Wzorzec ten może nie mieć sensu w przypadku prostych UI, ze względu na złożoność. Abstrakcje modelu, widoku i kontrolera mogą nie pasować do niektórych zestawów narzędzi do tworzenia interfejsów użytkownika.


Użycie

MVC to wzorzec architektoniczny, który jest powszechnie używany podczas tworzenia UI w aplikacjach webowych oraz mobilnych.


Event Driven Architecture


Kontekst

Należy tutaj zapewnić zasoby obliczeniowe i informacyjne, aby obsłużyć przychodzące, niezależne i asynchroniczne zdarzenia generowane przez aplikację w sposób, który można skalować w miarę wzrostu zapotrzebowania.


Problem

Jak stworzyć systemy rozproszone, które mogą obsługiwać asynchroniczne komunikaty kojarzone ze zdarzeniem i które mogą się skalować od małych i prostych do dużych i złożonych?


Rozwiązanie


Można tutaj wdrożyć niezależne procesy/procesory do obsługi zdarzeń. Nadchodzące wydarzenia są umieszczane w kolejce. Scheduler pobiera zdarzenia z kolejki i dystrybuuje je do odpowiedniego narzędzia obsługującego je, na podstawie odpowiednich zasad planowania.


Minusy

Mogą się pojawić problemy z wydajnością oraz z error recovery. 


Użycie

Apka e-commerce, korzystająca z tego podejścia działałaby w następujący sposób:

Opcja zamówień tworzy dane zamówienie w stanie oczekującym i publikuje zdarzenie OrderCreated.

  • Obsługa klienta odbiera zdarzenie i próbuje zarezerwować kredyt na to zamówienie. Następnie publikuje zdarzenie Credit Reserved lub CreditLimitExceeded
  • Opcja z zamówieniami otrzymuje zdarzenie od Obsługi Klienta i zmienia stan zamówienia na zatwierdzone lub anulowane.


Mirkoserwisy


Kontekst

Mamy tutaj deployment serwerowych aplikacji biznesowych. Aplikacje te obsługują różne przeglądarki i natywnych klientów mobilnych. Aplikacja obsługuje żądania klientów, wykonując logikę biznesową, uzyskując dostęp do bazy danych, wymieniając komunikaty z innymi systemami, i zwracając odpowiedzi. Aplikacja może udostępniać jakieś zewnętrzne API.


Problem

Aplikacje monolityczne mogą stać się zbyt duże i złożone, aby zapewnić wydajną obsługę, czy deployment w celu optymalnego wykorzystania zasobów rozproszonych, na przykład w środowiskach chmurowych.


Rozwiązanie


Twórz aplikacje jako zestawy serwisów. Każda usługa jest niezależnie wdrażana i skalowalna oraz ma granice wyznaczone przez API. Różne serwisy mogą być napisane w różnych językach programowania i opracowywane przez różne zespoły. Mogą one również zarządzać swoją własną bazą danych.


Minusy

Systemy muszą być zaprojektowane tak, aby radziły sobie z awariami usług, które wymagają obszerniejszego monitorowania systemu. Mamy tutaj również choreografię usług.

Będziemy również potrzebować znacznie więcej pamięci. 


Użycie

Wiele przypadków użycia ma zastosowanie w mikroserwisach, a szczególnie te, które operują na obszernym potoku danych. System oparty na mikroserwisach byłby idealny dla systemu raportowania sprzedaży w sklepie detalicznym.

Każdy etap procesu przygotowania danych byłby obsługiwany przez mikroserwis: zbieranie danych, czyszczenie, normalizacja, wzbogacanie, agregacja, raportowanie itp.

Proste, prawda?


Oryginał tekstu w języku angielskim możesz przeczytać tutaj

Rozpocznij dyskusję

Lubisz dzielić się wiedzą i chcesz zostać autorem?

Podziel się wiedzą z 160 tysiącami naszych czytelników

Dowiedz się więcej