Learning Dependency Injection using Swift

Want to make your Apps conform to the principles known as SOLID?

Image for post
Image for post

In object-oriented programming SOLID is an acronym for five design principles. One of these design principles is the Dependency inversion principle. We can use this principle to create better, more testable Swift code.

Motivation

High level modules should not be dependent on low-level modules, but rather abstractions. If this is true, we can swap out classes rather than making a fixed dependency for a concrete class.

The Theory

Dependency injection requires:

  • a server to be used
  • a client that uses the service
  • an interface between the client and service (used by the client and implemented by the service)
  • an injector that creates a service instance and injects it into the client

This can then be used for mocking and testing the implementation of a server, with any particular client.

Step-by-step

A high-level class A would be dependent on a specific instance of class B

Image for post
Image for post
A tightly coupled class where the Client relies on the Server

In Swift this might look something like the following implementation:

The Client Class is highly dependent on the Server Class, and any changes to the Server class would likely require changes to the Client class. This tight coupling is highly discouraged.

Image for post
Image for post
The client is highly dependent on the service here

Dependency inversion works in such a way that we can swap in another server at any point. Any server instance can be swapped out.

Image for post
Image for post
The client can use any particular service instance

However, in Swift we declare an protocol (an interface) outside the client. In this model, we have both the client and the server as dependencies on the receiver protocol.

To overcome this we can compose the client out of abstractions, and inject the instance.

Image for post
Image for post

In Swift code we have a position as below:

Dependency injection in view controllers

Property-based dependency injection

If the view controller identifier in the storyboard changes, the data would silently not be passed to the view controller. This gives unexpected behaviour that is only apparent at runtime.

The interface to the SegueViewController implies that the view controller cannot be used without the passed data, but the view controller can be created without one.

var passedData : String!

Initializer-based dependency injection

We can create

And within the view controller we declare the xib file to be used.

Conclusions

It isn’t a coincidence that dependency injection is a major principle that software developers integrate into their code.

By using dependency injection there is a chance of properly testing your code, which will increase you test coverage and make your manager happy!

By combining the principles with your existing code (that might use storyboards) you are creating a more stable, and better quality project even if you have come onto an existing project at some point of development in the App.

As we have seen, it is not that difficult. Why not implement this in your project today?

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store