Zastanawiasz się, jak zorganizować swoją aplikację, by była zarówno skalowalna, jak i łatwa w utrzymaniu? Architektura warstwowa (n-tier), to odpowiedź na Twój problem.
Wstęp
Chyba każdy programista chce tworzyć kod, który nie tylko działa, ale jest również dobrze zorganizowany i stosunkowo łatwy w utrzymaniu. W świecie programowania kluczowe znaczenie ma właściwe rozplanowanie struktury aplikacji. Dziś zaprezentuję Ci jedną z wielu możliwości, jak poukładać swój kod na poziomie architektury aplikacyjnej. Zagłębimy się w szczegóły architektury warstwowej, zwanej często n-tier. Temat ten lekko poruszyłem we wpisie pt. „Jak zostać architektem oprogramowania”, jednak dzisiaj będzie bardziej szczegółowo. Zaczynajmy!
Architektura warstwowa à la n-tier – czym jest?
Architektura n-tier, zwana również warstwową, to sposób organizacji aplikacji, w którym poszczególne warstwy pełnią konkretne role w obsłudze logiki i komunikacji z innymi elementami systemu. Zapytanie zaczyna się zwykle w warstwie pierwszej i podążą hierarchicznie, poprzez kolejne, zdefiniowane w warstwy fragmenty kodu. Z racji faktu, iż jest to obecnie jedna z najczęściej wybieranych architektur aplikacyjnych dla systemów back end-owych, często nazywamy ją tą domyślną, początkową. Określana jest początkową, tą po którą sięgamy zaczynając nasze projekty, ponieważ system wraz z rozwojem może stać zbyt skomplikowany do tego typu architektury. Należy wtedy zastanowić się nad innym rodzajem, który spełniał będzie nowe wymagania.
Architektura trzy warstwowa – czyli najczęstszy typ n-tier
Najczęstszym wariantem architektury n-tier jest ten, w którym występują trzy warstwy:
- UI (User Interface) – tutaj zaczyna się zapytanie, najczęściej jest to kontroler REST API, który uruchamia walidację danych wejściowych i deleguje zadania dla kolejnego poziomu, a następnie odpowiednio przerabia wynik działania i zwraca rezultat dla użytkownika.
export class IncomesController {
constructor(private readonly incomesService: IncomesService) {}
@Post('calculate/year')
async calculateYearIncome(@Body() request: CalculateYearIncomeRequest): Promise<YearIncomeResponse> {
const yearIncome = await this.incomesService.calculateYearIncome(request as CalculateYearIncomeDTO);
return YearIncomeResponseMapper.mapIncomeEntity(yearIncome);
}
}
- Logic – warstwa, która odpowiedzialna jest za realizację logiki naszego systemu. Taki kod najczęściej umieszczamy w klasach serwisowych, które kontrolują logiczne flow realizowanego zadania, często korzystając przy tym z innych elementów takich, jak np.: fabryki, klienty HTTP czy elementy z warstwy niższej.
export class ReservationsService {
constructor(private readonly reservationRepository: ReservationRepository) {}
create(createReservationDTO: CreateReservationDTO): Promise<void> {
const reservation = ReservationEntity.create(createReservationDTO);
await this.reservationRepository.save(reservation);
}
}
- DAL (Data Access Layer) – najniższy poziom, który zawiera elementy zapisujące i odczytujące dane, np. z bazy danych czy cache. Najczęściej umieszczamy tutaj DAO, bądź repozytoria.
export class UserRepository {
constructor(private readonly userDAO: UserDAO) {}
async findOneById(id: string): Promise<UserEntity> {
const user = await this.userDAO.findOneById(id);
const address = JSON.parse(user.address);
user.setAddress(address);
return user;
}
}
Ile tych warstw?
Oczywiście, architektura n-tier ma to do siebie, że może być rozszerzona o kolejne warstwy, np. domenową czy dedykowaną dla cache. Zazwyczaj jednak, jeśli nasz system potrzebuje kolejnych warstw, to znak, że może nie jest to odpowiedni typ architektury aplikacyjnej?
Niemniej jednak, oprócz wersji podstawowej, z trzema warstwami, możemy czasami znaleźć wariant, gdzie poziomów jest cztery. Wariant 4-tier występuje w bardziej skomplikowanych przykładach. Dochodzi wówczas dodatkowa warstwa, domeny, zaś warstwa logiki przekształca się w warstwę aplikacji. Nasze serwisy stają się wtedy małymi procedurami, które jedynie operują na elementach domeny, wywołując odpowiednie metody i korzystając z DAL, umieszczają zmienione elementy w źródle danych systemu.
Kiedy warto sięgnąć po architekturę warstwową?
Architektura n-tier sprawdzi się idealnie na początku projektu, a także w przypadku prostych systemów, które można w łatwy sposób, logicznie podzielić na warstwy. Wszystkie CRUD-y, bądź aplikacje, które nie zawierają sporej ilości logiki domenowej, to idealne przykłady do zastosowania 3-tier. Nie jest to jednak odpowiedni rodzaj architektury dla bardziej skomplikowanych projektów z silną logiką biznesową. W takich przypadkach lepiej zastanowić się nad innymi architekturami, takimi jak: pipes and filters, shared kernel, hexagonal czy onion.
Wszystkie te rodzaje architektury aplikacyjnej: pipes and filters, shared kernel, hexagonal oraz onion omówię już niebawem. Aby nie przegapić tych wpisów, to zachęcam Cię do zapisania się do mojego newsletter-a (kliknij).
Polecam również przeczytać artykuł Martina Fowler-a, który zebrał w bullet point-y wytyczne do pracy z tym rodzajem architektury: Layering Principles.
Podsumowanie
- Architektura warstwowa: Organizacja aplikacji przy pomocy warstw, gdzie każda z nich pełni inną rolę logiczną oraz komunikacyjną.
- 3-tier: UI, Logic, DAL, to podstawowy wariant architektury warstwowej.
- Architektura dla CRUD-ów: n-tier, to rodzaj architektury aplikacyjnej skrojony pod stosunkowo proste systemy.
Dodaj komentarz