По мере того, как автоматизированные системы не просто заменяли бумажные документы, отражающие текущую деятельность, а брали на себя задачу их обработки, включая задачи по планированию и управлению, возрастала потребность в описании их внутреннего устройства, алгоритмов в виде, понятном для заказчиков и пользователей систем. Описание в виде черного ящика предполагало, что внутри творится магия, придуманная разработчиками. Но эта магия оказывалась вовсе не такой, на которую рассчитывал бизнес.
Решение — подход DDD, Domain Driven Design, было предложено Эриком Эвансом в 2003. Но прежде, чем о нем говорить, необходимо немного углубиться в историю развития разработки софта как такового.
Долгое время основным способом проектирования софта был процедурный подход, включающий описание структур данных и алгоритмов обработки этих данных. Классическая книга — Николас Вирт «Алгоритмы + структуры данных = Программы» — была написана в 1976. Если мы сравним содержание книги Вирта со многими современными постановками, то увидим, что добавились лишь описания экранных форм. Однако, это не позволяло эффективно писать сложные системы, множество разрозненных процедур плохо поддавалось пониманию и управлению.
Решение дали объектные языки программирования, начиная с C++, который на рубеже 1980-х дал первую эффективную реализацию Объектно-ориентированного программирования, ООП. Уменьшение сложности достигается за счет инкапсуляции в объекты структур данных и связанных с ними алгоритмов обработки, с методами наследования и полиморфизма объектов, и это в целом структурирует системы: мы отдельно рассматриваем устройство каждого объекта и взаимодействие между разными объектами.
Через некоторое время эти же принципы применили для проектирования софта и даже попробовали написать язык, на котором по замыслу авторов непрограммисты могли бы описывать, что им требуется от софта. Так в 1997 появился UML. Идея UML как средства описания устройства софта, позволяющего создавать его без разработчиков, провалилась, так UML не работает. Однако встроенные в него способы графического изображения устройства софта в виде различных диаграмм оказались эффективными, и активно используются.
Итак, в начале нулевых основным способом, которым разработчики описывали устройство софта, был язык объектов, инкапсулирующих данные и бизнес-логику. Таким образом, получалось две модели: модель предметной области, обычно в виде бизнес-процессов, с которой работал бизнес-аналитик, и модель устройства системы через формализм объектов, которую создавал разработчик или системный аналитик, а сопряжение между ними были требования и модели интерфейсов. Подробнее это было рассмотрено в предыдущей статье «Какие нужны требования: развитие концепта».
В целом это неплохо работало для первого прохода: модель бизнес-процессов → требования → дизайн системы. Но если в процессе разработки возникали изменения, то согласованное ведение двух моделей на разных языках вызывало проблемы. А это обязательно происходило в процессе внедрения, так как при этом обычно происходило изменение бизнес-процессов, а не только замена софта, и выяснялось много деталей, которые не учли в проекте: ведь бизнес-процессы живут и не всегда хорошо наблюдаемой жизнью. Эта проблемная ситуация показана на схеме.
DDD предложил так же, через объекты, описывать предметную область, а затем прозрачно отражать объекты предметной области в код. Это был следующий шаг по отношению к рекомендованному на этапе анализа составлению словаря предметной области: мы говорим, что у нас теперь будет не просто словарь понятий, а набор объектов со своими атрибутами и методами. И язык этих объектов будут понимать все участники проекта: заказчики, разработчики, аналитики, пользователи, менеджеры. Именно названия объектов и атрибутов из этого языка будут отражаться на интерфейсах системы. Этот язык, создаваемый для каждого проекта, DDD назвал ubiquitous language, в русском переводе — единым языком.
Таким образом, DDD сместил фокус от описания системы как черного ящика к описанию внутреннего устройства, или системы прозрачного ящика. А требования как описание черного ящика стали короткоживущими временными объектами от пожелания пользователя до внесения изменений в модель. Они заменили две модели, предметной области и системы, на единую модель, описанную на едином языке проекта.
На рисунке мы видим описание бизнес-процессов в виде activity diagram, диаграмму классов для документов и диаграмму состояний документов, которые и реализуют бизнес-процесс. Но при этом все три модели — на едином языке и с прозрачной связью между ними. И принципы DDD говорят, что в коде информационной системы должны присутствовать те же самые объекты, а не какая-то другая реализация.
Этим DDD в значительной мере обесценил требования как таковые и внимание к ним. Ведь если заказчик и пользователи понимают модель системы, то они сами могут оценить, подойдет она для их целей или нет. И примерно понять объем требуемых доработок: достаточно ли для их целей просто добавить в объект атрибут, или улучшить алгоритм обработки, или потребуется изменение многих объектов. Это как раз то, что не дает описание черного ящика: там ты формулируешь, что надо добавить поле на интерфейсе, что всегда просто, а вот насколько надо изменить внутреннюю магию системы, чтобы она учитывала новое поле, и сколько это займет времени, неясно.
DDD сместил фокус от требований, описания системы как черного ящика, к описанию ее как прозрачного ящика в модели на едином языке
Еще одно важное изменение, которое принес DDD, — признание, что единую непротиворечивую модель предметной области построить невозможно, а значит и не стоит браться за эту задачу. Ведь это получается антипаттерн Big Object, когда всю логику пробуют реализовать в одном объекте. Вместо этого предложено предметную область делить на ограниченные контексты, в рамках каждого из которых строить свою модель, сопрягая их теми же способами, которыми в объектном подходе сопрягаются разные системы или фрагменты системы: через выделение общего ядра с наследованием, создание специальных прослоек-переводчиков или иным образом.
Это схема из книги Эрика Эванса. В зависимости от соотношения контекстов, могут быть различные способы сопряжения. Может быть выделено общее ядро, или периферийная часть, описывающая только передаваемую информацию в шаблоне поставщик — заказчик, а может быть использован общедоступный язык. А в случае сопряжения с областью с устаревшими процессами, которая не склонна изменяться и поддерживается легаси-системой, можно либо следовать за ними в шаблоне «Конформист», либо сделать специальный предохранительный уровень для изоляции.
DDD актуален и сейчас, только в современных распределенных системах способы отражения в код изменились. Вместо простого шаблона Business Objects для каждого бизнес-объекта в коде создают несколько: транспортный объект без логики, контроллеры, реализующие логику на сервере и на клиенте, и так далее. Важно, что это отражение является единообразным, бизнес-объекты по-прежнему можно проследить в коде.
Правда, сейчас есть сложность с современной архитектурой, в которой системы реализуют активные сервисы, асинхронно взаимодействующие через очереди. Классические объекты с обработкой через вызовы методов плохо отражают такую архитектуру, ик требуются другие методы представления устройства софта, понятные бизнесу. Такой модели посвящена моя серия докладов «Акторная модель». Активные сервисы представляются гномиками, работающими и взаимодействующими для обработки запросов к системе. Для иллюстрации — схема интернет-магазина в таком представлении.
На этом я завершаю статью, посвященную моделям. Продолжение следует…