اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
سه دقیقه
معمولا زمانیکه متدی از امکانات کلاس دیگری غیر از کلاسی که در آن تعریف شده است استفاده میکند، نیاز به چنین بازسازی کدی داریم. روش کلی این بازسازی کد، انتقال متد به کلاسی است که بیشترین تعلق را به آن دارد!
جابجایی متد یکی از موارد پر تکرار و مهم در امر بازسازی کد است. این بازسازی در مراحل انجام دیگر بازسازیهای کد، مانند شکستن کلاس نیز استفاده میشود. با این روش ساده میتوان کلاسهایی با مسئولیتهای محدود و مشخص را توسعه داد.
مراحل انجام این بازسازی کد
- تمامی امکانات کلاس مبدا را که متد مورد نظر از آنها استفاده میکند، بررسی نمایید که آیا آنها نیز نیاز به انتقال دارند یا خیر.
- کلاسهای پدر و فرزند کلاس مبدا را برای یافتن تعاریف دیگری از متد مورد نظر بررسی نمایید. اگر تعاریف دیگری وجود داشتند به راحتی نمیتوان متد را جابجا کرد. در این صورت اگر قصد جابجایی داشتید، باید به فکر جابجایی رابطه چند ریختی موجود نیز باشید.
- متد را در کلاس مقصد ایجاد نمایید.
- بدنه متد را به متد مقصد منتقل نمایید و تمامی امکانات استفاده شده در آن را طوری تغییر دهید که در کلاس جدید کار کند. اگر متد، نیاز به اشارهای به کلاس مبدا داشت، باید تعیین نمایید که به چه صورت این اشاره انجام شود. اگر مکانیزم مدیریت خطایی (exception handling) در متد مبدا پیاده سازی شده بود، تعیین کنید که آیا متد مبدا نیز کماکان امر مدیریت خطا را انجام خواهد داد، یا به متد مقصد انتقال خواهد یافت.
- کد کلاس مقصد را کامپایل و تست نمایید.
- اگر متد مبدا را به عنوان فراخوان متد مقصد نگه داشتید، باید تصمیم بگیرید که کلاس مقصد در آن متد به چه صورت استفاده خواهد شد.
- فراخوانی متد مقصد را به بدنه متد مبدا اضافه کنید.
- کد را کامپایل و تست نمایید.
- در مورد سرنوشت متد مبدا تصمیم گیری نمایید که آیا نیازی به وجود آن هست یا خیر. در صورتیکه از متد مبدا در مکانهای زیادی استفاده شده یا متد در کتابخانه یا فریم ورکی است که کنترلی بر روی استفاده کنندگان آن وجود ندارد، احتمالا باقی ماندن متد به عنوان صرفا فراخوان، ایده خوبی باشد.
- اگر متد مبدا را حذف کردید تمامی استفاده از آن را باید به متد مقصد تغییر دهید. توجه داشته باشید ممکن است سناریو ساختن کلاس جدید با کلاس قدیمی متفاوت باشد.
- مجددا کد را کامپایل و تست نمایید.
مثال: فرض کنید نرم افزاری برای مدیریت رویدادها و شرکت کنندگان آنها تهیه کردهایم. در این نرم افزار، کلاسی با نام Event وجود دارد و کلاسی نیز با نام Person که نام آنها کاملا نمایانگر استفاده آنها است.
بخشی از بدنه این کلاسها به صورت زیر است:
public class Event { public List<Person> Participants { get; internal set; } } public class Person { public int Id { get; private set; } public void Participate(Event ev) { var isParticipatedAlready = ev.Participants.Any(ff => ff.Id == Id); if (isParticipatedAlready) return; ev.Participants.Add(this); } }
در کد مربوط به کلاس Person، شاهد متدی هستیم که عمل ثبتنام فرد را در یک رویداد انجام میدهد. اما با دقت به این متد مشاهده میکنیم که بدنه این متد بیشتر از اعضای کلاس Event استفاده میکند. حتی این استفاده باعث شده است که خصوصیت Participants از کلاس Event به صورت public تعریف شود که خود مشکل دیگری در این طراحی است.
در چنین شرایطی، بازسازی کد جابجایی متد میتواند در راستای انتقال مسئولیتهای مناسب هر کلاس به بدنه آن و بهبود طراحی کمک کند. بعد از بازسازی کد شاهد چنین طراحیای هستیم:
public class Event { protected List<Person> Participants { get; set; } public void Participate(Person person) { var isParticipatedAlready = Participants.Any(ff => ff.Id == person.Id); if (isParticipatedAlready) return; Participants.Add(person); } } public class Person { public int Id { get; private set; } }
بازسازیای که انجام شد، دو تاثیر را بر روی طراحی این کلاسها داشته است:
اول: جایگذاری بهتر و منطقیتر مسئولیتهای یک کلاس
دوم: کپسوله سازی آسانتر کلاس ها
بازسازی کد جابجایی متد، سنگ بنای بیشتر بازسازیهای مورد نیاز در فعالیتهای روزمره تولید یا نگهداری نرم افزار است. علارغم این که این بازسازی ساده به نظر میرسد، در مجموعه کدهای پیچیده، انجام این بازسازی ممکن است امری طاقت فرسا شود.