نوسازی (Refactoring) و از نو نویسی (Rewriting) رو به روی هم نیستن. ما فقط دو انتخاب نداریم که یا «کدهامون رو دور بریزیم و از نو شروع کنیم» یا «یک بیل برداریم و آروم آروم خاکبرداری کنیم». برای زنده نگه داشتن یک محصول نرمافزاری باید روشهای مختلف رو در تلفیق با هم استفاده کرد. گاهی معماری تغییر میکنه و نوسازی بیمعنی میشه و گاهی تنها با نوسازی میشه عملکرد رو بهبود داد.
از نو نویسی رو گاهی معادل ضربه فنی شدن محصول، از دست بدهیهای فنی میدونن. اگه تو تیمی هستین که تا این حد بدهی فنی بار آوردین احتمال اینکه محصول از نو نوشته شدهتون هم همینقدر بدهی فنی ایجاد کنه، کم نیست. نوسازیهای دنبالهدار و همیشگی و از نو نویسیهای بهجا، در کنار هم، محصول رو زنده و پویا نگه میدارن.
اینجا توضیح دادم که چطور با استفاده از نوسازی و از نو نویسی به تیم قبلیم کمک کردم محصولمون رو بهبود بدیم.
نوسازی
نوسازی کد تغییر ساختار داخلی اون، بدون ایجاد تغییر تو رفتار بیرونیشه. به عنوان مثال با حذف کدهای اضافی، یا شکستن یه بخش بزرگ کد به زیربخشهای کوچکتر که هر کدوم وظیفه مشخص خودشون رو دارن میشه کد رو نوسازی کرد.
روش توسعه «برنامه نویسی Extreme» که ازش به عنوان نوسازی بیرحم هم اسم میبرن، معتقده که کدهامون باید به شکل مداوم نوسازی بشن. به شکل تئوری برنامهنویسهایی که به صورت مداوم کدهاشون رو نوسازی میکنن، اون رو برای پذیرش تغییرات جدید آمادهتر تحویل میگیرن.
یکی از اهداف نوسازی، جنگیدن با بدهیهای فنیه. نوسازی کدهای پیچیده و کثیف رو به کدهای سادهتر و تمیزتر تبدیل میکنه. اما کد تمیز چه ویژگیهایی داره؟
کد تمیز برای بقیه قابل درک و واضحه.
کد تمیز، قسمتهای تکراری نداره.
کد تمیز تعداد کلاسهای حداقلی داره.
همه تستها تو کد تمیز با موفقیت انجام میشن.
نگهداری و توسعه کد تمیز آسونتر و ارزونتره.
چه زمانی نوسازی کنیم؟
اگه برای بار اوله که انجامش میدی، فقط انجامش بده.
اگه دومین باره که انجامش میدی یه کم اخم کن و همون کار رو تکرار کن.
دفعه سوم که شد نوسازی رو شروع کن.
ویژگی جدید اضافه میکنی؟
نوسازی به درک کد بقیه کمک میکنه. اگه با کد کثیف بقیه سر و کار داری، اول نوسازیش کن. با این کار هم برای خودت آسونش میکنی و هم نفر بعد از خودت.
کد نوسازی شده، اضافه کردن ویژگی جدید رو آسون میکنه. تغییر تو کد تمیز سادهتره.
باگ رو اصلاح میکنی؟
باگها تو نقاط تاریک و کثیف کد زندگی میکنن. با تمیز کردن کد پیدا کردنشون آسونتر میشه.
نوسازیهای کوچک و مداوم، نیاز به نوسازیهای بزرگ رو کم میکنن.
زمان بازبینی کد
بازبینی کد شاید آخرین فرصت قبل از انتشار کد باشه. اگه با نویسنده اصلی کد همراه بشی و کد رو در زمان بازبینی، نوسازی کنین خیلی سریعتر به نتیجه میرسین.
تکنیکهای نوسازی
روشهای زیادی برای نوسازی کدها وجود داره و میشه گفت نوسازی کدها هیچوقت تموم نمیشه و همیشه جا برای بهبود وجود داره. اینجا خیلی خلاصه به بعضی از تکنیکها اشاره میکنم.
اصلاح متدها: بار اصلی نوسازی روی دوش چگونگی استفاده از متدهاست. متدهای طولانی و بزرگ ریشه بیشتر کثیفیها هستن. اتفاقاتی که توی بدنه متدهای بزرگ میفته باعث میشه درک منطقشون دشوار بشه و اگه نتونیم منطق متدی رو بفهمیم تغییر دادنش ممکن نخواهد بود. با روشهایی مثل استخراج متدها، شکستن منطق، اصلاح پارامترها میشه وضعیت رو بهبود داد.
انتقال ویژگیها بین اشیا: توزیع متدها و ویژگیها بین کلاسها باعث میشه کد تمیزتری داشته باشیم. کارهایی مثل جابجا کردن متدها یا فیلدها از یه کلاس به کلاسی که استفاده بیشتری از اون داره. تبدیل یه کلاس بزرگ به دو یا چند کلاس کوچکتر که هر کدوم هدف مشخصی دارن نمونههایی از اجرای این تکنیک هستن.
سادهسازی عبارات شرطی: عبارات شرطی با گذر زمان پیچیده و پیچیدهتر میشن. برای ساده سازی عبارات شرطی میشه از روشهایی مثل یکی کردن شرطهایی که نتیجه مشابه به همراه دارن، جابجا کردن کدهای تکراری که توی همه شاخهها استفاده شدن، حذف فلگهای کنترلی داخل حلقهها و استفاده از ویژگیهای حلقهها (break, continue, return) به جای اون، استفاده کرد.
سادهسازی صدا کردن متدها: با روشهایی مثل اضافه کردن پارامتر مورد نیاز بیرونی به امضای متد یا حذف یه پارامتر بلااستفاده از امضا، تغییر نام متد به چیزی که کارش رو توضیح بده، ساخت متدهای مجزا از متدی که با استفاده از شروط کارهای مختلفی انجام میده و ... میشه کد تمیزتری درست کرد.
مزایای نوسازی
نوسازی همیشه گزینه روی میزه. برنامهنویسها نیازی به اجازه کسی برای نوسازی ندارن.
امکان نوسازی برای هر مدل معماری و نرمافزاری وجود داره.
نوسازی به بالا بردن کیفیت کد بدون کند کردن فرایند توسعه کمک میکنه. برخلاف از نو نویسی، نوسازی نیاز به مدیریت دو یا چند کدبیس مجزا از هم، به صورت همزمان رو از بین میبره.
اگه برنامهنویسی تنها روی بخشی از کد یه نرمافزار کار میکنه میتونه تنها همون بخش رو نوسازی کنه.
معایب نوسازی
درسته که نوسازی کیفیت کد رو بهبود میده اما توانایی حل مشکلات عمیق رو نداره. مثلا نرمافزاری که معماری بهینهای نداره رو نمیشه با نوسازی بهینه کرد.
نوسازی همیشه شرایط موجود نرمافزار رو حفظ میکنه. بنابراین امکان اینکه بعد از نوسازی هنوز امکان اضافه کردن ویژگی جدید به محصول نداشته باشیم، وجود خواهد داشت.
برنامهنویسهایی که از تستنویسی فراری هستن از نوسازی هم فراری خواهند بود، چون نوسازی بدون وجود تست، معنی نداره.
با اینکه یکی از اهداف نوسازی کم کردن میزان کدهاست اما گاهی برای بهینه شدن باید میزان کدها را افزایش بدیم. این یعنی کدهای بیشتر برای نگهداری و تست.
از نو نویسی
گاهی اوقات نیازه به جای برررسی، خوندن و تمیز کردن کدهای قدیمی، کدها رو از نو بنویسیم. برخلاف نوسازی که تکنیکها و روشهای مختلفی داره و با تکرار و تمرین میشه توش بهتر شد، از نو نوشتن کد به نظر سرراستتر میاد، چرا که باید ویژگیهای موجود تو اون بخش از کد که داریم از نو مینویسیمش رو، خب از نو بنویسیم!
برای از نو نویسی معمولا تیمها به دو بخش تقسیم میشن. یک بخش کد قدیمی رو نگهداری میکنه و بخش دوم شروع به از نو نوشتن میکنه. اتفاق ناگوار اینجا اینه که کد قدیمی هنوز در حال کاره و نیاز به بروزرسانی و اضافه کردن ویژگیهای جدید داره. بنابراین از نو نویسی اگه درست مدیریت و برنامهریزی نشه میتونه اصطلاحات «محصول قدیمی» و «محصول جدید» رو ایجاد کنه و اینطوری محصول جدید هیچوقت جایگزین محصول قدیمی نشه. گاهی اوقات چارهای جز از نو نوشتن همه محصول نیست (وقتایی که معماری کل محصول رو تغییر میدیم و ...) اما همیشه بهتره از نو نوشتن کد رو روی ویژگیهای کوچکتر محصول پیش ببریم.
مزایای از نو نویسی
از نو نوشتن کد، راه رو برای ورود کاربران جدید، تکنولوژیهای جدید و بازار جدید فراهم میکنه. به عنوان مثال میشه یه محصول که وابسته به سیستمعامل ویندوز بود رو روی وب از نو نوشت و بازار هدفش رو گسترش داد.
از نو نویسی کدبیسی تازه و تمیز ایجاد میکنه (البته اگه بشه حفظش کرد)
از نو نویسی کدهای legacy رو به شکل کامل کنار میذاره و نیاز به بروزرسانی تکنولوژیها و بازبینی و اصلاح syntax زبانها رو از بین میبره.
معایب از نو نویسی
از نو نویسی کامل، زمانبر و هزینهبره و تنها وقتی باید سراغش رفت که توان هزینه کردن زمان و پول براش وجود داشته باشه.
کد قدیمی کثیفه و ممکنه کثیفتر هم بشه. برای از نو نویسی، برنامهنویسها باید به شکل مداوم کدهای قدیمی رو بررسی کنن. وجود دو دنیای مجزا برای کد جدید و قدیم، باعث میشه نتیجه این بررسیها همیشه بروز نباشه.
از نو نویسی لزوما مساله کد کثیف رو حل نمیکنه و بهتره ازش به عنوان راه حل تمیز کردن کد استفاده نشه.