Простой дизайн. В рамках TDD вы пишете только тот код, который необходим для успешного выполнения тестов, вы удаляете из него любое дублирование, значит, вы автоматически получаете код, который идеально адаптирован к текущим требованиям и подготовлен к любым будущим пожеланиям. Общая доктрина требует, чтобы дизайна было достаточно для получения идеальной архитектуры для текущей системы. Эта доктрина также облегчает разработку тестов.
Рефакторинг. Устранение дублирования – это основная цель рефакторинга. Тесты дают вам уверенность в том, что поведение системы не изменится даже в случае, если в ходе рефакторинга вы вносите достаточно крупномасштабные изменения. Чем выше ваша уверенность, тем более агрессивно вы выполняете рефакторинг. Рефакторинг продлевает жизнь вашей системе. Благодаря рефакторингу вы упрощаете дальнейшую разработку тестов.
Частые выпуски версий. Если тесты TDD действительно улучшают MTBF вашей системы (в этом вы можете убедиться сами), значит, вы можете чаще внедрять разрабатываемый код в реальные производственные условия и при этом не наносить ущерба вашим заказчикам. Гарет Ривс (Gareth Reeves) приводит аналогию с куплей-продажей ценных бумаг на бирже в течение дня. Если вы занимаетесь краткосрочной спекуляцией ценными бумагами, в конце торгового дня вы должны продать все имеющиеся у вас ценные бумаги, так как вы не хотите принимать риск, связанный с сохранением некоторых ценных бумаг до следующего торгового дня, – этот риск вам не подконтролен. Разрабатывая систему, вы хотите, чтобы вносимые вами изменения как можно быстрее были опробованы в реальных производственных условиях, так как не хотите тратить время на разработку кода, в полезности которого не уверены.
Нерешенные проблемы TDDДарач Эннис (Darach Ennis) бросил вызов поклонникам TDD, размышляющим о возможностях расширения области применения TDD. Он сказал:
Множество различных организаций сталкивается с многочисленными проблемами TDD, и эти проблемы никак не затронуты в книге. Возможно, эти проблемы вообще никак не решить в рамках TDD. Вот некоторые из них:
• не существует способа автоматического тестирования GUI (например, Swing, CGI, JSP/Servlets/Struts);
• не существует способа автоматического тестирования распределенных объектов (например, RPC, Messaging, CORBA/EJB и JMS);
• TDD нельзя использовать для разработки схемы базы данных (например, JDBC);
• нет необходимости тестировать код, разработанный сторонними разработчиками, или код, генерируемый внешними инструментами автоматизации разработки;
• TDD нельзя использовать для разработки компилятора/интерпретатора языка программирования.
Я не уверен, что он прав, но я также не уверен, что он не прав. В любом случае это почва для размышлений о дальнейшем развитии TDD.
Приложение I
Диаграммы взаимовлияния
В данной книге можно встретить несколько примеров диаграмм взаимовлияния. Идея диаграмм взаимовлияния позаимствована из серии книг Quality Software Management Джеральда Вейнберга (Gerald Weinberg), точнее говоря, из книги 1: Systems Thinking[32]. Цель диаграммы взаимовлияния – продемонстрировать, каким образом элементы системы влияют друг на друга.
Диаграмма взаимовлияния включает элементы трех типов:
• Действие или деятельность[33] – обозначается словом или короткой фразой.
• Положительное соединение – обозначается стрелкой, указывающей от одного действия к другому действию. Положительное соединение сообщает, что усиление интенсивности исходного действия приводит к усилению интенсивности целевого действия, а снижение интенсивности исходного действия приводит к снижению интенсивности целевого действия.
• Отрицательное соединение – обозначается стрелкой между двумя действиями, поверх которой нарисован кружочек. Отрицательное соединение сообщает, что усиление интенсивности исходного действия ведет к снижению интенсивности целевого действия, и, наоборот, снижение интенсивности исходного действия приводит к усилению интенсивности целевого действия.
Слишком много слов для очень простой концепции. На рис. П1.1–П1.3 приводится несколько примеров диаграмм взаимовлияния.
Рис. П1.1. Два действия, которые, по всей видимости, не влияют друг на друга
Рис. П1.2. Два действия, связанные положительным соединением
Рис. П1.3. Два действия, связанные отрицательным соединением
Чем больше я ем, тем больше моя масса тела. Чем меньше я ем, тем меньше моя масса тела. Конечно же, масса человеческого тела – это значительно более сложная система. Диаграммы взаимовлияния – это модели, которые помогают понять некоторые аспекты системы, однако они вовсе не предназначены для того, чтобы понимать и контролировать систему в полной мере.
Обратная связьВлияние распространяется не только в одном направлении. Действие может быть связано обратной связью само с собой. Иначе говоря, в некоторых случаях изменение интенсивности действия влияет на само это действие. Иногда это влияние положительно, а иногда – отрицательно. Пример подобной обратной связи продемонстрирован на рис. П1.4.
Существует два типа обратной связи – положительная и отрицательная. Положительная обратная связь приводит к тому, что интенсивность действия в системе
Рис. П1.4. Обратная связь
постоянно увеличивается. Чтобы обнаружить положительную обратную связь, достаточно посчитать количество отрицательных соединений в цикле. Если в цикле четное количество отрицательных соединений, значит, этот цикл является циклом положительной обратной связи. На рис. П1.4 изображен цикл положительной обратной связи: попав в этот цикл, вы продолжаете набирать вес, пока в составе цикла не появится какое-либо дополнительное действие.
Отрицательная обратная связь снижает интенсивность действия. Если в цикле присутствует нечетное количество отрицательных соединений, значит, цикл является циклом отрицательной обратной связи.
Вот три ключа хорошего системного дизайна:
• создание благоприятных циклов, в которых положительная обратная связь приводит к увеличению интенсивности полезных действий;
• устранение вредных циклов, в которых положительная обратная связь приводит к увеличению интенсивности бесполезных, вредных и деструктивных действий;
• создание циклов негативной обратной связи, которые предотвращают чрезмерное использование благоприятных действий.
Контроль над системойВыбирая систему практик разработки программного обеспечения, добивайтесь, чтобы каждая практика способствовала применению других практик, благодаря этому вы сможете использовать каждую из практик в достаточном объеме даже в состоянии стресса. На рис. П1.5 показан пример системы практик, которая приводит к недостаточному тестированию.
Когда время начинает поджимать, вы снижаете интенсивность тестирования, что приводит к увеличению количества ошибок, что, в свою очередь, приводит к еще большему недостатку времени. Со временем на сцене появляется некоторое внешнее действие (например, недостаток денег), которое заставляет вас завершить работу над проектом, несмотря ни на что.
Рис. П1.5. Недостаток времени для тестирования приводит к общему недостатку времени
Если вы имеете дело с системой, которая ведет себя не так, как вам того хотелось бы, у вас есть несколько вариантов исправить ситуацию:
• Сформируйте цикл положительной обратной связи в обратном направлении. Если у вас цикл между тестами и уверенностью и тесты все время терпят неудачу, снижая тем самым уверенность, тогда вы сможете сделать больше успешных тестов, повысив тем самым уверенность в вашей способности увеличить количество работающих тестов.
• Сформируйте цикл отрицательной обратной связи, который позволит