theme | transition | highlightTheme | logoImg | slideNumber | title |
---|---|---|---|---|---|
white |
slide |
monokai |
true |
DIP & IoC Talk |
A breif about DIP & IoC including theory and examples.
slides using Markdown with vscode-reveal
- Dependency is a class and/or interface required by another component to function
- High Level Module is the one will require the dependency
- Low Level Module is the one will fulfill the dependency
classDiagram
HighLevelModule --> LowLovelModule
class LowLovelModule {
}
class HighLevelModule {
- LowLovelModule lowLevelModule;
}
The 5th principle in SOLID
--
- High level modules should not depend on low level modules; both should depend on abstractions.
classDiagram
HighLevelModule --> Abstraction
LowLovelModule --|> Abstraction
--
// c#
class HighLevelModule {
private LowLevelModule lowLevelModule;
public HighLevelModule() {
lowLevelModule = new LowLevelModule();
}
}
=>
// c#
class HighLevelModule {
private Abstraction abstraction;
public HighLevelModule(Abstraction abstraction) {
this.abstraction = abstraction;
}
}
class LowLevelModule : Abstraction {
}
- Is this the only way?
--
Abstractions
should not depend ondetails
. Details should depend upon abstractions
classDiagram
HighLevelModule --> Abstraction
Detail --|> Abstraction
Detail --> LowLovelModule
class Abstraction {
+ doSomething(arg)
}
class Detail {
+ doSomething(arg)
}
class LowLovelModule {
+ doSomething(arg, argX)
}
--
// c#
class HighLevelModule {
private Abstraction abstraction;
public HighLevelModule(Abstraction abstraction) {
this.abstraction = abstraction;
}
}
abstract class Abstraction {
public abstract void DoSomething(ArgType arg);
}
class LowLevelModule : Abstraction {
public override void DoSomething(AnotherArgType arg) {}
}
- Does it looks familiar to you?
--
- Is this the way to go?
// c#
class HighLevelModule {
private Abstraction abstraction;
public HighLevelModule(Abstraction abstraction) {
this.abstraction = abstraction;
}
}
abstract class Abstraction {
public abstract void DoSomething(AnotherArgType arg);
}
class LowLevelModule : Abstraction {
public override void DoSomething(AnotherArgType arg) {}
}
--
class HighLevelModule {
// thousand lines of code...
}
abstract class Abstraction {
public abstract void DoSomething(ArgType arg);
}
class Detail : Abstraction {
private LowLevelModule llm;
public override void DoSomething(ArgType arg) {
llm.DoSomething(CreateAnotherArgType(arg));
}
}
class LowLevelModule {
public override void DoSomething(AnotherArgType arg) {}
}
A mediator should always be the way to go!!!!
--
In software engineering, Inversion of Control (IoC) is a design pattern in which custom-written portions of a computer program receive the flow of control from a generic framework.
--wikipedia--
--
// c#
class HighLevelModule {
private LowLevelModule lowLevelModule;
public HighLevelModule() {
// I knows how to create my dependency
lowLevelModule = new LowLevelModule();
}
}
=>
// c#
class HighLevelModule {
private Abstraction abstraction;
public HighLevelModule(Abstraction abstraction) {
// I know my dependency will be given (injected)
// by the **generic** framework
this.abstraction = abstraction;
}
}
class LowLevelModule : Abstraction {
}
- Service Locator
- Dependency Injection
- Constructor Injection
- Several others
--wikipedia--
- HighLevelModule only need to know the locator and the abstractions. It will find right implemtations.
--
class HighLevelModule {
HighLevelModule() {
this.abs1 = ServiceLocator.Get<Abs1>();
}
}
class Impl1 : Abs1 {
Impl1() {
this.abs2 = ServiceLocator.Get<Abs2>();
}
}
class Impl2 : Abs2 {}
// At the time of app boostrap
ServiceLocator.Register<Abs1>(() => new Impl1());
ServiceLocator.Register<Abs2>(() => new Impl2());
--
+ | - |
---|---|
+ Easy to implement | - A new dependency introduced |
+ Easy to apply for legacy system | - Have to register every dependency (automate-able) |
+ Easy to do UTs | - Hides dependencies |
+ Easy to extend | - Hard to maintain |
--
- HighLevelModule only depends on the abstractions. The implementations will be injected by the DI container
--
class HighLevelModule {
HighLevelModule(Abs1 abs1) {//Constructor injection
this.abs1 = abs1;
}
}
class Impl1 : Abs1 { }
// At the time of app boostrap
DIContainer.Register<Abs1>(() => new Impl1());
DIContainer.Register<HighLevelModule>(
() => new HighLevelModule(
DIContainer.Resolve<Abs1>()
));
var hlm = DIContainer.Resolve<HighLevelModule>();
--
+ | - |
---|---|
+ All from Service Locator | - Not easy for newbie to understand |
+ Easy to maintain | - Have to register every dependency (automate-able) |
+ Easy to get-started | |
+ Eliminate most of Service locator's cons |
--
--