Ми робимо проекти, але використовуємо багато кодів між проектами і маємо багато бібліотек, які містять наш загальний код. Коли ми реалізовуємо нові проекти, ми знаходимо більше способів виділити загальний код і помістити його в бібліотеки. Бібліотеки залежать одна від одної, а проекти залежать від бібліотек. Кожен проект та всі бібліотеки, що використовуються в цьому проекті, повинні використовувати однакову версію всіх бібліотек, на які вони посилаються. Якщо ми випустимо частину програмного забезпечення, нам доведеться виправляти помилки і, можливо, додавати нові функції протягом багатьох років, а іноді й десятиліть. У нас є близько десятка бібліотек, зміни часто охоплюють більше двох, і кілька команд працюють над декількома проектами паралельно, вносячи паралельні зміни у всі ці бібліотеки.
Нещодавно ми перейшли на git та налаштували сховища для кожної бібліотеки та кожного проекту. Ми використовуємо сховище як загальний сховище, робимо нові речі на гілках функцій, потім робимо запити на витягування та об’єднуємо їх лише після огляду.
Багато питань, з якими нам доводиться вирішувати проекти, вимагають зміни в декількох бібліотеках та конкретного коду проекту. Вони часто включають зміни інтерфейсів бібліотеки, деякі з яких несумісні. (Якщо ви думаєте, що це звучить риба. Ми взаємодіємо з обладнанням і ховаємо конкретне обладнання за загальними інтерфейсами. Майже кожен раз, коли ми інтегруємо якесь інше обладнання виробника, ми стикаємося з випадками, коли наші поточні інтерфейси не передбачали, і тому доводиться їх удосконалювати.) наприклад, уявіть проект з P1
використанням бібліотек L1
, L2
і L3
. L1
також використовує L2
і L3
, і також L2
використовує L3
. Графік залежності виглядає приблизно так:
<-------L1<--+
P1 <----+ ^ |
<-+ | | |
| +--L2 |
| ^ |
| | |
+-----L3---+
Тепер уявімо, що функція цього проекту вимагає змін P1
та L3
зміни інтерфейсу L3
. Тепер додайте проекти P2
та P3
в суміш, які також посилаються на ці бібліотеки. Ми не можемо дозволити собі переключити їх на новий інтерфейс, виконати всі тести та розгорнути нове програмне забезпечення. То яка альтернатива?
- впровадити новий інтерфейс у
L3
- зробіть запит на тягу
L3
та чекайте на перегляд - злиття змін
- створити новий випуск
L3
- почніть працювати над функцією
P1
, зробивши її посиланням наL3
новий випуск, а потім реалізуйте функцію уP1
відділенні функції - зробіть запит на потяг, перегляньте це та об’єднайте
(Я щойно помітив, що забув переключитися L1
і L2
до нового випуску. І навіть не знаю, куди це вставити, бо це потрібно робити паралельно з P1
...)
Це виснажливий, схильний до помилок і дуже тривалий процес реалізації цієї функції, він вимагає незалежних оглядів (що робить їх набагато складнішими для перегляду), зовсім не масштабує, і, ймовірно, може вивести нас із бізнесу, тому що ми так заграбувати в процесі, що ми ніколи нічого не зробимо.
Але як ми використовуємо розгалуження та тегування для того, щоб створити процес, який дозволяє нам реалізовувати нові функції в нових проектах без надто великих витрат?