Привет, Хабр.
Сегодня зашел в канал #school в русскоязычном GoCommunity в Slack и обнаружил там один интересный диалог. Данный диалог навел меня на некоторые мысли относительно того, как коллеги интерпретируют понятие “модель предметной области (домена)”.
Как оказалось, существует достаточно много неверных или не совсем точных, а иногда совсем неточных интерпретаций данного термина, что по сути искажает его. Вокруг этого диалога и родилась идея данной статьи. Подробности под катом.
Итак, разработчик задал в сообществе следующий вопрос:
На который другим программистом был дан следующий ответ:
Прочитав это, я вдруг понял, почему вокруг так много споров в организации слоя бизнес-логики, и почему у многих не получается применять на практике такие подходы как Clean Architecture и т.п. Ведь что значит “архитектура с анемичной моделью”?
Если вы попробуете найти такое понятие в сети, вы его скорее всего не обнаружите, потому что такой архитектуры нет. Есть понятие “AnemicDomainModel”, и если обратится к тому же Фаулеру, окажется, что это просто процедурный подход к созданию архитектуры приложений (привет Fortran, ALGOL, COBOL, BASIC, Pascal и C). Это в сущности и есть то, что автор ответа называет “архитектура с анемичной моделью”.
Далее возникает следующий вопрос, а является ли “анемичная модель” моделью по сути? Я думаю, нет, и вот почему.
Правда заключается в том, что модель предметной области — это не модель данных, в отличие от “модели БД” или “модели ответа API”. Модель предметной области, имеет вполне конкретное определение. Тем более неправильно мешать ее с моделью БД, которая по сути является моделью данных.
Когда речь идет о модели предметной области, имеется ввиду именно концептуальная модель. А это совокупность понятий предметной области и отношений между ними (т.е. совокупность поведения и данных). В целом главной чертой, отличающей одну модель предметной области от другой, является именно набор бизнес-правил.
Да, концептуальная модель может работать с данными, которые представлены в разном виде (данные из БД или ответы API), но суть от этого не изменится, первостепенно поведение. Мы передаем на вход модели данные, чтобы получить определенный результат на выходе. Этот результат достигается с помощью реализации бизнес-логики внутри модели (другими словами применения бизнес-правил). Я нахожу здесь аналогию с математическими моделями и моделированием технологических процессов (привет студенческие годы).
Когда вы называете структуры данных “моделью домена”, вы вольно или нет подменяете понятия. Это приводит к тому, что зачастую бизнес-логика размазывается по всему приложению. На самом деле, моделью предметной области в таком случае является тот самый размазанный набор функций, оперирующий структурами данных.
В случае разработки средних и больших приложений, непонимание или смешивание этих понятий, как правило, приводит к ряду проблем и вопросов уже на старте разработки системы, не говоря уже о долгосрочной поддержке. Среди них, к примеру, встречаются такие распространенные вопросы как:
При этом, если у вас простой CRUD, т.е. по сути интерфейс к базе данных, проблем скорее всего не будет. Если вы пишете библиотеку инфраструктурного уровня (к примеру для работы с сетью или с той же БД), проблем также не должно возникнуть. Все потому, что, есть RFC и все “бизнес-правила” давно ясны, а логика давно понятна. Можно написать простую процедурную программу, и все так или иначе будет нормально.
Если вернуться к тому, что диалог о моделях предметной области возник в Go комьюнити, я бы сказал так. В силу того, что Go является мультипарадигменным языком и поддерживает ряд наиболее удачных ООП концепций (Композиция, Интерфейсы), не стоит игнорировать их при моделировании предметной области и писать код исключительно в процедурном стиле, как будто вы работаете с BASIC или С.
Правильно интерпретируя понятие “модель предметной области” становится вполне очевидно, почему зачастую принято выделять бизнес-логику в отдельный слой. Так же становится понятно, каким образом можно выделить этот самый слой и реализовать Clean Architecture или любую другую ее вариацию. Выделяя отдельный слой, мы по сути создаем библиотеку, которая реализует концептуальную модель в виде программного кода. Как результат, бизнес-логика становится инкапуслирована в рамках этой библиотеки, а не размазана по всему приложению (как при чистом процедурном подходе).
Конечно, понимание этих концепций не избавит вас от ошибок при проектировании, не сделает из вас идеального разработчика или системного архитектора и не научит делать все правильно с первого раза. Здесь важна не только теория, но и практика. Тем не менее, как только вы правильно поймете концепции и интерпретируете определения, многие вещи станут для вас на порядок очевиднее и проще.
Внимательно относитесь к определениям, изучайте их глубже чем просто читая по диагонали. Очень часто мы ленимся и хватаем информацию кусками, после чего непременно происходит искажение. Не забывайте возвращаться и поднимать в памяти вещи, которые вам кажутся давно очевидными, и всегда обращайтесь к первоисточникам и называйте вещи своими именами.
Всем добра! Спасибо за внимание.
PS. Буду рад выслушать конструктивную критику, а так же ваше видение того, что такое «модель предметной области». Ссылки на первоисточники приветствуются.
UPD: Статья не является попыткой вольной интерпретации понятия «модель предметной области» и вкладывания в это понятие одному мне известного смысла. Я хочу донести вот что: Смысл в данное понятие давно вложен, и оно подробно описано в книгах и статьях по ComputerScience. Статья является попыткой донести до коллег по цеху важность правильного восприятия этих самых концепций не искажая их смысл (Это важно, потому что на практике позволит писать более осмысленный код).
UPD2: Я не enterprise-архитектор теоретик. Я такой же практикующий разработчик как и вы. Я пишу код каждый день и рассуждаю об этих вещах с целью сделать свой код лучше, а заказчиков счастливее. Если на ваш взгляд, я исказил первоначальный смысл, поделитесь ссылками на первоисточники а так же укажите, где я выразился некорректно, так чтобы я смог это исправить.
UPD3: Т.к. многие интерпретируют термин «предметная область» по разному, привожу некоторые примеры предметных областей, чтобы не было путаницы и подмены понятий. Предметная область всегда зависит от того, какую проблему вы решаете с помощью разработки приложения:
Сегодня зашел в канал #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 или любую другую ее вариацию. Выделяя отдельный слой, мы по сути создаем библиотеку, которая реализует концептуальную модель в виде программного кода. Как результат, бизнес-логика становится инкапуслирована в рамках этой библиотеки, а не размазана по всему приложению (как при чистом процедурном подходе).
Конечно, понимание этих концепций не избавит вас от ошибок при проектировании, не сделает из вас идеального разработчика или системного архитектора и не научит делать все правильно с первого раза. Здесь важна не только теория, но и практика. Тем не менее, как только вы правильно поймете концепции и интерпретируете определения, многие вещи станут для вас на порядок очевиднее и проще.
Подведем итоги.
- Не корректно называть «данные» моделью предметной области.
- Модель предметной области — это концептуальная модель, которая включает в себя как поведение, так и данные. Она может быть инкапсулирована в отдельный слой, а может быть размазана по всему приложению.
- “Архитектура с анемичной моделью” не что иное как процедурный подход к созданию архитектуры приложений в котором модель предметной области размазана по всему приложению
Внимательно относитесь к определениям, изучайте их глубже чем просто читая по диагонали. Очень часто мы ленимся и хватаем информацию кусками, после чего непременно происходит искажение. Не забывайте возвращаться и поднимать в памяти вещи, которые вам кажутся давно очевидными, и всегда обращайтесь к первоисточникам и называйте вещи своими именами.
Всем добра! Спасибо за внимание.
PS. Буду рад выслушать конструктивную критику, а так же ваше видение того, что такое «модель предметной области». Ссылки на первоисточники приветствуются.
UPD: Статья не является попыткой вольной интерпретации понятия «модель предметной области» и вкладывания в это понятие одному мне известного смысла. Я хочу донести вот что: Смысл в данное понятие давно вложен, и оно подробно описано в книгах и статьях по ComputerScience. Статья является попыткой донести до коллег по цеху важность правильного восприятия этих самых концепций не искажая их смысл (Это важно, потому что на практике позволит писать более осмысленный код).
UPD2: Я не enterprise-архитектор теоретик. Я такой же практикующий разработчик как и вы. Я пишу код каждый день и рассуждаю об этих вещах с целью сделать свой код лучше, а заказчиков счастливее. Если на ваш взгляд, я исказил первоначальный смысл, поделитесь ссылками на первоисточники а так же укажите, где я выразился некорректно, так чтобы я смог это исправить.
UPD3: Т.к. многие интерпретируют термин «предметная область» по разному, привожу некоторые примеры предметных областей, чтобы не было путаницы и подмены понятий. Предметная область всегда зависит от того, какую проблему вы решаете с помощью разработки приложения:
- Бронирование билетов (Если вы разработчик систем бронирования)
- Банкинг (Если вы разработчик банковских приложений)
- Операционные системы (Если вы разработчик разработчик ОС)
- Управление облачной инфраструктурой (Если вы разработчик k8s)
- Виртуализация (Если вы разработчик Docker)
- Мониторинг производительности (Если вы разработчик Prometheus/Grafana)