مهاجرت کد و ارتقای نسخه با کمک هوش مصنوعی

پروژه‌ای که چهار سال روی نسخه‌ی قدیمی مانده، یک روز مجبور به ارتقا می‌شود. سؤال این نیست که ابزار کمک می‌کند یا نه؛ این است که کجا باید جلویش را گرفت.

🍊 تیم نارنگی ⏱ 5 دقیقه مطالعه
ارتقای نسخه و بازنویسی کد قدیمی با کمک ابزارهای هوشمند

یک پروژه‌ی داخلی که چهار سال روی نسخه‌ی قدیمی مانده، تیمش عوض شده، مستنداتش کامل نیست و تست هم ندارد. حالا کتابخانه‌ی پرداخت اعلام کرده نسخه‌ی قدیمی را پشتیبانی نمی‌کند و ارتقا اجباری شده. این سناریو در بیشتر شرکت‌های نرم‌افزاری ایران تکرار می‌شود.

وسوسه‌ی اول واضح است: کل کد را بدهیم و نسخه‌ی جدید بگیریم. این کار تقریباً همیشه بد تمام می‌شود — نه چون خروجی بی‌کیفیت است، چون کسی آن حجم خروجی را واقعاً مرور نمی‌کند.

چرا مهاجرت‌ها شکست می‌خورند

مشکل معمولاً فنی نیست. مهاجرت وقتی از دست می‌رود که مقیاس تغییر از توان مرور تیم بزرگ‌تر شود. وقتی هزار خط تغییر در یک کامیت باشد و همه‌چیز هم‌زمان عوض شده باشد، هیچ‌کس نمی‌تواند بگوید کدام تغییر باعث آن رفتار عجیب در تولید شده است.

دومین دلیل شایع، فرض نانوشته است. کد قدیمی معمولاً پر از رفتارهایی است که کسی عمداً ننوشته ولی سیستم به آن‌ها وابسته شده. مدل این‌ها را نمی‌بیند و «تمیزشان می‌کند».

مرحله‌ی صفر: شبکه‌ی ایمنی

قبل از تغییر یک خط، سه چیز باید سر جایش باشد. بدون این‌ها، مهاجرت با کمک ابزار فقط سرعت خراب‌کاری را بالا می‌برد.

  • کنترل نسخه با شاخه‌ی جدا و کامیت‌های کوچک با پیام روشن. اگر لازم شد برگردید، باید بتوانید فقط یک تکه را برگردانید.
  • تست برای مسیرهای حیاتی. نه پوشش کامل — همان چند کاری که اگر بشکنند کسب‌وکار می‌خوابد: ورود، ثبت سفارش، پرداخت.
  • محیط آزمایشی با داده‌ی واقعیِ ناشناس‌شده. باگ‌های مهاجرت معمولاً با داده‌ی تمیز ظاهر نمی‌شوند.
⚠️ بدون تست شروع نکنید

اگر پروژه تست ندارد، اولین کار نوشتن تست است، نه ارتقا. خودِ نوشتن این تست‌ها را هم می‌توانید بسپارید — ولی حتماً هرکدام را یک بار عمداً بشکنید تا مطمئن شوید واقعاً چیزی را می‌سنجند. تستی که همیشه سبز است، بدتر از نداشتن تست است.

تکه‌تکه، نه یک‌جا

واحد کار درست، یک فایل یا یک ماژول کوچک است. برای هر واحد، همین چرخه: تبدیل، مرور، تست، کامیت. کند به‌نظر می‌رسد و در عمل سریع‌تر تمام می‌شود، چون هیچ‌وقت مجبور نمی‌شوید یک هفته کار را دور بریزید.

این فایل را از [نسخه‌ی مبدأ] به [نسخه‌ی مقصد] ببر.

قواعد:
- فقط چیزهایی را عوض کن که برای سازگاری لازم است
- ساختار، نام‌ها و منطق را دست نزن
- «بهترسازی» نکن؛ هر بهبود سلیقه‌ای را جدا فهرست کن
- اگر جایی مطمئن نیستی، تغییر نده و علامت بزن

خروجی در سه بخش:
۱) کد نهایی
۲) جدول تغییرات: خط | قبل | بعد | دلیل
۳) مواردی که باید انسان بررسی کند

--- کد:
[کد]

بند «بهترسازی نکن» را حذف نکنید. بدون آن، مدل هم‌زمان با مهاجرت شروع می‌کند به تغییر نام متغیرها و بازچینی توابع، و بعد نمی‌شود فهمید کدام تغییر ضروری بوده و کدام سلیقه‌ای.

کدام مهاجرت‌ها خوب جواب می‌دهند

نوع مهاجرتکیفیتنکته
ارتقای نسخه‌ی زبانخوبتغییرات معمولاً مکانیکی و مستندند
ارتقای فریم‌ورک، یکی دو نسخهخوبراهنمای رسمی را هم در پرامپت بگذارید
جایگزینی کتابخانه‌ی مشابهمتوسطتفاوت‌های رفتاری ظریف را چک کنید
تبدیل نحو قدیمی به مدرنخوبمثل تبدیل callback به async
تغییر زبان برنامه‌نویسیضعیف تا متوسطترجمه‌ی خط‌به‌خط، کد بی‌روح می‌سازد
تغییر معماریضعیفتصمیم طراحی لازم است، نه ترجمه

یک ترفند مؤثر برای ردیف دوم: بخش مربوطه از راهنمای رسمی ارتقا را مستقیم در پرامپت بچسبانید. مثلاً برای PHP، صفحه‌ی رسمی مهاجرت به نسخه‌ی ۸ فهرست دقیق تغییرات ناسازگار را دارد. با این کار، مدل به‌جای اتکا به حافظه‌اش، از سند واقعی استفاده می‌کند.

خطاهایی که بی‌سروصدا رد می‌شوند

خطای خوب، خطایی است که برنامه را متوقف می‌کند. خطرناک‌ترین باگ‌های مهاجرت آن‌هایی هستند که کد را اجرا می‌کنند، پیامی نمی‌دهند، و نتیجه‌ی متفاوتی تولید می‌کنند. چهار جای کلاسیک:

  1. مقایسه و تبدیل نوع. رفتار مقایسه‌ی رشته و عدد بین نسخه‌ها عوض می‌شود و شرط‌هایی که قبلاً درست بودند، بی‌صدا برعکس می‌شوند.
  2. گرد کردن و اعشار. هر جا پول در کار است، خروجی قدیم و جدید را روی چند نمونه‌ی واقعی مقایسه کنید.
  3. ترتیب پیش‌فرض مرتب‌سازی. فهرستی که قبلاً به‌طور اتفاقی مرتب می‌آمد، ممکن است دیگر نیاید.
  4. منطقه‌ی زمانی و تاریخ. در پروژه‌های ایرانی با تاریخ شمسی، این بخش بیشترین دردسر را می‌سازد.

برای هر کدام از این موارد، بهترین بررسی مقایسه‌ی خروجی دو نسخه روی ورودی یکسان است — نه خواندن کد. الگوی کلی همان چیزی است که در مقاله‌ی اشتباهات رایج هم آمده: خروجی مطمئن، دلیل درست بودن نیست.

بازنویسی کامل: کجا واقع‌بینانه نیست

گاهی تصمیم این است که پروژه از اول با فریم‌ورک دیگری نوشته شود. اینجا مدل در نقش مترجم بد عمل می‌کند، چون ترجمه‌ی خط‌به‌خط، کدی می‌سازد که در زبان مقصد غریبه است.

کاری که خوب جواب می‌دهد، نقش دیگری است: از مدل بخواهید کد قدیمی را توضیح دهد — منطق کسب‌وکار، ورودی و خروجی، حالت‌های لبه — و بعد بر اساس آن توضیح، خودتان طراحی جدید را بنویسید. روش کار با کد ناآشنا در راهنمای برنامه‌نویسی باز شده است.

جمع‌بندی

مهاجرت با کمک ابزار، سرعت را دو تا سه برابر می‌کند به شرطی که مقیاس کار کوچک بماند. فایل‌به‌فایل، کامیت‌به‌کامیت، با تستی که قبلش نوشته شده. هر بار که وسوسه شدید یک ماژول کامل را یک‌جا بدهید، یادتان باشد که هزینه‌ی مرور نکردن را بعداً در محیط تولید می‌پردازید.

و یک قاعده که همه‌ی این‌ها را جمع می‌کند: هر تغییری که دلیلش را نمی‌فهمید، نپذیرید. اگر پرسیدید و توضیح قانع‌کننده نبود، همان‌جا علامت بزنید و بعداً با آدم بررسی کنید. برای امتحان کردن این چرخه روی یک فایل واقعی، نارنگی نقطه‌ی شروع ساده‌ای است.

مطالب مرتبط:

پرسش‌های پرتکرار

می‌توانم کل پروژه را یک‌جا بدهم و نسخه‌ی جدید بگیرم؟ +
حتی اگر اندازه‌ی پروژه در پنجره‌ی زمینه جا شود، نتیجه قابل اعتماد نیست. خروجی حجیم را کسی خط‌به‌خط مرور نمی‌کند و همان جایی که مرور نشود، باگ می‌ماند. فایل‌به‌فایل با کامیت جداگانه، کندتر به‌نظر می‌رسد و در عمل سریع‌تر تمام می‌شود.
اگر پروژه هیچ تستی ندارد چه کار کنم؟ +
قبل از هر تغییری، برای مسیرهای حیاتی تست بنویسید — همان چند کاری که اگر بشکنند کسب‌وکار می‌خوابد. نوشتن این تست‌ها را هم می‌توانید به ابزار بسپارید. مهاجرت بدون شبکه‌ی ایمنی یعنی هیچ راهی برای فهمیدن اینکه چیزی خراب شده یا نه.
برای تغییر زبان یا فریم‌ورک هم خوب کار می‌کند؟ +
برای زبان‌های نزدیک و ترجمه‌ی الگوهای مشابه، تا حدی. برای بازنویسی از یک معماری به معماری دیگر نه — آنجا تصمیم‌های طراحی لازم است که در کد قدیمی نوشته نشده و مدل آن‌ها را حدس می‌زند.
چطور بفهمم کد تولیدشده رفتار قبلی را حفظ کرده؟ +
با اجرای هر دو نسخه روی ورودی یکسان و مقایسه‌ی خروجی. برای توابع خالص این کار ساده است. برای کدی که با دیتابیس یا سرویس بیرونی کار می‌کند، حداقل مسیرهای پرکاربرد را در محیط آزمایشی دستی چک کنید.
خطرناک‌ترین بخش این کار کجاست؟ +
تغییرات بی‌سروصدا: کدی که اجرا می‌شود، خطا نمی‌دهد، و نتیجه‌ی متفاوتی تولید می‌کند. گرد کردن اعداد، مقایسه‌ی نوع‌ها، ترتیب مرتب‌سازی و منطقه‌ی زمانی، چهار جای کلاسیک این اتفاق‌اند.
#مهاجرت کد #ارتقای نسخه #ریفکتور کد #کد قدیمی #بازنویسی پروژه
به‌دردِ کسی می‌خورد؟ تلگرام واتساپ
🍊

خواندنش خوب بود — حالا امتحانش کن

هرچه در این صفحه خواندی، همین حالا داخلِ نارنگی قابلِ اجراست. ثبت‌نام با شماره‌ی موبایل، نارنگیِ رایگانِ شروع، بدونِ نیاز به کارت یا تحریم‌شکن.

بدونِ نصب هم کار می‌کند — ولی در اپ سریع‌تر است