134
Building SOLID Software with Dependency Injection Jeremy Rosenberg

Building SOLID Software with Dependency Injection Jeremy Rosenberg

Embed Size (px)

Citation preview

Page 1: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Building SOLID Software with Dependency Injection

Jeremy Rosenberg

Page 2: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Me

Page 3: Building SOLID Software with Dependency Injection Jeremy Rosenberg
Page 4: Building SOLID Software with Dependency Injection Jeremy Rosenberg
Page 5: Building SOLID Software with Dependency Injection Jeremy Rosenberg
Page 6: Building SOLID Software with Dependency Injection Jeremy Rosenberg
Page 7: Building SOLID Software with Dependency Injection Jeremy Rosenberg
Page 8: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Who cares about software design?

Page 9: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What are our goals?

• Deliver yesterday• Communicate telepathically• No bugs

Page 10: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What are our goals?

• Deliver yesterday• Communicate telepathically• No bugs

Page 11: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What are our goals?

• Deliver quickly• Communicate quickly• Few bugs• Fix bugs quickly

• Deliver yesterday• Communicate telepathically• No bugs

Page 12: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What are our goals?

• Deliver quickly• Communicate quickly• Few bugs• Fix bugs quickly

• Deliver yesterday• Communicate telepathically• No bugs

aka

Efficiently deal with Change

Page 13: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What is a bad design?

Page 14: Building SOLID Software with Dependency Injection Jeremy Rosenberg

A bad design causes these

• Deliver slowly or unpredictably• Slow ramp-up for new team members• Slow sharing between veteran team members

Page 15: Building SOLID Software with Dependency Injection Jeremy Rosenberg

A bad design causes these

• Frequent bugs• Simple bugs need complex changes• Lots of regressions• Lots of regression testing

Page 16: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What is a good design?

Page 17: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What is SOLID?

Page 18: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What it is

• Catchy acronym• Principles for dealing with change

Page 19: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What it is

• Catchy acronym• Principles for dealing with change

Page 20: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What it is

• Catchy acronym• Principles for dealing with change

SDOLI

Page 21: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What it’s not

• Framework• Library• Pattern• Goal

Page 22: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What is Dependency Injection?

• Pattern• Jives well with SOLID

Page 23: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What kinds of code?

• Object-oriented• Statically typed*

(code examples are in C#)

Page 24: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What does this method do?

Page 25: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What does this method do?– Coordinates a book checkout process for a member

• Checkout• Storage

Page 26: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What does this method do?– Coordinates a book checkout process for a member

• Checkout• Storage

Is that all?

Page 27: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What does this class do?

Page 28: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What does this class do?

• Configuration

• DB Access

Page 29: Building SOLID Software with Dependency Injection Jeremy Rosenberg

So what does this method really do?

• Checkout• Storage

Page 30: Building SOLID Software with Dependency Injection Jeremy Rosenberg

So what does this method really do?

• Checkout• Storage

– Configuration– DB access

Implicit!

Page 31: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Let’s write a test case

Page 32: Building SOLID Software with Dependency Injection Jeremy Rosenberg

SDOLI: Single Responsibility Principle

• “Do one thing and do it well”

• Applies to a method, class, service, system, …

Page 33: Building SOLID Software with Dependency Injection Jeremy Rosenberg
Page 34: Building SOLID Software with Dependency Injection Jeremy Rosenberg

How do we isolate the coordination?

Page 35: Building SOLID Software with Dependency Injection Jeremy Rosenberg

SDOLI: Dependency Inversion Principle

• Depend on contracts, not implementations

• Goal: Decouple the single responsibility from implementations of its dependencies

Page 36: Building SOLID Software with Dependency Injection Jeremy Rosenberg

SDOLI: Dependency Inversion Principle

• Depend on a contract at design-time– e.g. IBookRepository or BookRepositoryBase

• Receive an implementation at runtime– e.g. SqlBookRepository

Page 37: Building SOLID Software with Dependency Injection Jeremy Rosenberg
Page 38: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Dependency Injection

• A class declares its dependencies through its own contract

• Providing dependencies is someone else’s job

Page 39: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Dependency Injection

• Constructor injection• Property injection• Method injection

Page 40: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Constructor injection

Page 41: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Our test case

• No configuration• No database• Only coordination

Page 42: Building SOLID Software with Dependency Injection Jeremy Rosenberg

All this “just” for test cases?

• What else have we gained?– “Tightly bound, loosely coupled”• Focused responsibility => readability• Dependent on behavior, not implementation

– Dependencies are explicit• Limits unexpected side effects• Straightforward (re)usage

– Composability

Page 43: Building SOLID Software with Dependency Injection Jeremy Rosenberg

You’re a hack!

Page 44: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Composition Root

• Constructs the object graph

• Lives near the entry point

Page 45: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Example: Console app

Page 46: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What about that repository?

Page 47: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Make the dependencies explicit

Page 48: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Updated Composition Root

Page 49: Building SOLID Software with Dependency Injection Jeremy Rosenberg

With me?

Page 50: Building SOLID Software with Dependency Injection Jeremy Rosenberg
Page 51: Building SOLID Software with Dependency Injection Jeremy Rosenberg

SDOLI: Open/Closed Principle

• Open for extensibility, closed for modification

• Add behavior without changing existing code

Page 52: Building SOLID Software with Dependency Injection Jeremy Rosenberg
Page 53: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Decorator

• Inject behavior into an application

• Man-in-the-middle

Page 54: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Example: Document storage

Page 55: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Composition Root

Page 56: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Add Logging

Page 57: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Add Logging

Page 58: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Add Authorization

Page 59: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Add Authorization

Page 60: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Add Caching

Page 61: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Add Caching

Page 62: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Noticing a pattern?

Page 63: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Open…

Page 64: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Closed.

Page 65: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Closed.

Page 66: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Closed.

Page 67: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Closed.

Page 68: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Closed.

Page 69: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Composite

• Implements a contract• Delegates to others with the same contract

Page 70: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Example

Page 71: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Build it like this

Page 72: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Use it like this

Page 73: Building SOLID Software with Dependency Injection Jeremy Rosenberg

A more concrete example

Page 74: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Move the responsibility

Page 75: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Notify billing

Page 76: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Notify inventory

Page 77: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Notify shipping

Page 78: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Dispatch all notifications

Page 79: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Open / closed

Page 80: Building SOLID Software with Dependency Injection Jeremy Rosenberg

SDOLI: Liskov Substitution Principle

• Functions that use pointers to base types must be able to use objects of derived types without knowing it.

• “Leaky abstraction principle”-Me

Page 81: Building SOLID Software with Dependency Injection Jeremy Rosenberg
Page 82: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Is a Square a Rectangle?

Page 83: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Is a Square a Rectangle?

SetWidth / SetHeight ?

Page 84: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Example: calculator

Page 85: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Usage

Page 86: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Guess what’s next

Page 87: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Guess what’s next

Page 88: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Guess what’s next

Oops

Page 89: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Plug the leak – Part 1

Page 90: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Plug the leak – Part 1

- Nine fingers left!

Page 91: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Plug the leak – Part 2

Page 92: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What to do

• Some ideas– Kill the abstraction– Adapt each calculator to something that supports

input validation

Page 93: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Another example: more documents…

Page 94: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Read-only integration

Page 95: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Oops

Page 96: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Plug the leak

Page 97: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What to do?

• Some ideas– IReadOnlyDocRepo and IReadWriteDocRepo– IReadDocs and IWriteDocs– SupportsXYZ methods

Page 98: Building SOLID Software with Dependency Injection Jeremy Rosenberg

How can DI help apply the LSP?

Page 99: Building SOLID Software with Dependency Injection Jeremy Rosenberg

How can DI help apply the LSP?

It can’t.

Page 100: Building SOLID Software with Dependency Injection Jeremy Rosenberg
Page 101: Building SOLID Software with Dependency Injection Jeremy Rosenberg

SDOLI: Interface Segregation Principle

• Thin interfaces are better than fat ones

• Client-focused

Page 102: Building SOLID Software with Dependency Injection Jeremy Rosenberg
Page 103: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Example: more books…

Page 104: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Who’s using it?

Page 105: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Cache books?

Page 106: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Don’t need these

Page 107: Building SOLID Software with Dependency Injection Jeremy Rosenberg

These are ok

Page 108: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What about these?

Page 109: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Client-specific interface

Page 110: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Adapter

This:

or this:

Page 111: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Slimmer caching

Page 112: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Focused dependencies

Page 113: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Let’s review

Page 114: Building SOLID Software with Dependency Injection Jeremy Rosenberg

SOLID Principles

• Single Responsibility• Open/Closed• Liskov Substitution• Interface Segregation• Dependency Inversion

Page 115: Building SOLID Software with Dependency Injection Jeremy Rosenberg
Page 116: Building SOLID Software with Dependency Injection Jeremy Rosenberg

I don’t know about you…

Page 117: Building SOLID Software with Dependency Injection Jeremy Rosenberg

DI Container

• Auto-wiring of dependencies

• Lifetime management

Page 118: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Ninject

Page 119: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Ninject

Register

Page 120: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Ninject

Register

Resolve

Page 121: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Ninject

Register

Resolve

Release

Page 122: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Other containers

• Castle Windsor• Autofac• StructureMap• Unity• …

Page 123: Building SOLID Software with Dependency Injection Jeremy Rosenberg

What not to do

Page 124: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Don’t use Service Locator

Page 125: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Don’t use Service Locator

• Hides dependencies• Consumers must use the same container• Testing becomes un-fun

Page 126: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Don’t use Service Locator

• Composition root should be the only place referencing the DI Container.

• General rule: if it’s not just initializing the object graph, it’s not the composition root.

Page 127: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Don’t just new it

Page 128: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Don’t just new it

• Useless interface definition• Same tight coupling• No way to swap, decorate, or otherwise

compose implementations

Page 129: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Don’t be double minded

Page 130: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Don’t be double minded

• Two paths…• Dependencies are still not always apparent• Auto-wiring can be difficult

Page 131: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Building SOLID software

Page 132: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Building SOLID software

• SOLID encourages good designs

• Dependency injection is a tool to bring closer alignment with SOLID

Page 133: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Join us

Page 134: Building SOLID Software with Dependency Injection Jeremy Rosenberg

Resources

• The Principles of OOD http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod

• Dependency Injection in .NET by Mark Seemann

• ploeh blog – DependencyInjection http://blog.ploeh.dk/CategoryView,category,DependencyInjection.aspx

• SOLID (object-oriented design) http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)