Парадигмы программирования. Data Driven vs Domain Driven

Информационные технологии развиваются семимильными шагами, появляются новые устройства, платформы, операционные системы, и вместе с этим растет спектр задач, который приходится решать разработчикам. Но, не все так плохо — на помощь программистам спешат новые средства разработки, ide’шки, новые языки программирования, методологии и т.д. Один только список парадигм программирования впечатляет, а с учетом современных мультипарадигменных ЯП (например, C#) резонно встает вопрос: «Как с этим всем быть? Что выбрать?».

Попробуем немного разобраться.

Откуда взялось так много парадигм?


На самом деле ответ уже прозвучал в этом посте — разные типы задач легче и быстрее решать, используя подходящие парадигмы. Соответственно, с развитием ИТ появлялись новые виды задач (или старые становились актуальными), а решать их используя старые подходы было неудобно, что влекло за собой переосмысление и появление новых методик.

Что выбрать?


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

Для категоризации парадигм я использую 4 измерения, которые присущи практически любой задаче:
  • Данные
    Любая программа, так или иначе, работает с данными: хранит их, обрабатывает, анализирует, передает
  • Действия.
    Любая программа должна что-то делать, обычно действия связанны с данными.
  • Логика.
    Логика или бизнес-логика определяет правила, которым подчиняются данные и действия. Без логики программа лишена смысла
  • Интерфейс.
    То, как программа взаимодействует с внешним миром


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

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

Рассмотрим примеры:
  • Ориентация на данные (Data Driven Design).Нам важны в первую очередь данные, а не то, как они между собой связанны.
    Типы подходящих приложений:
    • грабберы (собираем данные из разных источников, сохраняем куда-нибудь)
    • различные админки, интерфейсы к базам данным, все, где много простых CRUD операций
    • случаи, когда работа с данными уже определена, например, требуется разработать программу, а база данных уже существует и схему данных не изменить. В таком случае возможно проще ориентироваться на то, что уже есть, чем создавать дополнительные обертки над данными и уровнями доступа к данным
    • часто ориентация на данные появляется при использовании ORM, но нельзя заранее сказать хорошо это, или плохо (об этом ниже)

  • Ориентация на действия — императивные подходы к разработке. Думаю, что сюда можно отнести такие парадигмы как Event Driven Programming, Aspect Oriented Programming.
  • Ориентация на логику — Domain Driven Design (DDD) и все, что с этим связанно. Здесь нам важна предметная область задачи, мы уделяем внимание моделированию объектов, анализу связей и зависимостей. Применяется преимущественно в бизнес приложениях.
    Так же, сюда относится декларативный подход и отчасти функциональное программирование (решение задач, которые хорошо описываются математическими формулами)
  • Ориентация на интерфейс. Используется, когда в первую очередь важно как программа взаимодействует с внешним миром.
    Разработка приложения с ориентацией только на интерфейс — ситуация довольно редкая. Хотя в некоторых книгах я встречал упоминание о том, что такой подход рассматривался в серьез, причем базируясь на пользовательском интерфейсе — брали, что непосредственно видит пользователь и, исходя из этого, проектировали структуры данных и все остальное.
    Ориентация на пользовательский интерфейс в бизнес приложениях часто проявляется косвенно: к примеру, пользователю требуется видеть определенные данные, которые получить сложно, за счет чего архитектура обрастает дополнительными конструкциями (например, вынужденной избыточностью данных).
    Формально сюда можно отнести Event Driven Programming


А, что на практике?


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

На основе моего опыта могу сказать, что в данной сфере превалируют два подхода: ориентация на данные (Data Driven) и ориентация на логику (Domain Driven). По сути, они являются конкурирующими методологиями, но на практике могут объединяться в симбиозы, которые часто являются известными анти-паттернами.

Одним из преимуществ Data Driven в сравнении с Domain Driven является простота использования и внедрения. Поэтому Data Driven начинают использовать там, где надо применить Domain Driven (причем часто это происходит бессознательно). Проблемы же возникают с тем, что Data Driven плохо совместим с концепциями объектно-ориентированного программирования (конечно, если вы вообще используете ООП). На небольших приложениях эти проблемы почти незаметны. На средних по размеру приложениях эти проблемы уже заметны и начинают приводить к анти-паттернам, ну, а на крупных проектах проблемы становятся серьезными и требуют соответствующих мер.

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

Для того, чтобы понять разницу в подходах рассмотрим более конкретный пример. Допустим, нам требуется разработать систему учета ордеров. У нас есть такие сущности как:
  • Продукт
  • Клиент
  • Квота (отправляется клиенту как предложение)
  • Ордер (заказ)
  • Инвойс (платежка)
  • Ордер поставщику
  • Билл (по сути, платежка от поставщика)


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

Проходит время, и нам требуется добавить дополнительную логику в программу — например, находить у ордера товар с самой высокой ценой. Здесь уже могут возникнуть проблемы, если ваша orm не поддерживает внешние связи (т.е. сущностные классы ничего не знаю о контексте данных), в этом случае, придется создавать сервис, в котором будет метод — по ордеру вернуть нужный продукт. Но, наша orm хорошая, умеет работать с внешними связями, и мы просто добавляем метод в класс ордера. Снова радуемся жизни, цель достигнута, в класс добавлен метод, у нас почти настоящее ООП.

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

Проходит время, и появляется логика, которую не описать внешними связами в бд, и поэтому разместить ее в сущностных классах нет возможности. Мы начинаем создавать сервисы, которые выполняют эти функции. В итоге получаем, что бизнес логика разбросана по сущностным классам и сервисам, понять, где искать нужный метод становится все сложнее. Решаем провести рефакторинг и вынести, к примеру, повторяющейся код в сервисы — выделяем общий функционал в интерфейс (например, делаем интерфейс — IProductable, т.е. нечто, что содержит продукты), сервисы могут работать с этими интерфейсами, за счет чего немного выигрываем в абстракции. Но кардинально это не решает проблему, получаем больше методов в сервисах и решаем для единства картины перенести все методы из сущностных классов в сервисы. Теперь мы знаем, где искать методы, но наши сущностные классы лишись всякой логики, и мы получили так называемую «Анемичную модель» (Anemic Model).

На этом этапе мы полностью ушли от концепции ООП — объекты хранят только данные, вся логика находится в отдельных классах, ни инкапсуляции, ни наследования.

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

Как вы наверно догадались, этот сценарий описывает использование Data Driven подхода и его проблемы.
В случае с Domain Driven мы бы поступили следующим образом. Во-первых, ни о каком проектировании бд на первом этапе речи бы не шло. Нам потребовалось бы тщательно проанализировали контекстную область задачи, смоделировать ее и перенести на язык ООП.

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

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

Более того, вы не застрахованы от ошибки при моделировании, что может привести к сложному рефакторингу.

Итак, подведем итог Data Driven vs Domain Driven:
Data Driven:
  • Плюсы
    • Позволяет быстро разработать приложение или прототип
    • Удобно проектировать (кодогенерация по схеме и тп)
    • На небольших или средних по размеру проектах может быть вполне себе решением

  • Минусы
    • Может приводить к анти-паттернам и уходу от ООП
    • На больших проектах приводит к хаосу, сложной поддержке и т.п.



Domain Driven:
  • Плюсы
    • Использует всю мощь ООП
    • Позволяет контролировать сложность контекстной области (домена)
    • Есть еще ряд преимуществ, не описанных в статье, например, создание доменного языка и внедрение BDD.
    • Дает мощный инструмент для разработки сложных и больших решений

  • Минусы
    • Требует значительно больше ресурсов при разработке, что приводит к удорожанию решения
    • Определенные части становятся сложнее в поддержке (мепперы данных и т.п.)



Так, что же, черт возьми, мне выбрать?


К сожалению, однозначного ответа нет. Анализируйте вашу проблему, ваши ресурсы, перспективы развития, цели и задачи. Правильный выбор — это всегда компромисс.
Поделиться публикацией
Комментарии 97
    +1
    Дааа, знакомые проблемы.
      +8
      О чем статья-то?

      Ну и да, Data-driven design и domain-driven design к ООП/не-ООП имеют мало отношения, они в первую очередь влияют на выбор общей реализации приложения. И, что важнее, они влияют на выбор способа анализа предметной области (за что я, собственно, и не люблю data-driven).
        0
        В целом с вами безусловно согласен, но на практике случается, что Data driven с ООП плохо дружат, хоть и с этим вполне можно жить. Статья от части об этом.
          +1
          Просто не надо думать, что ООП — это обязательно Domain model. Даже у Фаулера это не единственный способ организации приложения.

          Можно иметь чисто ОО-приложение, которое при этом будет поток данных гнать в, простите, DataTable. И ничего.
            0
            Я кажется и не говорил такое :)
              0
              Ну а как решение data vs driven влияет на все остальные области приложения?
                0
                Data и domain — это просто два разных подхода, которые удобно использовать каждый в своей ситуации. На практике же, если говорить о «бизнес» приложениях, часто ситуации бывают неоднозначные, вот, ну, и собственно, системный архитектор как раз и должен решать эти проблемы.

                Отвечая на ваш вопрос — я не могу сказать, как data или domain влияет на остальное приложение, так как это очень абстрактный вопрос, имхо. Мерой влияния может быть сложность перехода от data к domain и обратно
                  +1
                  А не надо между ними переходить, смена методологии разработки на живом процессе разработки всегда очень дорого обходится.
                    0
                    В статье написано так, как будто бы Data-driven совсем не требует связей между данными, совсем ничего не моделирует и просто в таблички пишут и читают. И к предметной области не имеет отношения.

                    У вас внешние ключи используют?

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

                    В общем — Domain Driven — не относится ни к шарпу, ни к SQL. Эванс книгу писал для ООП, но это всего лишь дань моде. Он, кстати, там и указывал об этом. Моделировать предметную область с помощью ООП, причем вида — джава, шарп — это один из вариантов.
                    Реляционными таблицами тоже можно моделировать предметную область. Причем — это декларативный способ.
                      0
                      без обид, но по-моему вы не внимательно прочитал пост и комментарии, и про моделирование домена через схему бд и про то, что DDD и DbDDD к ООП не имеет отношения (в теории) про все это тут уже написано
                        0
                        Может поторопился и не прочитал все комментарии.

                        Но я о посте. Собственно, о противопоставлении Data Driven vs Domain Driven. Не вижу причин их противопоставлять. Это ортогональные измерения. Ничто не мешает быть одновременно Data Driven and Domain Driven
              0
              А зачем излишне хорошо «дружить с ООП»? ООП что-то говорит про какое-то таинственное «поведение» объектов, но я не слышал, чтобы оно что-то говорило про их взаимодействие.

              Не, ну ОК, «поведение» — это когда он один, и других объектов нет. Типа «спрятать окно». Но при усложнении и детализации системы на каком-то этапе неизбежно появится другой объект, и «поведение» превратится во взаимодействие. Превед, редизайн, превед, визитор. Так что рассказки про «поведение» лучше изначально выкинуть как пережиток прошлого.
              0
              Эта статья — краткое содержание, этой хорошей книги:
              www.ozon.ru/context/detail/id/5497184/
                0
                я ее пару месяцев назад перечитывал, да
                  +1
                  Тот факт, что у Эванса словосочетание «data-driven design» не встречается, вас не смущает?
                    –1
                    нет, не смущает
                    потому что data driven (или data centric) встречается у других довольно, на мой взгляд, авторитетных гайдлайнах о разработке (например, в гайдлайнах от майкрософта, у них вообще прямое противопоставление идет, мол если у вас приложение простецкое возможно вам стоит обратить внимание на Data Driven)
                      +1
                      потому что data driven (или data centric) встречается у других довольно, на мой взгляд, авторитетных гайдлайнах о разработке

                      Я просто не очень понимаю, как статья может быть пересказом книжки, в которой вообще не упоминается подход, обсуждаемый в статье.
                        0
                        Ну так вы спросите Noofiz почему он так считает.
                        Статья — не пересказ книжки, статья — пересказ моего осмысления пачки книжек, гуглинга темы, практического опыта. Как-то так.
                          0
                          Так я его и спросил, не смущает ли его этот факт.
                            0
                            а, сорри, мне показалось это ко мне вопрос был :)
                        0
                        Еще для сущностей, имеющих данные, но не имеющих поведения, применяют термин Anemic Domain Model.
                          +1
                          да ладно? :)
                            0
                            Это правда
                  +2
                  Подскажите, пожалуйста, примеры open source приложений с Rich Domain — очень хочется посмотреть на реально работающий код.DDDSample, естественно, не в счет. Так же интересен пример BDD. Сам найти не смог.
                  При anemic'е все проблемы решаемы — если классов сущностей очень много — можно их разделять на области.
                  Повторное использование кода, как в примере с документом, тоже возможно, но в не в иерархии сущностей домена, а в иерархии репозиториев (слой доступа к данным).
                  Но самая главная проблема rich, которая озвучена, но не вынесена в отдельный пункт — это:
                  Более того, вы не застрахованы от ошибки при моделировании, что может привести к сложному рефакторингу.
                  потому что пути заказчика и его бизнеса неисповедимы и Enterprise разработка отличается частыми и ощутитмыми изменениями требований, а рефакторить rich домен в такой ситуации становится довольно затратно и рефакторится он в сторону anemic.
                  Вообще тема холиварная )

                  зы Естественно, imho.
                    0
                    «Подскажите, пожалуйста, примеры open source приложений с Rich Domain» — не подскажу, ибо сам таких не знаю. Мне кажется «чистый» DDD найти можно только в надуманным примерах.
                    Проблема анемичной модели в том, что она уходит от ООП. Поэтому если вы программируете в стиле ООП, анемичная модель просто будет инородной деталькой. Хорошо это или плохо — тема холиварная, я довольно много изучал этот вопрос и сталкивался с обилием споров, и у всех есть аргументы :)
                    Имхо, если разработчик знает суть ddd и dbdd и других «dd», то он осознано может уйти и в анемичную модель, и все у него будет хорошо, но проблема то в том, что многие программисты знают, что такое orm и как нагенерить классов, а вот, что потом с этим делать не знают (или думают, что знают :)
                    Заявляю это на основании проведенных собеседований.
                      +2
                      Поэтому если вы программируете в стиле ООП, анемичная модель просто будет инородной деталькой.

                      Это зависит от вашего определения ООП.
                        0
                        С этим не поспоришь.
                        Как сказал keith, тема действительно холиварная.
                        0
                        А можно поподробнее о вопросах собеседований? Что спрашивали и что слышали / хотели услышать?
                        На счет того, что anemic менее ООП — это вопрос еще тот )
                        Какая разница в какой иерархии будет наследование в сущностях домена или в сервисах?
                        Как измерить степень ООП?
                        Потом, у самой сущности (ее пропертей) и у ее логики может быть разное время жизненного цикла.
                        При маппинге в DDD возникает слой с кучей DTO, которые являются дублированием сущностей домена.
                        Я не против DTO, но только когда сущность покидает границы приложения (или даже команды разработчиков).
                        Ну и в завершение:
                        Cohesion wiki
                        Communicational cohesion — это логика в сущностях домена.
                        Functional cohesion (best) — это логика в сервисах домена или в репозиториях (слое доступа к данным).

                        зы не холивара ради, надеюсь на логичную аргументацию.
                          0
                          «А можно поподробнее о вопросах собеседований? Что спрашивали и что слышали / хотели услышать?»
                          Я постараюсь чуть позже об этом написать, в двух словах наверно не выйдет.

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

                          Попробую ответить.

                          «Какая разница в какой иерархии будет наследование в сущностях домена или в сервисах?»
                          В ООП объекты могут обладать не только данными, но и действиями / методами, это известно всем и на этом строится собственно весь ООП (инкапсуляция, наследования и тп)
                          Поэтому ООП хорошо подходит для моделирования чего-то, что обладает не только данными, но и действиями, а так же поведением.
                          Когда мы выносим весь функционал из моделей в сервисы, то мы разделяем данные и «действия», ведь в ваших сервисах обычно нет данных, это абстракция поведения. Сервисы не могут менять внутреннее состояние модели.
                          По сути, если идти дальше, то такие модели можно сделать immutable, да, и это нас приблизит к функциональным паттернам. Это не хорошо и не плохо (если говорить об абстрактном решении), это просто по-другому.

                          Более того, такая anemic модель может лежать в основе rich модели (т.е. rich модель может быть большой «оберткой» для anemic).

                          «При маппинге в DDD возникает слой с кучей DTO, которые являются дублированием сущностей домена.»
                          Да, именно поэтому полноценный ddd получается дорогим для небольших проектов, особенно, если у вас реляционная СУБД

                          Вообще, DTO тема тоже отдельная. Уровень DTO зависит от сложности модели.

                          ps кстати, добавлю масла в холивар :) anemic model добавляет в жизнь программиста как минимум две «сущности»: модель и сервис, а domain подход, больше стремится к упаковыванию всего этого в модель, поэтому вам не надо вспоминать какой сервис делает, то что вам нужно
                            0
                            > domain подход, больше стремится к упаковыванию всего этого в модель, поэтому вам не надо вспоминать какой сервис делает, то что вам нужно

                            Неправда, serivce — это одна из разновидностей доменных объектов в DDD. Стремление запаковать всю логику в хранимые entity не имеет отношения ни к DDD, ни к здравому смыслу.
                              0
                              По-первых, я не говорил, что надо запаковывать всю логику в сервисы, я говорил о тенденциях. В Anemic модели непонятно, что хранится в моделях, а что в сервисах, обычно это связанно с ограничениями уровня персистенции (orm и тп)

                              Во-вторых, посмею в вам не согласиться, но сервисы не есть доменные объекты. Сервисы могут находиться (и часто находятся) в уровне бизнес логики и работать с сущностями, но доменными объектами они не являются по определению.
                                0
                                Ну да, наверное не доменный объект, а часть доменной модели.
                              +1
                              В ООП объекты могут обладать не только данными, но и действиями / методами, это известно всем и на этом строится собственно весь ООП (инкапсуляция, наследования и тп)
                              Крайне редко сущности моделируют что-то содержащее поведение — ордер, инвойс, клиент и пр. — это не модели с поведениями, а скорее документы с информацией о реальных ордерах, инвойсах и пр. Документы не содержат своего поведения.
                              Даже в играх, где, казалось бы, поведение присутствует, его часто выносят в отдельные классы — я специально интересовался на эту тему у игроделов. Человек, конечно, может сам иметь метод «сесть в транспортное средство», но как правило, за эту логику отвечает отдельный сервис, который знает как конкретному человеку содиться в конкретное транспортное средство и задействует для этого несколько модулей, в т.ч. проигрыватель анимации. Конечно, можно в методе Person.SeatInTheTransport() вызывать этот самый сервис, но это не более ООП'шно, на мой взгляд.
                              Сервисы не могут менять внутреннее состояние модели.
                              Тут под сервисами имелись ввиду репозитории, а они могут менять состояние. Да и сервисам домена (из DDD) ничто не мешает менять состояние сущностей.
                              Вообще, DTO тема тоже отдельная. Уровень DTO зависит от сложности модели.
                              В вьюхих Вы используете DTO или сущности домена? Потому что DDD'шники любят там DTO, а это автоматически создает почти полную копию домена и чаще даже еще больше сущностей, т.к. одно и тоже надо отображать и так и этак и начинаются PersonWithPhotoDTO, PersonFullDto и пр. Я опять-таки не проив этого если данные передаются по сети на клиента, но даже тут можно не писать DTO, если клиента пишет ваша команда и клиент с серверной частью сильно связаны и не имеют нескольких версий протокола одновременно.
                              anemic model добавляет в жизнь программиста как минимум две «сущности»: модель и сервис, а domain подход, больше стремится к упаковыванию всего этого в модель
                              только Rich DDD взамен плодит целых два упомянутых слоя — Mappings и DTO's.

                              Очень интересно продолжить поиск истины, а то сколько этим занимаюсь, а все тема открыта ) Понятно, что разница может быть незначительной, т.е. по сути не важно как делать — rich или anemic, но более детально рассмотреть плюсы и минусы всегда полезно )
                                0
                                «Крайне редко сущности моделируют что-то содержащее поведение» — да, согласен, это известная проблема, но она приводит к полной дискредитации самого ООП. Над этим можно размышлять долго, я пока не готов заявить что-то определенное :)

                                По идее внутреннее состояние менять может только сама модель, ни один сервис, в том числе и репозиторий, не имеет доступа к внутреннему состоянию, а работает только с «интерфейсом» публичных свойств и методов (грубо говоря, сервис не может изменить приватную переменную объекта)
                                Вообще, довольно интересная тема о состояниях модели в ооп, я размышлял на эту тему, гуглил, но к сожалению не смог найти никаких упоминаний об этом. Можно выделить внутреннее и внешнее состояния моделей, причем множество состояний в общем случае штука не конечная, и основываясь на этом можно попытаться перейти к каким-то другим штукам. Я пробовал изобрести некий мат. аппарат для этого (кстати, когда использовал anemic :) ), но потерпел своего рода фиаско, так как не смог извлечь практической выгоды

                                «только Rich DDD взамен плодит целых два упомянутых слоя — Mappings и DTO's.»
                                да, такая проблема есть :)

                                  0
                                  По идее внутреннее состояние менять может только сама модель, ни один сервис, в том числе и репозиторий, не имеет доступа к внутреннему состоянию, а работает только с «интерфейсом» публичных свойств и методов (грубо говоря, сервис не может изменить приватную переменную объекта)
                                  Имел ввиду свойства. Закрытые переменные, конечно, сервис изменить не сможет, но если сервису это будет нужно, то переменная превратиться в открытое свойство. Не встречал необходимости что-то прятать в anemic'е от сервисов. Может у Вас есть подходящий пример?
                                    0
                                    >Вообще, довольно интересная тема о состояниях модели в ооп, я размышлял на эту тему, гуглил, но к сожалению не смог найти никаких упоминаний об этом.

                                    Тоже много думал на эту тему. Есть вот такой интересный топик на эту тему: c2.com/cgi/wiki?GateKeeper
                                      0
                                      Спасибо, обязательно ознакомлюсь
                                      0
                                      «Крайне редко сущности моделируют что-то содержащее поведение» — да, согласен, это известная проблема, но она приводит к полной дискредитации самого ООП.
                                      Вопрос, что такое «поведение»? Обычно нет никакой ложки го «поведения», есть только «взаимодействие» и «воздействие». А «поведение» — это нечто, замкнутое внутри объекта и не влекущее внешних последствий и воздействий на внешнюю среду. Его часто надо моделировать?
                                        0
                                        Поведение — это воздействие на состояние.
                                        В случае, если поведение это часть модели, то оно может изменить внутреннее состояние модели (конечно, если такое имеется). Необходимо ли реально внутреннее состояние модели — вопрос отдельный.
                                        В случае сервисов — они могут изменить внутреннее состояние только косвенно, через доступные интерфейсы модели
                                          0
                                          Поведение — это воздействие на состояние.
                                          Ну да, то, что я читал в хелпе к Visual Basic 5.0 в 1998 году. «Классика». Я готов использовать это определение. Остаётся понять, состояние какого из объектов мы меняем, когда заставляем их взаимодействовать. Например, сажаем человека в транспортное средство. Пока либо человек либо транспортное средство — ненужная абстракция, мы можем считать, что меняем состояние только одного объекта (другого из них). Когда не можем один из них считать ненужной абстракцией — anemic object (не буду использовать слишком многозначный термин «модель») так и просится.
                                            0
                                            Мне кажется подобные попытки создать демо-модель на «людях-транспортах» несколько неудачны по той причине, что они слишком абстрактны и вырваны из контекста.
                                            В реальной ситуации у вас будет еще масса условий, в том числе и не связанных с программированием. И мой подход — это комплексный анализ всех условий.
                                            Ведь в ddd есть еще такие понятия как value-object и aggregate model. Может быть у вас «человек» это value-object? А может и нет. Может быть у вас автобус это aggregate model и содержит человека как часть себя?
                                      +1
                                      Человек, конечно, может сам иметь метод «сесть в транспортное средство»
                                      А почему это не метод транспортного средства «принять в себя человека»? Так вот похоливарят-похоливарят, и вынесут логику в сервисы — чтоб ни тому ни этому.
                                        +1
                                        Точно, и выйдет anemic ;)
                                    0
                                    Наследование (если нельзя поменять предка в рантайме) считается bad style, ибо tight cohesion. Советуют предпочитать ему композицию.
                                      0
                                      Полностью согласен. Liskov substitution principle понятен и композиция тоже нравится больше наследования, просто тут вопрос был в другом — при том или ином подходе более или менее ООП'шно ли решение.
                                      0
                                      > Как измерить степень ООП?

                                      Простой индикатор: сущности в «правильном» ООП имеют поведение и инкапсулируют данные.
                                      В процедурном стиле же мы имеем immutable слой бизнес-логики (сервисы) — своего рода «конвейер», через который мы гоняем классы-данные (DTO).
                                        +1
                                        О, новый раунд.
                                    0
                                    Как пишет Фаулер, шаблоны проектирования имеют свойство вытанцовываться сами собой в процессе неоднократного рефакторинга. Считается, что типа шаблоны проектирования — это хорошо и круто. Если анемичная модель тоже имеет свойство вытанцовываться в результате неоднократного злобного рефакторинга, то не повод ли это считать её тоже чем-то хорошим и крутым?

                                    Кстати, куда относить доменную логику — к модели или к контроллеру — это тоже холиварная тема.
                                      0
                                      … или к сервису :) То есть недетерминизм еще больше.
                                        0
                                        Тут холивар в том, куда относить сервис в рамках MVC — в «модель» или в «контроллер»…
                                          0
                                          Методом исключения получается в модель. Вообще, слово «модель» может иметь много смыслов, имхо в mvc модель имеется ввиду не модель сущности, а уровень бизнес логики
                                    +2
                                    Почему-то «data-driven» подход часто считают устаревшим «процедурным». Я считаю что это неверно.

                                    В моем понимании «data-driven» — это уход от ООП в ФП-сторону. Данные отдельно, функции отдельно. Данные по-возможности immutable, функции — по-возможности чистые.

                                    Такой ФП-стиль подходит для очень большого класса приложений. Большая часть enterprise-логики, например, на это очень хорошо ложится. Очень важно понимать что сам по себе этот подход ни к какому бардаку не приводит. Более того, мой опыт говорит что этот подход очень часто сильно лучше классического ООП.

                                    Между тем есть области где ФП требует сильно и заморочено абстрагироваться, а ООП позволяет делать просто и понятно. Яркий пример — UI. И вот там пока цветет классический ООП, и это наверное наиболее прагматичное решение на данный момент. Хотя FRP в виде всяких продвинутых data-binding-ов и тут подступает.
                                      +1
                                      Кажется, налицо непонимание того, что такое data-driven design.

                                      Впрочем, я и сам затруднился бы дать определение.
                                        0
                                        Согласен и с вами, собственно, как вы уже сказали выше data driven и domain driven понятие вне ООП и ФП.
                                        Единственное, имхо, на практике картина другая
                                          +1
                                          В ООП вообще очень плохо с точными определениями и терминологией. Очень оно с гуманитарной стороны заходит.

                                          Скажу так: под современным data-driven я понимаю систему из «голых» DTO-классов почти без методов, и набора сервисов с логикой. На DTO-классы сверху декларативно навешивается сериализация, мэппинг на базу, всякая валидация и т.п. Сервисы же неплохо структурируются и управляются каким-нибудь dependency-injection-фреймворком.

                                          Некоторые воспринимают это как процедурное программирование на стероидах. Я вижу в этом уход в ФП и декларативное программирование.
                                            0
                                            Насколько я знаю, это на сегодня мейнстрим до степени капитанства и боянизма.
                                              0
                                              Я про второй абзац.
                                                0
                                                под современным data-driven я понимаю систему из «голых» DTO-классов почти без методов, и набора сервисов с логикой.

                                                Вот только при чем тут data-driven, если это прекрасно вписывается, например, в SOA?

                                                Ну и да, с автором-то вы не совпадаете в определениях.
                                                  0
                                                  А чем принципиально SOA отличается от anemic, data-driven и других еще модных терминов?
                                                    0
                                                    Про это больше одной книжки написано.

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

                                                        Но вообще, конечно, меня забавляет ваше отношение к гуманитарным наукам.
                                                          0
                                                          А всю эту бурду классическую — Буча, Фаулера, GoF, всякие Domain-Driven Design и т.п.
                                                            0
                                                            Ну понятно. В этом списке ни одной книги про SOA нет, если что.
                                                              0
                                                              Я не понимаю зачем писать целую книжку про SOA, и с какой стороны SOA вообще прилетело в тему разговора.
                                                                0
                                                                Я не понимаю зачем писать целую книжку про SOA

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

                                                                с какой стороны SOA вообще прилетело в тему разговора.

                                                                Ну так вы тред-то перечитайте:

                                                                Вот только при чем тут data-driven, если это [система из «голых» DTO-классов почти без методов, и набора сервисов с логикой] прекрасно вписывается, например, в SOA?
                                                                  0
                                                                  Я примерно 5 лет на работе вижу SOA-системы. В свое время очень модно было, вот и наплодили. Иногда в тему, но в основном — жуткая инертность на изменения и дикие проблемы с производительностью и доступностью.

                                                                  >Вот только при чем тут data-driven, если это [система из «голых» DTO-классов почти без методов, и набора сервисов с логикой] прекрасно вписывается, например, в SOA?

                                                                  Звучит как «причем тут сахар, если мед сладкий?»
                                                                    0
                                                                    Иногда в тему, но в основном — жуткая инертность на изменения и дикие проблемы с производительностью и доступностью.

                                                                    Я эту фразу слышу про практически любой подход.

                                                                    Звучит как «причем тут сахар, если мед сладкий?»

                                                                    Почти. Точнее было бы сказать «почему вы определяете сахар как „что-то сладкое“, когда есть еще и мед»?
                                                    0
                                                    Причём здесь SOA, основной отличительной чертой которой является взаимодействие компонентов через web? Тут термин «сервисы» взят в полужаргонном значении из современной архитектуры Java-web-ORM-приложения: сервлет-контроллер-сервис-DAO-Entity.

                                                    Ну а то, что data-driven вписывается в SOA, это не повод приплетать сюда web-взаимодействие.
                                                      0
                                                      основной отличительной чертой которой является взаимодействие компонентов через web?

                                                      Ну во-первых, не является.

                                                      А во-вторых, при том, что подход-то, в реальности, тот же самый, только некоторые детали реализации отличаются.
                                                0
                                                Абсолютно с вами согласен. Data-Driven-Design + FP + SOA — это очень мощная связка.
                                                  0
                                                  Согласен с вами.
                                                  Близость того, о чем вы говорите (хотя это не совсем data-driven), к ФП меня всегда интересовала и интриговала. К сожалению, мой опыт в ФП не настолько хорош, чтоб я мог выдвигать какие-то теоретические гипотезы, поэтому я не стал упоминать об этом.
                                                    0
                                                    UI вроде бы сейчас весь такой из себя event-driven, нет?
                                                      0
                                                      Ну там же строго ООП-иерархия в контролах, в мейнстриме. И event-driven он тоже, конечно. Хотя event-driven и ООП — ортогональные штуки.
                                                        0
                                                        Ну там композиция тоже часто используется, а это уже предпосылка к тому, что ООП еще меньше нужно.
                                                          0
                                                          Да, именно так. В UI с ООП такая же движуха происходит.

                                                          А event-driven в UI потихоньку эволюционирует в reactive programming, это заметно по новым UI-фреймворкам, в javascript-сообществе сейчас особенно модно — knokout.js и иже с ним.
                                                            0
                                                            Вы имели в виду knockout.js
                                                        0
                                                        Главный кандидат на «последнее пристанище ООП»;-)…
                                                      –2
                                                      Пишите код бля, теоретики.
                                                        +4
                                                        Вообще, когда-то я «писал код блять», но это слишком затратно — иногда в разы.
                                                        Поэтому мой лозунг — «Прежде чем писать код — думай, блять!» )
                                                        0
                                                        да, думать намного, намного интересней, чем писать код
                                                          +1
                                                          За думать денег не платят. Нужно думать и кодить одновременно.
                                                            0
                                                            Думать — деньги экономит. А за экономию — да, обычно не платят.
                                                              0
                                                              Значит мне повезло :)
                                                              0
                                                              Как -то пункты «Ориентация на действия» и «Ориентация на интерфейс» у автора оказались проработаны слабо, и «Event Driven Programming» отнесено к обоим пунктам. Наверное потому, что в IRL они редко встречаются…
                                                                0
                                                                Да, вы правы, в моей практике мы разрабатываем ПО, в котором «Ориентация на действия» и «Ориентация на интерфейс» не являются особо выраженными направлениями. Т.е. обычно с этим все довольно ясно и вопросов не вызывает
                                                                  0
                                                                  Подозреваю, не только вы, вообще мало кто разрабатывает такое ПО…
                                                                +1
                                                                Были бы в языке trait-ы — вопрос бы куда в Data Driven-случае всунуть getMaximalPricedProduct() не стоял бы… А так — имеем оверхед в виде лишнего интерфейса и реализации паттерна «визитор»…
                                                                  0
                                                                  Последняя фраза очень точная, есть только две парадигмы: помогающая решить задачу и мешающая решению оной.
                                                                    0
                                                                    В контексте сложности хранения данных с Domain-driven design. Является ли OODMS решением? Что вы думаете о состоянии OODMS рынка на данный момент?
                                                                      0
                                                                      К сожалению, реального практического опыта с OODMS пока нет. Из нереляционных СУБД мы используем MongoDb (с .net'ом потому что у него есть linq адаптер, и как показала практика переехать с mssql на mongo вышло не так уж и сложно, за счет абстракций уровня данных, но тем не менее основной субд является mssql по ряду других практических причин). Раньше использовали CouchBase (в основном в связке с проектами где много javascript'а).
                                                                      Вот, и хотя Mongo не является OODMS, но она позволяет сохранять скимлесс-документы и, да, это порой может реально упростить меппинг моделей (ну т.е. тут и меппать ничего не надо).

                                                                      Могу предположить, что в OODMS все может быть еще круче и удобней и в один прекрасный день мы начнем использовать такой типа субд :)
                                                                        +1
                                                                        Позволите, я отвечу :)

                                                                        Проблема хранения данных в контексте ООП заключается не сколько в сложности меппинга структуры таблиц, на структуру объектов, сколько в меппинге структур в памяти на некое представление на диске. Говоря проще, основной проблема сидит в свистоплясках с сессией, lazy load, каскадах и так далее. Есть ощущение, что такого рода ORM-мепперы вечно текущая абстракция. Таким образом OODMS решают только проблему со стуктурой, но основная проблема никуда не девается.

                                                                        Решения проблемы я вижу следующие:
                                                                        1) Поместить на уровень предметной области знания о деталях хранения объектов. Код становится менее объектным по ряду причин.
                                                                        2) Реально хранить все объекты в памяти, а бд использовать для долговременного хранения, используя минимум возможностей субд.
                                                                          0
                                                                          Второй вариант все же не подходит для большинства программ, по причине неотказаустойчивости. И если использоваить минимум возможностей субд, то придется писать много лишнего кода в BL или где там еще. Зачем изобретать велосипед? Если уже не пользоватся ORM, которая будучи абстракцией над БД усложняющей прямой доступ к ней, то разумно пользоваться плюсом отсутствия ORM — прямым доступом ко все богатствам БД.
                                                                            0
                                                                            Насчет второго варианта: отказоустойчивость там таки есть, бд используется как журнал, а если хотим кластер, то используем распределенный кэш. Что касается такого подхода с точки зрения лишнего программирования, то такая схема больше годится для oltp, поэтому ничего особо кроме как взять по ключу и вставить запись и не нужно. Если хотим аналитику, тот orm и тому подобное априори не нужно — просто используем мощный язык для аналитии, встроенный в субд
                                                                        0
                                                                        У вас DataDriven «вырождается» в то, что называется DCI. Он фактически строится вокруг идеи анемичной модели. Далее, как я понимаю, всякие методы вида «получи то-то» отправляются в роли (ведь правда же для роли Customer совершенно не важен метод getAvatar), а взаимодействия описываются отдельными классами в терминах ролей.
                                                                        Сам пока не пробовал эту модель, но звучит очень разумно, не как антипаттерн, а вполне себе как парадигма программирования (довольно модная нынче). Одна проблема, что в чистом виде реализовать это можно не в любом языке, но это вопрос не к парадигме, а к языку.
                                                                          0
                                                                          Проходит время, и нам требуется добавить дополнительную логику в программу — например, находить у ордера товар с самой высокой ценой. Здесь уже могут возникнуть проблемы, если ваша orm не поддерживает внешние связи (т.е. сущностные классы ничего не знаю о контексте данных), в этом случае, придется создавать сервис, в котором будет метод — по ордеру вернуть нужный продукт. Но, наша orm хорошая, умеет работать с внешними связями, и мы просто добавляем метод в класс ордера. Снова радуемся жизни, цель достигнута, в класс добавлен метод, у нас почти настоящее ООП.


                                                                          Это и на два абзаца ниже.
                                                                          Во-первых, что значит «внешние связи»? Как это связано с поиском товара?
                                                                          Во-вторых, это не DDD. В методологии явно указано, как нужно поступать в таких случаях. И это совсем не «добавляем метод». Так что одинаковых методов в итоге бы не было, и рефакторинга бы не было, и анемичной модели бы не было.
                                                                            0
                                                                            1. Мне кажется пример проблемы с orm довольно очевиден, возможно вы не так поняли, что я пытался сказать в посте. Ок, внешняя связь — в общем случае, это абстракция связи между двумя сущностями. В контексте рел. субд это например внешние ключи. Большинство современных ORM отлично обрабатывают внешние ключи и переносят абстракцию в сгенерированные сущностные классы, поэтому пример проблемы на самом деле больше надуман, чтоб показать суть. Если более конкретно, то например, из моделей сгенерированных через linq2sql ( sqlmetal ) нельзя получить контекст, и, если представить, что sqlmetal не умел бы обрабатывать внешние ключи (или ключа бы просто не было), то вместо такого «order.Products» вообще у сущности ордера ничего не было б, поэтому из сущностного класса получить сведение о связанных продуктах не получилось б.

                                                                            2. Естественно это не ddd. Как бы об этом потом и говорится.

                                                                            Интересно было б услышать Ваш вариант реализации описанной задачи в методологии DDD

                                                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                          Самое читаемое