(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

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

Источник: habrahabr
primepix

Информационные технологии развиваются семимильными шагами, появляются новые устройства, платформы, операционные системы, и вместе с этим растет спектр задач, который приходится решать разработчикам. Но, не все так плохо - на помощь программистам спешат новые средства разработки, 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.
    • Дает мощный инструмент для разработки сложных и больших решений

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

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


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

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 13.11.2012 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Quest Software. TOAD Xpert Edition
NauDoc Enterprise 10 рабочих мест
Stimulsoft Reports.Ultimate Single License Includes one year subscription, source code
IBM RATIONAL Quality Manager Quality Professional Authorized User Single Install License + Sw Subscription & Support 12 Months
Купить CommView for WiFi 1 лицензия
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Безопасность компьютерных сетей и защита информации
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
Новости мира 3D-ускорителей
Новые программы для Windows
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100