Як зробити рефактор, коли весь ваш розвиток відбувається на галузях?


24

У моїй компанії вся наша розробка (виправлення помилок та нові функції) здійснюється на окремих відділеннях. Коли він закінчений, ми відправляємо його QA, який тестує його на цій гілці, і коли вони дають нам зелене світло, ми об'єднуємо його в нашу основну гілку. Це може зайняти десь від дня до року.

Якщо ми спробуємо втиснути будь-який рефакторинг на гілку, ми не знаємо, як довго це буде "поза", тому це може спричинити багато конфліктів при його об'єднанні назад.

Наприклад, скажімо, що я хочу перейменувати функцію, оскільки функція, над якою я працюю, сильно використовує цю функцію, і я виявила, що її ім'я не дуже відповідає його призначенню (знову ж, це лише приклад). Тож я обходжу і знаходжу кожне використання цієї функції, і перейменую їх на нове ім'я, і ​​все працює чудово, тому я відсилаю його до QA.

Тим часом відбувається нова розробка, і моя перейменована функція не існує в жодній із гілок, які відхиляються від основної. Коли мою проблему знову об’єднають, вони все порушаться.

Чи є спосіб вирішення цього питання?

Це не так, як менеджмент коли-небудь схвалює проблему, що стосується лише рефактора, тому її потрібно вирішити з іншими роботами. Це не може бути розроблено безпосередньо на основному, оскільки всі зміни повинні пройти через контроль якості, і ніхто не хоче бути ривком, який зламався головним, щоб він міг зробити трохи неістотного рефакторингу.


Який контроль версій ви використовуєте? Існують різні підходи для DVCS та моделі централізованого сервера. Крім того, з чого знімаються галузі розвитку? Якщо гілка функцій прийнята, як інші гілки розробників підбирають зміни?

2
Як осторонь, діаграма поточної структури розгалуження може бути дуже корисною. Цілком можливо, що корінь проблеми із труднощами з рефакторингом частково викликаний деякою ... нетрадиційною політикою розгалуження (див. Програмісти.stackexchange.com/ questions/210360 для одного такого прикладу). Я б також запропонував прочитати vance.com/steve/perforce/Branching_Strategies.html, щоб отримати деякі ідеї та передумови (якщо я зможу відповісти на це питання, що стане основним орієнтиром).

1
Останній абзац підсумовує це - якщо Бізнес не сприймає цінність, немає можливості, щоб основний рефактор міг продовжувати роботу. Вам потрібно співпрацювати зі своєю тестовою командою, щоб вирішити їх терміни. (Я підозрюю, що ваш QA справді є тестом на перетягування (вони надягають перуку та помаду і роблять вигляд, що вони не є). Справжня команда QA розповіла б вам, що робити рефактор, не заважаючи.)
mattnz

1
@mattnz: Ти абсолютно прав. Вони не справжня команда з якості. Вони в основному підтримують клієнтів. Я думаю, що багато їхніх обов'язків слід перекласти на команду Dev, тому що вони просто не можуть впоратися з усім, що ми на них скидаємо, але це питання управління та бій, який я ще виграю.
1313

3
Ти пропустив мій коп. Тест! = QA. QA контролює якість та має на меті покращити результати бізнесу. Тестові спроби довести відсутність дефектів шляхом їх пошуку.
mattnz

Відповіді:


12

Є кілька проблем, які поєднуються разом, щоб зробити рефакторинг складним у цьому середовищі. До цього приєднуються деякі нетехнічні проблеми ("але це питання управління та бій, який я ще виграв").

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

  • Коли код буде завершений - дайте йому ще раз (нехай служба підтримки клієнтів перегляне його, якщо вони хочуть), але злийте його швидко в розробку, щоб інші зміни, які залежать від нього, змогли бути підібрані, а зміни, що конфліктують, будуть виявлені рано в процесі.
  • Якщо з певних причин під час рефакторингу якийсь брекет стає тривалим, воно, як правило, є хорошою практикою зливатися зі стабільної у гілку, щоб отримати зміни та рефакторинг. Часто це мінімізує конфлікти та сюрпризи при злитті від функції функції у стабільну гілку.
  • Все тестування інтеграції потрібно робити на випусках, а не на функціях . У цьому середовищі функції можуть або не можуть бути повністю інтегровані в систему. Незважаючи на те, що можна перевірити цінність функції окремо, вона не визначає проблеми після випуску.
  • З моменту завершення коду для злиття (давайте називати його розвиватися - розгалуження від master / stable / release має власні проблеми не збору останніх змін в розробці) не повинно тривати занадто довго. Чим довше ви чекаєте, тим більше знань втрачається і тим важче інтегрувати код в інші рядки коду.

Ще одне питання, яке поєднується з цим, полягає в тому, що я натякав на вищезазначені моменти - це зміна ролі галузі з часом. Він починається як галузь розвитку, де розробники здійснюють зобов'язання, а потім стає тестовою областю (що тут робиться тестування, що може бути значимим у всій програмі?), Яка потім об'єднується в стабільну (і, імовірно, випущена - це знову перевірений?).

Якщо коротший час початку та закінчення функції, рефакторинг простіше мати можливість отримати інші гілки.

Заохочуйте розробників отримати все середовище. Просто зміни вишні можуть призвести до ... давайте говорити про цікаве середовище для розробників. Хоча збирання вишні має свої користі, тому що такий режим за замовчуванням втягування змін у гілку може викликати занепокоєння.

Рефакторинг - це те, що в ідеалі робиться постійно або якщо не постійно, коли є час простою. Відділіться, зробіть простий рефакторинг, запустіть одиничні тести, щоб переконатися, що все ще працює (його блок перевірений, правда? Так ? ), А потім з’єднайтеся назад у стабільний. Передайте інформацію іншим розробникам, щоб перетягнути ті зміни, які ви переробили у власні гілки.

Розробникам важливо володіти якістю коду. Хоча напрямок функцій надходить ззовні, а розподіл часу часто не є власним, якість коду - це те, чим потрібно пишатися і приділяти час.

Ви можете знайти наступні питання, корисні в пошуках виділення часу на вирішення технічної заборгованості:

Ви також можете переглянути такі інструменти, як sonar, які допоможуть визначити області коду, які потребують найбільшої роботи для рефакторингу. Плагін технічного боргу є те , що може бути використано для допомоги точки з накопичення боргу з плином часу в коді.

Часто доводиться зазначати, що рентабельність інвестицій для вирішення технічної заборгованості - це швидший час виконання функцій та виправлень помилок від команди розробників.


Тести, по суті, проводяться в три моменти часу. Одного разу, коли проблема заявлена ​​фіксовано (щоб переконатися, що вона відповідає всім вимогам і немає великих проблем), знову, коли вона об’єднана назад у стандартне (інтеграційне тестування), і знову, коли ми зробимо збірку (інтеграція з усіма вибраними вишнями) питання / остаточний перегляд). Я думаю, що збирання вишні необхідне в нашому середовищі, оскільки ми працюємо в SaaS з дуже конкретними клієнтами. Я перегляну ці посилання, дякую за покажчики! Редагувати: Насправді є ще один перегляд виробництва, щоб переконатися, що воно вийшло добре.
13

3

Зазвичай я розробляю реконструйовану версію "паралельно" з поточною, тобто в тій самій кодовій базі даних, але не посилаюся на неї з основним додатком. І коли нове рішення буде зроблено і протестовано, я починаю власне рефакторинг.

Приклад 1. Припустимо, що у мене є річ, нехай це буде функція, інтерфейс, модуль чи інше. І я хочу це переробити. Я створюю Thing2 в тій же кодовій базі, це відновлена ​​версія Thing. Коли це зроблено і протестовано, я переробляю все, що посилається на Thing, щоб замінити його на Thing2. Зазвичай цей крок займає порівняно невелику кількість часу.

Якщо фактичне рефакторинг потребує занадто багато часу, щоб синхронізуватись без команд накручування, я приймаю всі відповідні функції та паралельно їх рефакторинг.

Приклад 2. У мене є новий бекенд візуалізації, тобто відновлена ​​версія старої. Але він не сумісний зі старим фронтендом візуалізації. Таким чином, мені потрібно зробити рефакторний фронтенд. І знову: в тій же кодовій базі. Коли все буде зроблено, я просто змінюю клас примірника інтерфейсу, в ідеалі це займе одну коротку комісію.

Так, рекурсивно можна прийти до висновку, що все потрібно робити паралельно. Але зазвичай це трапляється, коли в кодовій базі занадто багато з’єднань, або вона змінюється занадто швидко.

Нарешті, коли новий код інтегрований і працює добре, старі функції можуть бути видалені з кодової бази, а нові функції можуть бути перейменовані для отримання старих імен.

Як правило, ідея полягає в тому, щоб паралельно підготувати нові функції та перейти до їх використання одним невеликим кроком.

Джон Кармак використовує такий (або принаймні подібний) підхід, можливо, його повідомлення в блозі пояснює це краще: (посилання)


Це хороший підхід. Я намагаюся згадати, що насправді спонукало це питання зараз… Я не думаю, що це було щось дуже прихильне до паралелізації. Або якщо це було, я думаю, що я занепокоєний тим, що такий підхід викликає багато фрагментації в кодовій базі. У нас є "старі способи" робити речі і "нові способи" робити речі, і старі речі замінюються льодовиковим темпом, але це заподіює головний біль розробникам, оскільки тепер вони, по суті, повинні знати дві (або більше) системи.
13

1

Це може виглядати як складність з технічної сторони, коли насправді це стоїть з вимогами.

Там, де розвиток орієнтований на різні вимоги в різних галузях, це реальна складність. Керівники та архітектори команди повинні приймати рішення, які можуть сприяти спільному існуванню різних потреб бізнесу.

Процес ZBB та Co-Dev "компромісують", коли вони зроблені після прийняття правильних рішень із відповідними вкладеннями від усіх розробників, повинні післямови дозволити вам реалізувати те, що вам потрібно, не замислюючись - Як злити свій код.

ZBB розраховує на нульове бюджетування . Сказавши Co-Dev, я мав на увазі мало людей, які працюють в паралельному програмуванні.


2
що таке "ZBB" та "Co-Dev"?
гнат

ZBB - en.wikipedia.org/wiki/Zero-based_budgeting . Сказавши Co-Dev, я мав на увазі мало людей, які працюють в паралельному програмуванні.
Йосі Дахарі

1

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


0

Ваша проблема - модель гілки, яку ви використовуєте. Ви можете розвиватися на гілці, і коли вона буде повністю готова до якості, гілка об'єднується з «проміжним стовбуром», який іноді називають інтеграцією або тестом. Коли ви розробляєте наступну функцію, ви можете замість цього відключитися від цього проміжного стовбура.

Ця модель дозволяє паралельно розробляти декілька функцій на різних гілках, об’єднуючи їх усі разом у гілку Інтеграції для надсилання до QA, а також підтримувати єдиний магістраль випусків (ви об'єднуєте базу коду QA, отриману до основного магістралі, коли вони її сертифікують )

Ви робите припущення, що ваші зміни, доставлені до QA, будуть передані без великих змін - якщо код QA повернеться з інструкціями щодо видалення половини змін, вам доведеться відновити, але якщо цього не відбудеться, це зробить ваш розвиток набагато плавніший. Таким чином, ви в основному знімаєте гілки для нових функцій від того, яким буде ваш основний код (тобто магістраль після об'єднання коду, переданого QA), а не того, який він є сьогодні (тобто поточний магістраль), і тому більше не розвивається на основі бази даних коду попереднього випуску .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.