Как я реализовал антикоррупционный уровень

У каждой семьи своя хроника. По большей части это личное прошлое «записано на пленку». Я имею в виду фотографию. Подумайте об этом, если бы не фотографии, вы бы никогда не узнали, как выглядел ваш первый праздничный торт. Воспоминания об этом торте исчезли бы, если бы не постоянные напоминания. Как еще ваши родители нежно спорили бы о том, на кого вы больше похожи?

Я помню, как моя мама экспериментировала (надо мной) со своей новой камерой: «Посмотри на меня и понюхай цветы!», «Улыбнись!». Затем она творила чудеса в «красной комнате», в результате чего были получены черно-белые фотографии разных размеров. Хорошие фото она добавила в семейный альбом, остальные хранились в большом «Чумодане». Эти компрометирующие свидетельства моего детства все еще существуют. Мама (наверное, как и все мамы в мире) без колебаний выставляет их на всеобщее обозрение.

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

При всей нашей любви к прогрессу мы должны помнить, что некоторые люди, например моя мама, слишком привязаны к своим фотоальбомам. «Облако - это хорошо, но альбом на физическом носителе лучше», - говорит она. «Но я не чувствую этого!», - жалуется она. Итак, задача состоит в том, чтобы внедрить новую технологию, но дать возможность мамам повсюду хранить свои альбомы. Я имею в виду, мы должны помнить, что некоторым пользователям требуется больше времени, чтобы привыкнуть к новым технологиям. В мире высоких технологий уровень борьбы с коррупцией позволяет постепенно переходить от старого к новому.

В компании Behalf, в которой я работаю, унаследованная система была написана как монолит и использовала нетранзакционную базу данных. В моем примере слово Film-Camera будет использоваться для обозначения Monolith, а слово Photo-Album - для вызова устаревшей базы данных.

План состоял в том, чтобы переписать систему на микросервисах с использованием архитектуры Domain-Driven Design и заменить нетранзакционную базу данных транзакционной. В моем примере в качестве домена микросервиса будет использоваться «Цифровая камера», и он подключен к базе данных, которую мы назовем «Электронное хранилище».

Наше исследование показало, что пока мы создаем новую услугу «Цифровая камера», у нас все еще будут пользователи (Муооооом!), Которые будут придерживаться старых технологий. Это означало, что пока мир продолжал развиваться, некоторое наследие должно сохраняться, пока пользователи переходят.

По мере продолжения мы поняли, что эти две службы полностью несовместимы. Старый мир «Пленка-камера» и ультрасовременная «Цифровая камера» имели разную смысловую нагрузку и разные жизненные циклы своих сущностей, а именно фотографий. Таким образом, план развертывания услуги цифровой камеры должен был включать реализацию уровня защиты от коррупции.

Уровень борьбы с коррупцией: теория

Уровень защиты от коррупции - это причудливый термин для связующего кода, который объединяет микросервис в монолит, чтобы они могли обмениваться данными. Этот термин впервые появился в книге Эрика Эванса Domain-Driven Design. Этот клейкий код получил название Уровень защиты от коррупции, потому что он позволяет сохранить в первозданном виде код вашей новой и блестящей службы.

Подумайте об этом, цифровые изображения не портятся и не устаревают, поэтому нет необходимости отслеживать старение чернил или ухудшение качества физических изображений. Ограничение количества изображений на странице альбома не является проблемой для цифрового хранилища. Альбомы должны быть каталогизированы, иначе Chumodan в конечном итоге взорвется - это не проблема хранения цифровых изображений. С другой стороны, предполагается, что альбомы являются общедоступными. Они подвергаются всему из-за мам. Цифровые изображения вообще не считаются общедоступными, поэтому требуется логика авторизации, которой не было бы в Монолите. Это всего лишь несколько примеров устаревших концепций, которые наш микросервис не должен обрабатывать или даже знать. Уровень защиты от коррупции предотвращает загрязнение и искажение устаревших концепций модели предметной области вашей новой службы путем добавления некоторого промежуточного уровня.

В общих чертах антикоррупционный уровень выглядит так:

Слева - микросервис, справа - Монолит. Уровень борьбы с коррупцией находится между ними. У этого уровня есть API, который использует язык предметной области микросервиса. На другом конце уровня защиты от коррупции находится фасад, который эффективно скрывает особенности монолитных систем и скрывает устаревший язык. Между ними находится адаптер, который реализует API и осуществляет перевод между двумя отдельными моделями предметной области с помощью интерфейса переводчика.

Уровень борьбы с коррупцией: на практике

Мы хотим отразить изображения из области цифровой камеры в монолит пленочной камеры (и его области). Вот как мы это делаем:

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

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

А теперь перейдем к мелочам.

Цифровые фотоаппараты

Наша цель - представить изображение, созданное цифровой камерой, на устаревшем фотоальбоме. Мы можем с уверенностью предположить, что создание образа инициируется каким-то API, предоставляемым сервисом. Такой API обычно вызывает службу для создания нового изображения с использованием уровня репозитория изображений. Обычно на этом наша история заканчивается (новой записью в таблице), но на самом деле это только край нашего уровня защиты от коррупции. Краткая контекстная интерлюдия:

В компании Behalf мы используем архитектуру проектирования, основанную на домене, где у каждого бизнес-домена есть выделенная служба и выделенная база данных. Сервисы связываются друг с другом асинхронно, создавая бизнес-события. Каждое произведенное событие сообщает миру, что что-то случилось с объектом домена. Полезная нагрузка события включает в себя только идентификацию конкретного объекта. Другие заинтересованные домены могут получать данные, принадлежащие исходному домену. Они поглощают события и выполняют свои собственные действия.

Поэтому было решено внедрить коммуникацию внутри Антикоррупционного уровня и по событиям. Однако я действительно хотел, чтобы Film-Camera не извлекала данные из моей базы данных Digital-Camera напрямую. Поэтому я создал новый вид событий - Record Events. Эти события уведомляют о том, что определенная запись (в нашем случае запись изображения) была создана в базе данных микросервиса (электронное хранилище). Событие запускается вызовом репозитория, который вносит изменения, и его полезная нагрузка включает соответствующие детали записи (а не только идентификацию). Фактически, он включает в себя все данные, которые кинокамера должна знать, чтобы создать свою собственную запись новой фотографии и поместить ее в свою собственную базу данных (фотоальбом).

Но, по очереди, вернемся к репозиторию изображений. Мой репозиторий изображений расширяет некоторый BaseRepository (из основного уровня) и переопределяет базовый метод postCreate(). При создании записи изображения он называется класс Image Record Event Producer. Другими словами, это запускает процесс отражения.

Image Record Event Producer и его зависимость:

Производитель событий Image Record генерирует события, связанные с Image Record. В нашем примере он генерирует только событие Created. События несут полезную нагрузку, и в нашем случае семантика этой полезной нагрузки аналогична языку домена Film-Camera. Мероприятие должно, так сказать, «говорить о фотографии». Однако, поскольку эти два домена имеют различную семантику, мы не можем просто отправить необработанное изображение, его необходимо преобразовать.

Допустим, у цифрового изображения есть параметр разрешения. Чем выше разрешение изображения, тем лучше качество изображения. Качество изображения влияет на максимально доступный кадр фотографии. Какие еще параметры мы можем добавить сюда? Если вы родились в поколении X или в начале поколения Y, вы, вероятно, помните метку времени по умолчанию, которая наносилась на фотографии простыми коробчатыми камерами. Он был в определенном формате: одна или две цифры для дня, длинный интервал (возможно, двойной), затем одна или две цифры для месяца, апостроф, две цифры для года. 30 апреля 2002 г. выглядело как 30 4'02.

Подводя итог, наш класс изображений имеет следующие параметры:

Параметры события Image Record Created очень похожи на параметры Photo:

Событие включает параметр максимально доступного кадра, который получается из минимального разрешения изображения. У события есть параметр идентификатора ссылки на изображение. Этот параметр нам понадобится для связи между записями в отдельных доменах. Это поможет нам в процессах тестирования, мониторинга и обновления записей.

Преобразование Image в полезную нагрузку события включает некоторую логику. Чтобы производитель событий не имел логики, я создал класс Image Translator, который инкапсулирует грязную работу по преобразованию.

Вот как выглядит мой Image Record Event Producer. Это зависит от Image Translator, который переводит изображение в событие, и Event Producer, который фактически сгенерировал события.

Реализована цифровая камера уровня защиты от коррупции. Проверять! Теперь давайте посмотрим на часть слоя «Фильм-камера».

Кинематографическая служба

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

Использование события происходит в классе «Отражение изображения на фотографии». Класс Актера получает событие и выполняет определенное действие, подразумеваемое именем Актера. В нашем случае это своего рода сквозной интерфейс, потому что все, что он делает, - это перенаправляет на соответствующий метод в классе адаптера фотографии. YMMV.

Адаптер для фотосъемки:

Адаптер представляет цифровое изображение как физическую фотографию.

Предположим, вы сделали идеальный снимок на своем телефоне. Теперь вы хотите поделиться им с кем-нибудь из «олдскульных» (если это моя мама, она захочет, чтобы это фото было в ее альбоме). Вашим первым шагом будет выбор размера изображения, который будет соответствовать альбому (и согласовать разрешение для получения красивого четкого изображения). Затем выберите тип бумаги, затем распечатайте изображение и добавьте его в альбом (и, конечно же, добавьте симпатичную подпись). Другими словами, вы адаптируете цифровое изображение к области физической фотографии. Именно это и делает мой класс «Адаптер фотографии».

Я сопоставляю данные события Image Record Created с фотографией. Как я упоминал ранее, полезная нагрузка события очень близка к параметрам Фотографии.

Я использую Model Mapper для легкого преобразования:

Затем я обогащаю инициированную фотографию (применяя логику адаптера) такими параметрами, как оптимальный размер, тип бумаги и всеми остальными терминами в области фотографии. Наконец, я добавляю фотографию в фотоальбом, вызывая create() метод репозитория фотографий 😅.

Взгляните, как выглядит мой адаптер:

Это все! У тебя красивый образ, он есть и у твоей мамы в фотоальбоме. Все довольны!

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

Может в следующий раз.

Вот ссылка на проект git этого поста.