Разница между шестиугольной архитектурой и многоуровневой архитектурой

Архитектура

Как бэкенд-программист, я считаю, что все знакомы с моделью трехуровневой архитектуры MVC.Три уровня расположены сверху вниз, и только верхний уровень может вызывать нижний уровень. Как правило, чем ниже уровень, тем более общий, а чем выше уровень, тем больше деталей.

С развитием трафика некоторых основных видов деятельности нам обычно необходимо принимать меры по оптимизации, такие как добавление кеша, добавление MQ и изменение источников данных.

1.缓存可选redis,memcache
2.MQ可选kafka,rocketmq,rabbitmq
3.数据源可选:mysql,mongodb,elasticsearch

Конечно, когда мы будем проводить эти оптимизации, мы будем рассматривать mq, mongodb и т. д. как уровень инфраструктуры. Из этого вытекает четырехуровневая архитектура, а общая логика вызовов redis и mq инкапсулируется в инфраструктуру.

Эти оптимизированные действия обычно не меняют исходную бизнес-логику. Но для оптимизации напишем это в сервисном слое, например:

1.执行成功就发个MQ
2.执行某个事件的时候,同步一下缓存
3.依赖关系为,domain依赖infrastructure

вопрос:

Логически говоря, уровень предметной области пишет бизнес-логику, и оптимизация не включает изменения бизнес-логики, но изменяет слой предметной области. Поскольку уровень предметной области опирается на инфраструктуру, бизнес зависит от конкретной технологии реализации. Поэтому, чтобы отделить бизнес от конкретной реализации, мы используем средства инверсии зависимостей для реконструкции

依赖倒置原则的包含如下的三层含义:
1.高层模块不应该依赖低层模块,两者都应该依赖其抽象
2.抽象不应该依赖细节
3.细节应该依赖抽象

Модули высокого уровня не зависят от модулей низкого уровня: тогда можно определять интерфейсы хранения на уровне предметной области, например AARepository, но не писать конкретные технические реализации

Абстракция не зависит от деталей: на уровне домена классы, которые не зависят от других пакетов, например, когда используется хранилище данных, могут напрямую вызывать абстрактный интерфейс домена.

Верхний уровень передает реализацию инфраструктуры на уровень предметной области посредством внедрения зависимостей.

Таким образом, наша архитектура больше не является иерархической структурой (вызов сверху вниз). Вместо этого все абстракции размещаются на уровне предметной области, а все детали передаются в приложение и инфраструктуру. Чем абстрактнее, тем он стабильнее, поэтому такой подход может эффективно сократить изменения в бизнесе.

Архитектура стала логикой изнутри наружу, чем более абстрактной она становится, тем более детальной она выходит. В северном шлюзе rest и dubbo могут использоваться для вызова бизнес-логики, а южный шлюз может записывать данные в Redis или MQ.

конкретная реализация кода

Следующее дело: После того, как курс успешно отправлен, нужно отправить сообщение на IOT устройства, отправить MQ и обновить кеш.

Традиционная практика:

void sendCourse(){
	//执行业务逻辑
    //发送消息给设备IOT
    //发送MQ
    //更新缓存
}

С постоянным увеличением схем оптимизации бизнес-логика будет накапливаться все больше и больше Шестиугольная архитектура + практика EDA

public SendCourseService sendCourseService{
     void sendCourse(SendCourseCommand command){
	    //执行业务逻辑并发布发布课程事件
        eventBus.push(SendCourseEvent())
     } 
}

Когда мы хотим обновить операцию кеша, это на самом деле не имеет ничего общего с бизнес-логикой Мы можем определить прослушиватель для прослушивания опубликованного события курса.Где должен быть написан этот класс SendCourseCacheHandler?

public class SendCourseCacheHandler{
   
    private Jedis jedis;

    public void deleteCache(SendCourseEvent event){
         //删除缓存
    }
}
  1. Разделение записи в домен по абстракции и записи деталей наружу не подходит для записи в слой инфраструктуры, потому что сильно связано с бизнесом.

  2. Неуместно писать в домен, потому что это сильно связано с конкретной реализацией Redis.

Так что этот класс должен быть написан на прикладном уровне, на самом деле домен вызывает приложение, так сказано. . . Это не многоуровневая архитектура. Когда мы думаем, мы судим, где писать по уровню абстракции, а не вызывая сверху вниз.

Так как же этот слушатель сочетается с бизнесом? В это время в игру вступает роль прикладного уровня, и мы можем использовать приложение как логику бизнес-сборки.

Например, мы регистрируем прослушиватели до начала бизнеса, чтобы эти слушатели могли быть вызваны обратно, когда бизнес будет выполнен.

public class CourseAppService{
   
    private SendCourseCacheHandler sendCourseCacheHandler;

    private SendCourseMQHandler sendCourseMQHandler;

    private SendCourseService sendCourseService;

    private EventBus eventBus;

    public void sendCourse(SendCourseCommand command){
         //删除缓存
         eventBus.register(sendCourseCacheHandler);
         //发MQ
         eventBus.register(sendCourseMQHandler);
         sendCourseService.sendCourse(command);
    }
}

Подходящая сцена:

1.读/写比较大的场景
2.对查询实时性要求不高的场景
3.内部状态改变会触发各种数据的同步,如课程完成,课程发布等等等等。。。
4.外部实现可替换,如mq可以随意替换实现

Не подходит для сценариев:

只有简单CRUD的业务,没有重的业务逻辑,不适合搞那么复杂,因为没必要抽出domain层