آشنایی با Refactoring
ریفکتورینگ چیست؟ | Refactoring چیست؟
-
آشنایی با Refactoring (بخش اول)
ما قصد داریم در این مقاله Refactoring را برای شما با ذکر مثال بیان کنیم.
ریفکتورینگ کدهای مارا مرتب و باز سازی میکند بدون اینکه تغییری در خروجی کد های ما داشته باشد و معنا و قصد اصلی نویسنده کد را حفظ میکند. ما باید به نحوی کدهای خودرا پاکسازی کنیم که دیگر توسعه دهندگان از دیدن کدهای ما راضی باشند و بتوانند به راحتی کدهای مارا توسعه بدهند. ریفکتورینگ باید با دقت انجام شود تا از تغییر معنی وخروجی کدهای ما جلوگیری شود. از مزایای آن میتوان به بهبود قابلیت خواندن کد و کاهش پیچیدگی کدها نام برد و این میتواند قابلیت نگهدراری کد های مارا بهبود بخشد و کدهارا برای توسعه و گسترش مرتب تر و واضح تر نمایش بدهد. اگر ریفکتورینگ به خوبی انجام شود به توسعه دهندگان نرم افزاراین امکان را میدهد تا قسمت های آسیب پذیر پنهان یا خاموش سیستم خود را شناسایی کرده و سطوح پیچیده غیر ضروری را حذف کنند. بعنوان مثال میتوانیم آشپزخانه ای را در نظر بگیرم که چندین وعده غذایی برای بیش از چندین نفر درست میکند و به طور معمول میبینید که وسایل خودرا تمیز میکنند و به صورت مداوم ساماندهی میکنند. اگر این کار را نکنیم قطعا نمیتوانیم به خوبی آشپزی کنیم چرا که همه چیز کثیف و هیچ چیز سر جای خود نخواهد بود و دسترسی بعدی ما به ظروف سخت و نا ممکن خواهد بود.
Refactoring چیست؟
ما قصد داریم در این مقاله Refactoring را برای شما با ذکر مثال بیان کنیم.
ریفکتورینگ کدهای مارا مرتب و باز سازی میکند بدون اینکه تغییری در خروجی کد های ما داشته باشد و معنا و قصد اصلی نویسنده کد را حفظ میکند. ما باید به نحوی کدهای خودرا پاکسازی کنیم که دیگر توسعه دهندگان از دیدن کدهای ما راضی باشند و بتوانند به راحتی کدهای مارا توسعه بدهند. ریفکتورینگ باید با دقت انجام شود تا از تغییر معنی وخروجی کدهای ما جلوگیری شود. از مزایای آن میتوان به بهبود قابلیت خواندن کد و کاهش پیچیدگی کدها نام برد و این میتواند قابلیت نگهدراری کد های مارا بهبود بخشد و کدهارا برای توسعه و گسترش مرتب تر و واضح تر نمایش بدهد. اگر ریفکتورینگ به خوبی انجام شود به توسعه دهندگان نرم افزاراین امکان را میدهد تا قسمت های آسیب پذیر پنهان یا خاموش سیستم خود را شناسایی کرده و سطوح پیچیده غیر ضروری را حذف کنند. بعنوان مثال میتوانیم آشپزخانه ای را در نظر بگیرم که چندین وعده غذایی برای بیش از چندین نفر درست میکند و به طور معمول میبینید که وسایل خودرا تمیز میکنند و به صورت مداوم ساماندهی میکنند. اگر این کار را نکنیم قطعا نمیتوانیم به خوبی آشپزی کنیم چرا که همه چیز کثیف و هیچ چیز سر جای خود نخواهد بود و دسترسی بعدی ما به ظروف سخت و نا ممکن خواهد بود.
از جمله مزایای ریفکتورینگ میتوانیم به موارد زیر اشاره کنیم:
- بهبود وضوح و قابل خواندن یک صفحه
- حذف مطالب نامرتبط و نامشخص
- باز سازی کدها برای وضوح بیشتر
- انتقال کدها به بخش های دیگر صفحه یا به صفحات دیگر که مناسب تر است
Refactoring در برنامه نویسی
Refactoring: اولین مثال
صحبت در باره ی refactoring را از کجا شروع کنیم؟ اگر بخوایم به روش سنتی تعریفش کنیم باید تاریخچه ای از این موضع و اصول جامع و اصلی و چیز های از این قبیل را بیان کنیم. حتی اگر کسی بخواهد به این روش کنفرانس بدهد قطعا حوصله ی ما سر خواهد رفت و ممکن است کمی خوابمان بگیرد پس بهتر است که در هنگام صحبت کردن برای شنوندگان مثال هایی را همزمان نشان دهیم.
این مثالها میتواند شنوندگان رو بیدار نگه دارد چون آنها میبینند که چه اتفاقی رخ میدهد. ساختن و گفتن چنین تعاریفی بیش از حد آسان است، اما اینکه کارکرد آنهارا به شنوندگان بفهمانیم و بگوییم چطوری آنها را بکار بگیرند سخت است. بنابر این یک مثال میتواند همه چیز را واضح و روشن بیان کند.
ما درباره ی اینکه refactoring چگونه کار میکند میخواهیم صحبت کنیم و یک دید کلی از فرایند refactoing را به شما ارائه بدهیم. بعد از این ما میتوانیم به طور عادی و خیلی راحت اصول اصلی را در بخش و فصل های بعد معرفی کنیم.
با شروع یک مثال مقدماتی، ما با یک مشکل مواجه شدیم که اگر یک برنامه بزرگ را انتخاب کنم، توصیف، نحوه بازنویسی و کارکردن با آن برای خواننده خیلی پیچیده است با این وجود، اگر برنامه ای را انتخاب کنیم که به اندازه کافی کوچک وقابل فهم باشد، به نظر نمی رسد که ریفکتورینگ هم ارزشمند باشد.
صادقانه بخواهم بگویم اصلا ارزش این را ندارد که تمام refactoring هایی که قصد داریم به شما نشان بدهیم را در این برنامه کوچک استفاده کنید. اما اگر کدی که به شما نشان میدهیم بخشی از یک سیستم بزرگتر باشد ریفکتورینگ در آنجا مهم تر به نظرمیرسد. فقط به مثال نگاه کنید و آنرا در یک سیستم بزرگتر تصور کنید.
نقطه شروع
در ابتدا، برنامه ای که شروع کردیم برنامه ی چاپ قبض فروشگاه اجاره ویدیو بود، که ممکن است خیلی از شما بپرسید: فروشگاه اجاره ویدیو چیست؟ به جای پاسخ دادن به این سوال، از مثالی یاد میکنم که هم در قدیم بوده و هم در حال حاضر وجود دارد.
مثال شرکتی از بازیکنان تئاتر است که به رویدادهای مختلفی می پردازند. به طور معمول مشتری چند نمایشنامه را درخواست خواهد کرد و شرکت آنها را بر اساس اندازه مخاطبان و نوع بازی آنها انجام میدهد. در حال حاضر دو نوع نمایشنامه که شرکت انجام می دهد وجود دارد: تراژدی ها و کمدی ها. همچنین این شرکت به عنوان یک مکانیسم وفاداری به مشتریان خود اعتبار حجم میدهد که میتوانند بعنوان تخفیف در اجراهای آینده از آن استفاده کنند.
خوانندگان اطلاعات در مورد نمایشنامه های خود را در یک فایل ساده JSON ذخیره می کنند که به نظر می رسد چیزی شبیه به این است:
plays.json…
{
"hamlet": {"name": "Hamlet", "type": "tragedy"},
"aslike":
{"name": "As You Like It", "type": "comedy"},
"othello": {"name": "Othello", "type": "tragedy"}
{
اطلاعات مربوط به صورت حساب های آنها نیز در یک فایل JSON قرار می گیرد:
invoices.json…
[
{
"customer": "BigCo",
"performances": [
{
"playID": "hamlet",
"audience": 55
},
{
"playID": "aslike",
"audience": 35
},
{
"playID": "othello",
"audience": 40
}
]
}
]
کدی که لایحه را چاپ می کند این تابع ساده است:
function statement (invoice, plays) {
let totalAmount = 0;
let volumeCredits = 0;
let result = `Statement for ${invoice.customer}\n`;
const format = new Intl.NumberFormat("enUS",
{ style: "currency", currency: "USD",
minimumFractionDigits: 2 }).format;
for (let perf of invoice.performances) {
const play = plays[perf.playID];
let thisAmount = 0;
switch (play.type) {
case "tragedy":
thisAmount = 40000;
if (perf.audience > 30) {
thisAmount += 1000 * (perf.audience 30)
;
}
break;
case "comedy":
thisAmount = 30000;
if (perf.audience > 20) {
thisAmount += 10000 + 500 * (perf.audience 20)
;
}
thisAmount += 300 * perf.audience;
break;
default:
throw new Error(`unknown type: ${play.type}`);
}
// add volume credits
volumeCredits += Math.max(perf.audience 30,
0);
// add extra credit for every ten comedy attendees
if ("comedy" === play.type) volumeCredits += Math.floor(perf.audience / 5);
// print line for this order
result += ` ${play.name}: ${format(thisAmount/100)} (${perf.audience} seats)\totalAmount += thisAmount;
}
result += `Amount owed is ${format(totalAmount/100)}\n`;
result += `You earned ${volumeCredits} credits\n`;
return result;
}
خروجی زیر نتیجه اجرای کد بالا است:
Statement for BigCo
Hamlet: $650.00 (55 seats)
As You Like It: $580.00 (35 seats)
Othello: $500.00 (40 seats)
Amount owed is $1,730.00
You earned 47 credits
حال به نظرات در مورد برنامه ای که با آن شروع کردیم، می پردازیم:
نظر شما در باره طراحی این برنامه چیست؟ اولین چیزی که میخواهیم به شما بگویم این است که یک برنامه خیلی کوتاه نیاز به ترفندهای خیلی عمیق برای فهمیدن ندارد *تصور کنید این برنامه در مقیاس بزرگتر است مثلا صدها خط طولانی.**در این اندازه یک تابع تک خطی است که درک آن سخت است.
با توجه به اینکه این برنامه کار می کند، آیا دوست نداشتن کدهای زشت صرفا قضاوت در مورد ساختار زیبایی شناختی است؟
بعد از همه ی اینها کامپایلر اهمیتی نمی دهد که کد زشت و کثیف باشد یا زیبا و پاک باشد. سیستمی که ضعیف طراحی شده، برای تغییر سخت است زیرا دشوار است که چگونگی تغییر و چگونگی این تغییرات با کد موجود ارتباط برقرار کند تا رفتار مورد نظر ما را بدست آورد و اینکه سخت است که بفهمیم و بدانیم که چه چیزی باید تغییر کند. البته این یک فرصت خوب است، چرا که ما اشتباه می کنیم و میتوانیم اشکالاتمان را شناسایی و معرفی کنیم. بدین ترتیب، اگر با اصلاح یک برنامه با صدها خط کد مواجه شدیم، بهتر است آنها را به مجموعه ای از توابع و دیگر عناصر تبدیل کنیم که به ما اجازه بدهد به راحتی آنچه را که برنامه انجام میدهد درک کنیم.
منبع مورد استفاده:
refactoring.improving.the.design.of.existing.code.2nd.edition
در بخش ها بعد "refactoring چیست" به موارد بیشتری خواهیم پرداخت. با تشکر - مجموعه ABLY