ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 25.10.2023

Просмотров: 363

Скачиваний: 11

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Разработка через тестирование
179
структуру кода . Придется разорвать некоторые связи, добавить несколько абстракций, а может, и перенаправить некоторые вы- зовы функций и аргументы . Кажется, что переделана гора работы, потому что вы и так знаете, что код работает .
У вас плотный график, и есть работа поважнее . Поэтому вы от- кладываете тест . Вы убеждаете себя, что в нем нет необходимости и написать его можно попозже . И вот теперь у вас пробел в тесто- вом наборе .
И поскольку вы оставляли пробелы в тестовом наборе, вы подо- зреваете, что все остальные тоже так делают . Когда вы запускаете тестовый набор и видите, что он пройден успешно, вы покрякивае- те, ухмыляетесь или насмешливо отмахиваетесь, потому что знаете: прохождение тестов не означает, что программа работает .
Когда программа проходит такой набор тестов, нельзя принять решение . Все сведения, которые мы получаем от прохождения тестов, . . — это то, что работает все, что тестировалось .
Неполнота тестов оставляет вас без вариантов . Но если вы будете следовать тем самым трем правилам, каждая строка кода будет на- писана так, что тест будет пройден . Таким образом, тестовый набор станет полным . Когда программа проходит набор тестов, можно принять решение . Решение о развертывании .
Вот это цель! Мы хотим создать набор автоматизированных тестов, который даст уверенность, что развертывание программного обес- печения безопасно .
И снова хочу сказать, я не пишу вам тут картину маслом . Соблюде- ние трех правил позволит создать полный тестовый набор, но и тут нельзя быть на 100 % уверенным . Есть ситуации, когда три правила

Глава 5. Технические методы
180
разработки через тестирование неуместны . Эти ситуации выходят за рамки этой книги, скажу лишь, что они ограниченны, и есть ре- шения, которые смягчают их . В результате даже самые прилежные приверженцы наших трех правил вряд ли смогут создать тестовый набор, который будет выполнен на 100 % .
Но в 100 %-ной полноте тестов нет необходимости для принятия решения о развертывании . Значения в 95 % вполне достаточно — и такая полнота тестов поистине достижима .
Я создавал настолько полные тестовые наборы, что они позволяли принять решение о развертывании . Я видел, как многие другие де- лают то же самое . В каждом из таких случаев полнота не достигала
100 %, но ее хватало, чтобы принять решение о развертывании .
ВНИМАНИЕ
Полнота тестов — это показатели для команды, а не для руковод- ства. Менеджеры вряд ли знают, что на самом деле означают эти показатели. Менеджеры не должны ставить эти показатели
своей целью. Команда должна применять их исключительно в целях сообщения сведений о стратегии тестирования.
ЕЩЕ РАЗ ВНИМАНИЕ
Не завалите сборку на основании недостаточного прохождения
тестов. Если вы поступите так, программисты будут вынуждены избавиться от достаточного количества операторов подтверж- дения отсутствия ошибок, чтобы получить достаточно высокий процент выполнения. Полнота прохождения тестов — сложная тема, которую можно понять только в контексте глубокого зна- ния работы кода и тестов. Не позволяйте делать ее метрикой для менеджеров.


Разработка через тестирование
181
Проектирование
Помните ту функцию, которую было трудно протестировать, а код уже до этого тестировали вручную? Может, ее трудно протести- ровать потому, что она связана с задачами, которые вы не хотите запускать в тесте? Например, это может быть включение рентге- новского аппарата или удаление рядов из базы данных . Функцию тяжело протестировать, потому что она спроектирована не так, чтобы это можно было сделать легко . Вы сначала пишете код, а потом пишете тесты задним числом . Тестируемость конструкции была тем, о чем вы думали в последнюю очередь, когда писали код .
Теперь вы столкнулись с тем, что для прохождения теста нужно перепроектировать код . Вы смотрите на часы и понимаете, что те- стирование длится слишком долго . Поскольку вы уже тестировали все вручную и знаете, что все работает, то просто уходите прочь, оставляя еще один пробел в тестовом наборе . А вот когда вы снача- ла пишете тест, то все происходит совершенно иначе . У вас просто не получится написать функцию, которую трудно протестировать .
Поскольку вы сначала пишете тест, то естественным образом про- ектируете функцию так, чтобы ее легко было протестировать . Как писать функции так, чтобы они были легко тестируемы? Нужно убрать связи между ними . Тестируемость означает свободу от связей .
Когда вы сначала пишете тесты, то размыкаете связи внутри про- граммы таким способом, о котором бы никогда даже не подумали .
Программа будет тестируема целиком, то есть связи между функ- циями всей программы будут отсутствовать .
Именно по этой причине разработку через тестирование часто называют методом проектирования . Три правила в высшей мере способствуют уменьшению связанности .

Глава 5. Технические методы
182
Смелость
Пока мы видели, что если следовать трем правилам разработки через тестирование, то у нас появляется много преимуществ: мень- ше отладки, качественная низкоуровневая документация, радость и разделение связей . Но это лишь сопутствующие преимущества, ни одно из них не является главной причиной применения разра- ботки через тестирование . Настоящая причина — это воспитание смелости .
Я уже рассказывал историю в самом начале книги, но стоит ее по- вторить .
Представьте, что вы смотрите на некий уже написанный код на экране . Там бардак . Первая мысль, которая приходит в голову:
«Нужно почистить его» . Но следующая мысль будет примерно такой: «Нет, я в это не полезу!» Вы думаете, что если влезть в код, то он перестанет работать . А если он перестанет работать, вина ваша . Поэтому вы отстраняетесь от кода подальше, оставляя его гнить и чахнуть .
В вас говорит страх . Вы боитесь кода . Боитесь что-либо делать с ним . Боитесь что-то сломать, потому что будут последствия .
Так вы отказываетесь от того единственного, что может улучшить код, — от его чистки .
Если в команде каждый придерживается такого поведения, код бу- дет портиться . Никто не возьмется его почистить . Никто не улуч- шит его . Каждая новая функция будет добавлена таким образом, чтобы свести на нет непосредственный риск для программистов .
Будут добавлены связи и дубликаты, потому что они уменьшают непосредственный риск, даже если нарушают структуру и целост- ность кода .


Разработка через тестирование
183
В конце концов код становится чудовищно запутанным, как спа- гетти, его невозможно сопровождать, работа над таким кодом едва ли будет продвигаться . Сложность задач будет расти в геометриче- ской прогрессии . Менеджеры в отчаянии . Они будут нанимать все больше программистов в надежде улучшить производительность, но улучшение не будет достигнуто .
Наконец, достигнув критической точки, руководство согласится на требование программистов переписать всю программу с самого начала . И начинается то же самое .
Представьте себе другой сценарий . Вернемся к монитору, на кото- ром мы видим запутанный код . Первая мысль, которая вас посеща- ет, — надо почистить код . Что, если бы у вас был настолько полный тестовый набор, что ему можно полностью доверять? А если этот тестовый набор работал бы быстро? Что бы вы подумали следую- щим делом? Наверное, что-то вроде этого:
Боже, думаю, просто надо поменять имя этой переменной.
О, код все еще проходит тесты. Ладно, а теперь я разделю ту
большую функцию на две поменьше… Здорово, все еще удается
пройти… Хорошо, теперь, думаю, можно перенести одну из этих
новых функций в другой класс. Опа! Тест не пройден. Так, ну-ка,
вернем все… А, я понял, надо было переместить и саму перемен-
ную. Да, тест снова пройден…
Когда у вас есть полный набор тестов, вы больше не боитесь вносить изменения в код . Вы больше не боитесь его чистить . Вы просто возьмете и почистите код . Код будет опрятным и чистым .
Структура программы останется неизменной . Вы не будете пло- дить массу гниющего спагетти, которая вгонит команду в уныние, приводящее к низкой производительности и, в конце концов, к провалу .

1   ...   9   10   11   12   13   14   15   16   ...   20

Глава 5. Технические методы
184
Поэтому мы применяем разработку через тестирование . Мы при- меняем этот метод, потому что он вселяет в нас смелость поддер- живать код в чистоте и порядке . Смелость вести себя профессио- нально .
Рефакторинг
Рефакторинг — еще одна тема, достойная целой книги . К счастью, ее уже написал Мартин Фаулер
1
. В этой главе мы просто обсудим это тему, не углубляясь в отдельные методы . И как и прежде, в этой главе нет кода .
Рефакторинг — это метод улучшения структуры кода без изме- нения его поведения, определенного тестами . Другими словами, мы вносим изменения в имена, классы, функции и выражения, не проваливая никаких тестов . Мы улучшаем структуру программы без воздействия на ее выполнение .
Конечно же, эта дисциплина тесно связана с разработкой через тестирование . Чтобы без опасений перепроектировать код, нужен тестовый набор, который с высокой степенью вероятности укажет нам на то, что мы ничего не испортим .
Изменения, выполненные во время рефакторинга, разнятся от простых косметических до глубокой правки структуры . Такие из- менения могут представлять собой просто изменения в названиях или сложную замену операторов switch на полиморфные отправ- ки . Большие функции будут разбиты на те, что поменьше, с более удачными названиями . Списки аргументов будут изменены на
1
Fowler M . Refactoring: Improving the Design of Existing Code . 2nd ed . Boston,
Massachusetts: Addison-Wesley, 2019 .

Разработка через тестирование
185
объекты . Классы с большим количеством методов будут разделе- ны на множество мелких классов . Функции будут перемещены из одного класса в другой . Из классов будут выделены подклассы или внутренние классы . Зависимости будут инвертированы, а модули перемещены через границы архитектуры .
И пока все это происходит, наша программа непременно проходит тесты .
Красный/зеленый/рефакторинг
Ход рефакторинга естественным образом связан с тремя правила- ми разработки через тестирование приемом «красный/зеленый/
рефакторинг» (рис . 5 .1) .
Рефакторинг
Красный
Зеленый
Рис. 5.1. Цикл «красный/зеленый/рефакторинг»
1 . Сначала мы создаем тест, который не получается пройти .
2 . Потом пишем код и проходим тест .
3 . Затем подчищаем код .
4 . Далее возвращаемся к шагу 1 .

Глава 5. Технические методы
186
Написание рабочего кода и написание чистого кода — это две раз- ные вещи . Делать одновременно то и другое необычайно сложно, так как это совершенно разная деятельность .
Довольно тяжело написать рабочий код, не говоря уже о соблю- дении его чистоты . Поэтому мы сначала ориентируемся на напи- сание рабочего кода, что бы там ни происходило в головах нашего сумрачного гения . Затем, когда все заработало, мы устраняем бес- порядок, который натворили .
Это дает понять, что рефакторинг кода — процесс непрерывный, и его не проводят по плану . Мы не плодим беспорядок несколько дней кряду, чтобы потом долго его подчищать . Мы лучше создадим легкий беспорядок и через минуту-две все исправим .
Слово «рефакторинг» никогда не должно появляться в графике работ . Это не тот род деятельности, который можно провести по плану . Мы не выделяем времени на рефакторинг кода . Рефак- торинг — это часть нашей ежеминутной, ежечасной рутины при написании ПО .
Большой рефакторинг
Иногда требования меняются так, что вы осознаете: дизайн и ар- хитектура программы не совсем подходят . Тогда вы решаете внести значительные изменения в структуру программы . Такие изменения вносят в цикле «красный/зеленый/рефакторинг»ь
Мы не создаем программы специально для того, чтобы вносить изменения в структуру . Мы не выделяем времени в графике работ на такой глубокий рефакторинг кода . Маленькими порциями мы переносим код, продолжая добавлять новые функции за время обычного цикла Agile .


Простота проектирования
187
Такое изменение в структуру программы можно вносить несколько дней, недель или даже месяцев . Все это время программа проходит все необходимые тесты и готова к развертыванию, даже если из- менение структуры не полностью завершено .
ПРОСТОТА ПРОЕКТИРОВАНИЯ
Метод «простота проектирования» — одна из целей рефакторинга .
Простота проектирования — метод, предполагающий написание только необходимого кода, чтобы сохранять простоту структуры, его небольшой размер и наибольшую выразительность .
Правила простого проектирования Кента Бека .
1 . Пройти все тесты .
2 . Проявить намерение .
3 . Удалить дубликаты .
4 . Сократить количество элементов .
Номера пунктов означают порядок действий, в котором эти пра- вила выполняются, и их приоритет .
Пункт 1 говорит сам за себя . Код должен пройти все тесты . Он должен работать .
В пункте 2 указано, что после того как код заработал, ему нужно придать выразительность . Он должен явно отражать намерения программиста . Код нужно писать так, чтобы он легко читался и содержал достаточно сведений . Как раз сейчас мы проводим кос- метический рефакторинг кода, в течение которого вносим много простых изменений . Нужно также разделить большие функции на мелкие, дав им более простые и понятные названия .

Глава 5. Технические методы
188
В пункте 3 говорится, что после того как код получился в высшей мере описательным и выразительным, мы старательно выискива- ем и удаляем все дубликаты . Не нужно, чтобы в коде повторялось одно и то же . Во время такой деятельности проводить рефакторинг, как правило, сложнее . Иногда удалить дубликаты так же просто, как перенести дублирующийся код в функцию и вызвать его из разных мест . В других случаях требуются решения интереснее, например паттерны проектирования
1
: метод шаблонов, стратегия,
декоратор или посетитель .
В пункте 4 говорится о том, что как только мы удалили все ду- бликаты, нужно стремиться уменьшить количество структурных элементов, например классов, функций, переменных и так далее .
Цель метода «простота проектирования» — поддерживать наиболее возможную легковесность кода .
Легковесность
При проектировании программа может получиться как достаточно простой, так и необычайно сложной . Чем сложнее структура, тем больше умственная нагрузка на программиста . Эта умственная на- грузка — вес структуры программы . Чем больше вес программы, тем больше времени и усилий будет затрачено программистами на изучение и управление этой программой .
Таким же образом сложность требований также варьируется от небольших до огромных . Чем сложнее требования, тем больше времени и сил понадобится, чтобы изучить эту программу и управ- лять ею .
1
Гамма Э., Хелм Р., Джонсон Р., Влиссидес Дж . Паттерны объектно-ориенти- рованного проектирования . — СПб .: Питер, 2020 . — 448 с .: ил .