Красный, зеленый, рефакторинг - почему рефакторинг? - PullRequest
13 голосов
/ 22 апреля 2011

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

Это не имеет смысла для меня, потому что, если тесты проходят, то почему вы возитесь с кодом?Я также вижу TDD-мантры типа «пишите только достаточно кода, чтобы пройти тест».

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

РЕДАКТИРОВАТЬ:

Я нашел эту ссылку в другом сообщении stackoverflow, которое, я думаю, подтверждает единственную причину, по которой я придумал, чтоисходный код для прохождения теста может быть очень простым, даже жестко закодированным: http://blog.extracheese.org/2009/11/how_i_started_tdd.html

Ответы [ 8 ]

28 голосов
/ 22 апреля 2011

Обычно первая рабочая версия кода - даже если не беспорядок - все еще может быть улучшена.Таким образом, вы улучшаете его, делая его чище, более читабельным, удаляя дублирование, находя лучшие имена переменных / методов и т. Д. Это рефакторинг.А так как у вас есть тесты, вы можете безопасно выполнить рефакторинг, потому что тесты покажут, что вы случайно что-то сломали.

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

Ваш вопрос - перефразировка старого ", если он работает, неисправить это ".Однако, как объясняет Мартин Фаулер в Рефакторинг , код может быть разбит по-разному .Даже если он пройдет все тесты, его будет трудно понять, поэтому его сложно расширять и поддерживать.Более того, если это выглядит неаккуратно, будущие программисты будут заботиться о том, чтобы поддерживать его в чистоте, так что он будет ухудшаться все быстрее и в конечном итоге превращаться в полный неразрывный беспорядок.Чтобы предотвратить это, мы проводим рефакторинг, чтобы всегда содержать код в чистоте и порядке, насколько это возможно.Если мы (или наши предшественники) уже допустили хаос, рефакторинг - это огромное усилие без очевидной немедленной выгоды для руководства и заинтересованных сторон;таким образом, их трудно убедить в поддержке масштабного рефакторинга на практике.Поэтому мы выполняем рефакторинг небольшими, даже тривиальными шагами после каждого изменения кода.

5 голосов
/ 22 апреля 2011

Я видел мантру: «красный, зеленый, рефакторинг».

это не «мантра», это рутина.

Я также вижу TDD-мантры типа «только пишите достаточно кода, чтобы пройти тест».

Это руководство.

теперь ваш вопрос:

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

Ты почти у цели. Ключ находится в части «Дизайн» TDD. Вы не только программируете, вы все еще разрабатываете свое решение. Это означает, что точный API может быть еще не установлен, и ваши тесты могут не отражать окончательный дизайн (потому что это еще не сделано). Хотя кодирование «достаточно только для прохождения теста», вы столкнетесь с некоторыми проблемами, которые могут изменить ваше решение и направить дизайн. Только после того, как у вас есть рабочий код, вы сможете его улучшить.

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

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

4 голосов
/ 10 мая 2019

Трудно понять, почему скептицизм ОП не оправдан.Рабочий процесс TDD коренится в предотвращении преждевременных дизайнерских решений за счет наложения значительных затрат, если не исключая, кодирования «сиденья штанов», которое может быстро перерасти в необдуманное сафари YAGNI. [1]

Механизмом такой отсрочки преждевременного проектирования является рабочий процесс «наименьший возможный тест» / «наименьший возможный код», который предназначен для того, чтобы избежать соблазна «исправить» предполагаемый недостаток или требование до того, как оно обычно потребуетсядолжны быть устранены или даже встречены, т. е. предположительно, этот недостаток будет (должен?) устраняться в каком-либо будущем контрольном примере, сопоставленном непосредственно с критериями приемлемости, которые, в свою очередь, охватывают конкретную бизнес-задачу.

Кроме того, испытания вПредполагается, что TDD а) помогут уточнить требования к дизайну, б) поверхностные проблемы с проектом [2], и в) послужат активами проекта, которые фиксируют и документируют усилия, приложенные к конкретной истории, таким образом заменяя собой самостоятельные усилия по рефакторингу дляправильно составленный тест не только исключает какую-либо проницательность, которую может дать тест, но также не дает руководству и планировщикам информации о реальной стоимости реализации конкретной функции. [3]

Соответственно, я бы предложилв новом тестовом примере цель, созданная для введения в проект дополнительного требования, является надлежащим способом устранения любых предполагаемых недостатков, помимо стилистических изменений в тестируемом коде, и фаза «Рефакторинг», как бы она ни была из лучших побуждений, летитвопреки этой философии, и фактически является приглашением сделать очень преждевременное сафари на дизайн YAGNI, которое TDD должен предотвратить.Я считаю, что версия 3 правил Роберта Мартина согласуется с этой интерпретацией.[4 - вопиющее обращение к власти]


[1] Ранее цитированный http://blog.extracheese.org/2009/11/how_i_started_tdd.html элегантно демонстрирует ценность отложенных проектных решений до последнего возможного момента.(Хотя, возможно, последовательность Фибоначчи является несколько искусственным примером).

[2] См. https://blog.thecodewhisperer.com/permalink/how-a-smell-in-the-tests-points-to-a-risk-in-the-design

[3] Добавление истории о технологиях или всплесках (пахнет или нет)отставание было бы подходящим методом для обеспечения соблюдения формальных процессов и документирования и обоснования усилий по разработке ... и если вы не можете убедить владельца продукта добавить его, то вам не следует тратить на это время.

[4] http://www.butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd

3 голосов
/ 22 апреля 2011

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

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

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

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

3 голосов
/ 22 апреля 2011

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

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

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

2 голосов
/ 01 апреля 2015

Итеративный, эволюционный рефакторинг - это хороший подход, но сначала ...

Что-то, что не должно остаться незамеченным ...

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

Чувствительная зависимость от начальных условий (Теория хаоса):

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

Энтропия:

Существует множество определений энтропии ;тот, который я считаю становящимся разработчиком программного обеспечения: Количество энергии в системе, которое нельзя использовать для дополнительной работы .Вот почему повторное использование имеет решающее значение .Энтропия встречается в основном с точки зрения дублирования логики и понятности.Кроме того, это тесно связано с Butterfly Effect (чувствительной зависимостью от начальных условий) и разбитыми окнами - чем больше дублирующейся логики, тем больше CopyPaste для дополнительных реализаций и больше1X за реализацию, чтобы поддерживать все это.

Переменная Усиление и демпфирование (Теория появления и теория сети):

Разрушение плохого дизайна - хорошая реализация, хотя кажетсявесь ад разваливается, когда это происходит в первые несколько раз.Вот почему разумно иметь архитектуру , которая может поддерживать множество адаптаций .Поскольку ваша система движется к энтропии, вам нужен способ, чтобы модули правильно взаимодействовали друг с другом - вот где вступает Интерфейсы . Если каждый из ваших модулей не может взаимодействовать, если они не согласились на согласованный контракт,Без этого вы увидите, что ваша система немедленно начнет приспосабливаться к плохим реализациям - и какое бы колесо ни скрипнуло, вы получите масло;другие модули станут головной болью.Таким образом, не только плохие реализации вызывают больше плохих реализаций, они также создают нежелательное поведение в System Scale - заставляя вашу систему в целом адаптироваться к различным реализациям и усиливая энтропию в самом высоком масштабе.Когда это происходит, все, что вы можете сделать, это продолжать исправлять ошибки и надеяться, что одно изменение не будет конфликтовать с этими адаптациями - вызывать возникающие непредсказуемые ошибки.

Ключом ко всему этому является превращение ваших модулей в их собственные,дискретные подсистемы и предоставляют Определенную архитектуру , которая может позволить им обмениваться данными, такие как Mediator .Это приводит набор ( Decoupled ) поведения в Bottom-Up System , которая затем может сосредоточить свою сложность в компоненте, предназначенном именно для него.

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

1 голос
/ 22 апреля 2011

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

0 голосов
/ 19 мая 2012

Во-первых, спасибо, что заглянули в Test Driven Development.Это удивительный метод, который можно применять во многих ситуациях кодирования, который может помочь вам разработать отличный код, а также даст вам уверенность в том, что код может и не может делать.

Если вы посмотрите на субтитры вОбложка книги Мартина Фаулера «Рефакторинг» также отвечает на ваш вопрос - «Улучшение дизайна существующего кода»

Рефакторинг - это преобразования в вашем коде, которые не должны изменять поведение программы.

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

...