دوتا اصل اخر solid که تلاش برای استفاده درست از Interface ها دارد .
Interface
قابلیت های یکسان و پیاده سازی های متفاوت .
هدف : اعمال قوانین و رفتار ( behavior ) به نرم افزار که پیشنهاد شده برای تمام ، ( اصطلاحا module هامون ) قوانین داشته باشیم .
Interface segregation Principle
چهارمین اصل solid : اصل جداسازی Interface ها .
در این اصل تاکید میشود که کلاس ها نباید متد هایی که نیاز ندارن را پیاده سازی کنند ( اصطلاحا ، چرا باید متد هایی را در اختیار کاربر ( developer ) قرار دهیم که هیچوقت قرار نیست برایشان کد تولید شود و فقط NotImplimentedException ، throw میکند )
مثال : فرض کنید یه روال کار ( workflow ) داریم ، که سه مرحله دارد .
زمان پیاده سازی : تمام این سه مرحله را در یک interface قرار دهیم ( اصطلاحا : سه signature در یک interface ) و به اعضای هر مرحله ، در سه کلاس جدا پیاده سازی کنیم ( یعنی یک پدر و ۳ فرزند یا inheritance ) .
یادآوری : وقتی یک کلاس از Interface ارث بری میکن موظف است تمام signature های آن را پیاده سازی کند )
پس این عمل موجب میشود در هر پیاده سازی فقط یکی از مراحل ( method ها ) رفتار یا بدنه مربوط به آن مرحله را داشته باشه و دوتا متد دیگه NotImplimentedException پرتاپ کنند چون عملکرد انها مربوط به آن کلاس نیست .
حالا فرض کنید ، اگر بعد ها یک مرحله دیگر به مراحلمان اضافه شود، چیکار باید بکنیم ؟؟؟ :)
در این شرایط دو تا اصل solid را ( srp ، isp ) رعایت نمیکنیم .
نتیجه : به همان اندازه که کاربرمان ( developer ) نیاز دارد ، متد در اختیارش قرار میدهیم ، نه بیشتر .
Dependency Injection pattern
یکی از راه های پیاده سازی اصل پنجم solid یعنی dependency Inversion Principle (معکوس سازی وابستگی ها ) استفاده از Dependency Injection pattern هست که ، از اصل delegation استفاده میکند .
معکوس سازی وابستگی ها یعنی ماژول های سطح بالا ( high-level module ) ، نباید به ماژول های سطح پایین ( low-level module ) وابسته باشند و یا از آنها خبر داشته باشند ( اصطلاحا، لایه services نباید به لایه DAL وابسته باشه ).
: Delegation یا DI
هردو یک وظیفه دارند : وابستگی ها از کلاس ها خارج میکنند و به جای این که کلاس هایمان به پیاده سازی ( concrete ) وابسته شوند ، انهارا به یک سری قرار داد ( contract ) وابسته میکنند .
تعریف delegation : تصور کنید ، یک سرویس داریم که یک سری وظایف دارد ، برای انجام وظایفش نیاز به یک سری اشیاع بیرون دارد ( مثل class ) که اگر خود سرویس ، مسئولیت تهیه این وابستگیها را داشته باشد ، کاملا به انها وابسته میشود ( مثل نمونه سازی از کلاس اشیا داخل سرویس ) .
برای این که وابستگی ایجاد نشود ، میتوان مسئولیت ساخت نیازمندیها را به کلاس سرویس گیرنده ( استفاده کننده از سرویس ) داد و برایش قانون وضع کرد که اگر کسی خواست از کلاس سرویس دهنده استفاده کند ، باید خودش مسئولیت ساخت نیازمندیهایش را زمان نمونه سازی از سرویسدهنده ، برایش براورده کند .
با این روش ما تمام وابستگی ها را از داخل سرویس دهنده خارج یا حذف میکنیم و مسئولیت آن را به سرویس گیرنده میدهیم ولی این روش مشکل ساز و سخت است .
چطور از اصل DI یا delegation به درستی استفاده کنیم و مسئولیت تهیه نیازمندی هارا از سرویس گیرنده ، بگیریم و آن را به یک کلاس خارجی دیگر وابسته کنیم ( ارجاع بدیم جای دیگر ) .
: DIContiner
یه نوع service provider هست ( با رعایت اصل Delegation ) .
تعریف : همه وابستگی ها را یکجا ( در یک subsystem ) تعريف میکنیم و همان subsystem مسئول مديريت همه وابستگی های نرم افزار ماست .
برایش قانون وضع میکنیم :
مثال قانون : هر کی از سرویس Isms خواست استفاده کند ، کلاس sms را بهش پاس بده و بعد ها اگر business سرویس sms مان تغییر کند ، فقط کافی اسم کلاس sms فعلی را به اسم کلاس جدید مثل NewSMS تغییر دهیم .
بدون این که به کد هایمان دست بخورد ، رفتار جدید را جایگزین رفتار قبلی کردیم .
هدف :
جداسازی از وابستگی .
منعطف بودن نرم افزار یعنی قسمتی از نرم افزار رو تغییر بدیم بدون این که به جای دیگر نرمافزار دست بخوره .
قابلیت تست بالا .
اگه ایراد تایپی داشتم یا ایراد توضیح داشتم خیلی خوشحال میشم بهم بگید تا اصلاح کنم .