Недавно (на прошлой неделе) приступил к эксперименту, в котором я пытаюсь закодировать новую функцию в проекте, над которым я работаю над использованием принципов TDD. В прошлом наш подход был умеренно-гибким, но без особого строя. Тестирование модулей происходит здесь и там, когда это удобно. Основным препятствием для всестороннего тестирования является то, что наше приложение имеет сложную сеть зависимостей. Я выбрал функцию, которая была удобна, чтобы попытаться провести эксперимент; детали не важны и, вероятно, коммерчески чувствительны, достаточно сказать, что это простая проблема оптимизации.
До сих пор я обнаружил, что:
- TDD для меня, по-видимому, поощряет бессвязные, неочевидные проекты. Ограничение на то, что нельзя писать код без теста, как правило, блокирует возможности разложения функциональности на независимые единицы. Тренировка и запись тестов для многих функций одновременно слишком сложны на практике.
- TDD имеет тенденцию поощрять создание "объектов Бога", которые делают все, потому что вы написали много классных классов для класса x уже, но мало для класса y, поэтому кажется логичным в то время, когда класс x также должен реализовать функцию z вместо того, чтобы оставить ее в классе y.
- Написание тестов перед написанием кода требует, чтобы вы полностью понимали каждую сложность проблемы, прежде чем ее решить. Это кажется противоречием.
- Мне не удалось заставить команду на стороне начать использовать насмешливую структуру. Это означает, что происходит пролиферация трещин, созданных исключительно для проверки конкретной функции. Для каждого тестируемого метода вам будет нужна фальшивка, единственная задача которой - сообщить, что тестируемый класс называется тем, что он должен. Я начинаю писать что-то похожее на DSL исключительно для создания тестовых данных.
- Несмотря на вышеупомянутые проблемы, TDD разработала рабочий проект с небольшими таинственными ошибками, в отличие от шаблона разработки, к которому я привык. Рефакторинг разрастания беспорядка, который, однако, потребовал, чтобы я временно отказаться от TDD и просто сделать это. Я верю, что тесты будут продолжать обеспечивать правильность метода. Попытка сделать TDD упражнение рефакторинга, которое я чувствую, будет только более распространенным.
Тогда возникает вопрос: "Есть ли у кого-нибудь советы по снижению воздействия перечисленных выше проблем?". Я не сомневаюсь, что издевательская структура будет полезна; однако в настоящее время я уже заставляю свою удачу пытаться что-то, что, кажется, просто порождает бессвязный код.
изменить # 1:
Спасибо всем за ваши рассмотренные ответы. Я признаю, что я написал свой вопрос после нескольких вечерних сортов пива, поэтому местами это расплывчато и на самом деле не выражает настроения, которые я действительно намеревался. Я хотел бы подчеркнуть, что мне нравится философия TDD, и я нашел ее умеренно успешной, но также удивительной по причинам, которые я перечислял. У меня есть возможность спать на нем и снова смотреть на проблему свежими глазами на следующей неделе, так что, возможно, я смогу решить свои проблемы, запутавшись. Однако ни один из них не является стартером.
Что касается меня больше в том, что некоторые из членов команд устойчивы к попытке что-либо, что вы могли бы назвать "технику" в пользу "просто получить это сделать. Я обеспокоен тем, что появление трещины будет восприниматься как черная метка против этого процесса, а не доказательства того, что для достижения наилучших результатов это необходимо сделать полностью (т.е. С насмешливой каркасной структурой и сильным DI).
RE "TDD не обязательно означает" тест-первый ": (womp, btreat)
"Золотое правило" в каждом тексте, который я нашел в этом вопросе, - "Красный, Зеленый, Рефактор". То есть:
- Напишите тест, который ДОЛЖЕН провалиться
- Введите код, который проходит тест
- Рефакторинг кода, чтобы он прошел тест самым удобным способом.
Мне любопытно, как вы думаете, что делать Test-Driven Development, не следуя основному принципу TDD, как изначально написано. Мой коллега звонит в половину дома (или другой и в равной степени действительный подход, в зависимости от вашей точки зрения) "Test-Validated Development". В этом случае я думаю, что придумать новый термин - или, возможно, украсть его у кого-то другого и взять на него кредит - полезно.
RE DSL для тестовых данных: (Michael Venable)
Я рад, что ты это сказал. Я вижу, что общая форма становится все более полезной в рамках проекта, так как рассматриваемое приложение поддерживает довольно сложный графический объект, и, как правило, его тестирование означает запуск приложения и попытки его использования в графическом интерфейсе. (Не собираюсь отвлекать игру от соображений коммерческой чувствительности выше, но это в основном связано с оптимизацией различных показателей на ориентированном графике. Однако есть много предостережений и настраиваемых пользователем виджетов.)
Возможность настроить осмысленный тестовый сценарий программно поможет во всех ситуациях, которые могут не ограничиваться модульным тестированием.
Объекты RE God:
Я чувствовал себя так, потому что один класс, казалось, занимал большую часть набора функций. Возможно, это прекрасно, и это действительно важно, но это подняло несколько бровей, потому что это выглядело так же, как старый код, который не был разработан в этом направлении, и, похоже, нарушил SRP. Я полагаю, что неизбежно, что некоторые классы будут функционировать в первую очередь как швы между множеством различных инкапсулированных бит функциональности, а другие будут швырять лишь некоторые из них. Если это будет так, я полагаю, что мне нужно сделать очистку как можно большей логики от этого очевидного объекта Бога и изменить его поведение как точку соединения между всеми факторизованными частями.
(модераторам: я добавил свои ответы на сообщения здесь, потому что поле комментариев недостаточно длинное, чтобы содержать детали, которые мне бы хотелось.)
изменить # 2 (примерно через пять месяцев):
Хорошо, я чувствовал, что было бы неплохо обновить некоторые мысли после рассмотрения проблемы на некоторое время.
В конце концов, я отказался от подхода TDD, я сожалею. Тем не менее, я чувствую, что для этого есть некоторые конкретные и обоснованные причины, и я готов продолжить его в следующий раз, когда я получу возможность.
Следствием неапологического рефакторинга менталитета TDD является то, что я не был сильно расстроен, когда, кратко взглянув на мой код, ведущий разработчик заявил, что подавляющее большинство из них бессмысленно и нужно идти. В то время как есть сожаление о том, что нужно отбросить огромную тяжесть тяжелой работы, я точно видел, что он имел в виду.
Эта ситуация возникла из-за того, что я буквально принимал правило "код в интерфейс", но продолжал писать классы, которые пытались представить реальность. Довольно давно я впервые сделал выражение:
Классы не должны пытаться представлять реальность. Объектная модель должна только пытаться решить проблему.
... который я повторял так часто, как мог; к себе и ко всем, кто будет слушать.
Результатом этого поведения была объектная модель классов, которые выполняли функцию, и набор зеркальных отображений интерфейсов, которые повторяли функциональность классов. Указав это на меня и после непродолжительного, но интенсивного периода сопротивления, увидел свет и не имел проблем с удалением большей части его.
Это не значит, что я считаю, что "код для интерфейса" - это кушетка. Это означает, что кодирование интерфейса в первую очередь ценно, когда интерфейсы представляют собой реальные бизнес-функции, а не свойства какой-либо воображаемой идеальной объектной модели, которая выглядит как миниатюрная копия реальной жизни, но не считает ее единственным значением в чтобы ответить на заданный вами вопрос. Сила TDD заключается в том, что он не может создавать такие модели, кроме как случайно. Поскольку он начинается с задавания вопроса и заботится только о получении ответа, ваше эго и предварительное знание системы не участвуют.
Я сейчас болтаю, поэтому я бы сделал все возможное, чтобы закончить это, и просто заявляю, что я все рвусь, чтобы снова попробовать TDD, но имею лучший обзор доступных инструментов и тактики и сделаю все возможное, чтобы решите, как я хочу это сделать, прежде чем прыгать. Возможно, я должен пересадить эту вафли в блог, где он принадлежит, как только мне есть что сказать об этом.