В отчете State Of DevOps 2018 от DORA мы видим, что высокопроизводительные компании используют транковую разработку.
Давайте разберемся, почему так, какие преимущества и недостатки имеет данная модель.
Всем привет! Меня зовут Андрей.
Я консультант DevOps. Я работаю в Express 42, а также веду подкаст DevOps Deflope. И сегодня я расскажу о Trunk Based Development. Это дело очень сложное.
Я не уверен, что смогу объяснить все концепции и идеи, стоящие за этим, за 10 минут.
Почему эта модель лучше? Не буду обсуждать, лучше это или нет, потому что доказательства в индустрии уже есть:
- У нас есть Состояние DevOps , в котором ребята на основе статистики заметили, что результативность компании напрямую коррелирует с практиками и конкретно с Trunk Based Development.
- У нас есть книга Ускорение , который описывает, почему все работает именно так.
- У нас есть классный отчет три года назад от Google о том, что люди используют Trunk. В одном монопредприятии 25 000 человек.
- Вы также можете найти кучу статей Мартина Фаулера о том, как все это работает.
Мы хотим как можно быстрее проверить бизнес-гипотезы.
Мы хотим выдвинуть идею, протестировать ее, дать пользователям.
И Trunk Based Development идеально подходит для этого.
В чем суть магистральной разработки? Этот:
- Короткоживущие ветки.
У нас любая созданная ветка (кроме мастера) живет не более двух дней.
Два дня и все, Транка уже нет и все грустно.
Поэтому все ветки, кроме главной, например, релизная ветка или фича-ветка, живут не более двух дней.
- Флаги функций и ветвление по абстракции.
Об этом я расскажу вам чуть позже.
- Непрерывный анализ кода.
- А основная идея в том, что теперь мастер всегда готов к развертыванию, даже если он содержит недоработанные функции.
Он всегда готов к выпуску, и неважно, что в нем.
Давайте поговорим обо всех этих вещах.
Почему они хорошие? Все начинается с флагов функций.
Без этой вещи вы не сможете выполнить все последующие шаги.
В чем идея флагов функций? Дело в том, что теперь мы можем использовать ключ, чтобы сказать, какие функции мы включаем, а какие нет. Большинство функций заключены в флаги функций.
И когда мы запускаем наше приложение, мы говорим, что теперь наши пользователи могут покупать в один клик.
И таким образом мы можем проводить A/B-тесты и сливать в мастер те фичи, которые еще не готовы.
Что нам дает включение и выключение функций?
- Мы можем объединить и развернуть код, который еще не готов.
- Мы можем проводить A/B-тесты.
- Мы можем поискать код среди незавершенных функций.
В чем была проблема? У меня большой запрос на вытягивание.
Я сделал в нем кучу абстракций, полей в базе данных и так далее.
А они уже нужны в других функциях.
Но мы не можем использовать его повторно, потому что у меня еще не все готово.
И мы не можем это остановить.
И Trunk позволяет вам делать все это, потому что у нас есть флаги функций в качестве обязательного подхода.
Это самое сложное.
Именно здесь многие люди допускают ошибку.
У нас больше нет функциональных ветвей.
Это сложная концепция.
В чем идея? Мы больше не делаем ветки для функций, мы делаем ветки для изменения одной абстракции.
Например, у нас есть автомобиль, у него есть абстракция «передние колеса» и «задние колеса».
И мы хотим, чтобы эти колеса работали как-то по-другому.
Например, иметь другой тип колес и шин.
Как мы их изменим в случае с Trunk?
- Сначала мы создадим один запрос на включение и обернем колесо другой абстракцией.
Колесо будет вести себя так же, но оно будет скрыто за другой абстракцией, т. е.
мы сделали запрос на включение и объединили его.
- Следующий запрос на вытягивание.
Мы реализуем другое поведение для передних колес.
Мы добавили новую абстракцию.
Это отдельный запрос на вытягивание.
Они убили это.
В двух пул-реквестах мы создали абстракцию интерфейса, внутри нее создали новое поведение.
И здесь у нас уже есть Feature Flags, чтобы мы могли переключаться между новым типом колес и старым.
- У нас есть задние колеса.
Мы делаем то же самое.
Мы реализуем абстракцию интерфейса, которая позволит нам переключаться между колесами.
Внутри него мы заворачиваем логику выбора колес.
Мы делаем второй запрос на получение нового типа колес.
- Потом мы можем выпустить все это в прод и переключить Feature Flags на то, что теперь мы используем новые колеса.
- А при появлении новых пул-реквестов удаляйте старые.
И мы делаем пул-реквесты, чтобы изменить одну небольшую абстракцию.
Это ключевая идея.
И именно это делает Транка очень быстрым.
Что нам дает такой подход?
- У нас частые интеграции.
У нас была непрерывная интеграция в отрасли, куда мы приходили работать небольшими частями.
И это крайний вариант, т. е.
мы теперь все время работаем маленькими кусочками, даже микрокусочками.
- Мы можем реорганизовать наше приложение таким образом постепенно.
У нас нет такой ситуации, что надо переделывать все сразу.
Маленькие кусочки, маленькие итерации.
- И это позволяет нам быстро переключаться между задачами.
Например, мы делали одно дело, а теперь торопимся и нужно что-то исправить, мы можем спокойно заморозить то, что уже было, и переключиться на другую задачу.
Это ничего не сломает. Наш запрос на включение не будет потерян или забыт. И это легко проверить через 5 дней после написания, потому что они все маленькие.
- В чем идея подхода? Идея в том, что мы изменили небольшую абстракцию и сделали запрос на включение.
И в тот же момент кто-то еще начинает смотреть.
В тот момент, когда мы заканчиваем работу над своим изменением, мы смотрим на чужое.
То есть все коллеги постоянно наблюдают друг за другом.
- Поскольку наши запросы на включение очень малы, они меняют лишь небольшой фрагмент кода.
А наш обзор занимает пару минут. То есть пул-реквест не висит три дня, пока его кто-то не посмотрит, а потом ты еще что-то там поправишь и в итоге он висит не очень долго, а всего пару минут.
- На Trunkbaseddevelopment.com также отмечают, что если они смотрели пул-реквест 10 минут, то есть от создания до мержа прошло 10 минут, то это приемлемый результат. Не очень хорошо, но жить можно.
- Если пул-реквест висит больше часа, то на это нужно обратить внимание, здесь что-то не так.
Где-то у нас проблемы с подходом.
- Как и любой обзор, он дает нам возможность поделиться знаниями.
Все программисты понимают, как меняется код. Мы переиспользуем код, советуем друг другу лучшие практики и т. д. И делаем это постоянно, фактически каждые 10 минут, с каждой абстракцией.
- Вы можете использовать экстремальное программирование.
Когда два человека постоянно пишут код вместе, то ревью не нужно, ты его делаешь сразу.
Соответственно, вы уменьшаете эти долги, потому что мы все ищем.
- И мы ускоряем доставку.
Нам требуется несколько дней, чтобы подготовить запрос на включение.
Мы внесли изменения, они будут в проде через две минуты.
Это все очень и очень сложно.
Я уже несколько раз пытался поговорить о Транк.
И каждый раз у людей складывалось впечатление, что это что-то вроде Git Flow или GitHub Flow, но только проще, потому что не было пары-тройки лишних веток, поэтому Trunk Based Development — это очень просто.
Нет, это дело очень сложное.
- Во-первых, чтобы это сделать, у вас должно быть высокое тестовое покрытие.
Чтобы вы могли постоянно мерить все свои изменения в мастер и не бояться, что что-то сломается, нужно высокое тестовое покрытие.
- Флаги функций потребуют внесения изменений в инфраструктуру.
Теперь вам нужно использовать код и переменные, чтобы включить нужные вам функции.
И вам нужно написать код для ваших.
, ролей Ansible и т. д., чтобы вы могли им управлять.
- Ветвь по абстракции требует от вас навыков абстрагирования и декомпозиции задач, чтобы разбить их все на мелкие части.
По моему опыту общения с программистами, не у всех хорошо получается использовать практики SOLID. Если ваши программисты понимают SOLID, то, скорее всего, эта абстракция у них уже есть.
Потому что SOLID говорит нам: «Создайте объект и создайте вокруг него интерфейс абстракции».
Если у программиста с этим проблемы, то не взлетит и все это придется подкручивать.
Почему, несмотря на все эти трудности, мы приходим к выводу, что она лучшая? Потому что:
- Он имеет самые короткие итерации.
Когда за две минуты вносим изменение, за две минуты проверяем и мержим, а оно уже в проде, то это огонь.
- Мы можем развернуть все.
У нас нет блокировок, что в какой-то ветке не готова фича, мы все развертываем.
Мы делимся кодом и благодаря этому работаем быстрее.
- Обмен знаниями посредством непрерывного обзора, потому что все наблюдают за всем.
- И этот обзор занимает буквально несколько минут.
- https://www.youtube.com/watchЭv=Iq0Nm_cc0wo .
- https://speakerdeck.com/devopsmoscow/pochiemu-trunk-based-development-luchshaia-modiel-vietvlieniia .
- http://express42.com (Ссылка на сайт компании «Экспресс 42», где я работаю.
Возможно, мы сможем помочь вам с курсами, аудитами, проектами и т. д.).
- https://devopsdeflope.ru (Ссылка на подкаст DevOps Deflope, который мы с коллегой ведем).
- https://t.me/aladmit_world (Ссылка на Telegram-канал с новостями отрасли).
- https://t.me/devops_deflope (Мой личный канал, где я пишу обо всем, что приходит мне в голову).
Привет! Допустим, у нас есть команда, у которой вообще нет никаких процессов, то есть у нее нет даже Git Flow. Теоретически мы можем пропустить итерацию построения Git Flow и других процессов и сразу перейти к Trunk Based? И насколько это реально? Теоретически это возможно.
Развитие на основе ствола очень разнообразно.
Если вы не можете сразу перейти к ветвлению по абстракции прямо сейчас, вы можете использовать краткосрочные ветки.
Это похоже на ветки функций, только живут они очень недолго.
Один-два дня — это максимальное время жизни ветки с момента создания.
Вы можете начать с этого.
Можно сделать недолговечные ветки, а потом сверху все остальное.
Вы можете попробовать это.
Вы сказали, что для того, чтобы запрос на включение был принят, его должно увидеть достаточное количество глаз.
Обычно во время разработки у нас есть руководитель группы, который просматривает все, что поступает, и принимает единоличное решение о том, включать ли это в текущую ветку или нет. Как организовать пул-реквест, чтобы его посмотрели несколько человек и приняли решение? Вы голосуете? Вы можете сделать это по-разному.
Вы можете просто попросить любого коллегу посмотреть на это.
Следить за тем, чтобы TeamLead следил за всеми пул-реквестами — плохая идея, потому что теперь их у вас много, они очень частые и это становится узким местом.
То есть все-таки не мало людей смотрят? В компании это делается так.
За происходящим могут наблюдать несколько человек или один человек.
Но хоть кто-то должен посмотреть, иначе никакой пользы от ревью вам не будет, т. е.
ни совместного использования, ни мгновенного рефакторинга и т. д. Привет! Спасибо большое за отчет! Какого примерно размера должен быть проект? Должен ли это быть небольшой проект, микросервис, или эта идеология распространяется на проект любого размера? Абсолютно для любого.
По большому счету у вас в данном случае претензии к архитектуре.
Если вы сделали монолит по условному SOLID, и все абстракции нормально разделены, то проблем у вас не возникнет. Благодаря такому подходу, даже если изначально всё было сделано плохо, вы сможете постепенно реорганизовать его, шаг за шагом.
И при этом вы абсолютно не блокируете коллег своим рефакторингом.
Охватывается ли тестами работа Feature Flags? И сколько накладных расходов это покрытие вызывает при разработке и тестировании? Мы должны тестировать как вариант, когда функция включена, так и вариант, когда она отключена, иначе мы не поймем, ломаем мы прод или нет. Сколько накладных расходов? Здесь не очень понятно, как мерить.
То есть нужно ли писать тест дважды? Нужно написать для старой функции, нужно написать для новой функции? Нет, вы не пишете тест для старой функции, потому что вы ее уже написали.
Оно уже существует, да.
А для нового нужно писать.
А внутри пишут включилось и не включилось.
Да, внутри теста старой абстракции вы пишете «если включена новая функция», то эти тесты новые.
А еще – старый.
А ты гонишь и то и это.
Я не вижу здесь никаких накладных расходов, кроме добавления строки if, потому что у вас есть старые тесты и вы добавляете новые.
Спасибо за отчет! У нас есть большой проект. Мы занимаемся разработкой на основе соединительных линий уже год. Огонь.
Все в порядке, все работает. Только у нас есть СВН.
Итак, мы просто фиксируемся непосредственно в Trunk. И у нас нет запроса на включение, мы фиксируемся непосредственно в Trunk. Все здорово и хорошо.
Спасибо автотестам.
Но пришли новые люди и начали ныть: «Дайте нам Git Flow, у вас Trunk Based — это какой-то ужас».
И мы прогнулись и решили перейти на Git. И теперь у нас половина проекта в SVN, половина проекта в Git. Скоро весь проект будет в Git. И мне страшно.
Мне нравится разработка на основе ствола.
И я боюсь отказаться от этого.
Если мы перейдем от этой точки зрения, когда мы берем на себя обязательства непосредственно перед Trunk, к этой, не замедлимся ли мы? То есть, если Short-Living Branches будут не по фичам, а Branch By Abstraction, то это нас не замедлит? У вас есть один коммит к мастеру — это целая фича? Нет, у меня один коммит к мастеру — просто кто-то что-то написал и закоммитил.
Я понимаю.
Ветвь по абстракции, на самом деле только фиксация по абстракции? Да.
Если вы все-таки начнете оценивать друг друга, то это плюс две минуты на оценку кого-то.
Мы в Trunk смотрим на это и если что-то плохо, исправляем.
Тогда проблем быть не должно.
Если посмотреть тот же сайт Trunkbaseddevelopment.com, там написано, что если ты очень крутой, то можешь сразу идти к мастеру.
Но для этого нужно быть очень крутым.
Видимо ты крутой.
Привет! Спасибо за отчет! Я хотел спросить об этой картинке (Ветвь по абстракции вместо ветки функций).
Вы говорите, что над любой особенностью должна быть абстракция.
Почему же тогда он не останавливается на варианте 4? Если в следующий раз вам понадобится что-то изменить, вам придется дополнительно сократить эту абстракцию, как и на первом этапе.
Есть два варианта.
Есть вариант, когда мы оставляем эту абстракцию, и есть вариант, когда мы ее удаляем.
Каждый делает это по-разному.
Если мы посмотрим, например, блог Фаулера, он говорит, что давайте оставим эту штуку, давайте для всего будем иметь уровень абстракции или уровень интерфейса.
Это пример из Trunk Based Development, они объясняют это так.
Но можно оставить, можно убрать – не важно.
Но я бы все равно рекомендовал оставить это.
То есть мы убрали старый вариант, но оставили новый тип колес и абстракцию, посредством которой мы еще можем что-то с ним делать.
И у меня еще один вопрос по поводу Code Review. Очевидно, что когда в команду приходит младший разработчик, его Code Review вряд ли займет 10 минут, а PR — час.
Это может занять больше времени и может быть отклонено.
Что будет в таких случаях? Или вы вообще не берете в команду юниоров? Можете ли вы раскрыть вопрос? Когда за дело берется джуниор, ему нужно больше комментариев к коду и т. д. И, возможно, нужно внести какие-то исправления в пул-реквест. А вы говорите, что пул-реквест висит 10 минут, то есть за 10 минут его скорее всего не исправят. Что делать? Ваш юниор будет исключением.
10 минут – это еще приемлемый результат. Если больше часа, то считаем это плохим результатом.
Понятно, что Джуниору будет сложно.
Скорее всего, он все же поменял не те абстракции или пришел не из того места.
Для него придется сделать исключение.
Можно фото машины? Здесь вроде бы все ясно и хорошо.
Мы меняем только колеса.
А что, если это не автомобиль, а здоровенный космический корабль, состоящий из 50 150 деталей, которые изменяются одновременно? Хорошо, вернемся к этой машине.
У нас одновременно работает несколько команд, одни меняют поведение фар, другие поведение стекол, колес.
В конце концов, логичнее будет вместо красного тела иметь одну здоровенную абстракцию, а то мы и ее поменяем.
Не приводит ли это к какой-то сумасшедшей путанице с флагами функций, когда непонятно, как эти изменения должны взаимодействовать друг с другом? Потому что изменённое стекло, даже с абстракцией, не будет через кузов взаимодействовать с новыми колёсами и его абстракциями.
Я уже сам растерялся, пока объяснял.
Я понимаю.
Главный вопрос в том, что будет, если мы изменим кучу вещей одновременно.
Да, когда проект большой и изменений одновременно много.
Проблем не будет и вот почему.
Здесь у вас есть абстракция интерфейса, позволяющая менять колеса.
Вот абстракция, позволяющая менять фары.
Вот абстракция, позволяющая менять стекло.
Почему это не будет сложно? Потому что в каждый момент времени все ваши разработчики знают, что меняется.
Ваш разработчик отправляет сюда запрос на изменение фар, но он работает с самым актуальным кодом, потому что мы объединяемся каждые несколько минут. Так он видит, чем еще занимаются его коллеги.
И возможно они объединятся и создадут какой-то единый вариант абстракции или чего-то еще.
Когда кто-то отправит сюда запрос на включение, он увидит, что другие коллеги тоже что-то делают. Я вспомнил, что хочу провести опрос.
Поднимите руку, если вы уже слышали о Транк.
Неплохо, почти треть.
Кто использует его в своих проектах? 4 человека.
Мы в одной компании.
О, вы в одной компании, окей.
Большой.
Теги: #git #DevOps
-
Наркотическая Зависимость
19 Oct, 24 -
Биоэлектричество
19 Oct, 24 -
Уругвай
19 Oct, 24 -
Гейтс, Билл
19 Oct, 24 -
Как Мы Готовили Кристалл К Производству
19 Oct, 24 -
Прощай, Mongodb, Здравствуй, Postgresql
19 Oct, 24