حرف زیادی ندارم. دیروز بعد از مدتها یک مقاله خوندم که تو ذهنم قشنگ کلیک خورد و بسی لذت بردم و یاد خاطرات قدیم افتادم.
یادمه سالها پیش تو شرکت حسابداری کار میکردم که مدیر بعد از مدتی تصمیم گرفت به جای مدیریت حساب سه سطحی (حساب کل، حساب معین و حساب تفصیلی) از سیستم شناور استفاده کنه. به این معنا که کاربر بتونه تا «هر تعداد» که دلش خواست سطح بسازه. اسمش رو هم گذاشتند تفصیلی شناور.
پیچیدگی کار اینجا بود که یک عالمه کوئری سمت SQL Server با ساختار تفضیلی سهسطحی نوشته شده بود و تمام جدولهای دیگه بر همین مبنا طراحی شده بودند.
بدیهیه همچین تغییری کل سیستم رو دربر میگرفت. و تقریباً تمام گزارشهای باید تغییر میکرد. سؤال این بود که چطوری این تغییر گسترده رو انجام بدیم؟
اتفاقی که اون زمان افتاد این بود که سورس رو جدا کردیم. خوشحال بودیم. مدیر گفت یک Branch روی Git بسازیم و همکارمون بره روش کار کنه.
گذشت و ماهها روی اون فیچر کار شد. انصافاً هم همکارم وقت خوبی روش گذاشت و خیلی کوئریهای بهینهای نوشت و خلاصه سنگتموم گذاشت.
اما یک مشکل مهم وجود داشت. کد رو دیگه نمیشد مرج کرد! هزاران هزار خط کد وجود داشت که Conflict خورده بود. و رفع کردن اون Conflictها خودش به اندازه پروژه و حتی بیشتر زمانبر بود.
شاید بگید که اون برنامهنویس وظیفهاش بوده که مرتب کدهای سمت ما رو Pull بگیره و مرج کنه ولی این هم در عمل امکانپذیر نبود؛ چون هر روز ما ناخواسته کارهایی میکردیم که باعث میشد Conflict پیش بیاد.
گذشت و اون کد تا اون زمان که من اونجا بودم مرج نشد! عملاً دو تا سورس داشتیم: سورس اصلی و سورس آقای فلانی.
بدیش هم این بود که ما به سیستم یک عالمه ویژگی دیگه اضافه کرده بودیم که تو سورس آقای فلانی نبود و مشتری هم میخواست! چه کثیفکاریای بود اینطور وقتها. این پروژه از همون اول هم واضح بود که حداقل یک سال طول میکشه.
تجربه شخصی من هم این رو میگه که هر چی یک Branch دیرتر مرج بشه، احتمال کانفلیکت خوردن و دوباره کاری بیشتر میشه.
همه این مقدمهها رو چیدم که بگم یک راهکار خیلی خوب برای موارد مشابه Feature Flag هست.
با این روش شما سورسها رو با هم مرج میکنید و همه برنامهنویسها با خوبی و خوشی در یک Branch زندگی میکنند و کدشون رو توسعه میدن.
فقط در جایی از کد یا یک فایل کانفیگ یا دیتابیس، تنظیم میشه که از کدوم بخش کد استفاده بشه. انگار در یک Git Branch هستیم ولی دو تا مسیر اجرایی داریم.
مثلاً:
# Simple feature flag example
FEATURE_NEW_GREETING = True # Turn the feature on/off
def greet_user(name):
if FEATURE_NEW_GREETING:
print(f"✨ Hello, {name}! Welcome to the new experience!")
else:
print(f"Hello, {name}.")
# Test it
greet_user("Alice")
شاید به نظرتون همون بیاد. ولی این که در سطح گیت کد از هم جدا بشه یا در یک کد زندگی کنیم و با If else و موارد مشابه جدا بشیم، خیلی فرق داره.
اولی شاید هیچ وقت به مرحله پروداکشن نرسه. اما دومی هر چند ممکنه سالها هم طول بکشه ولی چون سورس جدا نشده، «امکان» اضافه شدنش به کد هست.
نمیدونم. شاید به نظر بدیهی بیاد اما اون زمان به فکر هیچ کدوممون نرسید و اگر هم میرسید احتمالاً فکر میکردیم کثیفکاریه.
این که یک روشی اسم داره و هزاران نفر راجع بهش صحبت کردند و استاندارد و Best Practice براش درآومده باعث میشه که نسبت بهش مقاومت کمتری وجود داشته باشه.
خلاصه همه این حرفها رو نوشتم بگم که اگر میخواهید راجع به این قضیه بیشتر بدونید، مقاله زیر رو از دست ندید.
من که از خوندنش بسیار لذت بردم. امیدوارم شما هم ببرید.
اگر مطالب بالا رو خوندید و دوست داشتید شاید این ویدئو و نوتهای مرتبطش هم براتون جالب باشه.