Interface Segregation Principle

این اصل می‌گوید که مصرف‌کنندگان یک کلاس نباید مجبور به استفاده از متدهایی باشند که به آن نیازی ندارند.
فرض کنید می‌خواهید یک وب‌سایت e-commerce توسعه دهید که نیاز به قابلیت سبد خرید و مکانیزمهای وابسته به پردازش سفارش دارد. در این حالت نیاز به اینترفیسی با نام IOrderProcessor خواهیم داشت که دارای متدهای زیر است:

bool ValidateCardInfo(....);
bool ValidateShippingAddress(....);
void ProcessOrder(....);

در ابتدا فرض بر این است که اپلیکیشن تنها پرداخت آنلاین را از طریق کارت‌های اعتباری ساپورت می‌کند؛ بنابراین برای اینترفیس IOrderProcessor سه متد تعریف کرده‌ایم؛ متد ValidateCardInfo قرار است اطلاعات کارت اعتباری را اعتبارسنجی کند. متد ValidateShippingAddress نیز قرار است اطلاعات مکان سفارش را اعتبارسنجی کند. در نهایت نیز متد ProcessOrder کار پردازش سفارش را با ثبت سفارش درون سیستم آغاز خواهد کرد.

بنابراین کلاس OnlineOrderProcessor اینترفیس IOrderProcessor را پیاده‌سازی خواهد کرد. فرض کنید بر حسب نیاز می‌خواهیم پرداخت آنلاین از طریق کارت اعتباری را غیرفعال کنیم؛ و پرداخت‌ها در محل انجام شوند. در نگاه اول راه‌حل خیلی ساده است؛ کافی است یک کلاس دیگر با نام CashOnDeliveryOrderProcessor که اینترفیس IOrderProcessor را پیاده‌سازی کرده باشد، ایجاد کنیم. اما در حالت پرداخت در محل نیازی به اعتبارسنجی کارت اعتباری نیست یعنی متد ValidateCardInfo در این کلاس جدید بلااستفاده خواهد بود بنابراین نباید برای این متد پیاده‌سازی‌یی ارائه شود:

public bool ValidateCardInfo(CardInfo obj)
{
    throw new NotImplementedException();
}

تا اینجا اپلیکیشن‌ به خوبی کار می‌کند، اما فرض کنید بنا به دلایلی حالت پرداخت آنلاین نیاز به چندین مرحله اعتبارسنجی دیگر دارد. طبیعتاً اینترفیس IOrderProcessor برای افزودن تغییرات جدید بروزرسانی خواهد شد، کلاس OnlineOrderProcessor نیز این تغییرات را پیاده‌سازی خواهد کرد. به هر حال اگرچه کلاس CashOnDeliveryOrderProcessor نیازی به این تغییرات ندارد، اما باید این تغییرات را در این کلاس نیز پیاده‌سازی کنید. به عبارت دیگر کلاس CashOnDeliveryOrderProcessor مجبور است این تغییرات را پیاده‌سازی کند (به صورت NotImplementedException). خب این اصل ISP را نقض خواهد کرد.

در طراحی جدید نیاز به دو اینترفیس IOrderProcessor and IOnlineOrderProcessor خواهیم داشت. اینترفیس IOrderProcessor تنها حاوی دو متد می‌باشد:
– ValidateShippingAddress
– ProcessOrder

public interface IOrderProcessor
{
	bool ValidateShippingAddress(/* input */);
	void ProcessOrder(/* input */);
}

public interface IOnlineOrderProcessor
{
	bool ValidateCardInfo(/* input */);
}

دو متد فوق توسط OnlineOrderProcessor و CashOnDeliveryOrderProcessor مورد استفاده قرار خواهند گرفت. متد ValidateCardInfo به درون اینترفیس IOnlineOrderProcessor جدید منتقل خواهد شد. این اینترفیس تنها توسط کلاس OnlineOrderProcessor پیاده‌سازی خواهد شد.

اکنون هر تغییر در حالت پرداخت توسط کارت اعتباری، تنها محدود به اینترفیس IOnlineOrderProcessor و کلاس‌هایی که این اینترفیس را پیاده‌سازی کنند خواهد بود. در نتیجه کلاس CashOnDeliveryOrderProcessor نیازی به تغییر ندارد.

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top