Привет, Хабр.

Сегодня зашел в канал #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)

Комментарии (49)


  1. evgenyk
    28.05.2019 22:08
    +3

    А я все равно ничего не понял.


  1. JustDont
    28.05.2019 22:38

    Когда вы называете структуры данных “моделью домена”, вы вольно или нет подменяете понятия.

    Um, no. Тут вся разница только в том, что «домен» в данном случае — это не домен всего приложения в целом.
    Доменная модель имеет смысл только с уточнением — а про какой же конкретно домен мы вообще говорим? Про всё приложение? Про отдельную подсистему? Про что-то еще?

    У фронтэндщика, пилящего отдельную красивую кнопочку — тоже есть своя доменная модель. Для кнопочки.


    1. DexterHD Автор
      28.05.2019 22:55

      Спасибо за обратную связь. А можете привести примеры доменов в вашем понимании?

      Я например выделяю такие домены (предметные области):
      — Shipping (Перевозка грузов)
      — Banking (Банковские услуги)
      — Booking (Продажа билетов)


      1. JustDont
        28.05.2019 23:02

        А можете привести примеры доменов в вашем понимании?

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

        Как только вы можете выделить подсистему в вашей системе — вы сразу же можете выделить и домен для неё.


        1. DexterHD Автор
          28.05.2019 23:13
          -1

          Ну можно же привести пример «предметной области» для человека пилящего кнопочку или UI компонент?

          К примеру если вы разрабатываете ядро библиотеки `React` (или реализуете компонент Button в ядре этой библиотеки) предметной областью для вас будет:
          — UI библиотеки для Web

          Но если вы на базе `React`рисуете кнопку «Снять наличные», для банковского приложения. Это домен «Banking», и вы как фронэндщик пользуетесь моделью доменного уровня через API. И это не зависит не от масштаба, не от точки зрения.

          Так же, если вы разрабатываете iOS, предметная область будет:
          — Операционные системы для мобильных платформ

          Но если вы решаете с помощью компьютера бизнес-задачи, домен будет отражать бизнес функции.


          1. JustDont
            28.05.2019 23:21

            Но если вы на базе `React`рисуете кнопку «Снять наличные», для банковского приложения.

            Конечно. Я так и написал, «зависит от масштаба и точки зрения». Если вы пилите кнопку с логикой для банковского приложения, имея в виду именно полную реализацию процедуры «снятие наличных» — вы работаете в доменной модели банковских услуг. Если вы пилите эту кнопку, но у вас просто есть ТЗ, что и как должно быть дёрнуто на бекэнде при нажатии на эту кнопку — вы работаете в доменной модели фронтэнда, дергающего API (впрочем, иметь в виду доменную модель верхнего уровня тут тоже бы неплохо). А если вы пилите кастомную кнопку, которая потом будет использоваться в том числе и в контексте снятия наличных — вам довольно сильно пофиг на доменную модель верхнего уровня (но скорее всего ТЗ на фичи для вашей кнопки вы сформулируете именно оттуда), у вас просто кнопка.


            1. DexterHD Автор
              28.05.2019 23:30

              Если вы пилите кнопку с логикой для банковского приложения, имея в виду именно полную реализацию процедуры «снятие наличных»

              Нет, реализацию процедуры «снятие наличных» я не имел ввиду.Я считаю эту процедуру всего лишь часть предметной области «Банкинг».

              вы работаете в доменной модели фронтэнда, дергающего API

              Правильно ли я понимаю, что предметная область в данном случае:
              — Фронтэнд дергающий API

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

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


  1. lohmatii
    29.05.2019 01:19

    Я всегда видел это совершенно иначе.
    В концептуальной модели данных не идет речи ни о каких БД или АПИ. Это совершенно абстрактная вещь, описывающая предметную область конкретного предприятия. А каждая из 100500 информационных систем предприятия имплементирует у себя какую-то проекцию этой модели.
    Это единое формализованное описание, которое ближе к бизнесу, чем к ИТ. Поэтому его можно подавать на вход в каждую новую внедряемую на предприятии систему и избегать того, что АБС и CRM у вас оперируют объектами, которые вообще друг на друга никак не мапятся.
    Т.е. концептуальная модель — это такой своеобразный объемный многогранник. Вокруг него под разными углами расположены плоскости — информационные системы. И проекции многогранника на эти плоскости — объектные модели этих систем.


    1. flancer
      29.05.2019 08:00

      Это единое формализованное описание, которое ближе к бизнесу, чем к ИТ.

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


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


      1. lohmatii
        29.05.2019 10:29

        Возможно, где-то в большом бизнесе, есть подобные формализованные описания. Но для этого в большом бизнесе должен быть специальный человек-агрегатор, который создаёт эти описания для бизнеса.

        Этот человек — энтерпрайз архитектор. Только создает он их не для бизнеса, а как раз от бизнеса для ИТ.
        я так вижу, что двигаться она должна не от концепта к проекциям, а от проекций к концепту.
        Тогда в ней не будет никакого практического смысла. Концептуальная модель предметной области — это инструмент, который позволяет поддерживать всю инфраструктуру компании в едином ± виде. Начиная новое внедрение архитектор решения получает на вход не только требования от бизнеса, но и концептуальную модель от архитектора предприятия. А потом согласует с ним свою можель данных. Или как минмум ту ее часть, которая может смотреть наружу. Однажды мне сразу выдали библиотеку классов для сериализации/десериализации, котороя я должен был пользоваться для интераций — генериалсь она автоматичеси на основе как раз концептуальной модели, распростарнялась между разными системами и периодически обновлялась.
        Я чаще сталкивался с ситуациями, когда есть данные, которые хранятся в различных репозиториях (БД, файлы, документы), и которые по факту отражают отдельные проекции концептуальной модели данных, которая нигде и никем не зафиксирована.

        Все так, увы. Буквально 2 раза встречал у заказчика энтерпрайз архитектора. Оба раза в международных компаниях. В остальных случаях просто зоопарк IT-систем, которые растут совершенно бесконтрольно. Тем не менее правильный путь именно от концептуальной модели к частной.


  1. muhaa
    29.05.2019 02:36

    Не корректно называть «данные» моделью предметной области.
    Проблема в том, что эта часть модели как раз наиболее статична и наиболее зависима от предметной области. Поведение, напротив, может состоять из алгоритмов, которые: 1. Зависят от конкретных выбранных методов решения задач а не от выбранной предметной области в целом. 2. Могут относиться скорее к математике или чему-то другому очень абстрактному, чем к предметной области.
    Эти алгоритмы можно реализовать как набор классов, функционально или процедурно.
    Завтра мы решим решать задачи глубже или детальнее и алгоритмы (классы, функции или процедуры) будут заменены совершенно другими. При этом, модель данных не поменяется т.к. это вся та же предметная область. Получается, мы поменяли доменную модель? Тогда в чем заключалась ее «доменность»?
    Модель предметной области — это концептуальная модель, которая включает в себя как поведение, так и данные. Она может быть инкапсулирована в отдельный слой, а может быть размазана по всему приложению.
    Допустим, мы описали те самые доменные объекты, которые содержат данные и описывают состояние предметной области. В идеальном случае доменное поведение может быть реализовано непосредственно в методах этих объектов. Но мне кажется, это возможно только в очень простых задачах. Можно собрать поведение в процедуры, но такой код сложно переиспользовать, тестировать или понимать. Можно реализовать поведение в виде множества «менеджеров» с довольно абстрактным и далеким от предметной области назначением, которые тем не менее будут хорошо переиспользоваться в будущих версиях и инкапсулировать промежуточные результаты и детали поведения. Там где работа с промежуточными данными не сложна менеджеры превратятся просто в static функции. Эти менеджеры и static функции никак не являются доменными сущностями, но содержат все поведение. Не это ли как раз и называют «анемичной моделью»?
    “Архитектура с анемичной моделью” не что иное как процедурный подход к созданию архитектуры приложений в котором модель предметной области размазана по всему приложению
    Процедурный подход, это когда разрабатывая процедуру мы никак не ограничиваем себя в том, какие данные она использует или поменяет и поэтому эту процедуру очень сложно использовать еще раз в другой задаче, тестировать и разобраться что же она в точности делает. Поведение как раз в процедурах концентрируется очень хорошо и понятно (есть такая старая идея — структурное программирование). Напротив, ООП подразумевает размазывание поведения по методам всех объектов, когда нечто главное всегда происходит в другом месте кода, где ни посмотри. Анемичная модель позволяет сконцентрировать поведение в неких объектах, которые оперируют не своими данными. Поэтому смысл вашего утверждения ускользает.


    1. EvgeniiR
      29.05.2019 06:59

      Если работа с данными из одних объектов происходит в других, это говорит лишь о проблемах в проектировании

      > Но мне кажется, это возможно только в очень простых задачах

      Обычно к такому заключению приходят когда из rich domain model уходят в другую крайность и они становятся огромные и непонятные, от того что в них помещается куча несвязанной логики и пара десятков полей.

      > Допустим, мы описали те самые доменные объекты, которые содержат данные и описывают состояние предметной области

      Объекты без поведения это просто структуры данных, они не описывают ограничения предметной области.
      Чаще всего они описывают лишь какие поля вместе во вьюшке отображаются, и пока декомпозиция делается через UI, о грамотном проектировании объектов речи не идёт.
      И да, анемичные модели первое время позволяют скрывать эти проблемы.


      1. muhaa
        29.05.2019 12:19

        Если работа с данными из одних объектов происходит в других, это говорит лишь о проблемах в проектировании
        Допустим, предметная область — это некие физические объекты с множеством свойств и некие события, которые с этими объектами происходят. Дальше, программа получает запрос, выполняет анализ этой модели и возвращает ответ. Алгоритм этого анализа сложен. Даже в лоб процедурно его может реализовать только очень хороший программист. Алгоритм удобно описать в стиле ФП (на входе вся модель и запрос, на выходе результат), или в виде нескольких объектов-модулей, каждый из которых выполняет часть работы. Эти объекты-модули будут работать с данными о физических объектах и событиях. Т.е. не со своими данными. Значит это ошибка проектирования. Как ее решить? И главное, зачем ее решать?
        Объекты без поведения это просто структуры данных, они не описывают ограничения предметной области.
        У предметной области может не быть никаких стабильных ограничений, кроме тех которые уже заложены самой структурой классов. Все дополнительные ограничения могут зависеть от того, какая задача сейчас решается. Что физически может происходить в предметной области, а что нет? Если пользователь вводит данные, которые выглядят некорректно, нужно запретить ввод таких данных или только предупредить пользователя, пояснив что он скорее всего делает не так? Ответы на эти вопросы могут меняться в разных версиях продукта или при решении разных задач. Тогда какой смысл жестко связывать ограничения на данные с самими данными?
        Чаще всего они описывают лишь какие поля вместе во вьюшке отображаются, и пока декомпозиция делается через UI, о грамотном проектировании объектов речи не идёт.
        В моем случае, они описывают (моделируют) нечто реально существующее в мире (объекты, события с объектами), как оно есть, независимо от UI.


  1. DmitriyTitov
    29.05.2019 07:38

    У Вас в начале статьи ссылка на сайт Slack. Это, как я понимаю, типа социальной сети что-то. Я там зарегистрировался, но всё равно пройти по ссылкам не могу. Это какой-то закрытый сайт? Зачем тогда ссылки в статье?


    1. DexterHD Автор
      29.05.2019 08:30

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


  1. flancer
    29.05.2019 08:15

    Я в вашей статье нашёл для себя ещё одно подтверждение тому, что данные нужно отделять от бизнес-логики. Вы пишете:


    “Архитектура с анемичной моделью” не что иное как процедурный подход к созданию архитектуры приложений в котором модель предметной области размазана по всему приложению

    Но на это можно посмотреть и так, что в приложении есть чисто данные — данные без поведения, а есть слой кода, который имплементирует бизнес-логику, которая оперирует данными так или иначе. И этот слой может быть создан как в процедурном стиле, так и в объектно-ориентированном. Таже можно размазать этот слой по всему приложению или сконцентрировать в отдельные группы (controllers, helpers, services).


    В таком случае мы в рамках одного приложения получаем то, о чём коллега lohmatii чуть выше говорил, как о "концептуальной модели данных" конкретного предприятия в рамках "большого бизнеса". Только тут мы имеем дело с "концептуальной моделью данных отдельного приложения" — она может быть формализована (сохранена в конкретной структуре в БД или файлах), а её проекции использоваться отдельными бизнес-функциями (процедурными или ОО). Хоть той же кнопкой "Снять наличные", если эта кнопка хоть что-то использует из "концептуальной модели данных приложения" (что маловероятно).


    1. DexterHD Автор
      29.05.2019 08:41

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

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

      “Архитектура с анемичной моделью” не что иное как процедурный подход к созданию архитектуры приложений в котором модель предметной области размазана по всему приложению

      Это к слову мой перевод вот этого предложения из статьи Фаулера про анемичную модель:
      The anemic domain model is really just a procedural style design, exactly the kind of thing that object bigots like me (and Eric) have been fighting since our early days in Smalltalk.


      1. EvgeniiR
        29.05.2019 08:59

        Модель бизнес логики это в первую очередь поведение. Бизнесу нет дела какие вы данные туда-сюда гоняете


      1. dedmagic
        30.05.2019 19:30

        “Архитектура с анемичной моделью” не что иное как процедурный подход к созданию архитектуры приложений в котором модель предметной области размазана по всему приложению

        В моём текущем проекте используется анемичная модель предметной области, но при этом вся бизнес-логика собрана в одном слое. Так что «модель предметной области размазана по всему приложению» — это не про анемичную модель, вещи ортогональные.
        И во фразе Фаулера, которую Вы как бы перевели, об этом ни слова.


        1. DexterHD Автор
          30.05.2019 23:13

          но при этом вся бизнес-логика собрана в одном слое

          Этот слой по сути и есть ваша «модель предметной области». Не данные которыми вы оперируете, а поведение. Ваша анемичная модель — статическая структура не имеющая для бизнеса ни какой ценности сама по себе и не выполняющая никакой работы. Это просто «данные».


    1. EvgeniiR
      29.05.2019 09:03

      Логика отдельно, данные отдельно это старый добрый процедурный код, добавление классов не делает его ОО.


      Где вы нашли подтверждение верности подхода с анемичными моделями — ума не приложу.


      1. 0x1000000
        30.05.2019 22:13

        Это совершенно не значит что код «процедурный». В функциональном программировании логика и данные всегда идут раздельно. Физически их можно запихать в один класс, но смысла в этом особого нет, т.к. все объекты этого класса неизменяемы.


  1. Sartor
    29.05.2019 09:00

    Автор как-будто сам себя пытается убедить. Нет никаких полностью абстрактных бизнес-логик. Всё равно всё хранится в каком-то харнилище. Не обманывайте себя и других людей. Если между хранилищем и бизнес логикой сделать очень хорошую изоляция в 99% это будет тормозить, т.к. вы не сможете использовать фичи хранилища или ваше приложение будет немасштабируемое. Нельзя всё взять и поделить. Всегда нужно думать.


    1. DexterHD Автор
      29.05.2019 10:08

      Автор как-будто сам себя пытается убедить.

      Да нет, я убежден в том, что бизнес-логику реально выделить в отдельный слой и имел возможность сделать это на практике. Я это проверял, это работает.

      Нет никаких полностью абстрактных бизнес-логик.

      Вы правы, бизнес-логика той или иной предметной области вполне конкретна. Я и не говорю про существование «абстрактных бизнес логик». Я просто говорю об общих принципах.

      Если между хранилищем и бизнес логикой сделать очень хорошую изоляция в 99% это будет тормозить, т.к. вы не сможете использовать фичи хранилища или ваше приложение будет немасштабируемое. Нельзя всё взять и поделить.

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

      Вот вам пример. В Kubernetes большая часть бизнес-логики изолирована и сосредоточена в пакете pkg/controller (а точнее его подпакетах). Если вы внимательно исследуете код, вы обнаружите, что этот слой практически полностью отделен от реализации набором интерфейсов.

      Всегда нужно думать.

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


      1. Sartor
        29.05.2019 15:01

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

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


  1. 0x1000000
    29.05.2019 10:10

    Причина почему НЕ надо хранить бизнес логику внутри модели, заключается в том, что эта самая логика сильно варьируется в разных сценариях (use cases), число и вариативность которых невозможно предсказать (если, конечно, у вас не “водопад”). Например, есть модель “Пользователь”: {id, login, name}. Субъект “Пользователь” может поменять только “name”, субъект “Администратор”, может поменять еще и “login”, но только в том случае если он уникальный, а какая-нибудь утилита интеграции может менять вообще все.
    В модели должны быть представлены только абсолютные ограничения, которые в 99% случаев выражаются в виде отношений между моделями и типов атрибутов.


    1. DexterHD Автор
      29.05.2019 10:22

      То что вы вкладываете в понятие «модель», называется «модель данных».
      То что выражено в коде как UseCases, является частью «модели предметной области».

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


      1. 0x1000000
        29.05.2019 11:23

        У коллег по цеху уже сложилась четкая ассоциация, что модель — это в первую очередь модель данных. “Модель предметной области” это настолько размытое понятие, что вряд ли ему можно найти значимое практическое применение.


      1. flancer
        29.05.2019 17:46

        Если разделять "модель данных" и "модель предметной области", то тогда нужно чётко фиксировать границы этой самой "предметной области" (границы применимости моделей). Я также допускаю, что в рамках одного приложения с одной моделью данных могут работать различные модели предметной области. В зависимости от того в какой проекции обрабатываются элементы этой модели данных (UI, API, validation, ACL verification, business processing). Например, грид на UI'е может работать с моделью предметной области "User Interface" (строки-столбцы), являющейся комбинацией различных элементов модели данных (номер заказа, имя клиента, ...). По большому счёту, гриду всё равно, из каких источников поднимаются в него данные (БД, файлы, внешний запрос), в его мире (области) все предметы — это строки, столбцы, рендереры, валидаторы, фильтры и т.п. Допустим, мы подтягиваем в своё приложение библиотеку/модуль для построения гридов, тогда мы должны имеющиеся в проекте данные представлять в виде, понятном для соответствующей предметной области (гридов). Получается, что у нас приложение разделяется на некоторое кол-во областей (представление данных, ввод-вывод, верификация, обработка, хранение, выборка) между которыми данные дрейфуют, преобразовываясь из одной структуры в другую. Да, кстати, и моделей данных у нас может быть множество. По большому счёту, для каждого внешнего приложения, с которым наше обменивается данными, присутствует своя "модель данных". И мы опять должны реструктурировать данные при передаче/получении в/из внешнего приложения из нашей структуры (наша модель данных о Клиенте) в структуру, понимаемую внешним приложением (их модель данных о Клиенте).


        Это так, мысли вслух, чтобы ещё больше запутаться самому и запутать остальных.


        1. DexterHD Автор
          29.05.2019 18:43

          Мне кажется что здесь вы слегка искажаете понятие «Предметная область».
          «User Interface» — как мне кажется не является предметной областью до тех пор пока вы не разрабатываете UI библиотеки и/или фреймворки.

          Грубо говоря, если вы разрабатываете приложение для «Банкинга», ваша предметная область: «Банкинг». Модель в этом случае реализована только на сервере. UI всего лишь рендерит результаты модели которые приходят в «удобном виде» через API. Вы всего лишь используете UI библиотеку чтобы построить UI банковского приложения.

          Предметная область (домен) — это всегда о том, какую вы проблему пытаетесь решить разрабатывая приложение в целом (Нужно задать вопросы: Зачем я пишу эту программу? Кому она поможет? Для какой она сферы? Это и есть предметная область.).

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

          Эту задачу за вас решили разработчики вашей операционки.
          Это для них, а точнее для отдела пользовательских интерфейсов «UI» является предметной областью.


          1. flancer
            29.05.2019 19:58

            Всё верно вы говорите, для отдела пользовательских интерфейсов UI является их предметной областью и я, используя их библиотеки/модули/компоненты в своём коде, должен адаптировать данные своей предметной области под их предметную область. И если их компонента не работает так, как мне нужно, я лезу с отладчиком в их код, чтобы выяснить кто из нас не прав, и там уже должен думать в терминах их предметной области (строки, столбцы, ...).


            Допустим, я интегрирую ERP-систему и e-commerce систему. Это разные предметные области с разными моделями (данных в первую очередь, и предметной области во вторую). Я не создаю новую, обобщённую модель предметной области (или обобщённую модель данных) для результата композиции двух систем. Я в каждой системе работаю со своей моделью данных / моделью предметной области, производя реструктуризацию данных из одной модели в другую на стыке двух систем.


            Граница между ERP-системой и e-commerce системой аналогична границе между UI и API при построении гридов, только масштаб другой. Данные мигрируют между различными областями, меняя свою структуру, но предметные области при этом не смешиваются. Реализация функционала для приложения "Банкинг" может потребовать выделения различных предметных областей в рамках одной информационной системы (UI, обработка, хранение). Да взять хотя бы версионирование процессов в BPMS, когда различные версии одного и того же бизнес-процесса оперируют с различным набором данных и имеют разное количество шагов. При этом различные предметные области (по версиям процесса) сосуществуют совместно в рамках одной информационной системы (правда между этими областями не происходит обмен данными, они параллельны в своём существовании).


            В общем, спасибо за подкинутый материал. Было интересно помозговать на тему :)


  1. forewar
    29.05.2019 11:12

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


  1. worldmind
    29.05.2019 14:49

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


    1. Sartor
      29.05.2019 15:03
      -1

      Пока академики рассказывают — джанги работают и приносят деньги. Не забывайте про это, хоть кому-то это покажется несправдливым.


      1. worldmind
        29.05.2019 15:07

        При чём тут оправданность, в случае простого CRUD'а подход джанги отлично работает, а вот чуть сложнее начинаются костыли, их конечно делают, они работают и приносят деньги, да только не стоит забывать, что это не лучшее решение.


    1. evgenyk
      29.05.2019 15:16
      +1

      Имхо, у Джанга тоже неслучайно так устроена. Есть некоторая проблема в разбивании на слои данных и бизнес логики. ИМХО она в том, что в реале данные храняться в базе данных и часть отношений между данными формулируются в виде отношений и ограничений в базе данных. Поэтому если мы выделяем бизнес логику в отдельный слой, то бизнес логика как ты ни крути будет размазана бежду базой и этим слоем.


      1. worldmind
        29.05.2019 15:18

        Я слышал что это чисто исторические причины, просто её изначально делали для для простого кейса.
        А ограничения в базе очень далеки от бизнес-логики, это просто обеспечение целостности данных.


        1. evgenyk
          29.05.2019 15:23
          +1

          А насчет отношений между таблицами и полями, они тоже не имеют отношения к бизнес логике?


          1. worldmind
            29.05.2019 15:26

            Что вы имеете ввиду под отношениями?


            1. evgenyk
              29.05.2019 15:29

              Foreign Key.


              1. worldmind
                29.05.2019 15:35
                +1

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


                1. evgenyk
                  29.05.2019 15:40

                  Конечно, только это не отменяет того, что часть бизнес логики будет в моделях, которые маппятся на таблицы, а часть — в слое бизнес логики, где будут реализованы сценарии.
                  Я сейчас далек от этого, но я бы делал конечно слой бизнес логики. Просто ИМХО нужно помнить и понимать, что часть бизнес логики в моделях (в терминах Джанго), а часть в слое бизнес логики.


                  1. worldmind
                    29.05.2019 15:42

                    Даже если так, то это никак не меняет сути — модель это не мапинг объектов в базу, как это сделано в джанге, хотя модель конечно включает схему сущностей, но это лишь малая часть модели.


                    1. evgenyk
                      29.05.2019 15:44

                      Ну, так это разные модели, только и всего. Я имею в виду термины.


                      1. worldmind
                        29.05.2019 15:47

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


                        1. evgenyk
                          29.05.2019 15:57

                          Странная претензия. В таком фреймворке как Джанго, невозможно да и ненужно и даже вредно пытатся заранее предусмотреть все случаи. Никто не мешает там писать свой слой.


                          1. worldmind
                            29.05.2019 19:33

                            При чём тут все случаи, фреймворк должен задавать правильную арзитектуру.


              1. worldmind
                29.05.2019 15:38

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


  1. evgenyk
    29.05.2019 15:29

    Удалил, написал не туда.