میراث رد شده یا Refused bequest به دسته «بد استفاده کنندگان از شیء گرایی» تعلق دارد. این دسته از کدهای بد بو، معمولا استفاده ناقص یا نادرستی از مفاهیم و اصول شیء گرایی دارند.
زمانیکه یک کلاس تنها بخشی از اعضای (خصوصیت، متد و ...) کلاس پدر خود را استفاده میکند، با این الگو سر و کار داریم. در چنین شرایطی دیگر اعضای کلاس پدر یا استفاده نمیشوند و یا حتی در صورت پیاده سازی شدن توسط کلاس، بلااستفاده میمانند. به طور مثال متدهایی از کلاس پدر پیاده سازی میشوند و با پرتاب یک استثناء در بدنهشان از کار میافتند.
یکی از دلایل مهم ایجاد چنین کدهای بد بویی، ایجاد رابطه ارث بری تنها برای استفاده دوباره از کدهای یک کلاس است. در صورتیکه ممکن است کلاس پدر و فرزند هیچ ارتباط منطقی ای از نظر ارث بری با یکدیگر نداشته باشند.
به طور مثال فرض کنید در حال توسعه یک محصول هستید که در آن فروش کالا اتفاق میافتد. در ابتدای کار، تنها کاربران این محصول، شرکتها هستند. روالی نیز برای محاسبه تخفیف مربوط به شرکتها ایجاد شده است. در این روال یک تخفیف پایه وجود دارد که به همه مشتریان تعلق میگیرید و تخفیفهایی نیز وجود دارند که به هر یک از شرکتها تعلق میگیرند. میزان تخفیف نهایی برای یک شرکت از مجموع این دو مقدار بدست میآید. کلاس مربوط به محاسبه تخفیف به این صورت است:
public class DiscountCalculator { protected decimal CalculateGeneralDiscount() { // calculate general discount return 0; } protected decimal AddSpecificDiscount(decimal baseDiscount) { // add specific discounts to base discount return 0; } protected virtual decimal GetFinalDiscount() { var baseDiscount = CalculateGeneralDiscount(); var addedDiscount = AddSpecificDiscount(baseDiscount); return addedDiscount; } }
public class PersonDiscountCalculator : DiscountCalculator { private decimal AddSpecificDiscountForPerson(decimal baseDiscount) { // calculate base discount for person return 0; } protected override decimal GetFinalDiscount() { var baseDiscount = CalculateGeneralDiscount(); var added = AddSpecificDiscountForPerson(baseDiscount); return added; } }
روشهای اصلاح این نوع کد بد بو
public abstract class DiscountCalculator { protected decimal CalculateGeneralDiscount() { // calculate general discount return 0; } protected abstract decimal AddSpecificDiscount(decimal baseDiscount); protected virtual decimal GetFinalDiscount() { var baseDiscount = CalculateGeneralDiscount(); var addedDiscount = AddSpecificDiscount(baseDiscount); return addedDiscount; } }
public class CompanyDiscountCalculator: DiscountCalculator { protected override decimal AddSpecificDiscount(decimal baseDiscount) { // add some customer specific discounts to base discount return 0; } } public class PersonDiscountCalculator : DiscountCalculator { protected override decimal AddSpecificDiscount(decimal baseDiscount) { // calculate base discount for person return 0; } }
جمع بندی
در صورتیکه این کد بد بو اصلاح شود، معمولا با کدی قابل درکتر و با سازماندهی منطقی بهتری روبرو خواهیم بود. به طور کلی رعایت رابطه منطقی بین کلاسها، علاوه بر جلوگیری از بروز مشکل «میراث رد شده»، خوانایی کد را افزایش داده و اعمال تغییرات در آن را نیز آسانتر میکند.