Как вы разрабатываете сложные системы с TDD?

Похоже на Знает ли TDD не думать о дизайне классов?, у меня возникли проблемы с мыслью о том, где традиционный этап "дизайна" вписывается в TDD.

В соответствии с Боулинг-игрой Kata (версия "беседы", чья связь ускользает от меня в данный момент) TDD, похоже, игнорирует принятые на ранней стадии проектные решения (отбросьте объект кадра, объект roll и т.д.). В этом примере я вижу, что неплохо следовать за тестами и игнорировать ваши первоначальные мысли о дизайне, но в больших проектах или в тех, где вы хотите оставить открытие для расширения/настройки, не лучше ли было бы поместить вещи в что у вас нет теста или нет необходимости немедленно, чтобы избежать длительных перезаписей позже?

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

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

Ответ 1

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

Часть TDD - это рефакторинг.

Ответ 2

Есть что сказать о "Проектирование больших сложных систем", которые не должны быть связаны с TDD, особенно когда TDD интерпретируется как "Test Driven Design", а не "Test Driven Development".

В контексте "Разработка" использование TDD гарантирует, что вы пишете тестируемый код, который дает все преимущества, упомянутые в TDD (раннее обнаружение ошибок, высокий коэффициент кода: коэффициент охвата тестированием, более простой рефакторинг в будущем и т.д.).

Но в "Проектировании" больших сложных систем TDD особо не учитывает следующие проблемы, присущие архитектуре системы.

  • (Engineering for) Performance
  • Безопасность
  • Масштабируемость
  • Наличие
  • (и все другие "функции" )

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

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

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

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

Мне еще предстоит встретить значительно сложную часть программного обеспечения (например, компилятор, базу данных, операционную систему), которая была выполнена в стиле Test Driven Design. В следующей статье в блоге очень хорошо сказано об этом вопросе ( Составители, TDD, Мастерство)

Кроме того, проверьте видео по архитектуре, что добавляет много здравого смысла в процесс мышления.

Ответ 3

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

Нужно быть внимательным, слушать и обнюхивать код, обнаруживать возможности рефакторинга и запахи кода.

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

Ответ 4

Я нашел три способа сделать дизайн с TDD:

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

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

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

Мне нравятся Real Options, и рефакторинг чего-то в совершенстве мне кажется как совершение дизайна без какой-либо реальной необходимости. Вместо этого я реорганизую "достаточно хорошо"; таким образом, если мой дизайн окажется ошибочным, я не потерял время. Предположим, что ваш дизайн будет неправильным, если вы никогда раньше не использовали его в подобном контексте.

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