Как мне справиться с рефакторингом, который занимает больше времени, чем один спринт?

49

Я работаю с кодовой базой, которая содержит более 500 тысяч строк кода. Он нуждается в серьезном рефакторинге. Были выявлены усилия по рефакторингу, которые займут больше времени, чем обычный двухнедельный спринт. Их нельзя разбить на более мелкие задачи, как я видел в других ответах на этом сайте. Продукт должен работать в конце итерации, и частичный рефакторинг оставит систему в непригодном для использования состоянии, поскольку зависимость между элементами ужасна. Так что будет лучшим способом преодолеть это препятствие? Я снова упоминаю, что разбить его на более мелкие кусочки - это уже не вариант, это уже сделано.

Обновление: Люди, кажется, нуждаются в объяснении того, почему это не вписывается в двухнедельный спринт. В спринте участвует больше, чем просто написание кода. У нас есть политика без кода без тестов. Такая политика не всегда существует, и большая часть кодовой базы не имеет их. Также некоторые из наших интеграционных тестов все еще являются ручными тестами. Проблема не в том, что сам рефакторинг настолько велик. Это связано с тем, что небольшие изменения влияют на многие части системы, и мы должны обеспечить правильную работу этих частей.

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

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

Ответ:

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

Чарльз Ламберт
источник
23
Как примечание стороны, это по определению масштабный редизайн, а не рефакторинг . Надеюсь, вы не воспринимаете это как придирку - ИМХО важно использовать четкую терминологию, чтобы избежать проблем со связью :-)
Péter Török
9
@Charles, «Рефакторинг обычно выполняется небольшими шагами. После каждого маленького шага у вас остается работающая система, которая функционально не изменяется». Цитируется на странице, на которую я ссылался выше.
Петер Тёрёк
2
@Charles: рефакторинг всегда можно выполнять постепенно, сохраняя работоспособность системы. поместите большой комментарий «Выполняется рефакторинг» вверху класса / пакета / модуля, который подвергается рефакторингу, и выполняйте части по одной за раз. Если вы отрежете промежуточную версию, пока объектная модель находится в переходном состоянии, это нормально.
Шон Макмиллан
7
Если вы делаете такие большие шаги, что у вас не может быть работающего фрагмента кода на регулярной основе, это и есть то самое определение, когда рефакторинг становится редизайном. Пожалуйста, не сердитесь на людей за то, что они назвали вас из-за неправильного использования этого слова. Нет ничего плохого в том, чтобы спрашивать о редизайне. Комментаторы просто пытаются указать, что вы не получите желаемых ответов, потому что неправильно используете слово, что уже произошло.
jprete
5
Я знаю, что это немного не по теме, но вы удивили меня тем, какие обстоятельства делают невозможным проведение рефакторинга небольшими шагами. Пожалуйста, поделитесь дополнительной информацией об этом.
Buhb

Ответы:

14

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

Buhb
источник
68

Мое предложение:

  1. Создать ветку
  2. Ежедневно сливайтесь из магистрали в свою ветку и разрешайте конфликты.
  3. Работайте, пока не закончите. Ваша ветка может находиться за пределами основного развития в течение нескольких спринтов.
  4. Сливаемся обратно в багажник.

Нельзя обойти стороной тот факт, что это, вероятно, станет безобразным. Я не завидую тебе. По моему опыту, когда вы радикально меняете проект, легче объединить текущую разработку в новую парадигму, чем каким-то образом объединить новую парадигму в измененную магистраль после того, как все будет завершено. Тем не менее, это будет больно.

Корбин Март
источник
1
Мы обсуждали использование этого подхода, и если другие идеи не появятся, прежде чем мы займемся этим, мы планируем это сделать.
Чарльз Ламберт
3
Боюсь, у вас будет много накладных расходов, сливающихся взад и вперед между стволом и веткой, если вы захотите провести такой тщательный рефакторинг.
Джорджио
В большинстве случаев (надеюсь) эти объединенные изменения не затронут рассматриваемый здесь код. Я не против продлить сроки этого изменения, если оно обеспечит надежный результат.
Чарльз Ламберт
1
Учитывая нестабильность, которую предлагает ваша презентация, возможно, вам следует рассмотреть Git , так как это облегчает спекулятивное разветвление и слияние.
Джон Тоблер
1
@ Джорджио: я тоже, ежедневное слияние кажется немного параноидальным, но тогда это действительно зависит от размера команды. Чем больше людей, тем больше изменений, и тем чаще вы должны объединяться. Ежедневно кажется нижним пределом, если вы хотите иметь время на работу.
Матье М.
40

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

Крис Кард
источник
3
Ваш ответ очень хорошая информация по теме. Я здесь, чтобы «встать и сделать это», как вы говорите. Я задал вопрос в надежде получить некоторую информацию, чтобы я мог придумать либо процесс, который будет работать параллельно моему существующему, либо каким-либо образом изменить текущий процесс, чтобы разрешить мою текущую ситуацию. Мне нужно что-то сказать разработчикам, чтобы у них были руководящие принципы для работы, поскольку это будет происходить как минимум еще 2 раза.
Чарльз Ламберт
+1 за «Процесс не более важен, чем конечный результат, и его следует рассматривать как ориентир, а не закон, который никогда не нарушать». - Люди действительно забывают об этом.
Бьярке Фрейнд-Хансен
32

Просто сделайте спринт на 3, 4 или 5 недель. Какая разница? Вы, очевидно, убеждены, что ничто не может быть сделано в более короткие сроки, поэтому прекратите бороться с этим.

Только не говорите своим товарищам в Королевском обществе слепой гибкой приверженности.

JeffO
источник
кажется, что по организационным причинам (ежемесячные исправления) спринты за 2 недели изменить довольно сложно.
Стив Беннетт
10

Я рекомендую начать с книги Майкла Фезерса « Эффективная работа с устаревшим кодом ». Он охватывает различные методы, чтобы уменьшить объем изменений в стиле рефакторинга.

kdgregory
источник
Конечно, хорошая книга, но я не думаю, что она охватывает разделение рефакторинга на несколько спринтов.
Адам Лир
4
Я собираюсь дать этому +1, потому что это, вероятно, лучшая книга для начала, когда вы начинаете учиться, как говорится в названии, эффективно работать с унаследованным кодом. Это относится к тому, кто может задать этот вопрос и не понять, что связано с разбиением вещей на более мелкие этапы.
Чарльз Ламберт
@ Анна - тогда, возможно, вы захотите (пере) прочитать главу 25, в которой рассказывается о методах разрыва соединений, которые предотвращают небольшие изменения.
kdgregory
@kdgregory Достаточно справедливо. :) Не могли бы вы добавить это к своему ответу, чтобы сделать его более удивительным?
Адам Лир
7

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

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

Эми Анушевски
источник
Это хорошая идея, но для ее реализации потребуется высокий уровень коммуникации. Например, когда я пишу код, если я идентифицирую метод, который нигде не используется, и он не является общедоступным, я его удалю.
Чарльз Ламберт
5

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

Карл Манастер
источник
Мы уже сделали все это. Именно по этой причине я ясно выразил, что это не может быть разбито.
Чарльз Ламберт
В самом деле? Вы потратили целый спринт, просто планируя, как провести рефакторинг, не ломая вашу систему, и ничего не придумали? Мне трудно поверить, что специальный спринт по планированию ничего не дал; может быть, вам нужно пригласить консультанта (и нет, я не один, не пытаюсь получить концерт).
Карл Манастер
1
Я не сказал ничего подобного. Я говорил, что мы прошли процесс, подобный тому, что вы описали, и на другом конце вышли с некоторым кодом, который нельзя реорганизовать за один спринт.
Чарльз Ламберт
Я сказал: «Посвятите один спринт, чтобы выяснить, как правильно поддерживать код в середине рефакторинга». Вы сказали: «Мы уже все это сделали». Вы сейчас говорите иначе? Мне очень жаль , если это звучит спорным, но я не понимаю.
Карл Манастер
5

+1 к ответу Корбина Марча, это именно то, о чем я думал. Похоже, ваша кодовая база немного уродлива, и для ее очистки потребуется не один цикл спринта.
Итак, как сказал Корбин,

  1. разделить его на «проект рефакторинга»
  2. проверить изменения в вашей ветке
  3. продвинуть в свою тестовую среду для тестирования качества
  4. постепенно объединяйте его обратно в магистраль, пока не будет выполнен рефакторинг.

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

bkdraper
источник
1
У меня есть все боеприпасы, которые мне нужны, чтобы уговорить всех. Мне просто нужен официальный план для его выполнения, когда я его представляю. Из ответов здесь я не сомневаюсь, что придумаю повторяемое решение.
Чарльз Ламберт
4

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

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

Мэтью Флинн
источник
3

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

Тем не менее, ИМХО должно быть возможно разделить рефакторинг на более мелкие истории, которые вписываются в 4-недельный спринт. Если вы не можете привести код в согласованное состояние в течение 4 недель, у меня возникает ощущение, что вы переписываете свое приложение, а не реорганизуете его.

Джорджио
источник
4-недельный спринт должен покрыть это. Однако мы не можем остановить текущий двухнедельный спринт из-за других исправлений ошибок и т. Д. Так что это должно было бы продлиться через более чем один спринт. Таким образом, суть моей проблемы.
Чарльз Ламберт
Как я уже сказал, мы используем 4-недельные спринты и, если история не закончена через 4 недели, мы просто планируем ее на следующий спринт. Можете ли вы по крайней мере привести систему в согласованное состояние в конце двухнедельного спринта (а затем продолжить во время следующего спринта)?
Джорджио
Не поддающееся проверке согласованное состояние.
Чарльз Ламберт
Я должен добавить свою волну к усилиям, предпринятым другими, чтобы надеяться, что вы найдете другое слово для использования, а не «рефакторинг». Рефакторинг четко определен, и его сфера гораздо более непосредственная и краткосрочная, чем масштабная и трудоемкая перепроектирование и перепрограммирование, которые вам необходимо выполнить.
Джон Тоблер
2

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

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

оборота IAbstract
источник
Мы не можем откладывать это навсегда, и ваш ответ не касается того, как выполнить рефакторинг.
Чарльз Ламберт
@Charles: «запланировано на другое время». ;) Я не сказал отменить проект.
IAbstract
2

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

Позвольте мне две небольшие заметки относительно других ответов здесь:

  • Ветвление поможет вам создать игровую площадку для себя, но никогда не объединяйте свои изменения в магистрали в один большой набор изменений. У вас будут серьезные проблемы с остальной частью команды.
  • Вы должны делать это постепенно, и это может быть сделано. Никаких оправданий. Прочитайте Работая эффективно с обложкой Legacy Code . Прочитайте это снова.
  • Думать, что вы можете сделать это одним большим шагом - заблуждение. Хотя это кажется более трудоемким, делать это постепенно проще в управлении.

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

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

Сделайте Scratch Refactoring и относитесь к нему как к такому. (Этакий рефакторинг прототипа «выбрасывается», бит «выбрасывать» важен!) Честно говоря, вряд ли вы знаете все последствия, которые будет иметь ваш рефакторинг. Рефакторинг царапин поможет вам в определенных отношениях:

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

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

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

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

Йоханнес Рудольф
источник
1

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

Кристофер Махан
источник
0

У нас под рукой два вида работ:

  1. Человеко-часовые работы
  2. Гениальные произведения

Рефакторинг обычно состоит из первого типа работы, так как разработчикам уже известны многие методы, такие как DRY , SRP , OCP , DI и т. Д. Таким образом, когда на рефакторинг проекта уходит два месяца, это просто занимает два месяца , то есть никак не обойтись. Таким образом, мое предложение состояло бы в том, чтобы не проводить рефакторинг исходного проекта, и позволить ему работать в его текущей ситуации. Прекратить получать новые запросы и требования от заинтересованных сторон и владельца продукта . Затем дайте команде поработать над проектом, пока он не будет переработан и готов к работе.

Saeed Neamati
источник
0

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

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

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

Джефф Григг
источник