Wzorzec architektoniczny, jakim jest architektura heksagonalna, pozwala zaimplementować logikę biznesową odseparowaną od zależności.
Co to jest architektura heksagonalna?
Wzorzec architektoniczny pozwala zaimplementować logikę biznesową, całkowicie odseparowaną od zależności. Założeniem jest wykorzystanie aplikacji przez dowolne wejście, np. aplikację konsolową czy API.
Przeczytaj również
Korzystając z portów i adapterów, można w prosty sposób uruchomić testy automatyczne, w izolacji od zewnętrznych serwerów i usług np. baz danych.
Architektura heksagonalna pozwala na modularyzację aplikacji, czyli bezproblemową zmianę komponentów. Można w łatwy sposób zaimplementować nowy interfejs użytkownika i przetestować domenę z wykorzystaniem Stubów lub Mocków.
Stosując tę architekturę, można uniknąć przeniknięcia logiki biznesowej do interfejsu użytkownika. Kod jest dzięki temu o wiele prostszy do przetestowania.
Jak wygląda architektura heksagonalna Java?
Architektura portów i adapterów bazuje na modelu warstwowym i dzieli się na dwie warstwy – Domeny i Infrastruktury. Kierunek zależności biegnie od Domeny na zewnątrz. Wyróżnić należy tu również porty i adaptery, dzięki którym można komunikować się między warstwami.
Porty i adaptery dzielą się na wejściowe i wyjściowe na każdym z boków umocowanego heksagonu.
Port to interfejs wejściowy do aplikacji lub forma dostępu do danych. Adapter to forma dopasowana do portu. W technicznym rozumieniu port jest traktowany jako interfejs, a adapter jako jego implementacja.
Architektura heksagonalna Java w praktyce
Działanie architektury heksagonalnej przedstawimy na podstawie aplikacji do przechowywania książek. Wyszukiwane będą wyłącznie zapisane publikacje.
Książki można przechowywać w bazie danych i przeszukiwać za pomocą API.
- Podstawą jest zdefiniowanie encji aplikacji.
public class Book {
private String title;
private String isbn;
private String author;
// standard constructor and getters
}
- Należy zdefiniować odpowiednik portu przychodzącego.
public interface ApiInterface {
Book get(String isbn);
}
- Należy zdefiniować port wyjściowy.
public interface BookDaoInterface {
Book get(String isbn);
}
- Należy zaimplementować wcześniej zdefiniowane porty wyjściowe.
public class BookDaoPostgres implements BookDaoInterface {
public Book get(String isbn) {
// TODO implement PostgreSQL logic here
return null;
}
}
- Należy zdefiniować usługę domenoą dla aplikacji.
public class BookService {
private BookDaoInterface dao;
public BookService(BookDaoInterface bookDao) {
dao = bookDao;
}
public Book search(String isbn) {
return dao.get(isbn);
}
}
- Należy stworzyć adapter dla portu wejściowego.
public class HttpApi implements ApiInterface {
private BookService service;
public HttpApi(BookService service) {
this.service = service;
}
// TODO implement HTTP endpoint
public Book get(String isbn) {
return service.search(isbn);
}
}
Architektura heksagonalna i jej zastosowanie
Stosując opisane wyżej podejście, można zyskać elastyczność w działaniach, zastępując różne zależności. Testowanie aplikacji może znajdować się na wyższym poziomie.