Farhad Nosrati فرهاد نصرتی
Farhad Nosrati فرهاد نصرتی
خواندن ۴ دقیقه·۳ سال پیش

Interface segregation Principle و dependency Inversion Principle

دوتا اصل اخر 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 تغییر دهیم .

بدون این که به کد هایمان دست بخورد ، رفتار جدید را جایگزین رفتار قبلی کردیم .

هدف :

جداسازی از وابستگی .

منعطف بودن نرم افزار یعنی قسمتی از نرم افزار رو تغییر بدیم بدون این که به جای دیگر نرمافزار دست بخوره .

قابلیت تست بالا .


اگه ایراد تایپی داشتم یا ایراد توضیح داشتم خیلی خوشحال میشم بهم بگید تا اصلاح کنم .






























https://github.com/nosratifarhad
شاید از این پست‌ها خوشتان بیاید