Inversion of Control (IoC)
Teagan Glenn
Teagan42
Senior Software Engineer
Aetna
Inversion of Control
An abstract principle describing an aspect of some software architecture designs in which the flow of control of a system is inverted in comparison to procedural programming
Huh?
Inversion of Control
A chunk of code that uses, or consumes, another chunk of code is in control of the process, not implementation
Inversion of Control
Purpose
Decouple Your App
- Dependency Contracts
- Allows for interchangeable code
- Encapsulation of modules
Facilitate Testing
- Dependencies with assertions
- Mock services
- Skip over implementation
- True unit testing
Inversion of Control
Dependencies
Constructor Injector
Dependencies are provided via constructor arguments
Example
interface ISettingsProvider {
getSetting<SettingType>(settingKey: String): SettingType
}
class TestSettingsProvider : ISettingsProvider {
getSetting<SettingType>(settingKey:String) =
when(settingKey) {
SETTING_IS_PRIVATE -> true
SETTING_ACCOUNT_NAME -> "MyUser"
SettING_SHARE_LOCATION -> false
}
}
class AccountSettingsActivity(val settingsProvider: ISettingsProvider) {
...
fun initialize() =
settingsProvider.run {
username = getSetting<String>(SETTING_ACCOUNT_NAME)
privacy_toggle = getSetting<Boolean>(SETTING_IS_PRIVATE)
share_location = getSettings<Boolean>(SETTING_SHARE_LOCATION)
}
....
}
Property Injection
Dependencies are set via accessors
Example
interface ISettingsProvider {
getSetting<SettingType>(settingKey: String): SettingType
}
class TestSettingsProvider : ISettingsProvider {
getSetting<SettingType>(settingKey:String) =
when(settingKey) {
SETTING_IS_PRIVATE -> true
SETTING_ACCOUNT_NAME -> "MyUser"
SettING_SHARE_LOCATION -> false
}
}
class AccountSettingsActivity() {
var settingsProvider: ISettingsProvider? = null
...
fun initialize() =
settingsProvider?.run {
username = getSetting<String>(SETTING_ACCOUNT_NAME)
privacy_toggle = getSetting<Boolean>(SETTING_IS_PRIVATE)
share_location = getSettings<Boolean>(SETTING_SHARE_LOCATION)
}
....
}
Service Locator
Locates a service, usually by type or name
Example
interface IRESTServiceLocator {
resolve(serviceClass: KClass<IRESTService>): IRestService
}
interface IRetrieveUserService : IRESTService {
...
}
class RetrieveUserService_v1 : IRetrieveUserService {
getCurrentUser(): User?
getUser(userId: Long): User?
}
class UserManager(val serviceLocator: IRESTServiceLocator) {
fun setUsername(username: String) =
serviceLocator.resolve(IRetrieveUserService::class)
.getCurrentUser()
.setUsername(username)
...
}
Inversion of Control
Containers
A Container is...
A framework, of sorts, that can create a given type with all necessary dependencies
Roll Your Own
class PreferenceWrapper : IPreferenceProvider {
constructor(sharedPreferences: SharedPreferences) {...}
constructor(mockPreferences: MockPreferences) {...}
fun getBoolean(prefName: String): Boolean { ... }
fun getString(prefName: String): String { ... }
}
interface ISingletonScope {
fun getApplicationContext(): Context
fun getPreferences(): IPreferenceProvider
}
class ApplicationContainer(private val context: Context)
: ISingletonScope {
private lateinit var preferences: SharedPreferences
init {
preferences =
PreferenceWrapper(
PreferenceManager.getDefaultSharedPreferences(context))
}
fun getApplicationContext() = context
fun getPreferences() = preferences
}
Roll Your Own
interface IConfigurationScope {
fun getUserSettings(): UserSettings
fun getPushNotificationSettings(): NotificationSettings
}
class PreferenceConfigurationContainer(private var singletons: ISingletonScope)
: IConfigurationScope {
fun setSingletons(singletonScope: ISingletonScope) {
singletons = singletonScope
}
fun getUserSettings() = with(singletons.getPreferences()) {
UserSettings(getString(PREF_USERNAME), getString(PREF_PASSWORD))
}
fun getPushNotificationSettings() = with(singletons.getPreferences()) {
NotificationSettings(getBoolean(PREF_PUSH_ENABLED),
getBoolean(PREF_PUSH_VIBRATE),
getString(PREF_PUSH_SOUND))
}
}
Dagger
IoC Container Builder
Further Reading
- Tutorial: http://www.tutorialsteacher.com/ioc
- Overview: https://www.codeproject.com/Articles/380748/Inversion-of-Control-Overview-with-Examples
- StackOverflow Discussion: https://stackoverflow.com/questions/3058/what-is-inversion-of-control
- DI vs IoC: https://www.codeproject.com/Articles/592372/Dependency-Injection-DI-vs-Inversion-of-Control-IO
Inversion of Control
By Teagan Glenn
Inversion of Control
Introduction to IoC with some basic examples
- 1,489