понедельник, 23 апреля 2012 г.

Мысли о третьем шаге в TDD

Сегодня второй раз в жизни пишу код согласно чистому TDD, прямо как заповедали такие мастера, как Роберт Мартин, Эндрю Хант и Майкл Физерс. Один случай меня заставил серьёзно задуматься о разнице в подходах к разработке.

Третий шаг в TDD гласит: «напиши ровно столько кода, сколько нужно для того, чтобы проваливающийся ранее тест начал завершаться успешно». (Первые два это «напиши проваливающийся тест» и «заставь этот тест компилироваться»). Несмотря на то, что он кажется довольно простым, пункт насчёт «ровно столько, сколько нужно» невероятно важен в рамках этой методологии.

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

Только после раздумья длиной что-то около полудня я понял, почему так важно соблюдать это правило, хотя ответ очень прост. Если ты напишешь код, который не предусматривают твои тесты, пусть даже он будет выполнять какую-то идейно полезную работу (а он, конечно же, будет выполнять идейно полезную работу), он не будет покрыт тестами. А код, который не покрыт тестами — это legacy код, которому положено гореть в аду. Более того, если ты оставишь весь этот код среди другого, чистого и покрытого тестами, он будет, как ржавая арматура, мешать добавлять новую функциональность. Так как он не покрыт тестами, а ты в целом стараешься следовать TDD, значит, все эти буквы становятся просто шумом, про полезность и надёжность которого ты не знаешь ничего.

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

2 комментария:

  1. Не соглашусь. Писать больше кода, чем нужно для озеленения вновь написанного теста, нельзя не потому, что он окажется не покрытым тестами (само по себе это не так уж и страшно - процент покрытия не должен быть самоцелью), а потому, что этап дизайна получится слишком большим (т.е. ты спекулируешь, создавая код "на будущее", даже если это будущее - в получасе работы). В результате получается 1. Прохой дизайн 2. Нетестируемый код 3. Возможно, вообще ненужный код 4. Не покрытый тестами код. Причем п. 1 - самый важный. Очень рекомендую почитать блог Uncle Bob-а, где он выполняет "word wrap kata" и "sort kata". В первой он просто приходит в тупик, делая большие шаги. Последняя интересна тем, что, тоже делая большие шаги, он приходит к bubble sort, а делая мелкие шаги - к quick sort :)

    ОтветитьУдалить
    Ответы
    1. В целом я именно это и имел в виду. Конечно же, то, что код не покрыт тестами, само по себе не плохо, плохо то, _почему_ он не покрыт тестами. Именно это ты и дописал. ;) Спасибо за прекрасное дополнение к моей мысли. Про каты в очередной раз читаю упоминание, уже пора, наверное, ими заняться. :)

      Удалить