Привет народ.

Сегодня зашел в канал #school в русскоязычном GoCommunity в Slack и обнаружил там один интересный диалог. Данный диалог навел меня на некоторые мысли относительно того, как коллеги интерпретируют понятие “модель предметной области (домена)”.

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

Вопрос об архитектуре.

Итак, разработчик задал в сообществе следующий вопрос:  

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

На который другим программистом был дан следующий ответ:

Самое простое - архитектура с анемичной моделью. это когда модель DB = модель домена = модель ответов API. rich domain model - редкий зверь и обычно вырождается в анемичую. Под анемичной подразумевается DTO структура. обычный набор аттрибутов(полей) без методов. Логика вырождается в набор функций, оперирующих такими dto. Фаулер временами считает такую архитектуру антипаттерном. Но потом хорошим микросервисным решением, и.т.д

Прочитав это, я вдруг понял, почему вокруг так много споров в организации слоя бизнес-логики, и почему у многих не получается применять на практике такие подходы как Clean Architecture и т.п. Ведь что значит “архитектура с анемичной моделью”?

Если вы попробуете найти такое понятие в сети, вы его скорее всего не обнаружите, потому что такой архитектуры нет. Есть понятие “AnemicDomainModel”, и если обратится к тому же Фаулеру, окажется, что это просто процедурный подход к созданию архитектуры приложений (привет Fortran, ALGOL, COBOL, BASIC, Pascal и C). Это в сущности и есть то, что автор ответа называет “архитектура с анемичной моделью”.

Модель предметной области (домена).

Далее возникает следующий вопрос, а является ли “анемичная модель” моделью по сути? Я думаю, нет, и вот почему.

Правда заключается в том, что модель предметной области - это не модель данных, в отличие от “модели БД” или “модели ответа API”. Модель предметной области, имеет вполне конкретное определение.  В широком смысле данная модель даже не является концепцией из мира ООП. Тем более неправильно мешать ее с моделью БД, которая по сути является моделью данных.

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

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

Чем чревата подмена понятий?

Когда вы называете структуры данных “моделью домена”, вы вольно или нет подменяете понятия. Это приводит к тому, что зачастую бизнес-логика размазывается по всему приложению. На самом деле, моделью предметной области в таком случае является тот самый размазанный  набор функций, оперирующий структурами данных.

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

  • "- Где валидировать данные?"
  • "- Как избежать циклических зависимостей?"
  • "- А является ли “это” бизнес логикой вообще?"
  • "- А где у нас хранится бизнес-логика?"
  • и т.п.

При этом, если у вас простой CRUD, т.е. по сути интерфейс к базе данных, проблем скорее всего не будет. Если вы пишете библиотеку инфраструктурного уровня (к примеру для работы с сетью или с той же БД), проблем также не должно возникнуть. Все потому, что, есть RFC и все “бизнес-правила” давно ясны, а логика давно понятна. Можно написать простую процедурную программу, и все так или иначе будет нормально.

Подведем итоги.

Если вернуться к тому, что диалог о моделях предметной области возник в Go комьюнити, я бы сказал так. В силу того, что Go является мультипарадигменным языком и поддерживает ряд наиболее удачных ООП концепций (Композиция, Интерфейсы), не стоит игнорировать их при моделировании предметной области и писать код исключительно в процедурном стиле, как будто вы работаете с BASIC или С.

Правильно интерпретируя понятие “модель предметной области” становится вполне очевидно, почему зачастую принято выделять бизнес-логику в отдельный слой. Так же становится понятно, каким образом можно выделить этот самый слой и реализовать Clean Architecture или любую другую ее вариацию. Выделяя отдельный слой, мы по сути создаем библиотеку, которая реализует концептуальную модель в виде программного кода. Как результат, бизнес-логика становится инкапуслирована в рамках этой библиотеки, а не размазана по всему приложению (как при чистом процедурном подходе).

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

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

Всем добра! Спасибо за внимание.