In one of the previous articles, I wrote about SOLID — great principles for developing great apps. But what is the Dependency Injection (DI) pattern, and why I mentioned SOLID?

What is the Dependency Injection (DI) pattern?

DI is a pattern that makes a class independent of its dependencies.

Let’s do some code:

public class FoxMiner {

    private var pick: Pick

    init(pick: Pick) {

        self.pick = pick

    }

    …

}

Don’t forget about D (dependency inversion) principle from SOLID:

public protocol Pick {

    func hit()

}

public class MinerPick: Pick {

    func hit() {

        print("The miner's pick hit hard")

    }
}

So why is DI important?

The common mistake that every young programmer makes is:

public class FoxMiner {

    private var pick: Pick = MinerPick()

    init() {}

    ...

}

Or even worse:

public class FoxMiner {

    private var pick: MinerPick = MinerPick(

    ...

}

It means that dependencies of your class rule it. DI pattern prevents it.

FoxMiner shouldn’t care about creating its dependencies. If you remember the first principle of SOLID — Single responsibility. You can interpret this as even creating any other objects inside the class breaking this principle. 

If FoxMiner creates MinerPick on its own, then the programmer can’t check the entire logic of FoxMiner class. The writing test process will be like hell hard. Someone else should create and then inject an instance of MinerPick (not an instance of that particular class, to be exact, but a mock of it).

It is easier to test logic when you can inject dependencies outside of the class:

public class FoxMiner {

    private var pick: Pick

    init(pick: Pick) {

        self.pick = pick

    }

    …

}

let fox = FoxMiner(pick: MinerPick()) //for production

or

let fox = FoxMiner(pick: MockMinerPick()) //for tests

So you can easily replace all dependencies with mock classes, and writing tests will be a fun process.

Ok, but who will create the necessary instances of classes?

Usually, we rely on the DI framework. Then it is the framework that will responsible for creating class instances.

DI framework

Let me introduce Swinject — a lightweight dependency injection framework for Swift.

For example, we have a bunch of protocols and classes:

protocol Food {
    var name: String? { get }
}

class HotDog: Food {
    let name: String?

    init(name: String?) {
        self.name = name
    }
}

and

protocol Person {
    func play()
}

class Buyer: Person {
    let food: Food

    init(pet: Food) {
        self.food = food
    }

    func eat() {
        let name = food.name ?? "something"
        print("I'm eating \(name).")
    }
}

Swinject is very simple in use. First, we should have a container that will register all our Protocols:

let container = Container()

Now let’s register some protocol and its realization:

container.register(Food.self) { _ in HotDog(name: "hot dog") }

Now when we want to get an object that matches to Food protocol, we call:

let foodObject = container.resolve(Food.self)!

We also can inject inside of registration process:

container.register(Person.self) { r in
    Buyer(pet: r.resolve(Food.self)!)
}

Now in code:

let buyer = container.resolve(Person.self)!
person.eat() // prints "I'm eating hot dog."

Services must be registered to a container before they are used. Services must be registered to a container before they are used. So you can register them in AppDelegate. Also, it is better to use a facade for the Swinject container so you can change the framework for injection whenever you want.

If you don’t want to use a third-party library, then definitely you should check out this library, as your own solution will be like Swinject in the end anyway.

Protocol Buffers vs JSON

Protocol Buffers vs JSON

Protocol Buffers vs JSON

Protocol Buffers vs JSON

Have you ever wondered how your favorite mobile app delivers lightning-fast updates or how social media platforms handle millions of messages per...

A comprehensive guide to mobile app development process

Mobile App Development Process: 7 Steps to Build an App

Mobile App Development Process: 7...

Mobile App Development Process: 7 Steps to Build an App

Developing a mobile application from A to Z is rather long and laborious work. But we have prepared for you a practical application development...

Unicorn Companies' Tech Stacks.

Tech Stack of Prominent Companies: What Are Industry...

Tech Stack of Prominent Companies:...

Tech Stack of Prominent Companies: What Are Industry Giants Using to Power Their Applications?

Netflix vs. Hulu, Hubspot vs. Salesforce, Spotify vs. Pandora, Databrick vs. ByteDance, Canva vs. Miro, and Uber vs Lyft are the rivalries that...