В моей компании все наши разработки (исправления ошибок и новые функции) выполняются в отдельных ветках. Когда он будет завершен, мы отправим его в QA, который тестирует его в этой ветви, и когда нам дают зеленый свет, мы объединяем его с нашей основной веткой. Это может занять от одного дня до года.
Если мы попытаемся втиснуть какой-либо рефакторинг в ветке, мы не будем знать, как долго он будет «отсутствовать», поэтому он может вызвать много конфликтов при повторном объединении.
Например, скажем, я хочу переименовать функцию, потому что функция, над которой я работаю, интенсивно использует эту функцию, и я обнаружил, что ее имя не совсем соответствует ее назначению (опять же, это всего лишь пример). Так что я обхожу все случаи использования этой функции и переименовываю их все в новое имя, и все работает отлично, поэтому я отправляю его в QA.
Между тем происходит новая разработка, и моя переименованная функция не существует ни в одной из ветвей, которые разветвляются от основной. Когда моя проблема снова будет объединена, они все сломаются.
Есть ли способ справиться с этим?
Не похоже, чтобы руководство когда-либо одобрило проблему, связанную только с рефакторингом, поэтому ее нужно увязать с другой работой. Он не может быть разработан непосредственно на main, потому что все изменения должны проходить через QA, и никто не хочет быть тем придурком, который сломал main, чтобы он мог выполнить незначительный рефакторинг.
Ответы:
Есть несколько проблем, которые смешиваются вместе, чтобы сделать рефакторинг сложным в этой среде. С этим связаны некоторые нетехнические проблемы («но это проблема управления и битва, которую мне еще предстоит выиграть»).
Первая проблема, на которую стоит обратить внимание, это ветка с длительным сроком действия. Эти ветки испытывают трудности с отслеживанием изменений вне поля зрения разработчика. Для решения этой проблемы:
Другая проблема, которая смешивается с этим, заключается в том, что я упомянул вышеупомянутые пункты, это изменение роли ветви с течением времени. Он начинается как ветвь разработки, где разработчики фиксируют, а затем становится областью тестирования (какое тестирование здесь проводится, что может быть значимым для всего приложения?), Которое затем объединяется в стабильный (и предположительно выпущенный - действительно ли это проверено снова?).
С более коротким временем начала и окончания функции для рефакторинга будет легче быть замеченным другими ветвями.
Поощряйте разработчиков, чтобы получить всю среду. Простые изменения в вишне могут привести к ... скажем, интересным средам для разработчиков. В то время как вишневый сбор имеет свое применение, для этого быть режимом по умолчанию для внесения изменений в ветвь может быть беспокойство.
Рефакторинг - это то, что в идеале выполняется постоянно или, если не постоянно, когда происходит небольшое время простоя. Branch, выполните простой рефакторинг, запустите модульные тесты, чтобы убедиться, что все по-прежнему работает (его модуль проверен, верно? Верно? ), А затем объединитесь в стабильный. Передайте информацию другим разработчикам, чтобы те изменения, которые вы реорганизовали, перенесли в их собственные ветви.
Разработчикам важно владеть качеством кода. В то время как управление функциями происходит извне, а распределение времени часто не наше, качество кода - это то, чем нужно гордиться и уделять время.
Вы можете найти следующие вопросы полезными в поиске времени для решения технических проблем:
Возможно, вы также захотите взглянуть на такие инструменты, как sonar, которые могут помочь определить области кода, которые требуют больше всего работы для рефакторинга. Плагин технического долга является то , что может быть использовано для помощи точки из накопления долга с течением времени в коде.
Часто необходимо указать, что окупаемость инвестиций в техническую задолженность - это более быстрое время выполнения функций и исправлений ошибок от команды разработчиков.
источник
Обычно я разрабатываю реорганизованную версию "параллельно" с текущей, то есть в той же кодовой базе, но не ссылаюсь на нее из основного приложения. И когда новое решение сделано и протестировано, я начинаю реальный рефакторинг.
Пример 1. Предположим, у меня есть Thing, пусть это будет функция, интерфейс, модуль или что-то еще. И я хочу провести его рефакторинг. Я создаю Thing2 в той же кодовой базе, это рефакторированная версия Thing. Когда это сделано и протестировано, я рефакторинг всего, что ссылается на Thing, чтобы заменить его на Thing2. Обычно этот шаг занимает относительно небольшое количество времени.
Если для реорганизации рефакторинга требуется слишком много времени без синхронизации с командой, я использую все соответствующие функции и выполняю их рефакторинг параллельно.
Пример 2. У меня новый рендеринг, то есть реорганизованная версия старого. Но это не совместимо со старым интерфейсом рендеринга. Таким образом, мне нужно реорганизовать интерфейс. И снова: в той же кодовой базе. Когда все будет сделано, я просто изменю класс экземпляра веб-интерфейса, в идеале это займет один короткий коммит.
Да, рекурсивно можно прийти к выводу, что все должно выполняться параллельно. Но обычно это происходит, когда в кодовой базе слишком много связей или она меняется слишком быстро.
Наконец, когда новый код интегрирован и работает хорошо, старые функции могут быть удалены из базы кода, а новые функции могут быть переименованы, чтобы получить старые имена.
Как правило, идея состоит в том, чтобы подготовить новые функции параллельно и переключиться на их использование одним маленьким шагом.
Джон Кармак использует этот (или, по крайней мере, похожий) подход, возможно, его пост в блоге объясняет это лучше: (ссылка)
источник
Это может выглядеть как сложность в технической части, когда на самом деле это касается требований.
Где разработка ориентирована на разные требования в разных отраслях, это настоящая трудность. Менеджеры и архитекторы команды должны принимать решения, которые могут позволить сосуществовать различным потребностям бизнеса.
Процесс ZBB и Co-Dev «идут на компромиссы», когда они сделаны после принятия правильных решений с соответствующими предложениями всех разработчиков, после этого они должны дать вам возможность реализовать то, что вам нужно, не задумываясь - как мне объединить мой код.
ZBB означает нулевое бюджетирование . Говоря Co-Dev, я имел в виду мало людей, которые работают в параллельном программировании.
источник
Мне кажется, проблема в том, что вы слишком долго работаете на ветках. Стоимость конфликтов растет в геометрической прогрессии в зависимости от длины каждого ветвления, поэтому при очень длительных конфликтах у вас мало шансов выполнить рефакторинг.
источник
Ваша проблема - модель ветки, которую вы используете. Вы можете разрабатывать ветку, и когда она завершена и готова к обеспечению качества, ветвь объединяется в «промежуточный ствол», иногда называемый интеграцией или тестированием. Когда вы разрабатываете следующую функцию, вы можете вместо этого переходить от этого промежуточного ствола.
Эта модель позволяет параллельно разрабатывать несколько функций в разных ветвях, объединяя их все вместе в ветке интеграции для отправки в QA, а также поддерживать единый ствол выпусков (вы объединяете QA кодовой базы, полученный в основной ствол, когда они его сертифицируют). )
Вы предполагаете, что ваши изменения, доставленные в QA, будут переданы без значительных изменений - если код QA вернется с инструкциями по удалению половины изменений, вам придется вернуться, но если этого не произойдет, он произведет Ваше развитие намного более плавное. Таким образом, вы в основном берете ветки для новых функций, исходя из того, каким будет ваш основной код (т. Е. Транк после слияния в коде, переданном в QA), а не с тем, что есть сегодня (т. Е. Текущий транк), и поэтому больше не развиваетесь в сравнении с базой кода предыдущего выпуска. ,
источник