Dependency Injection, Design Patterns, OO vs FP
Just look at https://arxiv.org/pdf/1003.3338.pdf
0.0.0.1 What are dependencies
Dependencies in software engineering terms means an object dependency. I’d like to extend that meaning to also include informational dependency.
This allows us to simply add an interface and the DI system will automatically initialize a class to fill that interface.
What is code reflection? It’s a form of meta-programming, where your code understands it’s own code.
An example is python eval("print('hello')")
which can evaluate strings as code.
ASP.NET Core uses reflection which is the only way it could swap a concrete class with an interface without the programmer’s “consent”.
0.0.0.2 Interfaces - Class is a subset relation
- Class Implements Interface
- Class Superset Interface
\[Interface \subset Class\] \[INat \subset Nat\]
- Design an interface example
- Given 4 classes: \(Dog, Cat, Mouse, Human\).
- \(\underset{properties}{\bigcap} \{Dog, Cat, Mouse, Human\} = IMammel\)
Notice these are strict subsets.
\(IMammel \nsubseteq Dog\) since \(Dog\) will always contain a constructor method new() which interfaces cannot have.
0.0.0.3 Without DI
0.0.0.3.1 All Concrete classes depend on their constructor new() method
This constructor dependency can be broken using DI.
The hidden method constructor new()::Nat is also a dependency and colored in red
def plus_OO():
= new()::Nat; #new() creates an Nat object one::Nat
a = new()::Nat;
b return a + b
0.0.0.4 With DI
= new Injector(new()::Nat)
INatInjector
def plus_OO():
; #Injector fills a with an object one::Nat
INat a; #Injector fills b with an object one::Nat
INat b#INatInjector autofills the interfaces with concrete objects
return a + b
0.0.1 Compare OO vs FP
FP version
def plus_FP(a::INat,b::INat):
return a + b
- FP does not have dependencies
- we dont create objects in FP
Some might say that simply passing INat type arguments to a function is a form of dependency injection.
The true difficulty of FP is modifying existing code base.
Imagine we are given an exist chain of compositions.
We need to modify add new customer data to type “Bool” and convert it to “F Bool”
Int –[f]–> Bool –[g]–> Float –[h]–> Maybe Int –[k]–> IO
- We must modify functions next to Bool: f, g
- What if we need to also output the additional data in “F Bool” to IO
- We must modify every function downstream of “Bool”: g,h,k to accept the extra data in “F Bool”
- Similar to prop drilling in React
- We must modify every function downstream of “Bool”: g,h,k to accept the extra data in “F Bool”