Что означает аббревиатура tdd в разработке по

TDD: Что пошло не так?

Эта статья является переводом материала «TDD: What went wrong or did it?».

В сфере разработки программного обеспечения уже давно хвалят Test Driven Development (TDD, разработка через тестирование). Однако в последнее время было сказано много резких слов в адрес TDD, поскольку его обвиняют в плохом проектировании программного обеспечения и невыполнении многих своих обещаний. Кульминацией этой тенденции стал пост Дэвида Хайнемайера Ханссона «TDD is dead. Long live testing.» (TDD мертв. Да здравствует тестирование).

Как это возможно, что одна и та же техника, которая так выгодна для стольких разработчиков, так губительна для других? В этой статье Владислав Кононов расскажет о трех заблуждениях, которые могли бы объяснить это явление.

Начнем с самого тонкого и самого деструктивного.

TDD это не «Проектирование через тестирование»

TDD расшифровывается как “Разработка через тестирование”. К сожалению, многие неверно истолковывают это как “Проектирование, основанное на тестировании”. Эта неточность может показаться невинной, но поверьте мне, это не так. Позвольте мне объяснить.

Если вы разрабатываете в первую очередь для тестируемости, вы получаете то, за что платите, — тестируемый код. Чаще всего этот дизайн будет полностью не связан с бизнес-областью и требованиями проекта. Он будет напоминать огромный граф объектов, полный случайных сложностей. но он будет проверяемым. Тестируемый тестами, которые тонут в моках (имеется в виду mock как тестовый двойник), и полностью сломается после изменения одного кусочка в реализации. Это то, что называется “повреждением, вызванным тестом”, и это ярко показано в блоге Дэвида Хайнемайера Ханссона «TDD is dead. Long live testing.»:

Нынешний фанатичный опыт TDD приводит к тому, что основное внимание уделяется модульным тестам, потому что это тесты, способные управлять дизайном кода (первоначальное обоснование для test-first – сначала тестирование, потом реализация). Я не думаю, что это здорово. Test-first приводят к чрезмерно сложной сети промежуточных объектов и косвенных обращений, чтобы избежать «медленных» действий. Например, попасть в базу данных. Или файл IO. Или пройти через браузер, чтобы протестировать всю систему. Это породило некоторые поистине ужасные архитектурные уродства. Густые джунгли служебных объектов, командных шаблонов и прочего.

TDD это не (только) о модульных тестах

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

Вы имеете дело со сложной бизнес-логикой? Вам действительно нужны модульные тесты здесь.

Вы выполняете только простые операции CRUD? Используйте интеграционные тесты или сквозные тесты.

Сценарий ETL? Достаточно сквозных тестов.

. И, говоря о модульных тестах, что вообще такое модуль? Переходим к третьему заблуждению.

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

Определение модуля, которое мне нравится больше всего, принадлежит Рою Ошерову, автору книги The Art of Unit Testing:

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

Отсутствие буквы D в TDD

В конечном счете, есть еще одно наблюдение, которым я хочу поделиться, потому что оно суммирует все вышеупомянутые заблуждения.

Общепризнанно, что хорошо спроектированный код также поддается тестированию. Однако это соотношение не является коммутативным: хорошо спроектированный код можно тестировать, но не весь тестируемый код хорошо спроектирован. Доказательство тривиально:

P.S TDD 2.0

TDD был «заново открыт» Кентом Беком более десяти лет назад. Возможно, пора снова открыть TDD. Помимо модульных тестов, новая спецификация должна касаться других типов автоматизированных тестов, которые в то время были недоступны. И, конечно же, вместо того, чтобы работать против, TDD должен тесно сотрудничать с бизнес-областью.

Источник

Test-Driven Development — телега или лошадь?

Test Driven Development (TDD) – неоспоримо выдающаяся техника, дающая ряд преимуществ. Прикладные разработчики, причём вне зависимости от масштаба проекта и количества вовлеченных специалистов, в широкой массе не следуют TDD. Но есть и ярые сторонники такого подхода, причём они готовы апеллировать не только к здравому смыслу или производственной необходимости, но и на безоговорочно успешные примеры его внедрения. Одним из таких апологетов является Александр Люлин, который не только рассказывает о степени позитивного влияния TDD на разработку, но и делится экспертизой внедрения и неукоснительного каждодневного применения этой техники вплоть до исходных кодов и примеров сценариев (в своем блоге). Однако главный тормоз на пути следования принципам TDD стоит, что предсказуемо, набор чисто психологических установок. В режиме «жёсткого разговора» мы пообщаемся с Александром на тему необходимости Test Driven Development.

Test Driven Development – попытка следования моде? Слепое копирование чужих подходов?

Давайте «сразу определимся». Я не использую TDD в его классическом понимании. И не надо здесь цитировать «википедию»! Вообще, вряд ли кто-то из профессионалов рассматривает энциклопедические статьи в качестве руководства к действию. Мы свой подход «выстрадали» в рамках реализации успешного проекта, поэтому за нами реальный опыт, а не «тупое использование чужих идей». Скорее, мы используем синтез из TDD и собственных представлений о том, как нужно разрабатывать ПО. Даже если эти «внешние идеи» исходят от очень умных людей, их следует критически осмыслить и адаптировать к реальной компании, существующей команды и стратегии развития и обеспечения качества. Но я далее буду говорить «TDD», имея ввиду тот процесс “разработки через тестирования», который близко соотносится с энциклопедическим Test Driven Development, но идёт гораздо дальше него.

TDD — это попытка поставить всё с ног на голову. В классике инженерного дела сначала создаётся установка/техническая система/машина/агрегат. Конечно, методика испытаний имеется в виду при проектировании… но всё-так, программисты – это какой-то особый вид инженеров? Генетически ущербных? Сами себя таким не считаете?

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

Что означает аббревиатура tdd в разработке по. Смотреть фото Что означает аббревиатура tdd в разработке по. Смотреть картинку Что означает аббревиатура tdd в разработке по. Картинка про Что означает аббревиатура tdd в разработке по. Фото Что означает аббревиатура tdd в разработке по

Считаю ли я себя «генетически ущербным»? В силу профессии, отчасти, да. Поэтому и стремлюсь всеми силами стать лучше. Разработка ПО – инженерное ремесло, поэтому не надо вдруг себя считать суперменом или неким творцом. Мы – ремесленники (за исключением единиц), это нужно осознать и смириться. И попытаться стать нормальным (а не генетически ущербным) инженером – допуски, чертежи, методики испытаний и т.д.

TDD — сковывает инициативу разработчика. Уже не сам разработчик контролирует процесс, а задание «валится на него снеговыми комками»? Нет ли психологического дискомфорта? Программист у нас теперь не творец, а бездумная машина реализации им функционала?

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

Что означает аббревиатура tdd в разработке по. Смотреть фото Что означает аббревиатура tdd в разработке по. Смотреть картинку Что означает аббревиатура tdd в разработке по. Картинка про Что означает аббревиатура tdd в разработке по. Фото Что означает аббревиатура tdd в разработке по

Только никто не контролирует разработчика, он сам себя контролирует – «бьёт по рукам». Но это не мазохизм. Взамен разработчик получает кое-что важное – ощущение стабильности и уверенности в своём профессиональном завтрашнем дне. А как творец – он творит в два раза больше. Именно творит, а не «пашет». Пашет он как раз меньше. Жду следующего вопроса для разъяснений.

TDD — ставит во главу угла не качество реализации, а сиюминутные фичи. Как можно говорить о качестве кода? Об архитектуре системы? Мы на выходе с точки зрения программного кода получаем «салат оливье» — механическую смесь разных на вкус и цвет мелкопорезанных кусочков? Вы верите, что из винегрета, сложенный большой кучкой может символизировать собой архитектурное совершенно и конструктивное качество?

Вот это – совсем уж неправда. Именно качество и стабильность ставится во главу угла. Как раз, есть «фича» – есть тест, подтверждающий, что это «фича», а не «бага». Что не попало в ТЗ, то не попало в тесты, откуда тогда оно возьмётся в функционале? Только так: желание заказчика выражается в ТЗ, оттуда перетекает в тесты, и только потом появляется функционал.

Что означает аббревиатура tdd в разработке по. Смотреть фото Что означает аббревиатура tdd в разработке по. Смотреть картинку Что означает аббревиатура tdd в разработке по. Картинка про Что означает аббревиатура tdd в разработке по. Фото Что означает аббревиатура tdd в разработке по

Теперь про архитектуру… Архитектура это не есть что-то универсальное и самоценное. И не есть серебряная пуля. И не то, из чего делается плохая пуля. Я знаю архитектуру системы, т.к. я 15 лет ей занимаюсь и знаю великолепно, спасибо UML-чертежам. У меня полный набор проектных решений в виде UML-диаграмм. Но и здесь есть вероятность не удержать всё в памяти. Как всё это восстановить в памяти? Просто на конкретный тест посмотреть.
Тесты — это «архивированная память», а также «документация» и «варианты использования».

При этом тесты — более стабильны и инвариантны по сравнению с проектным кодом. Код перерождается. Эволюционирует. Умирает. С тестами это происходит гораздо реже. Видите, нет никакого конфликта интересов у архитектуры и тестов. И они в своей связке важнее кода.

Что означает аббревиатура tdd в разработке по. Смотреть фото Что означает аббревиатура tdd в разработке по. Смотреть картинку Что означает аббревиатура tdd в разработке по. Картинка про Что означает аббревиатура tdd в разработке по. Фото Что означает аббревиатура tdd в разработке по

TDD – некий бич, которым хлещут непокорных IT-рабов? Это что – некий вид «управы» на свободолюбцев, гордо именуемых «разработчиками»? Вы, разрабочтики, не должны думать. Ваша дело – тянуть лямку, выполнять план по валу! Смотри на тесты, данные тобой свыше, и не вздумай проявлять инициативу!

Значит так… «Руководству», (директорату и тем более заказчикам) реально нет дела, какие технологии используются (за редкими исключениями, на что мы надеяться не будем). Вообще, никого не парит, и что там «внутри» делают разработчики. Используют они RUP, TDD/ШмеДД, Agile/СуперАгиле или что-то иное…

Что означает аббревиатура tdd в разработке по. Смотреть фото Что означает аббревиатура tdd в разработке по. Смотреть картинку Что означает аббревиатура tdd в разработке по. Картинка про Что означает аббревиатура tdd в разработке по. Фото Что означает аббревиатура tdd в разработке по

Всем выше перечисленным «стейкхолдерам» – важен результат, а не процесс. Никакой здравомыслящий начальник не будет навязывать TDD. Ему нужен результат, а не раздражение разработчиков — «вот этот умник опять какие-то новомодные фишки нам навязывает». Умный начальник… реально умный (в IT это чаще, чем в других областях) может лишь сделать так, чтобы разработчики сами почувствовали эту необходимость. Это – единственный путь, иначе – тупик.

Нету никаких тестов, данных свыше. Тесты это — внутреннее дело разработчиков. И чем лучше тесты и чем их больше, тем разработчики «крепче спят». И тем меньше они вызываются на ковёр. Тесты – для разработчиков, не для начальников.

TDD – попытка некомпетентных и далёких от кодирования людей продвигать свою, чуждую разработчикам идеологию… своё, часто неправильное видение стратегии развития продукта.

Ещё раз. Тесты не диктует «директорат», руководство или заказчики. Тесты — это средство разработки. Тесты это – «внутренняя кухня» разработчиков и группы качества. Все остальные «стейкхолдеры» оперируют ТЗ. Ну или «экранами». Максимум… Тесты и «стратегия развития» вообще никак не соотносятся.

Допустим, меня обязали следовать технике TDD, хотя, согласитесь, очень многие люди комфортно чувствуют себя без этого. Ну и что это даёт по сравнению с нормальной техникой, когда «запланировали – реализовали – сделали тесты – протестировали»? Просто «красивая сказка» для начальника «мы используем передовые подходы?»

Можно же быть таким упёртым противником TDD! «Обязать» использовать тесты невозможно. Можно лишь уговорить. Если кто-то чувствует себя комфортно без тестов, то значит, что:
— его проект не такой сложный;
— он всё тестирует на реальных пользователях (не повезло им)
— он гений;
— он работает один.
Давайте, посмотрим в зеркало и выберем свою категорию.

Что означает аббревиатура tdd в разработке по. Смотреть фото Что означает аббревиатура tdd в разработке по. Смотреть картинку Что означает аббревиатура tdd в разработке по. Картинка про Что означает аббревиатура tdd в разработке по. Фото Что означает аббревиатура tdd в разработке по

Ещё раз: «Сказки» — нет, начальству – всё равно, ему нужен результат, сроки и качество.

Напахал я тестов. Начал под них (скрепя сердце) подгонять функциональный код. Выясняется… потом, что тест придуман неправильно. Я поработал впустую?

Вот «напахивать» ничего не надо. Одна фича – один тест. Итеративно. Фича порождает тест, а тест порождает фичу. XP, kiss-принцип.

А не бывает такого, что «тесты», которые приобрели вид «жёсткого задания», начали противоречить друг-другу?

Это мой любимый вопрос из разряда «гениальных»! Если тесты противоречат друг-другу, значит:
— ТЗ недостаточно проработано;
— ТЗ противоречиво.
Тут надо сказать «спасибо» тестам и вернутся к проработке ТЗ.

TDD – потеря времени. Давайте уж сначала напишем код, а потом будем его тестировать. Любое хождение «задом-наперёд», ненатуральный порядок разработки, даже если не сказывается на качестве, обязательно вызовет «тормоза».

Логично. Так многие и делают. Напишем код. Напишем. Покоммитим его в CVS/SVN. И что? Мы свою работу сделали? Типа «как повезёт»? Прокатит/не прокатит? Можно и так. Только потом тебя «поднимут с постели» и спросят «что за хрень ты тут написал?» Так?

Можно ведь по-другому — написать код и проверить его. А как мы его будем проверять? «Тупым» протыкиванием?
А если для «протыкивания» надо сделать 20-ть шагов? А если 100? А если «данных нет»? А если «смежники не готовы»? Не проще ли «написать тест» хотя бы для отладки? С придуманными «из головы» входом и выходом. По-моему, проще. А если тест УЖЕ написан и использовался для отладки, то почему не включить этот тест в «ночную сборку»?

Что означает аббревиатура tdd в разработке по. Смотреть фото Что означает аббревиатура tdd в разработке по. Смотреть картинку Что означает аббревиатура tdd в разработке по. Картинка про Что означает аббревиатура tdd в разработке по. Фото Что означает аббревиатура tdd в разработке по

TDD – способ поставить разработчика в унизительное положение. «Битый небитого везёт». Программист работает «от чувства вины» в перманентном состоянии нереализованности поставленной задачи.

Наоборот, у программиста есть всегда «реперные точки». Тут вот я написал тест. Он не проходит. Тут я реализовал функционал. Тест стал проходить.
Я всё покоммитил в CVS/SVN. Я свою работу СДЕЛАЛ и «могу спать спокойно».

TDD – нет ли ощущения, что программист всё время решает обратную задачу? Или разработчик – двоечник, подгоняющий решение под ответ задачи?

А программисты всегда решают обратную задачу. Ну или «строят сферического коня в вакууме». Программист – не двоечник, а обычный человек, который не может предусмотреть всё. Но зато то, что он предусмотрел – гарантировано работает. Есть и другие люди. Но они – гении, но их мало.

TDD – разработка в зазеркалье. Мы выполнили тесты, что не есть гарантия безошибочности. Кто отвечает за качество тестов?

Гарантии полной безошибочности» нет. Есть лишь гарантия того, что разработчик правильно понял ТЗ и реализовал его так, как понял.

TDD – телега впереди лошади. Лошадь постоянно тыкается мордой «в задний бампер», не видя ничего впереди себя. Как можно говорить о продумывании функционала в целом на уровне архитектуры системы, когда впереди – вдаль до самого горизонта – просто свалка потребностей?

Вот тут опять давайте вернёмся к «самому научному спору». Определим термины, что – телега, а что – лошадь. И не надо мне грозить википедией (как можно тестировать то, чего нет)?

Вот так будет правильно:
— «лошадь» — это ТЗ;
— «телега» — это КОД.

First: ТЗ и набросок архитектуры, дальше начинается итерационная разработка.
И что особенно вкусно, что как только мы написали тест, нам не надо думать, а где проверять работоспособность нашего класса? Мы уже настроили всю инфраструктуру для его тестирования и проверки. Именно это и означает слово Driven в TDD.

Что означает аббревиатура tdd в разработке по. Смотреть фото Что означает аббревиатура tdd в разработке по. Смотреть картинку Что означает аббревиатура tdd в разработке по. Картинка про Что означает аббревиатура tdd в разработке по. Фото Что означает аббревиатура tdd в разработке по

Ладно, есть на свете «извращенцы». Тогда хоть как можно облегчить страдания? Какой правильный процесс при этом?

Не, ну спасибо за эпитет. Цепочку я описал выше. Если мозг готов, то процесс выстроится сам собой. Дальше то вопрос в выборе инструментария.

Ладно, мы теперь не извращенцы, а правильные разработчики. Как впрячь коня (упрямого тестового пони на коротких ножках) и трепетную лань (мысль разработчика)?

Инструментарий, который мы используем:
— DUnit.
— Доработки к DUnit;
— Confluence;
— самописный аналог JIRA; в ту пору JIRA была ещё «сыра» поэтому мы её не взяли; сейчас — я думаю — взяли бы её;
— скриптовая машина;
— FishEye (https://www.atlassian.com/software/fisheye/overview);
— Доработки к Confluence и FishEye позволяющие отслеживать связь коммитов, изменений кода и строящие привязку конкретных изменений кода к конкретным задачам;
— интеграция UML и Confluence;

Что означает аббревиатура tdd в разработке по. Смотреть фото Что означает аббревиатура tdd в разработке по. Смотреть картинку Что означает аббревиатура tdd в разработке по. Картинка про Что означает аббревиатура tdd в разработке по. Фото Что означает аббревиатура tdd в разработке по

Кто создает тесты? А если «роль» создателя тестов не предполагает знание программирования?

Тесты создают разработчики. Если речь идёт о новой функциональности.
Или тестировщики. Если речь идёт об ошибках.
И чаще всего, тестировщики пишут ошибку и сразу пишут к ней тест.
Тут кстати надо понимать одну простую вещь, ТЗ и ошибки в общем-то ничем не отличаются друг от друга принципиально. Только лишь «зоной ответственности».
«А если «роль» создателя тестов не предполагает знание программирования?» — на BDD или Fit-таблицы — мы пока не «замахивались», но мы работаем над этим.

TDD – это наше «всё» или Вы всё-таки признаёте ограниченность данной техники?

«Разруха она в головах, а не в коде». Нет ограниченности. Есть нежелание применять.

Ко всем ли системам применима техника TDD? Есть «особые случаи» или «другие подходы»?

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

Что означает аббревиатура tdd в разработке по. Смотреть фото Что означает аббревиатура tdd в разработке по. Смотреть картинку Что означает аббревиатура tdd в разработке по. Картинка про Что означает аббревиатура tdd в разработке по. Фото Что означает аббревиатура tdd в разработке по

Есть что-то что можно выкинуть из TDD, есть что-то что можно привнести. Но в целом, TDD остаётся и гарантирует отсутствие паники. Panic-Driven Development исключается.

Что привело Вас к TDD?

Нужда. По мере роста сложности системы мы поняли, что «делаем одно», «отваливается другое». Тогда тесты стали необходимой составляющей. Мы к ним пришли эволюционно, но все к этому рано или поздно приходят. Также эволюционно перешли и к TDD. Внезапно оказалось. Что тесты не только полезно, но и удобно. Не надо инфраструктуру настраивать каждый раз. Написали тест, окружение для отладки готово, запускай этот тест хоть миллион раз. Так что кто уже «почувствовал» — welcome to TDD.

Что по-Вашему может быть лучше, чем TDD?

BDD. Есть люди в мире Delphi, которые этим занимаются и пропагандируют. Роман Янковский над этим работает. Ну и Fit-таблицы. Если есть желание развиваться, то можно до много самому дойти. Либо воспользоваться полунамёками, отрывочными статьями, википедией (в крайнем случае). Но сегодня я рассказал о реально работающем процессе. В деталях пишу в своём блоге, но общение с аудиторией доказало (выходя за рамки читателей), что главная проблема именно в понимании ценности TDD. Об этом сегодня попытался рассказать.

Ничего, что часть вопросов прозвучала как «троллинг»?

В жизни и не такое случалось, когда внедряли TDD в производственный процесс. Нормальная реакция.

Источник

За счет чего TDD “драйвит” разработку

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

Поэтому я не хотел писать еще одну статью с описанием техники Red-Green-Refactor. Мне хотелось взглянуть на TDD немного глубже и описать, как и почему TDD влияет на поведение человека.

В статье речь пойдет о неких абстракциях, которые применимы на разных слоях мировоззрения и, вне зависимости от контекста, помогают достигать хорошего результата. Универсальность этих абстракций и факт, что они применимы даже к процессу написания кода, сделали меня ярым приверженцем как TDD подхода, так и этих абстракций.

Мои первые шаги в TDD

Я работаю web-разработчиком 12 лет, и недавно я поменял свой базовый стек с php (CMS-ки) на javascript (React). Немного обидно и, для кого-то, удивительно, но познакомился с TDD я совсем недавно (в этом году), хотя многие из статей, которые я читаю, датируются далеким 2013 годом. Еще интереснее то, что познакомило меня с TDD не рабочее окружение или корпоративные стандарты, а Скрамгайд и самостоятельная подготовка к сертификации Professional Scrum Developer на scrum.org.

И вот в какой-то момент я оказался один на один с целью прочитать книгу “Test Driven Development: By Example” от Kent Beck. В тот момент у меня было некое понимание, что такое TDD, и оно преимущественно совпадало с коллегами, которые также что-то слышали о нем, но толком не пробовали. В двух словах, я думал, что “TDD — это те же самые юнит тесты, только написанные до имплементации”. Звучит немного отпугивающим и сложным, но мне понравилась идея. И я начал читать…

В районе 50-ой страницы ко мне пришло озарение, насколько ложным и неправильным было мое прежнее понимание. Тесты, написанные при TDD, — это другие тесты, категорически и совершенно другие тесты… по их логике, по их коду, по их смыслу. Если вкратце, то такой тест не должен соответствовать и проверять требование задачи, его цель — проверить только следующий маленький шаг, которые разработчик собрался реализовать в ближайших строках кода в следующие 2–5–15 минут. Пример, как это может выглядит — Example of TDD by H. Koehnemann, и обратите внимание, что acceptance test пишется уже в самом конце.

Но это не все. Я осознал, что TDD базируется на тех же психологических принципах и лайфхаках, которые я уже использую в своей работе и своей жизни. И я начал об этом говорить с коллегами, а позже родилась мысль написать об статью о механиках, которые лежат под капотом TDD и объясняют, почему TDD стимулирует (драйвит) разработку кода на ментальном уровне.

Верхнеуровневый список задач (todo list)

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

Кент Бек на протяжении всей книги описывает этот процесс, как неотъемлемую его часть. И эта идея совершенно не нова. По меньшей мере, этот подход описывается как базовая составляющая менеджемент-системы GettingThingsDone. GTD утверждает, что уровень стресса резко уменьшится, а продуктивность возрастет, если человек освободит свой разум от запоминания текущих задач, перенесет их на внешний носитель и сфокусирует полную силу своего сознания на конкретную текущую задачу.

Если человек не фиксирует мысли/задачи в списке, а держит (пытается держать) их все в голове, это делает его менее сообразительным, более раздражительным, у него создается ощущение бурной активности (“ничего не успеваю”, “белка в колесе”), а ресурсы мозга в этот момент утекают с повышенной скоростью и впустую. Все это приводит к более скудным результатам и психологическому выгоранию.

Внезапно появилась новая гениальная идея? Не переключайтесь на неё, отправьте её в список. Потом к ней вернётесь.

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

Test-First Thinking

Test-first мышление — это уже нечто большее чем техника — это сдвиг в видении задач и подхода к их решению. Обычно, перед началом имплементации, разработчик задается вопросом “как я реализую эту функцию?”. Основная идея test-first подхода в том, что такой вопрос смещает фокус с задачи на имплементацию этой задачи. Это смещение может привести к выстраиванию “воздушных замков”, излишней преждевременной оптимизации, нарушения принципа о простоте из Agile манифеста, не говоря о конкретных YAGNI и KISS правилах разработки. Но даже если этого не произойдет и код не будет нарушать эти принципы, это все равно не ответит на вопрос “как я узнаю, что я действительно достиг своей цели?”.

Измерение достижения цели — это то, что делает цель целью. Без измерения это уже не цель, это только желание, неформализованная хотелка. Бывало ли у вас, что вроде бы все шаги сделаны, а понимания, что желаемое получено, — нет, и удовольствие от достижения цели отсутствует? Это происходит тогда, когда не были зафиксированы критерии достижения цели. Когда в процессе деятельности понимание цели видоизменилось, желание рассеялось, и возможно, цель вообще прошла мимо первоначальной её постановки. Это расстраивает, демотивирует. Потому что человеку крайне необходимо созерцать результаты своей работы, которые приводят к выбросу эндорфинов и мотивируют двигаться дальше (Что создаёт нам хорошие ощущения от работы).

И это именно то, что означает литера M в аббревиатуре S.M.A.R.T. постановке целей.

Но есть путь, который позволит избежать этой ловушки — Test-First Thinking. Не задавайтесь вопросом об имплементации. Спросите себя “Как я смогу кому-то продемонстрировать выполненную задачу?”, “Как я могу протестировать, что все выполнено правильно?”, “Как я узнаю тот момент, когда работа сделана?”. Вопросы такого типа провоцируют дополнительные мыслительные цепочки, которые позволят схватить нюансы, которые обычно теряются при мыслях только о реализации. Это поможет отделить зерна от плевел и более четко определить, что на самом деле нужно, а что сейчас избыточно. Это сместит фокус с написания кода на достижение результата, что в конечном счете и приводит чувству удовлетворения.

Понятная задача

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

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

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

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

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

Правильное наименование

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

1. Тест должен звучать как ответ на вопрос “Что делает” в полной формулировке, как будто задача уже сделана и является спецификацией для другого человека. Ведь если отвлечься, то мозг выпадет из контекста и понять, что надо сделать, уже тяжелее;

2. Название теста должно начинаться с глагола.

Эти правила опять же из описания GTD. Конкретно я об это почерпнул из Джедайских техник М. Дорофеева (Глава 3).

Прерывания

Сейчас (и уже давно) принято считать и громогласно говорить о высокой стоимости прерывания разработчика от рабочего процесса. Обычно речь идет о воздействии менеджеров на мыслительный процесс программиста. Например, THIS IS WHY YOU SHOULDN’T INTERRUPT A PROGRAMMER и The Cost of Interruption for Software Developers.

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

Как бы там ни было, если все описанные ранее приемы применяются, то в любую секунду разработчик может легко прерваться. Ведь достаточно просто запустить тест. Потому что последний (единственный) упавший тест назван исключительно с указанием, что должен сделать разработчик, в простой, понятной формулировке с использованием глагола “что делает” следующий (еще не написанный) кусок кода.

Отсюда вытекает очень интересный и эффективный трюк — завершайте работу на красном тесте (вечером, на обед, перед встречей). Каждый раз, возвращаясь к работе, это позволит практически моментально вернуться в контекст задачи одной командой.

Научение через обратную связь

Человек не может учиться эффективно без получения обратной связи на его действия. Это базовый психологический момент природы человека в принципе (Как стать лучшим в своем деле? — А. Курпатов) и это же наиболее эффективный способ обучения.

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

Тест coverage

Представьте, разработчик дописывает последние строки кода имплементации, и … все. Работа сделана. Ему не надо заставлять себя писать тесты на то, что по его твердому убеждение безоговорочно работает. Потому что все тесты уже написаны. Это сохраняет ресурс силы воли, который достаточно ограничен и применение которого потребляет еще и приличное количество ментальной энергии.

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

Рефакторинг

Я не буду уделять много внимания на вполне понятный профит для рефакторинга при наличии качественных автотестов (Начинаем писать тесты (правильно) — Кирилл Мокевнин [Хекслет]). Это действительно сильно уменьшает дискомфорт и страх и позволяет разработчику более удобно и легко перелопачивать уже написанный код. Но про это говорится почти всегда, когда речь заходит про TDD, и, честно говоря, в контексте рефакторинга я не вижу большой разницы между TDD и тестами, написанными после имплементации.

Дисциплинированный разработчик

На мой субъективный взгляд, самая ключевая ценность TDD в том, что при его использовании разработчик неосознанно использует классические приемы самоуправления применительно к процессу написания кода. А это, определенно, требует дисциплины. Конечно, любой может быть организованным в работе, вне зависимости от использования TDD. Но тот, кто использует TDD в правильной интерпретации, автоматически будет организованным и дисциплинированным хотя бы применительно к написанию кода. Я считаю это очень важной характеристикой в текущее время печенек и PS-ок в офисе (до 2020) и удаленной работы в 2020.

Минусы TDD

Простите, но в контексте вышеописанного я их не вижу.

Я поизучал самые популярные холиварные топики вокруг TDD и пришел к выводу, что есть две основные причины нелюбви к TDD со стороны профессиональных разработчиков:

Разный формат мышления при подходе к реализации задачи. Часть предпочитает строить верхний слой полного решения, а потом спускаться на нижние уровни и к детальной имплементации мелких функций, держа в голове весь алгоритм для всех кейсов. Если вы относите себя к таким людям, то, вероятно, TDD вам с первых попыток не понравится.
Но, лично в моем случае, такой подход является контр-продуктивным. Мне просто не хватает силы сознания держать в голове так много требований, ветвлений алгоритма и самих переменных/объектов, что приводит к ошибкам и плохому решению. Обдумывая верхний уровень, я, если не ленюсь, то не код пишу, а выписываю/рисую список шагов, прикидываю, что я мог забыть, и определяю ближайшие шаги.

Принуждение к TDD. Часть разработчиков подвергалась давлению и принуждению к использованию TDD. В случае неиспользования их оценивали как “недо-программист”. Это конечно ужасно, но я пишу эту статью в совершенно зеркальных условиях, когда попытки применять TDD воспринимается коллегами как нелепость и непрофессионализм (ведь я же не могу держать в голове все ветвления логики, кейсы, объекты).

Да никакого итога. Мысли вслух. Скомпоновал как смог.
Если кто-то нашел в этой статье пищу для размышлений, то я доволен. Стремление к горстке признания это ведь так по-человечески.

P.S. (добавлено)

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *