Как совместить строгий TDD и DDD?

15

TDD - это проектирование кода, руководствуясь тестами.
Таким образом, типичные слои обычно не создаются заранее; они должны слегка появиться через шаги рефакторинга.

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

Как начать вести кодовую часть проекта DDD с нуля, как себя вести?
Должен ли я строго позволить дизайну появиться из испытаний, что означает отсутствие разделения интересов (без слоев) и рефакторинга, чтобы соответствовать техническим шаблонам DDD?

Или я должен создать эти пустые слои (приложение, сущности / доменные службы, инфраструктура) и позволить TDD вписаться в каждый из них независимо (используя насмешки для изоляции между уровнями)?

Mik378
источник

Ответы:

12

Обязательно просмотрите последние комментарии дяди Боба о роли дизайна в TDD .

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

Уди Даан: «Боже, как я ненавижу наслоение». Он проводит некоторое время, обсуждая это в своем выступлении CQRS - но по-другому (расслоение начинается в 18-30-х годах)

Я бы написал ваше предложение немного иначе; «DDD признает, что существует ряд проблем, общих для большинства бизнес-приложений, и что решения этих проблем имеют различный срок службы» .

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

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

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

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

Тем временем технический директор хочет версию приложения, которая работает на его телефоне; Генеральный директор только что услышал от парня, что публикация API - это большая вещь.

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

Другими словами, вы применяете тактические шаблоны из не внедряя пустые заполнители и предполагая, что они будут заполнены позже, а вместо этого, распознавая, когда вы пересекаете потоки. «Эй, это постоянный код в моей доменной модели, я не должен рефакторинг еще не завершен. "

VoiceOfUnreason
источник
11

Test Driven Development (TDD) - это не дизайн. Это требование, которое влияет на ваш дизайн. Так же, как если бы вы были обязаны быть потокобезопасными, это не дизайн. Опять же, это требование, которое влияет на ваш дизайн.

Если вы радостно игнорируете все другие проблемы проектирования и неукоснительно придерживаетесь правил TDD, не вините TDD, когда ваш код превращается в дерьмо. Это будет проверяемое дерьмо, но это будет дерьмо.

Хорошая вещь в тестируемом дерьме состоит в том, что это рефакторизованное дерьмо, поэтому для некоторых людей этого достаточно. Мы будем фантазировать только тогда, когда это необходимо. Другие ненавидят это и обвиняют TDD в этом. Это твое дело.

Проектирование на основе доменов (DDD) - это то, что вы делаете перед циклом рефакторинга TDD.

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

Система DDD может иметь архитектуру, которая выглядит следующим образом:

введите описание изображения здесь

Эта архитектура DDD имеет много названий: Clean , Onion , Hexagonal и т. Д.

Вот разрыв, который я вижу у многих людей, когда они смотрят на этот дизайн. Это не конкретно. Я могу следовать этой схеме и никогда не писал ничего, что вы видите на диаграмме здесь. Я вижу, что другие настаивают на том, что должен быть объект прецедента или класс сущностей. Это набор правил, которые говорят вам, с кем вы можете поговорить и как.

Вот и все. Следуйте правилам этого дизайна, и вы можете TDD свое маленькое сердце. TDD не волнует, с кем ты говоришь. Он заботится о том, что все, что делает что-то, может быть доказано, что оно работает или нет одним нажатием кнопки. Нет, что-то где-то сломано. Он говорит вам, что именно сломано.

Все еще расплывчато? Посмотрите на диаграмму Controler- Use Case Interactor- Presenterв правом нижнем углу. Вот три конкретные вещи, общающиеся друг с другом. Конечно, это DDD, но как добавить сюда TDD? Просто издевайся над конкретным материалом. Ведущий должен получать информацию. PresenterMockКласс был бы хороший способ проверить , что это то , чего вы ожидали получить. Передайте и драйв , как если бы вы были и у вас есть хороший способ для модульного тестирования , так как насмешка скажет вам , если он получил то , что вы ожидали получить.Use Case InteractorPresenterMockUse Case InteractorControllerUse Case Interactor

Хорошо посмотри на это. TDD доволен, и нам не пришлось возиться с нашим дизайном DDD. Как это случилось? Мы начали с хорошо отделенного дизайна.

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

TDD не о дизайне. Если вам нужно внести изменения в дизайн, чтобы использовать TDD, у вас больше проблем, чем при тестировании.

candied_orange
источник
Я никогда не говорил, что TDD - это дизайн, но он касается дизайна.
Mik378
1
Дядя Боб велел тебе проектировать. Он не говорил вам: «Привет, если вы работаете на тестах и ​​заботитесь об остальных».
candied_orange
1
Как я уже сказал, просто следуйте правилам, с которыми вам разрешено разговаривать. Чистая архитектура не является предметом обсуждения BDUF. Просто определите, в какой части вы находитесь, и подумайте, с кем и как вы должны общаться. Это более проворно, чем вы думаете. После этого спросите, тестируется ли он TDD. Если это не так, ты сделал что-то не так. Если это так, то я надеюсь, что вы обратили внимание, потому что хороший дизайн - это больше, чем просто тестирование.
candied_orange
6
Тьфу ... Я действительно терпеть не могу неправильное определение "Test Driven Design". Вам все еще нужно немного придумать, прежде чем вы начнете блаженно стучать по клавиатуре, независимо от того, пишете вы тесты или нет.
RubberDuck
1
Чтобы процитировать дядю Боба именно по этому вопросу: «Вы должны ДИЗАЙН период» . Нажмите там, и если вы слишком нетерпеливы, чтобы прочитать все это, найдите эти слова. Вы обнаружите, что мистер Мартин совершенно непреклонен в том, что TDD не волшебная палочка и что вы должны разрабатывать не только свой код, но и свои тесты, если вы не хотите жить в очень хрупкой кодовой базе.
candied_orange
4

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

DDD - это дизайн высокого уровня, язык между экспертами и инженерами в области, отображение контекста и т. Д. Это должно быть движущей силой дизайна приложений высокого уровня.

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

Начните с языка DDD и сопоставления контекста, а затем, когда вы начнете писать код, начните практику TDD. Но практика TDD не должна влиять на дизайн высокого уровня, но она должна гарантировать, что что-то может быть проверено. Здесь есть небольшая оговорка.

Я думаю, что это может быть важно отметить: вы должны практиковать DDD, только если приложение достаточно сложное.

Мэтт Оахака
источник
1
Я не согласен, TDD - это не тестирование, а проектирование.
Mik378
Я основываюсь на 3 правилах TDD, описанных дядей Бобом.
Мэтт Оахака
Стив Фриман, автор книги ГСНО, заявил: перед началом циклов TDD не следует указывать какие-либо уровни или инфраструктуру.
Mik378
Я не знаком с этой книгой, но я бы не согласился. Я не хочу, чтобы TDD формировал мой DI и график классов.
Мэтт Оахака
3
@ Mik378: TDD - это не тестирование, но в первую очередь не проектирование. Единственный дизайн, созданный TDD, - это проект для модульной тестируемости. Любая другая часть дизайна должна происходить откуда-то еще. Я вижу TDD больше как метод реализации.
Док Браун
3

DDD о разработке программного обеспечения.
TDD о дизайне кода.

В DDD «модель» представляет собой абстракцию домена, все знания от эксперта области.

Мы могли бы использовать TDD для исходной модели программного кода. Домен имеет бизнес-правила и доменные модели, которые написанные тесты (первые) должны быть зелеными.

По сути, мы можем кодировать тесты после разработки модели, управляемой доменом.
Эта книга "Растущее объектно-ориентированное программное обеспечение, ориентированное на тесты". Ссылка для покупки.
Используйте этот подход с ходячим скелетом , гексагональной архитектурой и TDD.

Источник: DDD быстро - InfoQ

JonyLoscal
источник
1
ну для меня софт и код это одно и то же
Конрад
1
Это может быть тоже самое. Я пытался сказать: программное обеспечение как «решение», «система», «высокий уровень» и код как «реализация», «низкий уровень», «детали».
JonyLoscal
Я думаю, что важно то, что «сначала мы тестируем, но нам нужен минимальный скелет, где мы бы начали тестирование». Вы?
JonyLoscal
1

Должен ли я строго позволить дизайну появиться из испытаний

Нет. (Управляемый доменом) Дизайн по определению должен исходить из требований домена. Это плохая идея, чтобы позволить чему-то другому управлять вашим дизайном, будь то набор тестов, схема базы данных или ... (продолжение следует)

Или я должен создать эти пустые слои (приложение, сущности / доменные службы, инфраструктура) и позволить TDD вписаться в каждый из них независимо

(продолжение) ... или какие-то канонические слои классов / иерархий классов на вашем любимом ОО-языке, даже если он очень зрелый и популярный (в конце концов "миллионы мух не могут ошибаться", верно?) ,

Когда дело доходит до DDD, ООП не отвечает требованиям, выражая их в удобочитаемой форме, то есть что-то, что было бы более или менее понятно для непрограммиста. Строго типизированные языки FP делают лучше. Я рекомендую прочитать книгу о DDD, используя функциональное программирование Скотта Влашина «Моделирование предметной области сделано функциональным»

https://pragprog.com/book/swdddf/domain-modeling-made-functional

Вам не нужно использовать язык FP, чтобы позаимствовать некоторые идеи оттуда (не все из них, к сожалению, к сожалению), но если вы действительно прочитаете его, то, возможно, вам захочется использовать функциональный язык.

Он также ответит на ваш вопрос о том, как TDD вписывается в изображение DDD. Вкратце, когда требования кодируются в функциональном стиле, это устраняет необходимость в большом количестве модульных тестов, поскольку делает большинство недопустимых состояний и сценариев непредставимыми / невозможными для компиляции. Конечно, в проекте FP все еще есть место для автоматизированного тестирования, но тесты ни в коем случае не будут определять какие-либо важные проектные решения.

Чтобы сделать полный круг, давайте вернемся к заглавному вопросу, т.е. «Как объединить строгий TDD и DDD?». Ответ прост: нечего объединять / нет конфликта интересов. Проектируйте в соответствии с требованиями, разрабатывайте в соответствии с дизайном (сначала пишите тесты, если вы действительно хотите сделать TDD)

Кола
источник
+1 за книгу FP DDD и общее объяснение.
Роман Суси