The Why and How of Dependency Injection
TCCC XX
CODE: https://github.com/seanmacavaney/tccc20
About Me
Sean MacAvaney
macavaney.us • @SeanMacAvaney • sean.macavaney@gmail.com
- Software Engineering
student atgraduate from Milwaukee School of Engineering - Software Developer at Integrated Inventory Technology
- Interest in web technologies
About You
Overview
- What?
- Why?
- How?
- Live Coding!
What?
Dependency Injection is a 25-dollar term for a 5-cent concept.
"
- James Shore
<http://www.jamesshore.com/Blog/Dependency-Injection-Demystified.html>
Dependency injection means giving an object its instance variables. Really. That's it.
Dependency Injection is a software design pattern that implements inversion of control for resolving dependencies. [...] Passing [dependencies] to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.
- Wikipedia
<https://en.wikipedia.org/wiki/Dependency_injection>
"
Injected or Not Injected?
class Aardvark {
private string name;
private double weightLbs;
public Aardvark(string name, double weightLbs) {
this.name = name;
this.weightLbs = weightLbs;
}
...
}
class AardvarkDriver {
public static void main(String[] args) {
Aardvark lenny = new Aardvark("Lenny", 130);
lenny.DoAardvarkStuff();
}
}
Injected or Not Injected?
class BreweryService {
private String name;
private IMarketingStrategy marketing = new HipsterMarketingStrategy();
private IProductionStrategy production = new MicrobrewingStrategy();
...
}
class BreweryDriver {
public static void main(String[] args) {
BreweryService mkeBrewing = new BreweryService();
mkeBrewery.Brew();
}
}
Injected or Not Injected?
class ConferenceService {
private IAttendeeRepository attendeeRepo;
public ConferenceService(IDatabaseFactory db) {
this.attendeeRepo = new AttendeeRepository(db);
}
...
}
class ConferenceDriver {
public static void main(String[] args) {
IDatabaseFactory db = new DatabaseFactory();
ConferenceService tccc = new ConferenceService(db);
tccc.EmailAttendees();
}
}
Injected or Not Injected?
class CongressService {
private ISenateService senateService;
private IHouseService houseService;
public CongressService(ISenateService senateService, IHouseService houseService) {
this.senateService = senateService;
this.houseService = houseService;
}
...
}
class CongressDriver {
public static void main(String[] args) {
IDatabaseFactory db = new DatabaseFactory();
ISenateServiceService senate = new SenateService(db);
IHouseService house = new HouseService(db);
CongressService congress = new CongressService(senate, house);
congress.DoNothing();
}
}
Injected or Not Injected?
(function () {
window.ShoeshineService = function () {
this.shineTheShoes = function (shoes) {
var polish = window.polishService.getPolish();
...
};
};
})();
Injected or Not Injected?
angular.module('secret', ['ngRoute', 'firebase'])
.service('nsa', function($q, prism, fbi, dhs) {
var self = this;
this.spy = function () {
...
};
...
});
Why?
Coupling.
Knowledge of Construction
class BreweryController {
private DatabaseConnection db;
private BreweryRepository repo;
public BreweryController() {
this.db = new DatabaseConnection("Server=myServerAddress;Database=myDatabase;");
this.repo = new BreweryRepository(this.db);
}
...
}
Knowledge of Construction
class BreweryController {
private DatabaseConnection db;
private BreweryRepository repo;
public BreweryController(DatabaseConnection db, BreweryRepository repo) {
this.db = db;
this.repo = repo;
}
...
}
Knowledge of Implementation
class Brewery {
private String name;
private IMarketingStrategy marketing = new HipsterMarketingStrategy();
private IProductionStrategy production = new MicrobrewingStrategy();
...
}
Test Environment
class Brewery {
private String name;
private IMarketingStrategy marketing;
private IProductionStrategy production;
public Brewery(String name, IMarketingStrategy marketing, IProductionStrategy production) {
this.name = name;
this.marketing = marketing;
this.production = production;
}
...
}
class TestBrewery {
void test() {
...
IMarketingStrategy strategy = new FakeMarketingStrategy();
Brewery brewery = new Brewery("test", strategy);
...
}
}
Runtime Configuration
interface IMarketingService { ... }
class HipsterMarketingService : IMarketingService { ... }
class BroMarketingService : IMarketingService { ... }
class ClassyMarketingService : IMarketingService { ... }
<dependencies>
<dependency for="IMarketingService" use="HipsterMarketingService" />
...
</dependencies>
How?
???
Dependency Resolver
class CongressService {
private ISenateService senateService;
private IHouseService houseService;
public CongressService(ISenateService senateService, IHouseService houseService) {
this.senateService = senateService;
this.houseService = houseService;
}
...
}
class CongressDriver {
public static void main(String[] args) {
IDatabaseFactory db = new DatabaseFactory();
ISenateServiceService senate = new SenateService(db);
IHouseService house = new HouseService(db);
CongressService congress = new CongressService(senate, house);
congress.DoNothing();
}
}
Dependency Resolver
interface IDependencyResolver {
T GetService<T>();
}
class CongressService {
private ISenateService senateService;
private IHouseService houseService;
public CongressService(ISenateService senateService, IHouseService houseService) {
this.senateService = senateService;
this.houseService = houseService;
}
...
}
class CongressDriver {
public static void main(String[] args) {
IDependencyResolver resolver = new DependencyResolver();
CongressService congress = resolver.GetService<CongressService>();
congress.DoNothing();
}
}
Reflection.
Reflection is the ability of a program to examine and modify its own structure and behavior at runtime.”
- Wikipedia
<https://en.wikipedia.org/wiki/Reflection_(computer_programming)>
"
Functions
-
Inspection
-
Invocation
-
Installation
Applications
-
Serialization
-
Adaptation
-
Extension
Inspection (C#)
static void main(String[] args) {
Aardvark lenny = new Aardvark("Lenny");
PrintTypeInfo(lenny);
}
static void PrintTypeInfo(object o) {
Type t = o.GetType();
System.Console.WriteLine(t.ToString());
System.Console.WriteLine("Properties:");
foreach (var prop in t.GetProperties()) {
System.Console.WriteLine(" - " + prop.Name + ": "
+ prop.PropertyType.ToString());
}
}
>> MyApp.Aardvark
>> Properties:
>> - Name: System.String
>> - WeightLbs: System.double
Invocation (C#)
static void main(String[] args) {
Aardvark lenny = new Aardvark("Lenny");
System.Console.WriteLine("before: " + lenny.Name);
OverrideName(lenny);
System.Console.WriteLine("after: " + lenny.Name);
}
static void OverrideName(object o) {
PropertyInfo nameProp =
o.GetType().GetProperties().Where(p => p.Name == "Name");
nameProp.SetValue(o, "Jessie");
}
>> before: Lenny
>> after: Jessie
Installation (C#)
static void main(String[] args) {
Type catClass = MakeType("Cat");
var catInstance = Activator.CreateInstance(catClass);
System.Console.WriteLine(catInstance.GetType().ToString());
}
static Type MakeType(string name) {
AssemblyName assembly = new AssemblyName("TmpAssembly");
AppDomain appDomain = System.Threading.Thread.GetDomain();
AssemblyBuilder assemblyBuilder = appDomain.DefineDynamicAssembly(assembly, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assembly.Name);
TypeBuilder typeBuilder = moduleBuilder.DefineType(name, ..., typeof(System.Object));
return typeBuilder.CreateType();
}
>> Cat
JS Examples
// Inspection
var cat = {
name: "Fritz",
lives: 9
};
var catProps = Reflect.ownKeys(cat);
console.log(catProps);
>> ["name", "lives"]
// Invocation
purr.apply(cat, ["15 seconds", 98]);
>> Fritz is purring for 15 seconds at 98%
// Installation
function purr(duration, intensity) {
console.log(this.name + "is purring for " + duration + " at " + intensity + "%");
};
cat.purr = purr;
cat.purr("8 seconds", 50);
>> Fritz is purring for 8 seconds at 50%
Demo
ASP.NET MVC Example
Questions?
https://slides.com/seanm/tccc20
http://speakerrate.com/talks/66491
Additional Resources
http://www.jamesshore.com/Blog/Dependency-Injection-Demystified.html
http://stackoverflow.com/questions/130794
https://msdn.microsoft.com/en-us/library/ff921152.asp
They Why and How of Dependency Injection
By seanm
They Why and How of Dependency Injection
- 1,010