Прочитал книгу Vlad Khononov “Learning Domain-Driven Design. Aligning Software Architecture and Business Strategy”, 2022 год. Эта книга посвящена практикам Domain Driven Design, применяющимся в программной инженерии.
Идея DDD состоит в том, что при разработке программного продукта в первую очередь нужно думать о предметной области (домене) и решения, принимаемые в разработке должны быть подчинены логике этой предметной области.
Важнейшая концепция в DDD это единый язык (ubiqutious language). Идея единого языка состоит в том, что при разработке используется язык, используемый предметными экспертами. Таким образом разработчик погружается в предметную область - ему помимо специфических знаний в разработке необходимо разбираться и в предметной области. Причем этот язык используется вплоть до названий переменных или типов. Через общение с предметными экспертами выявляем язык и далее используем этот язык везде в работе. Единый язык помогает сократить расстояние между разработчиком и предметным экспертом и решает известную проблему испорченного телефона, когда задача несколько раз переформулируется и до разработчика доходит в искаженном виде. Также в книге упомянуты аналитики и проговаривается, что аналитики - если они просто берут информацию от заказчика и передают разработчику - не нужны, у них должна быть некая инженерная функция, т.е. они должны принимать решения по продукту и в таком случае получается, что слово “аналитик” вводит в заблуждение, они являются инженерами.
Если домен/предметная область большая, то в ней есть смысл выделить несколько поддоменов. Вводятся три типа поддоменов: общий (generic), поддерживающий (support), основной (core).
Общие поддомены могут быть сложными, но не является ключевым преимуществом бизнеса, его используют все похожие бизнесы, тут можно использовать некий готовый софт или отдавать реализацию на аутсорс. Поддерживающие поддомены - это некоторая простая функциональность. Суть бизнеса заключена в основных поддоменах - именно здесь сосредоточены инновации и сложность. Основные поддомены обязательно должны разрабатываться In-house. Представьте себе, что компания Google отдала на аутсорс алгоритмы ранжирующие выдачу в поиске? Кстати, сложность и инновации основного поддомена могут быть и не завязаны на разработку, а лежать в других областях. В этом плане DDD конечно хорош, что он в первую очередь глядит не на софт, а на бизнес. А в бизнесе софт может играть совсем второстепенную роль, это нормально, а DDD это подсветит.
Подобное разделение на типы поддоменов позволяет сосредоточить внимание на важном и использовать для соответствующих поддоменов необходимые решения.
Важный вопрос в том, как именно провести границы между поддоменами. Это концепция Bounded Context. По границам Bounded Context проводится разделение функциональности и разделение команд, реализующих функциональность. Вообще Bounded Context и поддомены это немного разное - поддомены это то, что существует в реальном мире, на что делится предметная область - это данность, выявляемая в сотрудничестве с предметными экспертами. А Bounded Context проектируется - т.е. это то, как будет создаваться программный продукт, внутри этих границ создаются части продукта, и по этим границам проходят команды.
Есть такой закон Конвея, что создаваемый продукт повторяет структуру организации и обратный маневр Конвея, когда структура организации формируется под нужды создаваемого продукт. DDD и Bounded Context позволяют выявить границы продукта и выстроить продукт и организацию правильным образом.
В книге много советов и тактических приемов как выстраивать взаимодействие между частями продукта. Все крутится вокруг идеи единого языка. Разные части продукта будут работать в разных поддоменах и там будут разные языки. В таком случае важен перевод языка. Тут интересный момент - если мы говорим о разработке в рамках одного поддомена, то смена языка это то, с чем мы боремся - разработчик должен разрабатывать продукт и разговаривать с предметным экспертом на одном и том же языке. В то же время если идет взаимодействие двух частей продукта из разных поддоменов, то у них естественным образом два разных языка и с необходимостью требуется перевод с одного языка на другой. Разные тактические приемы предназначены для того, чтобы обеспечивать перевод таким образом, чтобы влияние частей продукта было минимально. Много говорится о слабой связности (loose coupling) частей продукта и про то как обеспечивать подобную связность.
Рассказано о конкретных практиках, которые можно использовать для разработки в стиле DDD. Некоторые практики предназначены для выявления предметной области, а некоторые - это паттерны разработки. Интересной показалась практика EventStorming, предназначенная как раз для того, чтобы выявить как работает предметная область, захотелось попробовать попрактиковать.
По паттернам разработки тоже много интересного. Мне показалось, что DDD более тяготеет к объектно-ориентированному подходу, особенно если смотреть на объекты в стиле BORO-фреймворка, тогда получается хорошо. Тут конечно много интересного и кажется самое важное - умение бегло работать с базовыми паттернами такими как Value Object, Transaction Script, Active Record.
Понял что Clojure как язык не очень сочетается с подходом DDD. В DDD основа это ubiqutios language. Это означает, что мы должны использовать концепты из предметной области и задавать типы. Clojure динамический, т.е. типы играют небольшую роль и проверка типов происходит только в рантайме. Также Clojure функциональный, что означает что основная работа будет происходить с простыми уже заданными структурами.
DDD хорошо согласуется с микросервисной архитектурой, это вопрос выделения Bounded Context, микросервисы должны проходить по границам поддоменов.
Также приведены паттерны для объединения всех частей в единый продукт.
Что хорошо, DDD не является all-or-nothing подходом. Отдельная глава посвящена приемам, позволяющим начать применять приемы DDD в существующих brownfield проектах. Вообще, мне нравится, что сейчас меньше говорят о legacy проектах, а более о brownfield проектах, т.к. концепция brownfield говорит о живущем проекте, а legacy - о проекте, которую в какой-то момент придется заменить. Кажется, что концепция legacy, устаревшего проекта сама уже чутка устарела - понятно, что проект в момент выпуска уже становится несовременным, это норма жизни сегодня.
Итого, для меня было довольно сложно читать эту книгу. Приведенные паттерны непривычные, я не привык разрабатывать и мыслить так. Что клево: приведенный подход кажется позволяет справится с системами большого размера и работать в команде, это круто. Одна из самых полезнейших техник мне кажется EventStorming, про нее есть отдельная книга, еще прочитаю.
С точки зрения системной инженерии, приведенные техники с адаптацией применимы не только к софту, но и к системам любого другого вида. Это про концепцию системы и про то, как выстраивать внутри системы взаимодействие подсистем.
Текст также опубликован в личном блоге Telegram: Contact @burganov