Рассказывает Майк Кронин, разработчик
Прим. ред. Мнение редакции может не совпадать с мнением автора.
Всё верно, я считаю, что разработка через тестирование (Test Driven Development — TDD) — это плохо. Более того, TDD пагубно влияет на джуниоров, ставя перед ними нереалистичные цели. Так что позвольте мне в насмешливой форме поразглагольствовать о том, почему написание тестов для несуществующих функций — это дико.
Почему я так считаю?
В частности потому, что мне нужно было о чём-то написать на этой неделе, но также и потому, что я общался с senior-разработчиками с реальным опытом. Не с теми, которым не нравится TDD, а наоборот. Когда я спрашивал их об использовании TDD, они в красках описали все его преимущества. Но стоило мне продолжить вопросом:«Так, а в реальности вы этим пользуетесь?», — как я получал очень разные ответы.
«Ну, эээ, в общем, с TDD такое дело…»
«На это нет времени»
«У нас так не принято»
«Мой коллега не хочет»
«Я всё время занимаюсь TDD со своей девушкой, ты просто её не знаешь, она ходит в другую школу»
Для чего-то настолько великолепного удивительно мало людей действительно этим пользовались. Это было особенно удручающе, так как на курсах я не видел, чтобы кто-то из преподавателей использовал TDD, но при этом они все говорили, что ты должен это делать. Учитывая, что все вокруг говорили о TDD, у меня начал появляться комплекс, так как в глубине души я никак не мог понять, чем это лучше, чем делать всё наоборот.
В чём вообще преимущества TDD?
Сторонники TDD признают, что с ним разработка идёт медленнее. В то же время, они уверяют, что в итоге код будет настолько чистым и продуманным, что вы сэкономите время в долгосрочной перспективе. Однако я начал понимать, что причина, по которой TDD-подход настолько медленный, заключается в том, что он просто… неэффективный. И я получил прекрасную иллюстрацию этого на днях, когда кто-то попытался использовать этот подход.
Пробуем TDD
Я был взволнован — senior-разработчик собирался показать мне, как это делается. Мы обсудили фичу и функцию, с которой мы начнём, написали тест и посмотрели, как он провалился. Мы начали работать над функцией, но минут через десять прекратили. Мы заметили, что из-за того, как мы писали функцию, тест не сможет её обнаружить. Нам пришлось прекратить работать над фичей и вернуться к работе над тестом снова.
Работа над функцией продолжилась, однако мы начали чувствовать, что не очень понимаем, как она будет взаимодействовать с остальной системой. Поэтому мы начали играться с кодом, чтобы посмотреть на его реакцию. Мы изменили функцию и залогировали результаты. Выяснилось, что дело можно упростить, если изменить файл конфигурации и сделать небольшие изменения, которые мы сразу же и сделали. Это заняло у нас немного времени, но мы наконец поняли, как фича будет взаимодействовать с системой. И тогда я заметил, что 1) наша функция была полностью написана и что 2) тест провалился. Снова.
Почему TDD не сработал?
Потому что не так просто разрабатывать ПО, реализующее бизнес-логику. Да, при работе над своими небольшими проектами TDD звучит клёво. Но в реальной жизни фичи устроены немного сложнее, чем «функция X должна принять имя и вывести приветствие с этим именем». Часто требования к продукту меняются посреди работы или вы вдруг осознаёте, что фича не может работать согласно требованиям. Или вы изначально всё не так поняли, и вам нужно начинать работу с нуля.
В этих ситуациях нет ничего необычного, но необходимость постоянно тратить время на написание теста в самом начале только усугубляет каждую из проблем. Гораздо проще писать код, вручную проводить какие-нибудь тесты и лишь затем писать автоматизированные тесты для имитации этих ситуаций. Имея надлежащие тесты вы можете свободно переходить к следующей фиче или провести рефакторинг, не боясь что-нибудь сломать. Используя тестирование как ограждение, а не карту, вы получаете все преимущества тестов БЕЗ проблем с попытками что-либо предвидеть.
У TDD есть хорошие идеи
В TDD есть много хорошего. На самом деле, хорошо буквально всё, кроме тестов. Идея TDD заключается в том, что вы можете написать тест потому, что вы сначала сели и обо всём подумали. И это здорово! Многие разработчики (я) окунаются с головой в написание кода, даже не подумав, что именно код должен делать. Просто составив список целей и требований к функции вы получаете все преимущества TDD без необходимости писать сами тесты.
В заключение
Я поднял эту тему, потому что тесты — это важно. Выпуск приложения в продакшн без тестов можно сравнить с ездой по шоссе без разметки. Я пытаюсь сказать, что TDD похож на попытку начертить разметку до того, как вы проложили шоссе. Возможно, вы с этим не согласны и используете TDD каждый день и вам это нравится. Но если это не так, то всё в порядке! Нам нужно быть честными с самими собой. Если стиль программирования выглядит хорошо в теории, но не на практике, то давайте оставим те части, которые работают, а всё остальное выкинем. Моя запутанная мысль заключается в следующем: есть разные стили написания кода, и мы должны перестать считать какой-либо из них «лучшим».
Подводя итог, скажу, что у Behavior Driven Development нет никаких недостатков, и если вы его не применяете, то вы дурак.
Шучу.
Перевод статьи «Test Driven Development Is Dumb. Fight Me.»