Ответ
При добавлении поддержки WebSocket в приложении, построенном по принципам чистой архитектуры, изменения коснутся в основном внешних слоев, в то время как ядро бизнес-логики останется неизменным. Главное правило — зависимости направлены внутрь.
Будут затронуты следующие слои:
-
Frameworks & Drivers (Инфраструктурный слой):
- Что здесь делается: Реализуется конкретный WebSocket-сервер с использованием внешней библиотеки (например,
gorilla/websocket). Этот код отвечает за установку соединений, чтение и запись байтов, обработку ошибок подключения. - Пример: Создается структура, которая реализует интерфейс, определенный в слое Use Cases.
- Что здесь делается: Реализуется конкретный WebSocket-сервер с использованием внешней библиотеки (например,
-
Interface Adapters (Слой адаптеров):
- Что здесь делается: Добавляется новый
ControllerилиHandler, который принимает входящие WebSocket-соединения. Он преобразует низкоуровневые сообщения WebSocket в вызовы методов из слоя Use Cases. Также здесь может бытьPresenter, который форматирует данные от Use Case для отправки клиенту.
- Что здесь делается: Добавляется новый
-
Use Cases (Слой сценариев использования):
- Что здесь делается: Этот слой определяет абстракции (интерфейсы), необходимые для его работы. Например, если use case должен рассылать уведомления, он определит интерфейс
Notifier.// Этот интерфейс живет в слое Use Cases type Notifier interface { Notify(userID string, message []byte) error } - Сам use case будет использовать этот интерфейс, не зная ничего о WebSocket. Реализация этого интерфейса будет находиться в инфраструктурном слое.
- Могут быть добавлены новые use cases (например,
HandleRealTimeUpdatesUseCase).
- Что здесь делается: Этот слой определяет абстракции (интерфейсы), необходимые для его работы. Например, если use case должен рассылать уведомления, он определит интерфейс
-
Entities (Слой сущностей):
- Этот слой не должен быть затронут. Бизнес-объекты и правила остаются независимыми от способа доставки данных.
Итог:
Основная работа происходит в инфраструктурном слое (реализация) и слое адаптеров (связывание). Слой Use Cases может потребовать добавления новых сценариев и определения интерфейсов, но его существующая логика не меняется. Доменный слой (Entities) остается нетронутым. Это и есть главное преимущество чистой архитектуры — изоляция бизнес-логики от деталей реализации.
Ответ 18+ 🔞
Да ты посмотри, какая хуйня творится! Решил ты, значит, в своё приложение WebSocket воткнуть, а оно у тебя по этим самым «чистым» принципам построено. Ну, типа, чтоб логика бизнеса в своём святом храме сидела, а всякие внешние штуки к ней через шлюзы подключались. И правильно, блядь!
Так вот, слушай сюда, главное правило — все зависимости смотрят внутрь, как будто на центральную иконку в храме молятся. Внешний мир нихуя не должен знать, как у тебя там кишки бизнес-правил шевелятся.
Куда же пойдут наши изменения? А пойдут они, как ни странно, наружу, на самые окраины архитектуры!
-
Frameworks & Drivers (Инфраструктура, она же обслуга) Вот тут-то и начнётся вся движуха, ёпта! Ты будешь городить конкретный WebSocket-сервер, используя какую-нибудь библиотеку —
gorilla/websocket, например. Этот код — он как сантехник: подключает трубы (соединения), следит, чтобы не текло (обрабатывает ошибки), гоняет воду (байты туда-сюда). Но! Он будет реализовывать интерфейс, который ему сверху, из более важных слоёв, спустили. Как холоп, блядь. -
Interface Adapters (Адаптеры, они же переводчики) Тут появится новый чувак —
ControllerилиHandler. Его задача — встретить входящее WebSocket-соединение, как гостьбу, и перевести тарабарщину клиентских сообщений на чёткий язык вызовов Use Cases. «О, клиент прислал „{„event“: „ping“}“ — значит, надо дернуть методSendPongUseCase.Execute()». И наоборот, когда Use Case что-то сделает, адаптер (черезPresenter) упакует результат обратно в JSON и плюнет в сокет. Всё как у людей, только с матами. -
Use Cases (Сценарии использования, они же мозги операции) А вот тут — внимание, ебать! — сама логика часто не меняется кардинально. Но этот слой начнёт требовать. Он определит интерфейсы, типа: «Слушай, а я хочу теперь уведомления рассылать в реальном времени. Реализуй-ка мне, голубчик, вот такой контракт».
// Этот интерфейс живёт в Use Cases, он как царский указ! type RealTimeNotifier interface { BroadcastToRoom(roomID string, payload []byte) error }Сам Use Case будет вызывать методы этого интерфейса, вообще не палясь, что там под капотом — WebSocket, carrier pigeon или телепатия. Реализацию-то, блядь, ему подсунут из самого нижнего, инфраструктурного слоя! Могут, конечно, и новые Use Cases добавиться, например
HandleLiveChatMessageUseCase. -
Entities (Сущности, они же святые коровы) А вот это святое место! Сюда НИ-НИ, НИ ХУЯ НЕ ТРОГАЕМ! Твои бизнес-объекты (
User,Order,Invoice) и все их правила должны спать спокойно, как младенцы, и не знать, что где-то там, на периферии, какие-то сокеты коннектятся и дисконнектятся. Их мир — это данные и законы, по которым они живут. Всё.
Итог, блядь, подводим:
Вся возня будет на задворках архитектуры — в инфраструктуре (пилишь сервер) и в адаптерах (придумываешь, как переводить). Слой Use Cases может покряхтеть и выдать пару новых интерфейсов или сценариев, но его старая, проверенная логика останется в неприкосновенности. А ядро (Entities) — так вообще под бронестеклом, в рот меня чих-пых!
В этом и есть, сука, вся соль и мощь этой архитектуры — твоя бизнес-логика остаётся чистой, как слеза младенца, пока вокруг неё весь этот технологический цирк с конями происходит. Красота!