Michael Long
2 min readDec 18, 2019

--

“Constructor injection should be your go-to technique for clear, decoupled code.”

I wrote about this in Modern Dependency Injection in Swift, but I tend to dislike constructor injection. For one thing, it tends to require a lot of boilerplate initialization code. (Define the property, make the initializer and define the argument, assign the argument to the property. Add even more code if you need to guard against nulls. Rinse and repeat as needed.)

class MyViewModel {    
private var userStateMachine: UserStateMachine
private var keyValueStore: KeyValueStore
private var bundle: BundleProviding
private var touchIdService: TouchIDManaging
private var status: SystemStatusProviding?

init(userStateMachine: UserStateMachine,
bundle: BundleProviding,
touchID: TouchIDManaging,
status: SystemStatusProviding?,
keyValueStore: KeyValueStore) {

self.userStateMachine = userStateMachine
self.bundle = bundle
self.touchIdService = touchID
self.status = status
self.keyValueStore = keyValueStore
}
...
}

But my primary issue with it is that it needlessly exposes your service’s internals.

To use your own example, I have something that wants to use the PayrollSystem. Fine. But now in order to get a payroll system I first need to know about BankingServices and where to get one, all in order to simply pass it to the payroll system.

Worse, what if the banking service has a dependency (repository)? What if that dependency has a dependency (api service)?

Now my code is neither clear nor decoupled. The “user” of the PayrollSystem now knows about and as such is coupled to half of my application’s code since it’s required to properly instantiate all of the objects needed. True, you could reach out to factories or singletons to get what you need, but that simply changes the nature of the coupling.

Do `BankingServices()` or `BankingServices.instance` and the end result is still the same. X still knows about and is coupled to BankingServices.

All of which is why one uses a dependency injection system. X needs a PayrollSystem and the injection system returns one, properly instantiated and ready to use. X neither knows about, nor cares about BankingServices or anything else the PayrollSystem needs.

Nor should it.

Dependency injection is a great technique, but done manually you still end up with relatively tightly coupled code. All that’s changed is the nature of the coupling.

--

--

Michael Long
Michael Long

Written by Michael Long

I write about Apple, Swift, and SwiftUI in particular, and technology in general. I'm also a Lead iOS Engineer at InRhythm, a modern digital consulting firm.

No responses yet