суббота, 28 августа 2010 г.

GTD и TDD

Вот вы думаете зря что ли в TDD и GTD две буквы из трех одинаковые? Вы еще, наверное, думаете, что TDD - это когда тесты пишут перед реализацией.

Дело в том, что нужно быстро взять и прочитать TDD by Example Кента Бека и все сразу станет на место - не может ведь быть, что 240 страниц текста посвящено только test first принципу.

Не может быть и не есть.

Кент, например, рассказывает нам, что основной принцип TDD - это движение маленькими шажками. При решении какой-то задачи, он предлагает записать её на листик (ну, в VS есть настоящий to do list, такой же как и в Outlook) и прикинуть, понятно ли как решить задачу прямо сейчас. Если нет, то подумать, какой шаг может нас приблизить к решению основной проблемы. Таким образом он предлагает идти рекурсивно до первой простейшей атомарной задачи, которую мы и возьмем для реализации.

Далее предлагается написать тест для этой задачи и прогнать его, чтобы убедиться, что он падает. Помимо чисто психологического аспекта, как показывает практика (вы будете смеяться), есть и практическая польза - иногда тест не падает.

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

Более того, если во время реализации пришла какая-то супер-идея как сделать что-то лучше, то мы не отвлекаемся, а просто вносим её в наш to do list. Это важно, мы выгружаем её из мозга, чтобы она не мешалась у нас под ногами и не мешала нам сконцентрироваться над текущей задачей.

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

Причем, стоит особо отметить, - не будь у нас зеленого теста (или теста вообще), мы бы не были на 100% уверены в завершенности задачи. А точнее мы бы на 99% процентов были уверены, что первый запуск выдаст нам парочку-другую - а может и больше - непростых ошибок.

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

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

Мы не боимся что-то поломать, потому что если возникает проблема, то тесты, которые мы написали ранее, сразу дадут нам знать об этом.  Мы не забываем, что 80% времени программист читает код, а не пишет, поэтому постоянный рефакторинг - это эффективный способ увеличить производительность нашу и наших коллег.

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

В результате, мы все время движемся маленькими шагами и при каждом очередном зеленом тесте получаем тот необходимый нам импульс "Фуух, сделал!", мотивирующий нас на движение вперед, и, в то же время, не забываем удовлетворять наше чувство прекрасного, уделяя время на правильную структуризацию кода (рефакторинг). Мы делаем только то, что необходимо для прогресса, максимально простым и быстрым способом. Мы уверены в будущем и не боимся, что слишком простая реализация может не удовлетворять всем нашим потребностям в будущем - код легко читать и менять, а тесты застрахуют нас от ошибок.

Господа, это и есть принципы Getting Things Done, адаптированные к программированию, то есть TDD - это и есть, не побоюсь громких слов, эффективная система time management для разработчиков.

И помните, только настоящим пацанам не нужны тесты!

5 комментариев:

  1. Вот такой получился опус в продолжение темы о TDD.

    http://www.grodnosoft.by/2010/09/test-driven-development-tak-daleko-tak.html

    ОтветитьУдалить
  2. Я считаю, что самый хороший способ научиться TDD - это парное программирование :) Учиться самому однозначно непросто, но можно (я тому живой и еще ходячий пример).

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

    Статистика говорит нам, что тесты добавляют +30% к разработке, но с сильной экономией на баг фиксинге и рефакторинге на более поздних этапах. Но это когда уже все умеют....

    ОтветитьУдалить
  3. Согласен насчет парного программирования, но мне кажется, что в этом случае хотя бы один человек из пары должен ориентироваться в TDD.

    В любом случае меня больше интересует (и заботит) внедрение этой практики. Тут, как вы правильно заметили, все еще тяжелее. Думаю имеет смысл:
    1) продвигать TDD своим примером
    2) попробовать посчитать выгоду от применения на небольшой задаче и представить результат руководству

    Тут, конечно же, встает вопрос об ответственности за результат - но я в своем случае справлюсь :)

    ОтветитьУдалить
  4. Да, стоит согласовать это с руководством.

    Тут еще один момент стоит учитывать. Есть понятие testable и not-testable код.

    Так вот если сначала написали кучу кода и потом подумали - дай-ка мы юнит-тестами его покроем, то выяснится, что код не testable (так как код писался без расчета на юнит-тесты), писать тесты тяжело и шансов на успех значительно меньше.

    Если писать тесты сразу, то код автоматически пишется так, чтобы было удобно тестировать. И этого не надо боятся, потому что на самом деле это скорее означает, что мы достигаем loose coupling, то есть зависимостей в коде меньше, потому и тестировать легче.

    ОтветитьУдалить
  5. Да, покрытие существующего кода юнит-тестами, как правило, дело гиблое. Приходилось с этим сталкиваться. В принципе это может быть дополнительным доводом в разговоре с руководством. Мол, "вы же хотели покрыть все юнит-тестами, но ничего не получилось. Есть решение!" - в таком духе.

    ОтветитьУдалить