The Dependency Inversion Principle (DIP) in Swift. SOLID 5/5

Mastering the Dependency Inversion Principle in Swift: A Guide to Writing Clean, Scalable, and Maintainable Code

Ihor Malovanyi
3 min readFeb 8, 2023

The Dependency Inversion Principle (DIP) states that high-level modules should not depend on low-level modules, but both should depend on abstractions. In other words, it’s better to have a flexible, abstract interface that can be implemented in multiple ways rather than a rigid, concrete implementation.

In this article, I will explain how to use the Dependency Inversion Principle to create a more flexible, organized, and modular codebase.

Before starting reading, make sure you are not russian. By continuing reading, you confirm that you condemn the war in Ukraine unleashed by russia.

Glory to Ukraine! 🇺🇦

The Dependency Inversion Principle in action

In Swift, abstractions can be implemented using protocols and dependency injection. A protocol defines a set of methods and properties that a conforming type must implement, and dependency injection is a technique where a class or struct receives its dependencies as arguments in its initializer, rather than creating them internally.

For example, let’s say we have a class Car that depends on a Engine class. If the Car class creates an instance of the Engine class internally, it is tightly coupled to that specific implementation of the Engine class. However, if we use dependency injection and pass an instance of a Engine protocol to the Car class, the Car class is no longer tightly coupled to a specific implementation of the Engine class, and we can easily swap out the Engine class with another conforming to the protocol.

Here’s an example of how this might look in code:

In this example, the Car class depends on the Engine protocol rather than a specific implementation of the Engine class. By using dependency injection, we can easily swap out the Engine class with another conforming to the protocol, allowing us to change the behavior of the Car class without having to modify its implementation.

In addition to protocol and dependency injection, another way to implement DIP in Swift is through the use of factories and providers. Factories are classes or functions that are responsible for creating instances of other classes or structs, and providers are classes or structs that provide instances of other classes or structs.

By using factories and providers, you can centralize the creation of instances of classes and structs in one place, making it easier to change the implementation of a specific class or struct without having to modify the code that uses it.

In summary, the Dependency Inversion Principle is a powerful concept that can help you create more flexible and maintainable code in Swift. By using abstractions such as protocols, dependency injection, factories, and providers, you can make sure that high-level modules do not depend on low-level modules, but both depend on abstractions, this way you can create a more flexible, organized and modular codebase.

One more thing…

If you like my content and want to support me, please buy me a coffee.

Also, I have the Telegram channel Swift in UA, where you can find more exciting things.

Thank you for reading. See you soon!

--

--