در یک بار دنج در حومهی کاتانیا (ایتالیا)، جایی که صدای برخورد لیوانهای ویسکی با مکالمات آرام در پسزمینهای هماهنگ ترکیب شده بود، پیرمردی به من گفت: «بهترین نوشیدنی، جدیدترین بطری روی قفسه نیست؛ بلکه آن است که به اندازه کافی قدیمی شده باشد.» حالا، شاید او واقعاً مست بوده و حتی یک کلمه انگلیسی بلد نبود، و البته این یک داستان خیالی است، اما نمیتوانم از ایجاد یک شباهت با دنیای دائماً در حال تغییر کدنویسی و نوآوریهای فناوری صرفنظر کنم؛ نیاز دائمی ما به بازنویسی.
یک مفهوم جالب در بودجهبندی وجود دارد — «پول کهنه» (Aging Money)، که راهحلی است برای ایجاد پایهای مالی محکم و رهایی از زندگی حقوق به حقوق:
یک دلار روزی متولد میشود که وارد زندگی شما شود. فرض کنید جمعه صبح در راه کار هستید. نمیتوانید برای ماشین بنزین بخرید، اما بعد از ظهر حقوق میگیرید، بنابراین در راه برگشت این کار را انجام میدهید. حقوق میگیرید، چک را نقد میکنید و باک را پر میکنید. وقتی بنزین میزنید، در واقع پولی را خرج میکنید که تازه ۱۵ دقیقه است وارد زندگی شما شده است. به محض ورود، پول در حال خروج است. این وضعیت بلافاصله عدم اطمینان ایجاد میکند. شما باید به نقطهای برسید که پول برای مدتی قبل از اینکه خارج شود، در حساب بماند.
حالا بیایید این موضوع را کمی سادهتر کنیم. ایده این است که ابتدا قدیمیترین پول موجود در حساب خود را خرج کنید. این سیستم، هرچند در فرهنگ مصرفگرایی فوری ما ضدشهودی به نظر میرسد، یکی از اصول اساسی ثبات مالی است. این کار به شما یک حائل برای مواقع اضطراری میدهد، جریان نقدی شما را هموار میکند و به شکل یک پسانداز برای سرمایهگذاریها، پایداری مالی را فراهم میکند. در اینجا پول قدیمی > پول جدید.
من میخواهم این مفهوم را یک قدم جلوتر ببرم — قدیمی بهتر است.
در جستجوی پایههای محکم، مهندسان نرمافزار اغلب در چرخه نوآوری گرفتار میشوند، که به جای ایجاد ثبات، ساختارهای پیچیده ایجاد میکند. خرد ساختن بر اساس اصول اثباتشده را بپذیرید تا هم در مالی و هم در کد انسجام داشته باشید.
البته، جاذبه چیزهای جدید اغواکننده است. این جاذبه با وعدهی امکانات هیجانانگیز و هیجان پیشرو بودن همراه است. چه کسی دوست ندارد جدیدترین فریمورک را پیادهسازی کند، آخرین سر و صداهای توییتر (یا ایکس، یا هر چه اسمش باشد) را دنبال کند، یا آن مدل GPT جدید را امتحان کند؟ اما، مثل هر نوع مستی، یک خماری هم در انتظار است. در جستجوی چیزهای جدید، اغلب ارزش آنچه که آزمون زمان را پس داده است، نادیده میگیریم.
این موضوع برای اخبار هم صدق میکند. همه ما میدانیم هر روز جهنم یا شگفتی تازهای گزارش میشود. اما یک راز وجود دارد: چیزهایی که واقعاً اهمیت دارند؟ آنها عمر طولانیتری دارند. آنقدر اتفاقات هر روز رخ میدهد که موضوعات مهم — همانهایی که در ۵ سال آینده به یاد خواهید داشت — همچنان فردا یا هفته آینده هم مهم هستند. شما وقت کافی دارید تا آنها را بخوانید، هضم کنید و دربارهشان فکر کنید. اینها مانند شیر خراب نمیشوند؛ بلکه مانند شراب، با گذشت زمان طعم و عمق جدیدی پیدا میکنند و با روشن شدن زمینههای بیشتر، پیچیدگیهای بیشتری به دست میآورند.
این موضوع برای کدنویسی هم صدق میکند. کتابخانههای جدید. زبانهای جدید. فریمورکهای جدید. کارآموز جدیدی که میآید و فکر میکند میتواند بخشهای مختلف کد را بهتر بازنویسی کند. راحت است که در این مسیر گرفتار شویم. اما آیا جدیدترین فریمورک همیشه بهترین انتخاب است؟ آیا بازنویسی واقعاً همه چیز را بهتر میکند؟ یا در کدی که سالهاست وجود داشته، با موارد غیرمنتظره آزمایش شده و همراه با کسبوکار تکامل یافته است، خردی نهفته است؟
وقتی به دنیای فناوری اطلاعات وارد میشویم، جایی که سیستمها سریعتر از شراب سیسیلی اتاقم پیر میشوند، زیبایی و مزیت پایگاههای کد بالغ را بررسی میکنیم و اینکه چرا گاهی بهتر است کد را همانطور که هست نگه داریم و فقط… کمی آرام شویم.
حکمت کدهای قدیمی
چرا باید به فکر پیر شدن کدهای خود باشید؟ چون هرچه کد شما بیشتر دوام آورده باشد، از بحرانهای مختلف (بخوانید: تغییرات اساسی کسبوکار) جان سالم به در برده و تکامل یافته باشد، قویتر و مقاومتر خواهد بود. تیمی که پیش از شما آن را نوشته است، زمان کافی برای دیباگ، بهینهسازی و بهبود داشتهاند – کدی که اکنون در اختیار دارید، سالها تجربه و رفع اشکالهایی را در خود جای داده که حتی تصورش را هم نمیکنید.
عیبها رفع شدهاند و آنچه باقی مانده یک سیستم بالغ و پایدار است که میتواند با هر چالشی مواجه شود. (البته شاید هم انبوهی از بدهیهای فنی باشد که بعداً درباره آن صحبت خواهیم کرد).
🏄 در این دنیای پرسرعت بازنویسیهای مداوم، چیزی به نام ثبات ارزش دارد. پیر کردن کدهای شما به معنای مقاومت در برابر پیشرفت نیست؛ بلکه به معنای اطمینان از این است که هر زمان پیشرفت صورت گیرد، بر پایهای محکم و استوار باشد.
دور شدن از معماری اصلی
آن کارآموز مشتاق را به یاد دارید که روز اول به تیم شما ملحق شد و میخواست دنیا را تغییر دهد؟ پر از ایده بود، اما کاملاً بیخبر از پیچیدگی سیستمهای موجود. او همانند یک چارچوب جدید است که توجه شما را جلب کرده و دنیایی نویدبخش را به نمایش میگذارد. پس شما بخشهایی از کد را بازنویسی میکنید، آن را ادغام میکنید و درست مانند همان کارآموز که بهسرعت متوجه میشود قوانین پیچیده کسبوکار چندان ساده نیستند، کد جدید هم بهزودی درمییابد که هماهنگی با سیستم موجود به این راحتی نیست.
حکمت سیستمهای اثباتشده را بپذیرید: گاهی حفظ یکپارچگی کد شما ارزشمندتر از بازنویسی عجولانه آن است. نوآوری را با قابلیت اطمینان متعادل کنید تا موفقیتی پایدار داشته باشید.
هر بار که یک کتابخانه جدید اضافه میکنید، گویی یک اتاق جدید به خانهای اضافه کردهاید. اما اگر اتاق جدید با نقشه معماری اصلی مطابقت نداشته باشد، چه میشود؟ اگر این اتاق جدید بیش از ظرفیت سیستم برق شما توان مصرف کند یا ساختار اصلی خانه را تحت تأثیر قرار دهد چه؟
جوئل اسپولسکی در مقالهاش با عنوان “چیزهایی که هرگز نباید انجام دهید” مینویسد:
یک دلیل ظریف وجود دارد که برنامهنویسان همیشه میخواهند کد قدیمی را کنار بگذارند و از نو شروع کنند. دلیلش این است که فکر میکنند کد قدیمی بههمریخته است. و نکته جالب این است که احتمالاً اشتباه میکنند. دلیل اینکه آنها فکر میکنند کد قدیمی آشفته است، به خاطر یک قانون بنیادی و اساسی برنامهنویسی است:
خواندن کد سختتر از نوشتن آن است.
به همین دلیل استفاده مجدد از کد سخت است. به همین دلیل هر کسی در تیم شما تابع متفاوتی را برای تقسیم رشتهها به آرایههای رشتهای ترجیح میدهد. آنها تابع خودشان را مینویسند چون آسانتر و جالبتر از این است که بفهمند تابع قدیمی چگونه کار میکند.
این همان اتفاقی است که برای سیستم IT شما رخ میدهد وقتی یک کتابخانه جدید اضافه میکنید یا بدون فکر شروع به بازنویسی میکنید. شما فقط یک بلوک دیگر از برج جنگا بیرون نمیکشید؛ بلکه از طراحی اصلی و سالها دانش تاریخی که در اطراف آن شکل گرفته نیز فاصله میگیرید.
از دست دادن سادگی، به دست آوردن پیچیدگی
وقتی از طراحی اصلی فاصله میگیرید و چارچوبهای مختلف را ترکیب میکنید و یکپارچگیهای تصادفی انجام میدهید، چیزی موذیانه رخ میدهد: شما شروع به از دست دادن یکپارچگی مفهومی کل سیستم میکنید. همان لحظهای را به یاد بیاورید که مجبور شدید یک راهنمای ۱۰ صفحهای بنویسید تا نحوه اجرای یک تابع ساده را توضیح دهید؟ این یک نشانه است. کد شما شبیه یک درخت کریسمس بیش از حد تزئینشده شده است، آنقدر پر از تزئینات که دیگر شاخهها دیده نمیشوند.
از دست دادن یکپارچگی سیستم فقط یک اصطلاح لوکس نیست؛ بلکه مسیری سریع به سوی “جهنم پیچیدگی” است. و جهنم پیچیدگی یک باشگاه شبانه نیست؛ بلکه یک دوزخ دانتهای است که روزها صرف دیباگ کدی میکنید که به چندین روش مختلف نوشته شده، هفتهها صرف خواندن مشکلات گیتهاب چارچوبهای مختلف، و ماهها تلاش برای ادغام ویژگیهای جدید در جاهایی که باید تنها چند ساعت طول میکشید.
هر بار بازنویسی بخشی از کد پایدار نه تنها به پیچیدگی اضافه میکند، بلکه هزینههای نگهداری خود را نیز به همراه دارد. بله، آن کتابخانه در دمو عالی به نظر میرسید، اما حالا باید آن را بهروزرسانی کنید، مطمئن شوید با باقی سیستم سازگار است، و خدایا، آیا بهتازگی کامپایل شکسته شد؟ چیزی که قرار بود یک راهحل سریع باشد، به یک بدهی بلندمدت تبدیل میشود.
و فراموش نکنید سازگاری را. یادتان هست چقدر راحت میشد ویژگیهای جدید اضافه کرد وقتی کدبیس شما فقط چند ده هزار خط بود؟ چه روزهایی بود، نه؟ هرچه بیشتر از معماری اصلیتان دور شوید و به سمت مجموعهای از «چیزهای جدید و براق» حرکت کنید (که با گذر زمان کدر میشوند)، سازگاری سختتر میشود. خود را در هزارتویی از وابستگیها، دستورات شرطی و باگهای عجیبی که جایگاهی در آنجا ندارند، گرفتار میبینید.
اگر سازگاری واحد پول دنیای مدرن تکنولوژی باشد، یک کدبیس پیچیده و متورم مانند این است که داراییهای شما مسدود شدهاند. نمیتوانید حرکت کنید؛ گیر کردهاید. و درحالیکه شما مانند گوزنی در برابر چراغهای جلو در پیچیدگیها منجمد شدهاید، دنیا در حال حرکت است و فرصتها از کنارتان میگذرند.
پرسیدن سوالات سخت
پس قبل از اینکه تسلیم وسوسه بازنویسی همهچیز با یک فریمورک جدید شوید که به شما وعده «افزایش X» میدهد (که X معمولاً یکی از اینهاست: نوآوری، عملکرد یا انعطافپذیری)، کمی عقبتر بروید. نگاهی جدی به کدبیس قابلاعتماد خود بیندازید. شاید درخشش تازگی را نداشته باشد، اما گرمای بلوغ را دارد. به یاد داشته باشید، شما فقط کد نمینویسید؛ شما میراثی برای توسعهدهندگان آینده میسازید. و میراثها با مدها ساخته نمیشوند؛ بلکه با پایههای مستحکم ساخته میشوند. پایههایی که بتوانند آزمون زمان، نوسانات بازار، و بله، حتی جذابیت چیزهای جدید را تحمل کنند.
نگاهی دقیقتر به وضعیت بیندازید:
- اهدافی که در تلاش برای دستیابی به آنها هستید چیست؟ آیا به اندازه کافی قابلتوجه هستند؟
- آیا این افزونههای جدید با معماری کلی شما سازگار هستند؟
- آیا با الگوهای توسعه شما تطابق دارند؟
- آیا مجبور خواهید شد برای ادغام آن تلاش کنید؟ آیا دیگران نیز مجبور خواهند شد؟
- آیا مطمئن هستید این ماژول نیاز به بهینهسازی/بهبود/بازنویسی دارد یا فقط غرورتان حرف میزند؟
🏄 فقط برای اطمینان از اینکه درک همگی از مطلب یکسان باشد — کد قدیمی به معنای مقاومت در برابر تغییر یا پایبندی به اصول در حالیکه دنیا پیش میرود نیست. بلکه به معنای درک این است که جدید همیشه بهتر نیست و قدیمی همیشه منسوخ نیست. این درک این است که استحکام پایهای، ضد نوآوری نیست، بلکه پیشنیاز آن است.
به رسمیت شناختن ضرورت تغییر
در این راستا، مهم است که اذعان کنیم مواقعی وجود دارد که انتخاب تکنولوژی جدید یا بازنویسی عمده نه تنها موجه، بلکه ضروری است.
در اینجا چند سناریو قابلتوجه آورده شده است:
پیشرفتهای تکنولوژیکی: یکی از نیروهای محرکه صنعت فناوری، نوآوری است. فریمورکها، زبانها، و ابزارهای جدید برای استفاده از قابلیتهای سختافزاری جدید توسعه داده میشوند. نادیده گرفتن کامل این نوآوریها میتواند به از دست دادن فرصتها منجر شود. ارزیابی اینکه آیا یک تکنولوژی جدید با اهداف شما همخوانی دارد و نسبت به پشته فعلی شما مزایای قابلتوجهی ارائه میدهد، ضروری است.
انباشت بدهی فنی: درحالیکه برخی بدهیهای فنی قابل مدیریت هستند و میتوان بهطور استراتژیک به آنها رسیدگی کرد، زمانی فرا میرسد که انباشت بدهی فنی طاقتفرسا میشود. اگر کدبیس شما پر از راهحلهای پیچیده و وصلههای متعدد است، حتی اگر کار میکند — ممکن است زمان بازنویسی فرا رسیده باشد تا قابلیت نگهداری را برای نیازهای آینده بازگردانید.
تغییر نیازهای کسبوکار: چشمانداز کسبوکار پویاست و گاهی کد قدیمی دیگر با نیازهای در حال تحول بازار همخوانی ندارد. اگر پشته تکنولوژی فعلی شما توانایی پاسخ سریع به خواستههای مشتری را محدود میکند، ممکن است ارزش بررسی بازنویسی در یک فریمورک جدید را داشته باشد.
اما در نهایت، بستگی به شرایط دارد. هر موقعیت منحصربهفرد است و تصمیم به بازنویسی، بازطراحی یا پذیرش تکنولوژی جدید باید بر اساس ارزیابی دقیق از شرایط خاص، اهداف تجاری، بودجه، تخصص تیم و ملاحظات فنی گرفته شود. نکته کلیدی این است که نقطه تعادل را پیدا کنید، جایی که سیستمهای بالغ و تکنولوژیهای نوآورانه بتوانند به شکلی هماهنگ همزیستی داشته باشند.