dependencyinjection

Dependency Injection

Inversion of Control Is a pattern of providing any type of object (that implements or controls something) instead of directly doing so. It is an act of inverting and or redirecting the control to an external agent.

Dependency Injection Is a specific usage of inversion control. Implementations are somehow passed on to the object, then this object starts to depend on it to be able to execute its behavior correctly.

Example Instead of calling a specific library directly, an app calls a contract or interface that refers to the concrete implementation. Which is controlled by the application instead of the library.

Pros

  1. Low coupling
  2. Testability
  3. Reusability
  4. Legibility
  5. Separation of Concerns

Cons

  1. Complexity
  2. Highly coupled to the DI framework

Basic Dependency Injection

Initializer Based

The dependencies are passed over to the object by its initializer Instead of relying on the singleton, we now utilize the NetworkProtocol, this is already a form of dependency injection. We can then test like the following:

Property Based

The dependency is injected from a property that can be modified externally. This is a good option when you have no control over the object’s initialization such as when you have ViewControllers from storyboards. Example of testing

Parameter Based

The dependency is injected from a parameter of a function. It’s a good option for testing legacy methods without breaking changes. Instead of passing the dependency to the initializer like an initializer-based DI, we pass it as a parameter of a function.

Advanced Dependency Injection

Singletons

Singletons are not always bad, it really depends on HOW, WHEN, and WHY are you using them. Just don’t make them ‘God’ classes with huge responsibilities. Make them as single-purpose as you possible by just taking care of a single aspect of the app.

Another way you might create a DI for a singleton is through the Singleton+ (read: singleton extended) pattern. You do not need to create private initializers like before. It’s gonna allow us to have more control over the shared state while still keeping the shared instance as an option. This implementation uses open access modifier to make it possible to be inherited by other classes so we can control some functions or properties. Now, how will we test this?

Factories

This design pattern focuses on solving the issue of creating objects without making their concrete types explicit. The objective here is to encapsulate (hide) implementation details about how the object is created. The advantage is that the consumer does not need to know the internal logic of how the object is created since we provide a common interface.

For example, we have the following view controller, and when we want to create tests, it would be really hard since the VC requires some dependencies. So what we can do is create a factory, essentially we are saying “hey factory please give me this VC, I don’t care how you do it but I just want this VC” Now, we can use our factory inside the view controller.

Service Locator

It is basically a big singleton of instances. It is a pattern that provides access to services/dependency instances. Resolver will tell you how to resolve something & Container will hold the dependency. When we want to register something, we simply get the key & save it to the dictionary. The first function is for the regular instances and the second function is for the lazy instances. When you register a lazy instance, you register effect reference(?), it’s a closure & connect a specific key to the factory. https://www.youtube.com/watch?v=M0c6DGNOUYc

Property Wrappers