با عرض سلام و احترام.
پیشاپیش از شما دوست عزیز و گرامی، بابت وقتی که برای مطالعه ی این مطلب خواهید گذاشت، سپاسگزارم.
تقاضا دارم، در صورت مشاهده ی اشتباه متنی یا محتوایی، به اینجانب اطلاع دهید تا (ضمن کمک به یادگیری بنده) در اسرع وقت برای اصلاح متن اقدام نمایم.
شماره ی تماس:
09215149218
نشانی پست الکترونیکی:
RezaQadimi.ir@Gmail.com
آدرس سایت ها:
https://Reza-Qadimi.ir - https://WannaDate.ir
هدف من در این مقاله، آشنایی شما با چهارمین اصل از اصول .S.O.L.I.D، یعنی ISP یا Interface Segregation Principle است.
اصل Interface Segregation، یکی دیگر از اصول SOLID است، که توسط Robert C. Martin معرفی شد.
این اصل بیان کننده ی آن است که:
کلاینت (کلاسی که وظیفه ی پیاده سازی Interface را بر عهده دارد)، نباید مجبور به پیاده سازی موجوداتی شود که به آن ها احتیاجی ندارد و از آن ها استفاده ای نمی کند.
به عبارتی این اصل به ما توصیه می کند که:
از طراحی اینترفیس های چاقی که کلاینت (کلاسی که وظیفه ی پیاده سازی Interface را بر عهده دارد) را مجبور به پیاده سازی ویژگی ها و رفتارهایی میکند که به آن نیازی ندارد، جلوگیری کنیم، و به جای آن اینترفیس های لاغرتری (کوچک تر) طراحی کنیم، که صرفا دارای ویژگی ها و رفتارهایی هستند که کلاس پیاده سازی کننده ی آن اینترفیس، به آنها نیاز دارد.
به مثال زیر توجه کنید:
public interface IPayment { T Status<T>(); void InitiatePayment(); System.Collections.Generic.IList<T> GetPayments<T>(); }
public class BankPayment : object, IPayment { public BankPayment() : base() { } public T Status<T>() { // ... } public void InitiatePayment() { // ... } public System.Collections.Generic.IList<T> GetPayments<T>() { // ... } }
نکته: برای کاهش پیچیدگی، پیاده سازی business را کنار گذاشته و به سراغ مفاهیم میرویم.
بعد از مدتی، از طرف بانک اعلام میکنند:
"علاوه بر سرویس پیاده سازی شده، به سرویس "LoanPayment" هم نیاز داریم."
و در ادامه بیان میکنند که:
"سرویس "Loan Payment" تا حدودی شبیه سرویس "Bank Payment" است، اما با عملیات های بیشتر."
public interface IPayment { // Original Method(s) void InitiateRePayment(); void InitiateLoanSettlement(); }
public class LoanPayment : object, IPayment { public BankPayment() : base() { } public void InitiatePayment() { // throw some exception... } public T Status<T>() { // ... } public System.Collections.Generic.IList<T> GetPayments<T>() { // ... } public void InitiateRePayment() { // ... } public void InitiateLoanSettlement() { // ... }
public class BankPayment : object, IPayment { public BankPayment() : base() { } public void InitiatePayment() { // ... } public T Status<T>() { // ... } public System.Collections.Generic.IList<T> GetPayments<T>() { // ... } public void InitiateRePayment() { // throw some exception... } public void InitiateLoanSettlement() { // throw some exception... } }
مسئله اینجاست، که پیاده سازی این رفتارها از سر ناچاری و کاملا ناخواسته است، و در آینده منجربه مشکلات جانبی زیادی میشود. اما راه حل چیست؟
public interface IPayment { T Status<T>(); System.Collections.Generic.IList<T> GetPayments<T>(); }
public interface IBankPayment : IPayment { void InitiatePayment(); }
public interface ILoanPayment : IPayment { void InitiateRePayment(); void InitiateLoanSettlement(); }
public class BankPayment : object, IBankPayment { public BankPayment() : base() { } public void InitiatePayment() { // ... } public T Status<T>() { // ... } public System.Collections.Generic.IList<T> GetPayments<T>() { // ... } }
public class LoanPayment : object, ILoan { public LoanPayment() : base() { } public void InitiateRePayment() { // ... } public void InitiateLoanSettlement() { // ... } public T Status<T>() { // ... } public System.Collections.Generic.IList<T> GetPayments<T>() { // ... } }
میبینید که با جا کردن اینترفیس ها، و تبدیل یک اینترفیس چاق به اینترفیس های کوچکتر، دیگر نیازی به پیاده سازی موجوداتی که مورد نیاز نیستند، نخواهیم بود و صرفا رفتارها و ویژگی هایی را پیاده سازی میکنیم، که در سرویس خود به آن نیاز داریم.
طراحی اینترفیس ها به این شکل، گاها موجب نقض اصل Single Responsibility می شود، چرا که باعث میشود بعضی از مواقع (سهوا) موجودات غیر مرتبط را در یک اینترفیس قرار بدهیم.
پی نوشت:
اصل Liskov Substitution (می توانید اینجا مطالعه کنید) در رابطه با Subtype ها و مفهوم Inheritance است، اما Interface Segregation Pinciple در رابطه با Business Logic ارتباط با کلاینت هاست.
پی نوشت: در مقاله ی بعد، به بررسی اصل Dependency Inversion Principle خواهیم پرداخت.
معرفی:
رضا قدیمی هستم. برنامه نویس و دانش آموزِ حوزه ی وب، بسیار مشتاق در یادگیری مفاهیم و اطلاعات جدید در این حوزه.