jargon

Design patterns·topic 3 of 10

Wiring: injection, containers and lifetimes

Somewhere a decision gets made about which concrete thing your code actually gets, and the whole testability of a codebase turns on where that somewhere is. This is the vocabulary of moving it out of the class and into one place.

Read in order · tick what you already know

  1. 01

    the class constructs its own collaborator inside a method, so testing it means standing up the real thing.

    Hard-coded dependency

  2. 02

    you stopped writing the loop and started writing the thing the framework calls, and you no longer decide when.

    Inversion of control

  3. 03

    you register your code and something else decides when it runs, which is the opposite of how a library feels.

    Hollywood principle

  4. 04

    the class asks for what it needs in its constructor and never goes looking, so a test can hand it anything.

    Dependency injection

  5. 05

    you cannot create the object without giving it what it needs, so there is no moment where it exists half-wired.

    Constructor injection

  6. 06

    the object is constructed first and wired afterwards, so there is a window where calling it throws a null reference.

    Setter injection

  7. 07

    there is exactly one file that knows every concrete class, and it is the one that runs at startup.

    Composition root

  8. 08

    one request for the top-level object built nineteen things underneath it, and you only asked for one.

    Object graph

  9. 09

    the wiring is forty lines of ordinary constructor calls at startup, and you can step through every one of them.

    Pure dependency injection

  10. 10

    you registered an interface against a class once, and everything that needs it gets one without anybody passing it.

    Dependency injection container

  11. 11

    nothing in the code says where the implementation came from, and the answer is that a scan found exactly one.

    Autowiring

  12. 12

    you put the file in the expected folder with the expected name and it was picked up, with nothing declaring it.

    Convention over configuration

  13. 13

    the same registration served one shared instance in one place and a new one per request in another, and that was configuration.

    Lifetime scope

  14. 14

    a long-lived object held a per-request one, and every request after the first got the first request's data.

    Captive dependency

  15. 15

    the class asks a global object for what it needs mid-method, so its dependencies are invisible until it runs.

    Service locator

  16. 16

    the code called a static Current property for the clock or the user, and nothing in the signature admitted it.

    Ambient context

  17. 17

    which implementation runs was decided when the program started, from a config value, not when it was compiled.

    Late binding