Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DI Control-Freak anti-pattern: Having trouble understanding

I'm reading Dependency Injection in .NET by Mark Seemann and I can not for the life of me get my head wrapped around this:

Although the new keyword is a code smell when it comes to VOLATILE DEPENDENCIES, you don't need to worry about using it for STABLE DEPENDENCIES. The new keyword isn't suddenly "illegal" in general, but you should refrain from using it to get instances of VOLATILE DEPENDENCIES.

Maybe it's because I still can't get my head wrapped around ambient context being an injection instead of just a global variable, but I am just not getting what the author is saying.

I'd really like to understand DI top to bottom but right now I'm stuck and this is just a 1/3 the way through the book... The Control-Freak anti-pattern seems to be every single programmer that ever lived...

Anyone have any insights?

like image 446
Grixxly Avatar asked Jul 04 '12 14:07

Grixxly


3 Answers

Volatility (to me) is a measure of the likeliness that a class will need to be changed.

Ideally you design classes to be open to extension but closed to modification (Open Closed Principle). This isn't always possible. Those classes that you close to change are less volatile than the others.

NDepend (a .Net static analysis metrics tool) has a metric called Instability that in my mind is synonymous. They define this as:

Instability (I): The ratio of efferent coupling (Ce) to total coupling. I = Ce / (Ce + Ca). This metric is an indicator of the assembly's resilience to change. The range for this metric is 0 to 1, with I=0 indicating a completely stable assembly and I=1 indicating a completely instable assembly.

You don't want Stable classes relying on less Stable ones.

As far as deciding to inject or not, that sounds more like a class role issue. From Domain Driven Design, (DDD) Classes are usually either Entities (they have identity), Services (they orchestrate things) or Values (they are immutable and comparable, like RED or 100ml).

You would inject Services, you would call new on Values. Entities usually come from a repository (that you inject), but internally the Repository would call new on them. Does that help?

like image 178
Nigel Thorne Avatar answered Sep 21 '22 14:09

Nigel Thorne


I haven't heard these terms before, but transposing what i know about dependency injection, i'd define them as follows.

A stable dependency is one whose concrete implementation will not vary, in class or configuration, over time or in different situations.

A volatile dependency is one whose concrete implementation might vary, in class or configuration, over time or in different situations.

If you can forgive an example in Java, a stable dependency would be StringBuilder. If you are writing a method to build up a string, you don't need to have a StringBuilder injected, you can just create it. Ditto for ArrayList, HashMap, etc. Beyond standard library classes, if you were writing a banking application, you would probably not inject a RunningTotaliser, because that's an object which just adds up numbers for you.

Examples of volatile dependencies in the standard library are harder to come up with. A classic example would be a DataSource - that's an object which encapsulate the connection details for a database, and those should almost certainly not be supplied by the code which is actually making the connections.

like image 27
Tom Anderson Avatar answered Sep 21 '22 14:09

Tom Anderson


Usually DI container resolve all dependencies to concrete implementation and handle lifetime for you. But DI Control-Freak does opposite: creates concrete object using new keyword, injects them and handles life time by himself only. So, noone else has possibility to configure and handle dependencies outside from your code. And thus, reuse or test it by providing other implementations or fakes.

Here is citation from @mark-seemann's book, that answers your question:

I named it CONTROL FREAK to describe a class that won’t relinquish control of its DEPENDENCIES.

This happens every time we create a new instance of a type by using the new key- word. When we do that, we explicitly state that we’re going to control the lifetime of the instance and that no one else will get a chance to intercept that particular object.

like image 26
Akim Avatar answered Sep 22 '22 14:09

Akim