Есть вопрос, который я никак не могу раскусить. Казалось бы, по нему есть масса информации: книги, статьи, доклады. Но сложность и многогранность темы не позволяет сразу ухватить суть. Поможешь мне в этом?
Чтобы действительно понять сложную тему, нужно прочитать и обдумать множество источников. Прелесть в том, что каждый из них предоставляет одну и ту же информацию по-своему и какой-то из этих подходов может сработать именно для тебя. Так что давай и я попробую внести свой вклад в общее информационное пространство. Так какой у тебя вопрос?
Что такое Domain Driven Design?
Это подход к автоматизации бизнес-процессов в сложных предметных областях.
То есть цель DDD это автоматизация?
Нет, автоматизировать можно и без него. Цель DDD — управление сложностью.
Сложностью чего нужно управлять и для чего это делать?
Речь идет о сложности разработки ПО. И чтобы ответить на твой вопрос, сначала нужно обратиться к теории. Стив Макконелл называет управление сложностью ни больше, ни меньше, а основным законом разработки [1]. Он, развивая идеи Фреда Брукса, делит сложность разработки на существенную и несущественную. Если вкратце, то существенная сложность — это сложность реального мира, а точнее предметной области, которую мы моделируем. Несущественная — это та сложность, которую мы сами, как разработчики, привносим в процессе реализации ПО. Например, выбираем слишком простое и поэтому ошибочное решение сложной проблемы, или наоборот переусложняем там, где в этом нет надобности.
Так вот, Макконелл для управления сложностью дает два совета. Если своими словами, то, во-первых, с существенной сложностью ничего не поделаешь, она зависит от конкретной предметной области и может быть огромна. Но в наших силах спроектировать программную модель так, чтобы в каждый конкретный момент времени нам приходилось работать только с ограниченное частью предметной области.
А во-вторых, соответствующие части модели должны быть реализованы с одной стороны настолько просто и очевидно, насколько это возможно в реалиях конкретной предметной области. А с другой — гибко, чтобы стоимость внесения изменений не взлетала со временем до небес, что позволило бы разрабатывать итеративно.
DDD предоставляет инструменты для реализации обоих пунктов.
Пока цель звучит довольно абстрактно. Зайдем с другой стороны: в чем основная идея DDD? Что этот поход отличает от других, от того, что было раньше?
Я думаю, что уникальная идея – это объединение экспертов предметной области с техническими специалистами в одну команду.
С техническими специалистами более или менее понятно, а что такое «эксперт предметной области»? Это аналитик или заказчик?
Вообще говоря, должность тут не имеет значения. Эксперт – это любой человек, обладающими глубокими знаниями в предметной области. Это может быть и аналитик, и заказчик, и топ-менеджер, и конечный пользователь, и разработчик-старожил, кто угодно.
Хорошо, кто такие эксперты разобрались. Но мне пока не очень представляется формат работы этой «команды». В чем функции экспертов? Они выступают в роли системных аналитиков?
Повторюсь, не привязывайся к должностям и ролям. Эксперт используется как источник знаний о предметной области, законов по которым она живет. Никто лучше экспертов этого не знает, кем бы они ни были. Каждая команда выбирает свой формат взаимодействия. Главное, чтобы это взаимодействие было.
Все равно не представляю как это работает. Обычно программисты неохотно отрываются от архитектуры, паттернов, фреймворков и кода, чтобы поговорить о бизнесе. Да и эти эксперты, как я понимаю, имеют свои прямые обязанности, которые могут быть далеки от разработки. Это же разные планеты. Как добиться этого общения?
А что нужно, чтобы люди общались?
Хм, ну наверное возможность и желание это делать.
Допустим. А что ты имеешь ввиду под возможностью общаться?
Ну конечно для общения люди должны понимать друг друга.
А конкретнее?
Ну хотя бы разговаривать на одном языке. Если мой собеседник начнет говорить на китайском, то я при все желании его не пойму.
Вот ты сам и пришел к первой и, возможно, важнейшей практике, которую предлагает DDD: эксперты предметной области и разработчики должны говорить на одном языке.
Звучит как-то слишком просто для “важнейшей практики”.
Не торопись, идея не такая простая как кажется. Чаще всего для экспертов язык разработчиков ничем не лучше, чем для тебя китайский. И к сожалению в обратную сторону бывают аналогичные проблемы с пониманием. DDD говорит нам, что внутри команды, объединяющей в себе разработчиков и экспертов, должен существовать Единый язык, который описывает предметную область[2].
То есть это набор терминов предметной области, которые должны выучить разработчики, чтобы понимать экспертов?
Нет. Единый язык вырабатывается экспертами и разработчиками совместно. То есть единый язык — это не то, что “дано”. Он сам по себе является результатом совместной работы.
А почему бы просто не использовать терминологию предметной области? Раз есть реальный бизнес-процесс, значит всему в нем уже есть описание. Обычное дело — подробная вики с терминологией.
Во-первых, как говорится, вики — это то место, куда информация отправляется умирать. Язык напротив должен жить и постоянно развиваться. А во-вторых, полная копия терминологии предметной области, возможно, не лучший вариант. Не задумывался, почему мы в своей речи используем заимствованные из других языков слова?
Наверное потому, что это изначально в родном языке не было аналогичного понятия.
Верно. А еще они возможно более емко и лаконично описывают уже имеющееся понятие или процесс. Например торговая марка — это бренд; подбор актеров и моделей — это кастинг. Когда-то этих терминов не было в русском языке, но они были заимствованы и прижились, потому что их удобно использовать. Так и в едином языке.
Конечно можно было бы просто взять неизменной терминологию предметной области и заставить разработчиков выучить ее. Но, во-первых, в ходе проектирования могут возникнуть новые термины, которых нет в предметной области. А во-вторых, тяжеловесные термины предметной области могут быть заменены более понятными и легкими в обращении. Плюс для команды будет работать эффект икеа и они будут относиться к выработанному языку как к чему-то своему, родному, и это очень важно.
Но единый язык не ограничивается только терминами, он может содержать в себе целые фразы и предложения, чтобы иметь возможность описать сущности предметной области, их поведение и отношения.
Интересно. В такой формулировке единый язык звучит как нечто, что можно выразить в коде.
Почему бы и нет. Как думаешь, какую пользу можно было бы от этого получить?
Если единому языку уделяется центральное место, то кажется логичной идея распространить его влияние и на код. Плюс в этом случае разработчики будут использовать единый язык не только для общения с экспертами и работы с задачами, но и непосредственно при написании кода.
Верно. Таким образом в DDD существует неразрывная связь единого языка и программной модели: программная модель ведёт себя согласно единому языку. Все что она описывает есть в языке и наоборот. И очевидная польза в том, что это снижает когнитивную нагрузку на мозг разработчика. Теперь ему не придется постоянно переключаться с документации на код и обратно: все будет выражено на одном и том же языке. Кроме этого, чем больше разработчики используют единый язык, тем “роднее” он им становится и это дает невероятные возможности для освоения тонкостей предметной области.
Давай немного отвлечемся от программирования и поговорим о русской душе. Ты не задумывался почему для того, чтобы понять русского человека, то как он думает и ведет себя, советуют читать классиков? Все дело в том, что они очень точно относились к использованию языка и никогда не поставили бы рядом два случайных слова. Поэтому чтобы прочувствовать значение того или иного понятия, что именно понимает под ним народ, нужно обратиться к его языку. Поищем: с какими другими словами сочетается интересующее нас понятие, почему так можно сказать, а так нельзя. Так говорят — а так не говорят. Это никогда не бывает случайным [6].
Ты спросишь: причем здесь DDD? Но в обоих случаях речь идет о языке. Подмечая как именно говорят эксперты, какие понятия и словосочетания, и в каких ситуациях они используют, разработчики могут по-настоящему проникнуться предметной областью. Не просто выучить словарь терминов (как любой турист с разговорником), а ухватить суть, понять как именно думают эксперты и, соответственно, что на самом деле творится в душе бизнес-процесса. Тогда они смогут по-настоящему стать “своими” в предметной области. Если ты думаешь, что это уже перебор, то как иначе мы создадим программное обеспечение, “отражающее ментальную модель экспертов в предметной области”, программное обеспечение, “которое написали бы сами эксперты в предметной области, если бы сами были программистами”[2]. А ведь именно такие формулировки использует Вон Вернон в Красной книге для описания результата, получаемого от использования DDD.
И наконец, такой подход облегчает вход в проект новых разработчиков. Читая код, новичок не просто знакомится с кодовой базой, он осваивает единый язык, а значит и получает представление о предметной области, ее понятиях, процессах и ограничениях.
Но если мы говорим о сложных предметных областях, то кажется единый язык для них просто огромен, чтобы он имел возможность описать все происходящие бизнес-процессы. А соответственно огромной будет и программная модель.
Думаешь это проблема?
Думаю да, ведь чем больше охватывает язык, тем сложнее его понимать каждому члену команды. Иметь представление о всем бизнесе целиком сразу — это сложная задача не только для программистов, даже для непосредственных участников бизнес- процесса.
Вот мы уже более подготовленными подошли к вопросу управления сложностью: как ты верно заметил сложность реального мира может быть очень большой, что не позволит работать с предметной областью целиком. Вспомним ещё раз первый совет Стива Макконелла, который говорит, что необходимо свести минимуму объем существенной сложности, с которым приходится работать в конкретный момент времени[1]. В DDD для этой цели используется паттерн Bounded context.
Ограниченный контекст? Непонятное название: что это за контекст и почему он ограниченный?
Чтобы ответить на твой вопрос давай сначала вернемся к проблеме, которую хотим решить. Нам нужно разбить предметную область на относительно небольшие части. Сама идея звучит просто, но, следуя совету Макконелла, разбить нужно так, чтобы эти части получились автономными.
Скажу честно, я немного уже устал от этих абстрактных определений. Можешь конкретнее? Под “небольшая часть” каждый понимает что-то своё. Только не говори, что она должна “умещаться в голове”. Что будет являться более или менее измеримым критерием правильного разбиения?
Точность, однозначность и согласованность языка. Этот на первый взгляд довольно абстрактный критерий приобретает конкретики, если вспомнить, что единый язык определяет программную модель, а она должна быть точной и однозначной, потому что “ambiguity doesn't compile”[4]
Хорошо, уже что-то. А что такое однозначность и согласованность языка?
Это значит, что каждый термин, словосочетание и фраза единого языка ясно и одинаково понимаются всеми членами команды. Но вопрос в том, как этого добиться в сложной предметной области? Забудь даже о предметной области и программировании, лучше скажи помидор — это овощ, фрукт или может быть ягода?
Овощ конечно.
Так вот на самом деле, это зависит от того, кто на него смотрит[7], а для нашей темы точнее сказать, что зависит от того, кто о нем говорит.
Я понял, это зависит от контекста.
Хорошо. А как бы ты поступил, если тебя бы попросили создать класс помидор, каким поведением ты бы его наделил: овоща, фрукта или ягоды? Давай я сам отвечу. Какое бы ты поведение не выбрал оно будет иметь смысл только в конкретном контексте. А значит применимость созданной тобой модели помидора также будет ограничена конкретным контекстом. Вот мы и раскрыли секрет неуклюжего термина. Bounded context создает контекст(context) для единого языка и ограничивает(bound) применимость программной модели. То есть, возможно, правильнее было бы перевести термин как “ограничивающий контекст”. Обрати внимание, секрет неуклюжести термина отчасти кроется в языковом барьере.
То есть Bounded context позволяет существовать единому языку?
Верно. Единый язык существует только в рамках Bounded context. Иначе он перестанет быть собой: будет размыт, потеряет ясность, что сделает невозможным создание компилируемой модели на его основе.
Ну а что насчет денег, какая от всего этого выгода бизнесу? DDD кажется довольно затратным с точки зрения времени подходом к проектированию и разработке.
Во-первых, за счет постоянной совместной работы разработчиков и экспертов повышается вероятность того, что заказчик получит именно то, что он хотел.
Во-вторых, затраченное время — это инвестиции в самое сердце системы, в ее конкурентное преимущество. Мы же говорим сейчас про ядро системы, вокруг которого уже можно строить приложения.
И наконец, это вклад в будущее, а именно в возможность сдержать увеличение стоимости разработки нового функционала.
У меня остался один вопрос: что такого написано в двух толстых книгах разных цветов, если как ты говоришь единый язык — это основная идея DDD, а ты доходчиво описал ее за несколько минут?
Во-первых, твой мозг тебя обманывает насчет того, что ты все понял, и занимается самоуспокоением. Для того, чтобы действительно разобраться в вопросе, надо еще хорошенько порефлексировать над полученной информацией, рассмотреть ее с разных сторон, попытаться донести услышанную идею до кого-то еще, ну и конечно попытаться применить полученные знания.
Во-вторых, я попытался объяснить только саму идею и показать ее глубину. Но это только самое начало и остается масса вопросов. Как ты добьешься общения разработчиков и экспертов? Мы определили критерий хорошего Bounded context, но как на практике найти его границы, чтобы обеспечить автономность моделей в них? Только одному этому вопросу посвящена целая книга, хоть и недописанная[3] И конечно же как собственно реализовать программную модель внутри этого BC?
На эти и многие другие вопросы можно найти ответы в упомянутых тобой книгах.
Мало того, что книги толстые, так еще вокруг самого DDD витает аура башни из слоновой кости.
Да, DDD — это сложный подход и его сложность конечно является проблемой. Адам Димитрюк так описал зависимость успешности внедрения практики от ее сложности: “… если организация хочет применить процесс Х и он требует прочтения одной книги, и участия в недельном воркшопе, то это сведет на нет эффективность Х независимо от того, насколько Х хорош"[5].
Думаю люди успешно приходят в DDD через боль: у них есть большие проблемы с проектом или проект уже умер. Тогда они ищут как решить проблемы или избежать повторения провала в будущем. В таких случаях толщина и сложность книг не будет смущать, потому что в них можно будет наконец-то найти ответы на волнующие тебя вопросы. Это как с зубной болью: пока она тебя не сильно беспокоит, то страх похода к врачу будет сильнее. Но как только действительно прихватит, то уже в тот же вечер с нетерпением стоишь в очереди к стоматологу и тебя уже не пугают ни запах, ни звуки из-за двери кабинета.
Ссылки
- Стив Макконнелл. Совершенный код
- Вон Вернон. Реализация методов предметно-ориентированного проектирования
- Альберто Брандолини. Event Storming
- Доклад Альберто Брандолини
- Adam Dymitruk. Event Modeling: What is it?
- Симон Соловейчик. Педагогика для всех.
- Фрукт или овощ