Dependency Inversion Swift
Dependency inversion is the last letter of SOLID therm. Last position doesn’t mean less important than the other, in my opinion this principle is the most important software design pattern.
The general idea of this principle is as simple as it is important:
High-level modules, which provide complex logic, should be easily reusable and unaffected by changes in low-level modules, which provide utility features.
In simple words — we shouldn’t use class name in any function and variable declaration. Instead of this, we should use protocols or abstract class.
Based on this idea, Robert C. Martin’s definition of the Dependency Inversion Principle consists of two parts:
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.
If it’s your first time with DI you probably don’t understand those sentences because it sounds incomprehensible. Don’t worry! In next step i will show you the difference between traditional and inversion dependency.
Imagine that you have to implement screen in your app to fetch user friends from API. In traditional way you will create some service and add property to the class. Example:
Congrats!🙌🏻 Project manager and client are happy. But in one day requirements are changing. You have to change logic of fetch friends from API to database (CoreData) 🤔.
service variable is of a concrete type
SpecificReceiver and you invoke service method directly. This means the high level Profile depends on the low level FriendsService.
Why is this bad? Because if you were to change the FriendsService, you would have to change the Profile as well.
So how to change the code to conform to dependency inversion principle? Let’s move to the next step.
To design this approach we have to start with an abstraction. You have to create protocol which service to fetch friends from API or database conform.
Let’s redesign Profile class.
In this scenario Profile class depends on the FriendsWorker protocol not on a concrete type
FriendsService. This approach give you the opportunity to change logic without changing code in Profile class! That's awesome. If you want to fetch friends list form API, create FriendsService class conform to FriendsWorker protocol and inject this object to Profile init! What about fetch friends from Database? How to do it? In the same way!
The following diagram presents the dependency inversion. Each service or database just needs to conform to the FriendsWorker protocol in order to be used by Profile.
That’s it. Thanks for being awesome. Please leave a comment below. Clap if you liked it ✌🏻