نرمافزار قدیمی را از نو بنویسیم یا کمکم نوسازی کنیم؟
7 دقیقه مطالعه

بازنویسی کامل نرمافزار قدیمی ساده به نظر میرسد ولی اغلب پرخطر است. با سه سؤال ساده، یک جدول تصمیم و الگوی Strangler Fig ببینید کدام راه برای شما مناسبتر است.
جواب کوتاه: در بیشتر موارد بهتر است نرمافزار قدیمی را کمکم و تکهتکه نوسازی کنید، نه اینکه یکباره از صفر بنویسید. بازنویسی کامل وقتی معقول است که سیستم کوچک باشد، دقیق بدانید چه کار میکند و بتوانید نسخهٔ جدید را کنار نسخهٔ قدیم اجرا و مقایسه کنید.
وقتی یک نرمافزار کند شده، با هر تغییر جای دیگریاش خراب میشود و کسی هم مستنداتش را ندارد، خیلی طبیعی است که بگوییم «بیایید از اول بسازیمش». ولی دو نویسندهٔ شناختهشدهٔ دنیای نرمافزار، هر کدام به زبان خودشان، دربارهٔ همین وسوسه هشدار دادهاند. در این مقاله میبینیم چرا، و با چند سؤال ساده تصمیم میگیریم کدام راه برای شما مناسبتر است. اینجا آمار یا درصد موفقیت نمیدهیم، چون منبع معتبری برایش نداریم.
چرا «همین را با تکنولوژی بهتر بسازیم» به این سادگی نیست؟
Martin Fowler توضیح میدهد که این نقشه در نگاه اول ساده است: میدانیم سیستم فعلی چه میکند، پس همان را با تکنولوژی جدیدتر میسازیم. اما به گفتهٔ او این نقشه بیشتر وقتها شکست خورده است. دلیلهایش اینهاست:
طول میکشد. جایگزین کردن یک سیستم جدی زمان زیادی میبرد.
کاربرها منتظر نمیمانند. در این مدت کسبوکار هنوز قابلیت جدید میخواهد.
رفتار فعلی را دقیق نمیدانیم. نوشتن «همان کاری که الان میکند» روی کاغذ ساده است، ولی جزئیاتش را درآوردن سخت است.
همهاش ارزش ساختن ندارد. بخش زیادی از رفتار فعلی را اصلاً کسی نمیخواهد و ساختن دوبارهاش هدر دادن وقت است.
دو دیدگاه معروف دربارهٔ بازنویسی
Joel Spolsky: بازنویسی از صفر بدترین اشتباه است
Spolsky در سال ۲۰۰۰ نوشت بازنویسی کد از صفر «بدترین اشتباه راهبردی» است که یک شرکت نرمافزاری میتواند بکند. به نظر او برنامهنویسها کد قدیمی را شلوغ و بههمریخته میبینند، چون خواندن کد از نوشتنش سختتر است. مثالهایش Netscape، Borland و پروژهٔ Pyramid مایکروسافت است.
یادتان باشد این یک یادداشت نظری و قدیمی است، نه پژوهش آماری، و مثالهایش هم مربوط به نرمافزارهای دسکتاپ همان دوره است.
Martin Fowler: کمکم و کنار سیستم قدیمی
Fowler راه تدریجی را ترجیح میدهد: با چیزهای کوچک شروع کنید، معمولاً با قابلیتهای جدید، و آنها را کنار کد قدیمی ولی جدا از آن بسازید. بعد رفتارهای سیستم قدیمی را تکهتکه به کد جدید منتقل کنید.
نکتهٔ مشترک هر دو: بازنویسی کامل باید استثنا باشد و دلیل روشن داشته باشد. صرفِ اینکه از کد فعلی خسته شدهایم دلیل کافی نیست.
سه سؤال که قبل از تصمیم باید جواب بدهید
این سه سؤال پیشنهاد ماست و از همین منابع الهام گرفته؛ قانون یا استاندارد رسمی نیست.
۱. دقیقاً به چه نتیجهای میخواهیم برسیم؟
Fowler میگوید اولین کار در نوسازی این است که روشن کنیم دقیقاً چه نتیجهای میخواهیم، و اشاره میکند که معمولاً گروههای مختلف هدفهای مبهم و متفاوتی در ذهن دارند. «سریعتر شود» یا «مدرن شود» هدف نیست. هدفی مثل «هر تغییر ظرف چند روز منتشر شود» یا «وابستگی به فلان تکنولوژی برداشته شود» را میشود سنجید.
۲. چقدر میدانیم سیستم فعلی دقیقاً چه کار میکند؟
اگر ندانید سیستم الان چه میکند، بازنویسی همان ندانستن را به پروژهٔ جدید منتقل میکند. اول قابلیتها و مسیرهای مهم را فهرست کنید و با داده یا تست مشخص کنید که هر کدام دقیقاً چه رفتاری دارد.
۳. اگر تا تمام شدن بازنویسی تغییری ندهیم، چه میشود؟
اگر کسبوکار نمیتواند چند ماه یا بیشتر بدون قابلیت جدید سر کند، راه تدریجی عملیتر است. این همان دلیلی است که Fowler برای شکست نقشهٔ ساده آورده است.
نوسازی تدریجی با الگوی Strangler Fig
در الگوی Strangler Fig، یک لایهٔ واسط درخواستها را کمکم از سیستم قدیم به سیستم جدید میبرد.
اسم این الگو از نوعی درخت انجیر در جنگلهای بارانی آمده که دور یک درخت دیگر رشد میکند و کمکم جایش را میگیرد. نرمافزار هم همینطور عوض میشود.
راهنمای معماری Azure مایکروسافت این الگو را اینطور توضیح میدهد:
قابلیتها یکییکی به برنامه یا سرویس جدید منتقل میشوند.
یک لایهٔ واسط (façade یا proxy) جلوی سیستم قرار میگیرد و هر درخواست را به سیستم قدیم یا جدید میفرستد.
کاربرها متوجه مهاجرت نمیشوند، چون همیشه با همان لایهٔ واسط کار میکنند.
وقتی همهچیز منتقل شد، سیستم قدیمی کنار گذاشته میشود.
همان راهنما یادآوری میکند که وقتی دو نسخه همزمان کار میکنند، باید معلوم باشد هر قابلیت در کدام نسخه است و درخواستها به جای درست بروند.
از کجا شروع کنیم؟ پیشنهاد عملی ما این است که اولین تکه را کوچک و کمخطر انتخاب کنید، مثلاً یک گزارش یا یک قابلیت جدید. اینطوری هم مسیردهی درخواستها را تمرین میکنید و هم روش مقایسهٔ رفتار نسخهٔ قدیم و جدید را. اگر اول میخواهید وضعیت کد، تستها و استقرار سیستم فعلی روشن شود، ممیزی مهندسی کمک میکند. اگر برای بازسازی کد از ابزارهای هوش مصنوعی استفاده میکنید، مقالهٔ استفاده از AI برای Refactoring را هم بخوانید.
پس بازنویسی کامل کی منطقی است؟
منابع بالا قانون «هرگز» یا «همیشه» نمیدهند. به نظر ما بازنویسی کامل وقتی قابل دفاعتر است که این شرایط با هم جمع باشند:
سیستم کوچک است.
رفتارش با تست یا مستندات مشخص است.
پلتفرم فعلی واقعاً قابل ادامه نیست، مثلاً پشتیبانیاش تمام شده.
میشود نسخهٔ جدید را کنار نسخهٔ قدیم اجرا کرد و نتیجهها را مقایسه کرد.
حتی در این حالت هم بهتر است نسخهٔ اول فقط بخشی از کار را بر عهده بگیرد.
جدول تصمیم: بازنویسی یا نوسازی تدریجی؟
وضعیت شماراه مناسبترسیستم بزرگ است و کسبوکار هر روز به آن وابسته استنوسازی تدریجیرفتار فعلی را دقیق نمیدانید و تست نداریداول رفتار را مستند کنید، بعد تدریجی جلو برویدکسبوکار نمیتواند ماهها منتظر قابلیت جدید بماندنوسازی تدریجیسیستم کوچک است و رفتارش با تست مشخص استبازنویسی کامل قابل بررسی استپلتفرم فعلی دیگر پشتیبانی نمیشود و میتوانید دو نسخه را موازی اجرا کنیدبازنویسی، ترجیحاً مرحلهبهمرحله
چکلیست قبل از تصمیم
هدف را به یک نتیجهٔ قابل سنجش تبدیل کردهایم.
فهرست قابلیتها و مسیرهای مهم را داریم و برای هر کدام شاهد (داده یا تست) هست.
برای هر تکه، روش مقایسهٔ رفتار قدیم و جدید و برنامهٔ برگشت داریم.
معلوم است در طول مهاجرت قابلیتهای جدید چطور ساخته میشوند.
معلوم است چه کسی تصمیم میگیرد و «تمام شد» یعنی چه.
سؤالهای رایج
بازنویسی کامل همیشه اشتباه است؟
نه. منابع این مقاله قانون «هرگز» نمیدهند. ولی بازنویسی کامل باید استثنا باشد و دلیل روشن داشته باشد؛ مثلاً سیستم کوچک باشد، رفتارش مشخص باشد و پلتفرم فعلی دیگر قابل ادامه نباشد.
الگوی Strangler Fig یعنی چه؟
یعنی سیستم قدیمی را یکباره عوض نکنید. یک لایهٔ واسط جلوی آن بگذارید، قابلیتها را یکییکی به سیستم جدید ببرید و درخواستها را به نسخهٔ درست بفرستید. آخر کار، سیستم قدیمی کنار گذاشته میشود.
در نوسازی تدریجی، کاربرها متوجه تغییر میشوند؟
اگر لایهٔ واسط درست کار کند، نه. طبق راهنمای مایکروسافت، کاربرها همچنان با همان نقطهٔ ورود کار میکنند و از مهاجرت پشت صحنه خبر ندارند.
اولین تکه را چطور انتخاب کنیم؟
یک بخش کوچک و کمخطر، مثل یک گزارش یا یک قابلیت جدید. هدف تکهٔ اول بیشتر تمرین روش است تا سود بزرگ.
مقالهٔ Joel Spolsky هنوز معتبر است؟
حرف اصلیاش، یعنی اینکه کد قدیمی دانش زیادی را در خودش دارد، هنوز ارزش فکر کردن دارد. ولی یادداشتی نظری از سال ۲۰۰۰ است، نه پژوهش آماری، و مثالهایش مربوط به نرمافزارهای دسکتاپ آن دوره است.
اگر میخواهید وضعیت سیستم خودتان را با یک تیم مرور کنید، توضیح کوتاهی در صفحهٔ شروع پروژه بفرستید. فرستادن فرم تعهدی برایتان ایجاد نمیکند.
منابع
Strangler Fig — Martin Fowler، ۲۲ اوت ۲۰۲۴
Things You Should Never Do, Part I — Joel Spolsky، ۶ آوریل ۲۰۰۰
Strangler Fig pattern — Microsoft Learn، Azure Architecture Center
نویسنده
سا
سهیل ابراهیمپور بنیانگذار FutureForge است. روی طراحی محصول، معماری و استقرار نرمافزار سفارشی کار میکند.
یادداشتهای مرتبط
برای انتخاب مسیر فنی پروژهتان کمک میخواهید؟
از مسئله و محدودیتهایتان بگویید؛ اگر بتوانیم همراهیتان کنیم، برای گفتوگو هماهنگ میکنیم.




