TDD - это дизайн сверху вниз или снизу вверх? - PullRequest
4 голосов
/ 18 апреля 2011

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

Но в TDD говорят, что я должен сначала рассмотреть очень маленькую функциональность (метод?), Написать тест, потерпеть неудачу, реализовать его и пройти тест. Составление их - последний шаг. Я не могу представить, как он получает хороший API.

И что самое странное, они говорят, что TDD - это не только модульные тесты, но и функциональные тесты. Я думаю, что это означает сверху вниз. Если есть функциональность A, состоящая из методов B, C и D. Из-за TDD я сначала пишу функциональный тест для A. Но ... B, C, D все не реализованы. Должен ли я использовать три заглушки? Если B зависит от трех других методов?

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

Ответы [ 3 ]

2 голосов
/ 18 апреля 2011

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

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

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

0 голосов
/ 19 апреля 2011

Я бы сказал, что это сверху вниз. Скажем, у меня был один PDF-файл, в котором было 4 отдельных документа, и я писал программное обеспечение для разделения их на 4 отдельных документа вместо одного документа; первый тест, который я, вероятно, написал бы:

// Note: Keeping this very abstract
@Test
public void splitsDocumentsAccordingToDocumentType() {
   List docs = new DocumentProcessor().split(new SinglePdfWithFourDocs());
   assertEquals(4, docs());
   ...
}

Я бы посчитал, что метод DocumentProcessor.split() похож на «А» в вашем примере. Теперь я могу реализовать весь алгоритм в одном методе split и сделать тесты успешными. Мне даже не нужны буквы "B" или "C", верно? Зная, что вы хороший разработчик, и вам не хватает мысли об этом 1500-строчном методе, вы начинаете искать способы реструктуризации своего кода для более подходящего дизайна. Возможно, вы видите, что из этого кода можно выделить два дополнительных объекта (обязанности):

1) Разбор содержимого файла для поиска отдельных документов и 2) Чтение и запись документа из файловой системы

Давайте сначала займемся # 1. Используйте пару рефакторингов «Извлечь метод», чтобы локализовать код, связанный с синтаксическим анализом содержимого, а затем рефакторинг «Извлечь класс», извлекая эти методы в класс с именем, скажем DocumentParser. Это может быть аналогично «B» в вашем примере. При желании вы можете переместить тесты, связанные с анализом документов, с вашего DocumentProcessorTest на новый DocumentParserTest и смоделировать или заглушить DocumentParser в DocumentProcessorTest.

Для # 2 это в значительной степени пена, промыть, повторить, и вы получите что-то вроде DocumentSerializer класса, AKA "C". Вы также можете смоделировать это в своем DocumentProcessorTest, и теперь у вас нет файлового ввода-вывода, и вы испытали компонент, в котором есть два дополнительных участника, без необходимости разрабатывать весь класс (с отдельными методами). Обратите внимание, что мы выбрали подход извне, который действительно позволяет проводить рефакторинг.

Спасибо

0 голосов
/ 18 апреля 2011

Я интенсивно пишу тесты rspec для моих проектов rails, сохраняя соотношение 1: 1.6 между кодом / тестами. У меня никогда не было вопроса о том, что писать первым или от чего это зависит. Если метод A, который я хочу написать, состоит из B и C, то я сначала реализую B и C, снова используя надлежащее тестирование. Для меня последовательность не так важна, если тесты хороши и точны.

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

Кстати, это считается нисходящим подходом. Это отрывок из Rspec Book:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...