دوستان, مفهوم واژه DIP یعنی dependency inversion principle. یکی از پنج اصل سالیده. اصلا ربطی به Depends نداره. یعنی که که ماژول‌های سطح بالا باید به Abstraction وابستگی داشته باشند به جای low level module. این اصل به کاهش وابستگی‌های میان اجزا در برنامه شما کمک میکنه و می‌تواند کد شما را انعطاف‌پذیرتر، قابل نگهداری‌تر و آزمایش‌پذیرتر کنه.

هیچ کدی نیست که DIP رو رعایت کرده باشه ولی نشه تستش کرد. میخواد streaming باشه. میخواد ربات باشه. میخواد کراول باشه. علتی که تو فریم ورکی مثل scrapy ما تست نویسی نداریم چون این فریم ورک سورس کدش شت کده و DIP توش رعایت نشده برای همین نمیشه تست نوشت. رعایت DIP یک اصله هیچ ربطی به Depends نداره. شما میتونی تو کل اپلیکیشنت ‍Depends بذاری ولی بازم DIP رو رعایت نکرده باشی.

چه چیزی رو باید dependancy inject کنید؟ هرجایی که میتونید decoupling انجام بدید, و یا flexibility اضافه کنید, و یا نیاز به maintainability داره باید براش اینترفیس بنویسید. بعد implementation های مختلف اون اینترفیس رو dependency inject کنید.

پس این بستگی داره به پروژتون. مثلا اگه دارین یک لایبری اوپن سورس مینویسید و میخواین دست یوزر باز باشه تو تغییر روتر ها, اون موقع باید کنترلر روتر رو اینجکت کنید. همیشه باید جواب این ۴ سوال رو بدید موقع inject

  1. Will it reduce the coupling?
  2. Will it make my code more maintable?
  3. Has flexibility increased?
  4. Can I now write the test easily with mocking dependencies? اگه یکی از این سوالا جوابش نه بود یعنی نباید DIP رو اعمال کنید.

مثلا authorization برای user role های مختلف باید inject شه!‌

حالا سوال اصلی, پس D‍epends چیه؟ depends یک فریم ورکی تو فست هست که DIP رو برای شما خیلی راحت میکنه. خلاصش اینه که یک مپر اون پشت هست که Depends object هارو به یک callable وصل میکنه و موقع اجرا شدن روتر اون callable رو اجرا میکنه.

از دو نظر خوبه: ۱. نیاز ‍global variable رو از بین میبره تو سطح برنامه. در نتیجه برنامتون میتونه RAM خیلی کمی مصرف کنه موقع استارت شدن و سریع استارت شه. ۲. پیاده سازی DIP رو خیلی راحت میکنه.

موقع استارت شدن اپلیکیشنتون شما میتونید override_dependency کنید. یا برای هر روتر میتونید هم همینکارو کنید. اینطوری مثلا شما یک abstract database دارید, بعد میتونید همون اینترفیس رو با چند مدل مختلف دیتابیستون تو روتر های مختلف استفاده کنید. یا مسیج بروکر. مثلا یک روترتون message رو با کافکا produce میکنه و یک روترتون میتونه مسیج رو با rabbitmq بفرسته.


Untitled

Untitled

همیشه موقع نوشتن یک کلس به این سوال جواب بدید:

If a class has "two possible reasons to change", then yes, it violates SRP.

دو مثال ساده, از دو کنترلری که یکیشون SRP رو نقض میکنه و اون یکی ‍نقض نمیکنه :)


یکی از بزرگ ترین argue ها اینه که خیلی ازم وقت میگیره و من به شدت مخالف این موضوعم.

ببینید من تجربه خودمو میگم. مورد اول:‌شما وقتی اصول SOLID رو رعایت کنی خیلی کم لازمه دیباگ کنی. هیچوقت با باگای خیلی عجیب و غریب نیازی نیست سرو کله بزنی. مثال میگم من چند روز پیش داشتم با کلاینت AioHTTP کار میکردم. یک باگی خوردم که حالشو نداشتم واقعا بشینم دیباگ کنم که از کجای کدم میاد. چون SOLID رو رعایت کرده بودم به جای اینکه ۳۰ دقیقه دیباگش کنم تو ۵ دقیقه یک کلاینت httpx نوشتم و از اون استفاده کردم :))) من یک ماه درگیر یک باگی تو سلنویم بودم در صورتی که اگه SOLID رو رعایت کرده بودم تو چند دقیقه میتونستم سلنیوم رو به playwright تغییر بدم! اون flexibility که به شما میده بهتون اجازه میده که صورت سوال رو کلا پاک کنید. حالا اگه SOLID ننوشته بودم هم تستامو باید ریفکتور میکردم هم کل کدامو!