Правильно ли я понял порты и адаптеры / шестиугольную архитектуру?
Архитектура портов и адаптеров направлена на создание разобщенного кода. Уровень домена не зависит напрямую от уровня инфраструктуры, а зависит от порта (интерфейса), а реализация порта находится на уровне инфраструктуры, верно?
Моя структура папок будет такой:
Проект для моего интерфейса
Проект для ядра приложения, который содержит службу приложений, доменные службы и доменные модели.
Проект для портов: он содержит строго интерфейсы.
Проект для инфраструктуры, и у меня там есть папка персистентности.
Механизм доставки может быть переключен (из консольного приложения в веб-приложение...), и ядро все равно будет работать так же.
То же самое с инфраструктурой, я мог бы использовать инфраструктуру сущностей один раз, а затем переключиться на более щадящий, не вызывая изменений в ядре.
Пока все хорошо, или я что-то упустил по пути, или мне не хватало самого базового понимания архитектуры?
Теперь используйте код:
Если у меня есть консольное приложение, где я должен набрать команду, и это создает клиента.
Класс из Службы приложений, найденный в проекте Core. Он использует внедрение зависимостей для доступа к реализации IPersistence.
public class AddNewCustomer
{
private readonly IPersistence _persistence;
public AddNewCustomer(IPersistence persistence)
{
_persistence = persistence;
}
public bool addToDb(customer customer)
{
return _persistence.add(customer);
}
}
Интерфейс в проекте порта.
public interface IPersistence
{
bool add(Customer customer);
}
Реализация в интерфейсе проекта.
public class Persistence: IPersistence
{
public bool add(customer customer)
{
//inserts into DB
}
}
Предполагается, что проект порта должен быть строго связан с интерфейсами? Как вы структурируете (структуру папок) ваш проект портов и адаптеров?
1 ответ
Пока все хорошо, или я что-то упустил по пути, или мне не хватало самого базового понимания архитектуры?
Я постараюсь выразить себя правильно. Надеюсь, поможет.
Архитектура портов и адаптеров направлена на создание разобщенного кода.
Это правда. Но это не главная цель "per se". Это способ достижения основной цели, которая заключается в том, чтобы иметь возможность тестировать приложение изолированно от внешних устройств (аппаратных средств, программного обеспечения, людей и т. Д.), Которые выходят за рамки приложения.
Уровень домена не зависит напрямую от уровня инфраструктуры, а зависит от порта (интерфейса), а реализация порта находится на уровне инфраструктуры, верно?
Вы говорите о слоях. Гексагональной архитектуры нет. Это просто говорит о том, что у вас есть приложение (шестиугольник) с портами, через которые внешние приложения реального мира (так называемые актеры) взаимодействуют с приложением. Порты принадлежат приложению (которое не зависит от технологии), а взаимодействие порт-субъект осуществляется через технологически зависимый адаптер.
Проект для ядра приложения, который содержит службу приложений, доменные службы и доменные модели.
Здесь я просто хотел бы прокомментировать, что шаблон шестигранной архитектуры ничего не говорит о внутренней структуре приложения (шестиугольник).
Механизм доставки может быть переключен (из консольного приложения в веб-приложение...), и ядро все равно будет работать так же.
Это нормально. Консоль и веб-приложения - это адаптеры, которые управляют приложением. Они используют порты драйвера (порты, которые предлагают функциональность приложения внешним субъектам).
Я мог бы использовать Entity Framework один раз, а затем переключиться на Dapper, не вызывая изменений в ядре.
Это нормально. Это могут быть адаптеры для персистентного порта, который является управляемым портом (управляемый адаптер реализует управляемый порт для взаимодействия с внешним субъектом).
Предполагается, что проект порта должен быть строго связан с интерфейсами? Как вы структурируете (структуру папок) ваш проект портов и адаптеров?
У меня есть "модуль java 9" для шестиугольника (вы называете его Core). И порты являются пакетами модулей, которые я экспортирую. Каждый порт представляет собой пакет с сервисным интерфейсом, определяющим операции порта. Но у вас может быть больше классов (представляющих аргументы операции, средства отображения, если вы не хотите открывать внутренние объекты для внешнего мира,...). Реализация зависит от вас.
Структура моей папки (java-пакетов):
Hexagon:
[app-name].hexagon.internal = внутренняя часть приложения
[app-name].hexagon.driver.[driver-port-name] = один или каждый порт драйвера (API приложения)
[имя-приложения].hexagon.driven.[имя-управляемого-порта] = один или каждый управляемый порт (SPI приложения)
Адаптер между портом и актером с использованием технологии:
[имя-приложения].adapter.driver.[имя-порта-драйвера].[имя-субъекта].[технология] = один для каждого адаптера драйвера
[имя-приложения].adapter.driven.[имя-управляемого-порта].[имя-субъекта].[технология] = один для каждого управляемого адаптера
Я написал статью о гексагональной архитектуре, где я объясняю шаблон, и я собираюсь опубликовать пример реализации. Если вы хотите прочитать это, вот ссылка:
https://softwarecampament.wordpress.com/portsadapters
Надеюсь, поможет.