Сегодня второй раз в жизни пишу код согласно чистому TDD, прямо как заповедали такие мастера, как Роберт Мартин, Эндрю Хант и Майкл Физерс. Один случай меня заставил серьёзно задуматься о разнице в подходах к разработке.
Третий шаг в TDD гласит: «напиши ровно столько кода, сколько нужно для того, чтобы проваливающийся ранее тест начал завершаться успешно». (Первые два это «напиши проваливающийся тест» и «заставь этот тест компилироваться»). Несмотря на то, что он кажется довольно простым, пункт насчёт «ровно столько, сколько нужно» невероятно важен в рамках этой методологии.
Этот пункт, среди прочего, означает, что, если твой тест не предусматривает обработку ошибочных данных — значит, тебе нельзя писать такую обработку в коде. Если твой тест только проверяет тип результата функции, но не корректность его значения — значит, тебе нельзя писать код, который генерирует реальные правильные данные.
Только после раздумья длиной что-то около полудня я понял, почему так важно соблюдать это правило, хотя ответ очень прост. Если ты напишешь код, который не предусматривают твои тесты, пусть даже он будет выполнять какую-то идейно полезную работу (а он, конечно же, будет выполнять идейно полезную работу), он не будет покрыт тестами. А код, который не покрыт тестами — это legacy код, которому положено гореть в аду. Более того, если ты оставишь весь этот код среди другого, чистого и покрытого тестами, он будет, как ржавая арматура, мешать добавлять новую функциональность. Так как он не покрыт тестами, а ты в целом стараешься следовать TDD, значит, все эти буквы становятся просто шумом, про полезность и надёжность которого ты не знаешь ничего.
Наверное, теперь я на самом деле понял, насколько иной философией разработки пользуюсь. Сегодня я удалил целый класс, почти 100 строк кода, который написал, пытаясь закрыть один проваливающийся тест, и ни разу не пожалел об этом. Скорее наоборот: вспоминая ту ужасную массу кода, я уверен, что моя программа стала гораздо лучше, лишившись её.
Не соглашусь. Писать больше кода, чем нужно для озеленения вновь написанного теста, нельзя не потому, что он окажется не покрытым тестами (само по себе это не так уж и страшно - процент покрытия не должен быть самоцелью), а потому, что этап дизайна получится слишком большим (т.е. ты спекулируешь, создавая код "на будущее", даже если это будущее - в получасе работы). В результате получается 1. Прохой дизайн 2. Нетестируемый код 3. Возможно, вообще ненужный код 4. Не покрытый тестами код. Причем п. 1 - самый важный. Очень рекомендую почитать блог Uncle Bob-а, где он выполняет "word wrap kata" и "sort kata". В первой он просто приходит в тупик, делая большие шаги. Последняя интересна тем, что, тоже делая большие шаги, он приходит к bubble sort, а делая мелкие шаги - к quick sort :)
ОтветитьУдалитьВ целом я именно это и имел в виду. Конечно же, то, что код не покрыт тестами, само по себе не плохо, плохо то, _почему_ он не покрыт тестами. Именно это ты и дописал. ;) Спасибо за прекрасное дополнение к моей мысли. Про каты в очередной раз читаю упоминание, уже пора, наверное, ими заняться. :)
Удалить