Экстремальное программирование. Разработка через тестирование - Бек Кент

Экстремальное программирование. Разработка через тестирование
Кент Бек


Библиотека программиста (Питер)
Возвращение знаменитого бестселлера. Изящный, гибкий и понятный код, который легко модифицировать, который корректно работает и который не подкидывает своим создателям неприятных сюрпризов. Неужели подобное возможно? Чтобы достичь цели, попробуйте тестировать программу еще до того, как она написана. Именно такая парадоксальная идея положена в основу методики TDD (Test-Driven-Development – разработка, основанная на тестировании). Бессмыслица? Не спешите делать скороспелые выводы. Рассматривая применение TDD на примере разработки реального программного кода, автор демонстрирует простоту и мощь этой методики. В книге приведены два программных проекта, целиком и полностью реализованных с использованием TDD. За рассмотрением примеров следует обширный каталог приемов работы в стиле TDD, а также паттернов и рефакторингов, имеющих отношение к TDD. Книга будет полезна для любого программиста, желающего повысить производительность своей работы и получить удовольствие от программирования.





Кент Бек

Экстремальное программирование: разработка через тестирование


Посвящается Синди: крыльям моей души



Права на издание получены по соглашению с Addison-Wesley Longman. Все права защищены. Никакая часть данной книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав.



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



ISBN 978-0321146533 англ.

ISBN 978-5-496-02570-6



© 2003 by Pearson Education, Inc.

© Перевод на русский язык ООО Издательство «Питер», 2017

© Издание на русском языке, оформление ООО Издательство «Питер», 2017

© Серия «Библиотека программиста», 2017




Предисловие


Чистый код, который работает (clean code that works), – в этой короткой, но содержательной фразе, придуманной Роном Джеффризом (Ron Jeffries), кроется весь смысл методики разработки через тестирование (Test-Driven Development, TDD). Чистый код, который работает, – это цель, к которой стоит стремиться потому, что

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

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

• улучшает жизнь пользователей ваших программ;

• позволяет вашим коллегам рассчитывать на вас, а вам – рассчитывать на них;

• писать такой код приятнее.

Но как получить чистый код, который работает? Многие силы мешают нам получить чистый код, а иногда не удается даже получить код, который просто работает. Чтобы избавиться от множества проблем, мы будем разрабатывать код, опираясь на автоматизированное тестирование. Такой стиль программирования называется разработкой через тестирование. Согласно этой методике

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

• любое дублирование устраняется.

Два простых правила, не правда ли? Однако они генерируют сложное индивидуальное и групповое поведение со множеством технических последствий:

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

• мы сами пишем тесты, так как не можем ждать, что кто-то другой напишет тесты для нас;

• наша среда разработки должна быстро реагировать на небольшие модификации кода;

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

Два упомянутых правила TDD определяют порядок этапов программирования.

1. Красный – напишите небольшой тест, который не работает, а возможно, даже не компилируется.

2. Зеленый – заставьте тест работать как можно быстрее, при этом не думайте о правильности дизайна и чистоте кода. Напишите ровно столько кода, чтобы тест сработал.

3. Рефакторинг – устраните из написанного кода любое дублирование.

Красный – зеленый – рефакторинг – это мантра TDD.

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

• при достаточно низкой плотности дефектов команда контроля качества (Quality Assurance, QA) сможет перейти от реагирования на ошибки к их предупреждению;

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

• если темы технических дискуссий будут четко определены, программисты смогут взаимодействовать друг с другом постоянно, а не раз в день или раз в неделю;

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

Итак, идея проста, но в чем наш интерес? Почему программист должен взять на себя дополнительную обязанность писать автоматизированные тесты? Зачем программисту двигаться вперед малюсенькими шажками, когда его мозг в состоянии продумать гораздо более сложную структуру дизайна? Храбрость.


Храбрость

TDD – это способ управления страхом в процессе программирования. Я не имею в виду страх падения со стула или страх перед начальником. Я имею в виду страх перед задачей, «настолько сложной, что я пока понятия не имею, как ее решить». Боль – это когда природа говорит нам: «Стоп!», а страх – это когда природа говорит нам: «Будь осторожен!» Осторожность – это совсем не плохо, однако помимо пользы страх оказывает на нас некоторое негативное влияние:

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

• страх заставляет нас меньше общаться;

• страх заставляет нас пугаться отзывов о нашей работе;

• страх делает нас раздражительными.

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

• не пытаться предсказать будущее, а немедленно приступить к практическому изучению проблемы;

• не отгораживаться от остального мира, а повысить уровень коммуникации;

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

• (с раздражением вы должны справиться самостоятельно).

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

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

Читатели книги Extreme Programming Explaine[1 - Бек К. Экстремальное программирование. СПб.: Питер, 2002. ISBN 5-94723-032-1.], должно быть, обратили внимание на разницу в тоне между экстремальным программированием (Extreme Programming, XP) и разработкой через тестирование (Test-Driven Development, TDD). В отличие от XP методика TDD не является абсолютной. XP говорит: «чтобы двигаться дальше, вы обязаны освоить это и это». TDD – менее конкретная методика. TDD предполагает наличие интервала между принятием решения и получением результатов, и предлагает инструменты управления продолжительностью этого интервала. «Что, если в течение недели я буду проектировать алгоритм на бумаге, а затем напишу код, использовав подход “сначала тесты”? Будет ли это соответствовать TDD?» Конечно, будет. Вы знаете величину интервала между принятием решения и оценкой результатов и осознанно контролируете этот интервал.

Большинство людей, освоивших TDD, утверждают, что их практика программирования изменилась к лучшему. Инфицированные тестами (test infected) – такое определение придумал Эрих Гамма (Erich Gamma), чтобы описать данное изменение. Освоив TDD, вы обнаруживаете, что пишете значительно больше тестов, чем раньше, и двигаетесь вперед малюсенькими шагами, которые раньше показались бы вам бессмысленными. С другой стороны, некоторые программисты, познакомившись с TDD, решают вернуться к использованию прежних практик, зарезервировав TDD для особых случаев, когда обычное программирование не приводит к желаемому прогрессу.

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

Прочитав эту книгу, вы сможете:

• начать применять TDD;

• писать автоматические тесты;

• выполнять рефакторинг, воплощая решения по одному за раз.

Книга разделена на три части.



Часть I. На примере денег. Пример разработки типичного прикладного кода с использованием TDD. Этот пример позаимствован мною у Уорда Каннингэма (Ward Cunningham) много лет назад, и с тех пор я неоднократно использовал его для демонстрации TDD. В нем рассматривается мультивалютная арифметика: выполнение математических операций над денежными величинами, выраженными в различных валютах. Этот пример научит вас писать тесты до тестируемого ими кода и органически развивать проект.

Часть II. На примере xUnit. Пример тестирования более сложной логики, использующей механизм рефлексии и исключения. В примере рассматривается разработка инфраструктуры автоматического тестирования. Этот пример познакомит вас также с архитектурой xUnit, которая лежит в основе множества инструментов тестирования. Во втором примере вы научитесь двигаться вперед еще меньшими шажками, а также разрабатывать систему с использованием механизмов самой этой системы.

Часть III. Шаблоны разработки через тестирование. Здесь рассматриваются шаблоны, которые помогут найти ответы на множество вопросов, в частности: какие тесты писать и как их писать с использованием xUnit. Кроме того, здесь вы найдете описание некоторых избранных шаблонов проектирования и рефакторинга, использовавшихся при создании примеров для данной книги.



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

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




Благодарности



Спасибо всем, кто с необычайным усердием и самоотверженностью просматривал рукопись данной книги. Я беру на себя всю ответственность за представленный в книге материал, однако без посторонней помощи данная книга была бы куда менее читабельной и менее полезной. Перечислю всех, кто помогал мне, в произвольном порядке: Стив Фриман (Steve Freeman), Франк Вестфал (Frank Westphall), Рон Джеффриз (Ron Jeffries), Дирк Кёниг (Dirk Koning), Эдвард Хейят (Edward Heiatt), Таммо Фриис (Tammo Freese), Джим Ньюкирк (Jim Newkirk), Йоханнес Линк (Johannes Link), Манфред Ланж (Manfred Lange), Стив Хайес (Steve Hayes), Алан Френсис (Alan Francis), Джонатан Расмуссон (Jonathan Rasmusson), Шейн Клаусон (Shane Clauson), Саймон Крэйз (Simon Crase), Кай Пентекост (Kay Pantecost), Мюррей Бишоп (Murrey Bishop), Райан Кинг (Ryan King), Билл Уэйк (Bill Wake), Эдмунд Швепп (Edmund Schweppe), Кевин Лауренс (Kevin Lawrence), Джон Картер (John Carter), Флип (Phlip), Петер Хансен (Peter Hansen), Бен Шрёдер (Ben Schroeder), Алекс Чаффи (Alex Chaffee), Петер ван Руйен (Peter van Rooijen), Рик Кавала (Rick Kawala), Марк ван Хамерсвельд (Mark van Hamersveld), Дуг Шварц (Doug Swartz), Лорен Боссави (Laurent Bossavit), Илья Преуз (Ilia Preuz), Дэниэл Ле Берре (Daniel Le Berre), Франк Карвер (Frank Carver), Майк Кларк (Mike Clark), Кристиан Пекелер (Christian Pekeler), Карл Скотланд (Karl Scotland), Карл Манастер (Carl Manaster), Дж. Б. Рэйнсбергер (J.B. Rainsberger), Петер Линдберг (Peter Lindberg), Дарач Эннис (Darach Ennis), Кайл Кордес (Kyle Cordes), Джастин Сампсон (Justin Sampson), Патрик Логан (Patrik Logan), Даррен Хоббс (Darren Hobbs), Аарон Сансоне (Aaron Sansone), Сайвер Энстад (Syver Enstad), Шинобу Каваи (Shinobu Kawai), Эрик Мид (Erik Meade), Патрик Логан (Patrik Logan), Дан Росторн (Dan Rawsthorne), Билл Рутисер (Bill Rutiser), Эрик Хэрман (Eric Herman), Пол Чишолм (Paul Chisholm), Аэзим Джалис (Asim Jalis), Айвэн Мур (Ivan Moor), Леви Первис (Levi Purvis), Рик Магридж (Rick Mugridge), Энтони Адаши (Antony Adachi), Найджел Торн (Nigel Thorne), Джон Блей (John Bley), Кари Хойджарви (Kari Hoijarvi), Мануэль Амаго (Manuel Amago), Каору Хосокава (Kaouru Hosokawa), Пэт Эйлер (Pat Eyler), Росс Шоу (Ross Shaw), Сэм Джэнтл (Sam Gentle), Джин Райотт (Jean Rajotte), Филип Антрас (Phillipe Antras) и Джейме Нино (Jaime Nino).



Я хотел бы выразить свою признательность всем программистам, с которыми разрабатывал код в стиле «сначала тесты». Спасибо вам за терпение и внимание к идее, которая звучала полным сумасшествием, в особенности в самом начале развития TDD. Благодаря вам я научился значительно большему, чем если бы действовал самостоятельно. Мое обучение было наиболее успешным, когда я сотрудничал с Массимо Арнольди (Massimo Arnoldi), Ральфом Битти (Ralph Beatti), Роном Джеффрисом (Ron Jeffries), Мартином Фаулером (Martin Fowler) и (безусловно, не в последнюю очередь) Эрихом Гаммой (Erich Gamma), однако я хотел бы отметить, что помимо этих людей были и другие, благодаря которым я тоже научился очень многому.

Я хотел бы поблагодарить Мартина Фаулера (Martin Fowler) за помощь с FrameMaker. Этот человек должен быть самым высокооплачиваемым на планете специалистом в области подготовки текста к печати (к счастью, он не против, чтобы гонорар за эту книгу целиком достался мне).

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

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

Спасибо Майку Хэндерсону (Mike Henderson) за воодушевление, а также Марси Барнс (Marcy Barns) за то, что она пришла на помощь в трудную минуту.

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


От издательства

Ваши замечания, предложения, вопросы отправляйте по адресу электронной почты comp@piter.com (издательство «Питер», компьютерная редакция).

Мы будем рады узнать ваше мнение!

На веб-сайте издательства http://www.piter.com вы найдете подробную информацию о наших книгах.




Введение


Однажды рано утром в пятницу к Уорду Каннингэму зашел босс и представил его Питеру, перспективному заказчику системы WyCash.



Читать бесплатно другие книги:

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

Очередное неудачное свидание Риз Аннесли грозило перерасти в катастрофу, но подсевший к ней и ее спутнику за столик б...

Быть поэтом опасно – особенно после революции. Граф Александр Ростов в 1922-м попадает под трибунал за давно написанн...

Самая популярная сага в истории отечественной фантастики – в полном составе! Весь сериал культовых «Дозоров» Сергея Л...

Книга об основах инвестирования и планирования портфеля. Главное, что пытается донести автор до читателей, заключаетс...

В учебнике рассмотрены вопросы формирования информационного общества. На основе современных теорий раскрываются содер...