среда, 20 мая 2015 г.

"А вы не любите TDD, как не люблю его я?"

Если вы хотели прочитать все аргументы против TDD в одном месте, то вот вам ссылка.

"TDD есть опиум для народа"

На данный момент, это самый аргументированный и подробный ответ апологетам TDD (из известных мне на русском языке).

Хотите узнать продолжение истории и проникнуться ответами другой стороны - подписывайтесь на дискуссию на страничке "Radio QA"

И как мне теперь с ним на работе общаться? Опасный человек оказывается :)

Да, кстати, подписывайтесь на блог Владимира, он классно пишет. Надо его мотивировать писать чаще :)


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

  1. Честно говоря, больше похоже на софистику в стиле:

    > Мне тут сказали, что программисты на Западе хорошо зарабатывают, так я сел в машину, поехал на запад и попал в Погорелое Городище - а там для программистов вообще работы нет. Значит, врут всё про работу на Западе! Опиум для народа, понимаешь ли...

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

    ОтветитьУдалить
  2. Интересный комментарий.Я воспринимаю статью (и не только эту, а вообще все что читаю) не как руководство к действию (или набор отмазок для руководства, или бальзам на свои больные места), а как набор аргументов, с которыми часто приходится сталкиваться. Просто тут они удобно собраны в одном месте, что дает возможность попробовать так же аргументированно на них ответить. Я со многим согласен, но вообще скорее получается "it depends on" - у каждого свои проблемы, и нет одного общего инструмента (silver bullet), который все это может решить. Ну и голова с тараканами у каждого своя.

    ОтветитьУдалить
  3. Да простите, фразе про "никогда переписывать не придется" не хватает слова "почти". Я же не взял этот аргумент с потолка, вполне типичный диалог происходит в стиле:
    - В моей практике код часто пишется итерационно, постепенно наращивается мясо, переписываются функции\классы, и если так писать используя TDD, то тесты очень часто ломаются не по делу
    - Вы не правы, ибо TDD помогает рано выявить нюансы, сформировать архитектуру и следовательно в коде будет МИНИМУМ переделок.

    ОтветитьУдалить
  4. Странные у Вас собеседники, конечно. Число переделок кода, на мой взгляд, никак не следует из наличия/отсутствия тестов. Более того, лично я вижу ситуацию ровно наоборот: если код "одноразовый", не предназначенный для изменения (и не слишком сложный), то его можно написать и без автотестов, тупо проверив все варианты работы один раз руками. Если же планируется код развивать и модифицировать, то я напрягусь и поскриплю извилинами, но всё же постараюсь создать для него тестовый сьют - именно потому, что юнит-тесты, как показывает мой опыт, позволяют проще и без большой боли менять код. Именно менять. Итерационно, шаг за шагом.

    Если же у Вас тесты "часто ломаются не по делу", то я вижу два (наиболее возможных) варианта, почему это происходит:


    * Либо в Вашем коде (или тестах) присутствуют паттерны, мешающие удобному тестированию (их много; помочь может каталог Мессароша http://www.ozon.ru/context/detail/id/4127815/, к примеру)

    * Либо Вы меняете сначала код, а потом тесты - но простите, это тогда уже не TDD! И обвинять TDD в Ваших болях уже несколько неэтично.

    ОтветитьУдалить
  5. Написал ответ, а он куда-то пропал :( Ох уж этот Disqus...

    Попробую повторить: мне удивительно, почему апологеты TDD, с которыми Вы спорите, утверждают, будто бы в коде будет минимум переделок при использовании этой техники. Мой опыт говорит, что число переделок редко бывает связано с тем, как именно разрабатывается тот или иной продукт. Более того, для меня связь чаще строится в обратную сторону: если заранее известно, что софтина не будет сильно развиваться, или если она очень простая, то я могу позволить себе не писать для неё тестов. Но если я создаю какой-то софт, который планируется итеративно развивать и дополнять, то лучше дополнительно поднапрягусь и поломаю голову, но создам для него тестовый сьют, который позволит мне развивать его через TDD. Именно потому, что методика разработка через тесты при правильном применении позволяет развивать приложение итеративно.

    В Вашем же случае стоит внимательней посмотреть на причину, из-за которой "тесты очень часто ломаются не по делу". Чаще всего это происходит по одной из двух причин:

    * Либо в коде много "запахов", которые мешают лёгкому тестированию (высокая связность кода, неявные зависимости, смесь высокоуровневой логики с низкоуровневыми деталями реализации и т.п.). С каждым из таких запахов можно разобраться, но без конкретных примеров я мало что могу посоветовать - по фотографии диагноз не ставлю :)

    * Либо Вы меняете тесты только после изменений в коде. Конечно, это может сломать тесты, но в таком случае некорректно утверждать, что применяемый Вами метод называется TDD (и, соответственно, обвинять его в том, что Ваши тесты ломаются).

    В любом случае, я бы посоветовал Вам поглядеть книгу "Шаблоны тестирования xUnit" Месароша http://www.ozon.ru/context/detail/id/4127815/. Довольно долго она была моей настольной книгой при работе с тестами и позволила понять многое из того, что было далеко не очевидно, когда я только начинал осваивать TDD.

    ОтветитьУдалить
  6. Андрей, сори, мой косяк. Сообщение с линком - модерация требовалась. Пусть будет 2 теперь :)

    ОтветитьУдалить
  7. Все про что Вы говорите - верно. И книжка правильная ;) Но жизнь чаще сложнее.
    Я, в последнее время, больше склоняюсь к тестам более высокого уровня, не юнит. Их тоже можно писать "до кода", но с ними проще его модифицировать. Может чуть подробнее на эту тему я писал здесь http://www.maxshulga.ru/2015/04/self-edu-3.html

    ОтветитьУдалить
  8. Эххх, надеялся на ответ Владимира, но что-то не дождался. Интересно было, из-за чего всё же падают его тесты :)

    ОтветитьУдалить
  9. Он там в своем блоге с Солнцевым баталится :) Там вернее дождаться ответа :)
    Но я могу попробовать ответить за него (как я себе это представляю). Скорее всего под его "ломаются" имеется ввиду, что их просто приходится переписывать, если меняется код (причем уже даже не важно в каком порядке). Все логично и ожидаемо: меняется код, меняются (= выбрасываются) тесты.
    А если мы говорим о тестах чуть выше уровнем (не юнит), то чаще всего они остаются без изменений или с минимальными изменениями.

    ОтветитьУдалить
  10. Пропустил уведомление что-то. Попробую объяснить, утрированно и с преувеличениями конечно, куда уж без этого:
    Допустим у нас есть очень хорошая, независимая, легко тестируемая функция. Примерно такого толка (она бессмысленна, просто пример):
    ...
    a = 0
    if x > 0:
    a = 1
    if y > 0:
    a+=1
    if x*y > 100:
    a*=100
    ...
    Мы использовали в ней, ну пусть, 5 if-ов, для качественного и полного покрытия юнит тестами, нужно все комбинации проверить (иначе не получится "спать спокойно") - итого, насколько я помню комбинаторику, 2^5 == 32 теста. Ну и конечно всякие особые случаи нужно проверить и т.п., но опустим. Поскольку в TDD мы тесты пишем до того, как были учтены все текущие требования, функцию мы продолжаем разрабатывать. Допустим следующим шагом мне понадобилось сделать крохотное изменение заменяю "a+=1" на "a+=2", это приведет, для подобного кода, к поломке половины (16) тестов. Одна цифра - ведет к изменению в 16!! тестах. И этот ад будет продолжаться и продолжаться. Штук 10 итераций и уже 160 переписанных тестов.
    А если принять за правило писать тесты после того как код более менее стабилизируется - у нас получится, что нам нужно написать всего навсего 32 теста 1 раз. И что характерно на выходе тоже самое - покрытая тестами функция, а если нет разницы зачем платить больше?

    ОтветитьУдалить
  11. > Поскольку в TDD мы тесты пишем до того, как были учтены все текущие требования...

    Простите, но с этим утверждением я категорически не соглашусь Писать тесты, не учитывая все текущие требования - это нелепо и ошибочно. Суть TDD именно в том, чтобы взять все текущие требования, формализовать их в примеры для кода, а затем создать код, шаг за шагом решая эти примеры. Это тоже достаточно утрированное описание, но всё же...

    Разумеется, такой подход приведёт к лишней работе и недовольству, но в чём здесь на самом деле изъян? Не в использовании TDD, а в игнорировании требований, простите.

    ОтветитьУдалить
  12. Не точно выразил мысль. Имелось ввиду, что тесты пишем до того, как в КОДЕ уже реализованы все текущие требования. Соответственно мы будем менять код, каждое изменение ведет к переписыванию тестов и далее по тексту в предыдущем комментарии...

    ОтветитьУдалить
  13. Владимир, я не понимаю: почему так получается, что требования (выраженные в тестах) остались неизменными, а логика в коде вдруг начинает меняться? ;)

    ОтветитьУдалить
  14. А вы смотрели видео, на которое я давал ссылку в начале? https://www.youtube.com/watch?v=8u6_hctdhqI&feature=youtu.be Просто объяснять долго, а на его примере хорошо видно, что с каждым новым тестом меняется старый код, причем весьма значительно

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