چند سال پیش، وسط یک جلسهی مهم نشسته بودیم. سیستمی که چندین سال توسط یک تیم خیلی حرفهای و حساس به جزئیات توسعه داده شده بود، در شرایطی بود که داشت زیر بار میشکست. نه به خاطر اینکه بد طراحی شده بود. اون روزی که نوشته شده بود، بهترین راهحلهای ممکن با توجه به تکنولوژی زمان خودش براش استفاده شده بود. مشکل اینجا بود که سالها بهش اضافه شده بود، وصلهپینه شده بود، کارکرد بعضی ماژولها از ایده اولیه (که موقع طراحی در نظر گرفته شده بود) فاصله گرفته بود و بعضی تکنولوژیهای استفاده شده کاملاً از رده خارج شده بودند. این بدهیهای کوچیک، به آرامی روی هم تلنبار شده بودند تا تبدیل به کوهی شدند که جبرانش دیگه با ریفکتورهای ساده ممکن نبود. بازنویسی کامل تنها راه بود.
چیزی که از اون روز برای همیشه با من موند، این تجربه بود که حتی حرفهایترین تیمهای توسعه هم از بدهی فنی در امان نیستند. فرقی نمیکنه چقدر دقیق باشی یا چقدر به جزئیات اهمیت بدی، بدهی فنی بخش جداییناپذیر هر سیستم زندهای هست. خطر اصلی اون موقعیه که بدهیها پنهان بمونن، نادیده گرفته بشن، و کمکم به تهدیدی برای کل بیزینس تبدیل بشن.
این اتفاق برای تیمهای در حال رشد خیلی آشناست: یه روزی میرسه که همه چیزی که در دوران کوچیکبودن تیم ساخته شده دیگه کافی نیست، و مجبور میشن از صفر شروع کنن (با همهی هزینهای که این بازنویسی داره). سؤال اینجاست که آیا میشه قبل از رسیدن به اون نقطه، کاری کرد؟ یا حتی هزینه بازنویسی رو پایین آورد؟
من این پست رو برای کسایی مینویسم که توی تیمهای کوچک کار میکنن، منابع محدودی دارن، و هر روز بین «سریع deliver کن» و «درست بنویس» گیر کردن. هدفم این نیست که بگم هر فرد چطوری میتونن کد تمیز بنویسه. من میخوام بگم یک تیم خوب چطوری میتونه هزینههای بدهی فنی رو کم کنه.

بدهی فنی (Technical Debt) اولین بار توسط Ward Cunningham بزرگ (اسطورهای که در به وجود اومدن مفاهیم زیادی در حوزه توسعه نرمافزار موثر بوده) مطرح شد.
استعاره بدهی فنی خیلی ساده است: وقتی یه راهحل سریع و ناقص رو به جای راهحل درست انتخاب میکنی، داری قرض میگیری. مثل هر قرضی، اگه بازپرداختش نکنی، بهرهاش اضافه میشه.
اما یه نکتهی مهم که خیلیها نادیده میگیرن اینه: بدهی فنی همیشه اشتباه نیست.
گاهی اوقات انتخاب آگاهانهی یه راهحل سریع، درستترین تصمیم تجاریه. استارتاپی که باید تا آخر ماه محصول رو launch کنه، نمیتونه شش ماه صبر کنه تا معماری کاملش رو بنویسه. مشکل وقتی شروع میشه که:
بدهی ناخواسته باشه. یعنی ندونستیم داریم قرض میگیریم
بدهی انباشته بشه. یعنی هیچوقت بازپرداختش نکنیم
بدهی پنهان بمونه. یعنی تیم ازش خبر نداشته باشه
توی تیمهای بزرگی که بدهی فنی براشون مهمه، بدهیها در نهایت به چشم دستهای از آدما میاد و معمولا افرادی هستن که بهش رسیدگی میکنن. توی تیمهای کوچک، همه چیز روی دوش همون چند نفریه که همه کارها رو با هم انجام میدن، فیچر میزنن، باگ فیکس میکنن، سیستم رو بالا نگه میدارن و هزار تا کار دیگه. تست نویسی؟ به روز نگه داشتن داکیومنت سیستم؟ فککککر نکنم برای این جنس کارها فرصت کافی باشه.
چند تا ویژگی خاص تیمهای کوچک بدهی رو خطرناکتر میکنه:
چرخش و جابجایی نیروها context رو از بین میبره وقتی یه نفر از تیم میره، یه بخش بزرگی از دانش سیستم باهاش میره. کدی که «فقط علی میدونست چرا اینجوریه» میشه یه بمب ساعتی.
مستندسازی ضعیف بدهی رو پنهان میکنه توی پروژههای کوچک، معمولاً وقتی برای نوشتن داکیومنت نیست. بدهی فنی پنهان میمونه تا اون لحظهای که یه نفر میخواد یه تغییر ساده بده و میفهمه کل سیستم به هم وابسته است.
فشار deadline مدام کار درست رو به تعویق میندازه یه چرخهی معیوب شکل میگیره: بدهی فنی باعث میشه توسعه کندتر بشه، کندی توسعه باعث فشار بیشتر میشه، فشار بیشتر باعث میشه راهحلهای سریعتر و کثیفتری بنویسیم.
من این چرخه رو از نزدیک دیدم و حدس میزنم برای خیلی از کسانی که این پست رو بخونن آشناست.

قبل از مدیریت بدهی فنی، باید بدونیم بدهی توی کجاست. چند تا نشانهی واضح برای این کار هست:
نشانههای فنی:
بخشهایی از کد که همه ازشون میترسن («به اون فایل دست نزن»ها)
باگهایی که مدام برمیگردن
تستهایی که هیچکس نمیدونه چرا fail میشن
جاهایی که یه تغییر کوچیک، باگهای غیرمنتظره در جاهای دیگه ایجاد میکنه
نشانههای تیمی:
توسعهدهندههای تازهوارد برای onboarding خیلی وقت میبرن
هر feature جدید بیشتر از قبلی طول میکشه
جلسات برنامهریزی پر از «اول باید X رو درست کنیم تا بتونیم Y رو اضافه کنیم» هست
یه تکنیک ساده: نقشهی هزینه تغییر. برای هر ماژول یا سرویس اصلی سیستم، از همه بخواید جواب بدن: «اگه بخوایم این رو تغییر بدیم، چقدر طول میکشه و چقدر میترسیم؟» جاهایی که ترس بالاست و زمان تخمینی زیاده، بدهی فنی بیشتره.
اینجا میرسیم به اصل ماجرا. وقتی نه وقت هست، نه نیرویی که این قضایا رو مدیریت کنه، چیکار میکنید؟
«کمپ رو تمیزتر از وقتی که اومدی تحویل بده.»
هر بار که یه فایل یا ماژول رو آپدیت میکنی، یه چیز کوچیک رو هم بهترش کن. حتی اگه تغییر از این جنسه که یه تابع که اسمش گویا نیست رو rename کنی یا یه کامنت که دیگه صادق نیست رو پاک کنی، یا یک تست که جاش خالی بود رو اضافه کنی.
این یک رویکرد انقلابی نیست، ولی بهبودهای کوچیک با هم ترکیب میشن. بعد از چند ماه، بخشهایی که بیشتر بهشون دست زدی (و احتمالا اینها همون بخشهای هستن که بدهی فنی دارن)، تمیز میشن و اگر مشکلاتشون رفع نشده باشه هم، حداقل معلومه که کدهاش چیکار میکنن.
یه قانون ساده که جواب میده: بخشی از هر sprint رو به ریفکتور و پرداخت بدهی فنی اختصاص بدید.
هر بدهی فنی ارزش پرداخت هزینه فوری نداره. سؤال اینه: این بدهی الان داره چقدر به ما آسیب میزنه؟
اولویتبندی بدهیها بر اساس:
فرکانس تغییر: هرچی بیشتر بهش دست میزنیم، تمیزتر بودنش مهمتره
تأثیر روی performance: bottleneck های واقعی سیستم
ریسک: بخشهایی که اگه بشکنن، همه چیز به هم میریزه
یه backlog جداگانه برای بدهی فنی داشته باشید. هر بار که یه میانبر زده میشه، اون رو ثبت کنید. این کار دو تا فایده داره: اول اینکه چیزی فراموش نمیشه، دوم اینکه به مرور میفهمید کجاها بیشتر میانبر زده میشه.
این شاید مهمترین مهارت باشه. مدیرها به «بدهی فنی» واکنش نشون نمیدن، ولی به این جملهها واکنش نشون میدن:
«اگه الان دو هفته وقت بذاریم روی این بخش، سرعت توسعهی feature های بعدی ۳۰٪ بیشتر میشه.»
یا:
«این بخش از کد هر ماه یه بار باعث یه incident میشه. هر دفعه هم یک روز کاری وقت از تیم میبره که برگردیم به حالت عادی. با یه هفته کار میتونیم این رو حل کنیم.»
اعداد و تأثیر تجاری! اینا چیزیه که مدیرها میفهمن.
بدهی فنی فقط توی کد نیست. توی تیمهای کوچک، بدهی فنی توی این جاها هم انباشته میشه:
فرایندها: مثلا یه deploy process دستی که «فقط محمد بلده انجام بده»
دانش: تصمیمات معماری که هیچجا مستند نشدن
تستها: سیستمی که همه میدونن باید تست بیشتری داشته باشه ولی هیچکس وقت نمیکنه بنویسه
پرداخت این نوع بدهیها هم به اندازهی بدهی کد مهمه.
هدف از مدیریت بدهی فنی، صفر کردنش نیست. هیچ سیستم واقعیای بدون بدهی فنی نیست. هدف باید این باشه که کنترل روند توسعه دست خودت باشه، نه دست بدهی.
وقتی میدونی بدهیات کجاست، چقدره، و داری آگاهانه باهاش کنار میای، دیگه یه بمب ساعتی نیست. میشه یه item توی backlog که نوبتش میرسه. تیمهای کوچیک نمیتونن همه چیز رو یکجا حل کنن، ولی میتونن هر روز یه کم تمیزتر از دیروز باشن و بیشتر وقتها همین کافیه.
اگه این مطلب براتون مفید بود یا تجربهی مشابهی داشتید، خوشحال میشم توی کامنتها بشنوم.