Візуально привабливе зображення, що представляє «Від складних релізів до демонстрацій у продукції: впровадження Feature Flags з Growthbook».
В одному з моїх робочих досвідів ми зіткнулися з проблемою, яка, як мені здається, є досить поширеною в нашій сфері: великі та складні розгортання в продукцію, великі гілки з великою кількістю змін у файлах, важко читається та налагоджується, жахливі баги перед демонстрацією, через що гілка не могла бути випущена, змушуючи розробників проводити демонстрацію в локальному середовищі.
І все це при випуску одного проекту, а тепер уявіть, як це виглядає при випуску кількох проектів в одному кодовому базі, всі на самому кінці кварталу; після випуску, якщо є якийсь баг у продукті, який вплинув на інші частини програми або зробив її нефункціональною в певних областях, використання відкатів було досить поширеним.
До того ж складність продукту не допомагала, розробка та підтримка складних обчислень для векселів (IOU), місячних знижок, платежів, відсотків, податків тощо; було складно врахувати всі сценарії або баги, які можуть виникнути з кожним новим релізом чи функціональністю.
Враховуючи всі ці труднощі, ми з усіма знали, що щось потрібно змінити в тому, як ми проводимо релізи, і я згадав стратегію, яка змінила гру в попередній компанії, де я працював: використання Feature Flags.
Виклик.
Ілюстрація викликів у розробці програмного забезпечення.
{
"prompt": "Depict a cluttered digital workspace with tangled lines representing complexities, and broken code.",
"size": "1024x1024"
}
Було кілька складних моментів, коли я думав про впровадження Feature Flags у кодову базу, і виникли деякі питання з цього приводу:
- Який найкращий спосіб впровадити цю методологію в команду?
- Як ми можемо виміряти ефективність цієї зміни?
- Яка оптимальна стратегія реалізації?
Я виніс цю ідею на щомісячний інженерний форум, і вона отримала чудові відгуки, ідея сподобалась усім, але я не отримав подальших кроків після цього. Тоді я був відповідальний за доставку нового модуля на нашій платформі, що стосувався переоцінки векселів, і вирішив використати це як доказ концепції для Feature Flags.
Початок роботи.
Я не хотів витрачати багато часу на першу ітерацію Feature Flags, оскільки планував використати час з проекту переоцінок.
Отже, за допомогою Feature Flags вже в перший місяць проекту щось було в продукції, готове до тестування.
Ось що я зробив:
- Додав атрибут
JSONB
до моделіOrganization
, щоб визначити та активувати флаги функцій. - Використав гем StoreModel для чистої реалізації.
class Organization
attribute :feature_flags, Settings::FeatureFlags.to_type
end
Залежно від того, чи активний флаг функцій організації, з'являється модуль переоцінок. Я також протестував цю поведінку за допомогою RSpec.
З цими змінами ми могли постійно вносити оновлення до продукції та тестувати їх поступово. У день демонстрації функціональність була показана в реальному часі в продукції.
Часи великих гілок, які було важко зливати, та розгортань в останній момент залишились позаду.
Розгортання пройшло гладко, і зворотний зв'язок надійшов рано в процесі, що призвело до значних покращень у порівнянні з попередніми поставками.
Масштабування успіху.
Зображення, що представляє «Масштабування успіху» в контексті розробки програмного забезпечення.
{
"prompt": "Show a visual metaphor of progress, a team climbing a staircase.",
"size": "1024x1024"
}
Після успішного випуску модуля переоцінок і після зміни керівництва, ми вирішили зробити Feature Flags необхідними для кожної функції, над якою ми працюємо та випускаємо в продукцію, тому нам потрібно було реалізувати кращу версію Feature Flags, можливо, створити платформу, яка допоможе нам керувати цими флагами.
Чому Growthbook?
Пригадався Flipper, популярний Ruby-гін, оскільки наш Back-end стек був на Ruby on Rails, це мало сенс, але він не вирішував нашу потребу мати Feature Flags і на Front-end, хоча Front-end міг би перевіряти статус флагів з Back-end, це створювало б зайву залежність.
Ми подивилися на інший інструмент, який міг би керувати різними мовами та платформами, і знайшли Growthbook.
Нам сподобався цей інструмент, він має різні SDK, які можна використовувати з будь-якою мовою, з якою вам зручно працювати, і дуже легко зрозуміти, як він працює: веб-сервіс зберігає інформацію та правила для флагів функцій, а SDK відповідає за застосування цієї логіки в вашому застосунку.
Рішення з імплементації.
Трохи технічно, ми прийняли кілька цікавих рішень при впровадженні Feature Flags, для кращого контексту всі команди були:
- Вивчали, як працювати з Shape Up під час першої ітерації будівельного циклу.
- Ми мали демо середини циклу, яке було б чудово показати в продукції.
- Я був лідером іншої пітч-презентації, тому не міг витратити весь час на побудову Feature Flags, тому нам потрібно було бути ефективними при її реалізації.
І ми хотіли:
- Добрий досвід розробника при використанні Feature Flags.
З найкращою кривою навчання, яку ми могли отримати для всіх. - Надійна і підтримувана реалізація.
- Доступно для наших різних стеків і команд.
Через це ми прийняли різні рішення:
- Щодня проводили “office hours” опівдні, щоб відповісти на питання або допомогти інтегрувати Feature Flags в різні проекти, над якими ми працювали.
- Розподілили роботу між продуктами, я був відповідальний за додавання флагів у наші численні Back-end API.
- Інтегрували це в наші тести, щоб забезпечити надійність.
- Провели презентацію, щоб представити та пояснити Feature Flags іншим командам (Продукт, Customer Success, Керівництво тощо).
Реалізація.
Реалізація була простою, щоб забезпечити хороший досвід розробника, я хотів, щоб це було легко використовувати:
FeatureFlags.on?(:feature_flag_name)
Це був API, який я хотів реалізувати при інтеграції Feature Flags.
# app/services/feature_flags.rb
module FeatureFlags
class << self
def context
@context = Growthbook.new.context
end
delegate :on?, to: :context
end
class Growthbook
attr_reader :context
def initialize
@context = Growthbook::Context.new(
features: features_json,
attributes: {
org_id: Current.organization.id,
user_id: Current.user.id
}
)
end
private
def features_json
Rails.cache.fetch('features_json', expires_in: x.minutes) do
repo = Growthbook::FeatureRepository.new(
endpoint: ENV['envvariableforgrowthbookendpoint'],
decryption_key: nil
)
repo.fetch || {}
end
end
end
end
Працюючи пліч-о-пліч зі Staff Engineer, ми розробили цю структуру для інтеграції Feature Flags, ми тестували це на endpoint для перевірки здоров'я, який ми мали на той час.
Також, щоб інтегрувати це в тести, я використав RSpec helpers, реалізуючи хелпер, який допоміг нам мати таку ж інтеграцію в усіх специфікаціях.
# spec/support/growthbook_helpers.rb
module GrowthbookHelpers
def setup_growthbook_context(forced_features: {}, attributes: {})
context = Growthbook::Context.new(
features: forced_features,
attributes: attributes
)
end
allow(FeatureFlags).to receive(:context).and_return(context)
end
# spec/requests/any_request_spec.rb
RSpec.describe AnyRequest, type: :request do
describe 'Any acceptance spec' do
before do
setup_growthbook_context(forced_features: forced_features)
end
context 'when feature flag is on' do
let(:forced_features) { { my_feature_key: true } }
it 'makes something' do
# when FeatureFlags.on?(:my_feature_key) is called it will
# return true
end
end
context 'when feature flag is off' do
let(:forced_features) { { my_feature_key: false } }
it 'doesn\'t make something' do
# when FeatureFlags.on?(:my_feature_key) is called it will
# return false
end
end
end
end
Я горджуся тим, як ми інтегрували SDK для роботи з бібліотекою RSpec.
Зараз важко згадати точну реалізацію, але це було щось подібне.
Результати.
Результати були вражаючими.
Наприкінці цього циклу кожен проект був інтегрований з Feature Flags, і кожен проект був показаний в продукції, що раніше було неможливо.
Інший хороший факт: до впровадження Feature Flags ми часто робили відкат, коли щось ламалося в продукції, і нам потрібно було швидко відновити роботу.
До впровадження Feature Flags було зроблено близько 30–40 відкотів Pull Request. Через рік після впровадження та використання Feature Flags був лише один відкат по всіх продуктах, і це було через невдалу спробу оновлення версії Ruby on Rails, для чого дуже важко використовувати Feature Flags.
І з тих пір, як були введені Feature Flags, ми спостерігали зменшення кількості багів P0-P1, де P0-P1 — це баги, які безпосередньо впливають на кілька клієнтів або коли платформа не працює через велику функціональність. Варто зазначити, що інші реалізації, такі як чергування Oncall, також можуть допомогти знизити цю кількість.
Останні думки.
Концептуальне зображення, яке представляє «Останні думки» в контексті розробки програмного забезпечення.
Впровадження Feature Flags змінило наш процес розробки.
Ранній зворотний зв'язок допоміг нам краще сформувати функціональність, інкрементальні розгортання зменшили ризик і дали змогу випустити функціональність в продукцію, і все це зробило стратегію безцінною.
Чи ви колись впроваджували Feature Flags або працювали з Growthbook? Я б із задоволенням послухав ваші досвіди! Якщо ви хочете дізнатися більше або потребуєте допомоги, не соромтеся залишити коментар. Дякую, що прочитали!
Перекладено з: From complex releases to demos in production: Implementing Feature Flags with Growthbook.