Mark Seemann's conflicting statements about Bastard Injection. Need some clarifications - dependency-injection

I'm reading his book Dependency Injection in Net.
1) Here he's saying that Bastard Injection occurs only when we use Foreign Default.
But in his book, the illustration on page 148 shows that Bastard Injection occurs when the default implementation of the dependency is either Foreign Default or Local Default:
So does Bastard Injection anti-pattern also occur when default implementation of dependency is a Local Default?
2) Here ( and also in his book ) he notes that it's ok for a class to have an optional dependency, provided that a default implementation of this dependency is a good Local Default:
But in next article he seems to object to having optional dependencies at all, even if the default implementation is a Local Default:
private readonly ILog log;
public MyConsumer(ILog log)
{
this.log = log ??LogManager.GetLogger("My");
}
In terms of encapsulation, the main problem with such an approach is
that it seems like the MyConsumer class can't really make up its mind
whether or not it controls the creation of its log dependency. While
this is a simplified example, this could become a problem if the ILog
instance returned by LogManager wraps an unmanaged resource which
should be disposed when it's no longer needed.
Are his arguments in the above excerpt also valid when default implementation of dependency is local? If so, then optional dependencies with local defaults should also be avoided?
3)
Pg. 147:
The main problem with Bastard Injection is its use of a FOREIGN
DEFAULT ... , we can no longer freely reuse the class because it drags
along a dependency we may not want. It also becomes more difficult to
do parallel development because the class depends strongly on its
DEPENDENCY.
Foreign Default is an implementation of a dependency that's used as a default and is defined in a different assembly than its consumer. Thus with Foreign Default, consumer's assembly will also drag along dependency's assembly.
Is he also implying that Foreign Default makes parallel development more difficult, while Local Default doesn't? If he is, then that doesn't make sense, since I would assume that what makes parallel development difficult is not so much that consumer's assembly has hard reference to dependency's assembly, but rather the fact that consumer class depends on a concrete implementation of a dependency?
thanks

Since there are many questions here, I'll first attempt to provide an synthesis on my view on the subject, and then answer each question explicitly based on this material.
Synthesis
When I wrote the book, I first and foremost attempted to describe the patterns and anti-patterns I'd witnessed in the wild. Thus, the patterns and anti-patterns in the book are first and foremost descriptive, and only to a lesser degree prescriptive. Obviously, dividing them into patterns and anti-patterns imply a certain degree of judgement :)
There are problems with Bastard Injection on multiple levels:
Package dependency
Encapsulation
Ease of use
The most dangerous problem is related to package dependencies. This is the concept I've attempted to make more actionable by the introduction of the terms Foreign Default versus Local Default. The problem with Foreign Defaults is that they drag along hard-coupled dependencies, which makes (de/re)composition impossible. A good resource that deals more explicitly with package management is Agile Principles, Patterns, and Practices.
On the level of encapsulation, code like this is difficult to reason about:
private readonly ILog log;
public MyConsumer(ILog log)
{
this.log = log ??LogManager.GetLogger("My");
}
Although it protects the class' invariants, the problem is that in this case, null is an acceptable input value. This is not always the case. In the example above, LogManager.GetLogger("My") may only introduce a Local Default. From this code snippet, we have no way to know if this is true, but for the sake of argument, let's assume this for now. If the default ILog is indeed a Local Default, a client of MyConsumer can pass in null instead of ILog. Keep in mind that encapsulation is about making it easy for a client to use an object without understanding all the implementation details. This means that this is all a client sees:
public MyConsumer(ILog log)
In C# (and similar languages) it's possible to pass null instead of ILog, and it's going to compile:
var mc = new MyConsumer(null);
With the above implementation, not only will this compile, but it also works at run-time. According to Postel's law, that's a good thing, right?
Unfortunately, it isn't.
Consider another class with a required dependency; let's call it a Repository, simply because this is such a well-known (albeit overused) pattern:
private readonly IRepository repository;
public MyOtherConsumer(IRepository repository)
{
if (repository == null)
throw new ArgumentNullException("repository");
this.repository = repository;
}
In keeping with encapsulation, a client only sees this:
public MyOtherConsumer(IRepository repository)
Based on previous experience, a programmer may be inclined to write code like this:
var moc = new MyOtherConsumer(null);
This still compiles, but fails at runtime!
How do you distinguish between these two constructors?
public MyConsumer(ILog log)
public MyOtherConsumer(IRepository repository)
You can't, but currently, you have inconsistent behaviour: in one case, null is a valid argument, but in another case, null will cause a runtime exception. This will decrease the trust that every client programmer will have in the API. Being consistent is a better way forward.
In order to make a class like MyConsumer easier to use, you must stay consistent. This is the reason why accepting null is a bad idea. A better approach is to use constructor chaining:
private readonly ILog log;
public MyConsumer() : this(LogManager.GetLogger("My")) {}
public MyConsumer(ILog log)
{
if (log == null)
throw new ArgumentNullException("log");
this.log = log;
}
The client now sees this:
public MyConsumer()
public MyConsumer(ILog log)
This is consistent with MyOtherConsumer because if you attempt to pass null instead of ILog, you will get a runtime error.
While this is technically still Bastard Injection, I can live with this design for Local Defaults; in fact, I sometimes design APIs like this because it's a well-known idiom in many languages.
For many purposes, this is good enough, but still violates an important design principle:
Explicit is better than implicit
While constructor chaining enables a client to use MyConsumer with a default ILog, there's no easy way to figure out what the default instance of ILog would be. Sometimes, that's important too.
Additionally, the presence of a default constructor exposes a risk that a piece of code is going to invoke that default constructor outside of the Composition Root. If that happens, you've prematurely coupled to objects to each other, and once you've done that, you can't decouple them from within the Composition Root.
Thus, there's less risk involved in using plain Constructor Injection:
private readonly ILog log;
public MyConsumer(ILog log)
{
if (log == null)
throw new ArgumentNullException("log");
this.log = log;
}
You can still compose MyConsumer with the default logger:
var mc = new MyConsumer(LogManager.GetLogger("My"));
If you want to make the Local Default more discoverable, you can expose it as a Factory somewhere, e.g. on the MyConsumer class itself:
public static ILog CreateDefaultLog()
{
return LogManager.GetLogger("My");
}
All this sets the stage for answering the specific sub-questions in this question.
1. Does Bastard Injection anti-pattern also occur when default implementation of dependency is a Local Default?
Yes, technically, it does, but the consequences are less severe. Bastard Injection is first and foremost a description that will enable you to easily identify it when you encounter it.
Please note that the above illustration from the book describes how to refactor away from Bastard Injection; not how to identify it.
2. [Should] optional dependencies with local defaults [...] also be avoided?
From a package dependency perspective, you don't need to avoid those; they are relatively benign.
From a usage perspective, I still tend to avoid them, but it depends on what I'm building.
If I create a reusable library (e.g. an OSS project) that many people will use, I may still choose Constructor Chaining in order to make it easier to get started with the API.
If I'm creating a class only for use within a particular code base, I tend to entirely avoid optional dependencies, and instead compose everything explicity in the Composition Root.
3. Is he also implying that Foreign Default makes parallel development more difficult, while Local Default doesn't?
No, I don't. If you have a default, the default must be in place before you can use; it doesn't matter whether it's Local or Foreign.

Related

Passing dependencies the "right way"

When injecting dependencies into a constructor, I'm not quite sure if it breaks SOLID if I do the following:
public MyClass(IConfiguration configuration)
{
_port = configuration.GetValue("Port");
}
instead of passing the pure value like so:
public MyClass(int port)
{
_port = port;
}
The first one seems to be some kind of a Service Locator.
Question here is: Is it okay to pass complex dependencies just to retrieve a single value the class actually relies on?
To me it doesn't look that wrong, but it unnecessarily hides the real dependency which could get passed much easier.
From perspective of the SOLID principles, I see no clear violation:
Single Responsibility: Whether or not you inject port or IConfiguration doesn't change the number of responsibilities that MyClass has.
Open/Closed: This principle is about preventing sweeping changes. I don't see how injecting port would prevent sweeping changes compared to injecting IConfiguration.
Liskov Substitution: This principle is about letting derivatives behave as their base class specification. Injection of IConfiguration has no impact on LSP.
Interface Segregation: This principle pushes towards the use of narrow interfaces. This is a bit more tricky, and a closer inspection of the code might be needed to see whether IConfiguration is wide and violates ISP. From just this code, however, I would say there is no ISP problem.
Dependency Inversion: This principle states that we should program to abstractions, and -almost as importantly- it states that the client should own the abstraction. In case IConfiguration is a framework-defined abstraction, we might consider this code to violate the DIP. But it's not always possible or feasible to remove all dependencies to framework abstractions, so we should be pragmatic. Whether or not it is pragmatic to take a dependency on IConfiguration is impossible to say in your case.
There is, however, other guidance besides the SOLID principles that might help us out here:
The injection constructor's body should be simple: When it comes to DI, the rule is that an Injection Constructor should do no more than receiving the dependencies. It should not use it. The MyClass constructor, however, is using IConfiguration inside the constructor.
The injection constructor's definition should be minimal: An injection constructor should only be provided with just the dependencies it requires to function. It's a sort of an ISP for constructors and relates to Nikola’s 4th law of IoC. In this case you are providing an interface (IConfiguration) with broad capabilities. In your question you are referring to the Service Locator anti-pattern in this regards. Although injecting IConfiguration can certainly not be regarded as a Service Locator, from loading configuration values, IConfiguration as similar capabilities. It's better to narrow this down and be as explicit as possible and int port is much more explicit compared to IConfiguration.
So with all that in place, let me try to answer your question:
Is it okay to pass complex dependencies just to retrieve a single value the class actually relies on?
Considering the guidance on DI above, I would say that it is better to either inject int port, or a typed configuration class that wraps int port, that is specific to MyClass; e.g. MyClassSettings:
public MyClass(MyClassSettings settings)
{
_settings = settings;
}
Both convey the same amount of information, but the latter is less ambiguous, as int could mean anything, while MyClassSettings is very precise and easily resolved from a DI Container.

What is wrong with making a constructor dependency optional and initializing it from within the constructor?

I'm new to Dart. I'm coming from Ruby and trying to understand dependency injection. It's a bit hard to get my head around all the examples I've seen online. There seems to be this idea of DI containers -- which seem foreign and overly complex to me.
So naturally, I keep drifting toward patterns and analogies that fit my Ruby mental model better.
I've come up with this example, and while it's probably not idiomatic Dart, I'm wondering the following:
What's wrong with this approach if anything?
What makes DI containers any better/worse than this?
void main() {
// Young Man
Man youngMan = Man();
youngMan.age(); // I am 12
// Older Man
Man olderMan = Man(base: OlderPerson());
olderMan.age(); // I am 39
}
abstract class Person {
void age();
}
class YoungPerson implements Person {
void age() {
print('I am 12');
}
}
class OlderPerson implements Person {
void age() {
print('I am 39');
}
}
class Man {
Person base;
Man({Person base = null}) : this.base = base ?? YoungPerson();
void age() {
print('Hello from Man!!!') // This is some work that happens only in Man
base.age();
}
}
If I understand your question correctly, you are wondering whether it is okay to make the component's dependency optional and in case it hasn't been provided, initialize the component with a default instance. In other words, the Man component has a Person dependency. In case no person is supplied to Man a new instance of YoungPerson is used.
Whether it is okay for Man to initialize a YoungPerson depends on whether YoungPerson is a Local Default of a Foreign Default. DIPP&P states the following about Local and Foreign Defaults:
A Local Default is a default implementation of a Dependency that originates in the same module or layer.
When you’re developing a class that has a Dependency, you probably have a particular implementation of that Dependency in mind. If you’re writing a domain service that accesses a Repository, you’re most likely planning to develop an implementation of a Repository that uses a relational database.
It would be tempting to make that implementation the default used by the class under development. But when such a prospective default is implemented in a different assembly, using it as a default means creating a hard reference to that other assembly, effectively violating many of the benefits of loose coupling described in chapter 1. Such implementation is the opposite of a Local Default — it’s a Foreign Default. A class that has a hard reference to a Foreign Default is applying the Control Freak anti-pattern. We’ll discuss Control Freak in chapter 5.
(source: DIPP&P, section 4.2.2)
Although Local Defaults are not a bad thing per se, I typically advise against their use because it decentralizes the creation of dependencies from the Composition Root (in your example, main is your Composition Root), and makes it possible to forget to supply the dependency, which will then cause for a possible incorrect default to be used. Instead, it's much clearer and safer to have all a class's dependencies to be required.
The use of Local Defaults, however, is a discussion separate from whether or not you should use a DI Container. DI, as a practice, helps in making your application code more loosely coupled and, therefore, more flexible and maintainable. DI Containers on the other hand, can help in making your Composition Root more maintainable. I say, can because in some cases it makes more sense in building object graphs by hand (by using the new keyword in your main method) as you are currently doing. DI Containers are especially useful when use Convention over Configuration and register all dependencies in the DI Container in an automated fashion (a.k.a. Auto-Registration).

Dependency injection: Is it ok to instatiate a concrete object from a concrete factory

I am fairly new to Dependency Injection, and I wrote a great little app that worked exactly like Mark Seemann told me it would and the world was great. I even added some extra complexity to it just to see if I could handle that using DI. And I could, happy days.
Then I took it to a real world application and spent a long time scratching my head. Mark tells me that I am not allowed to use the 'new' keyword to instantiate objects, and I should instead let the IoC do this for me.
However, say that I have a repository and I want it to be able to return me a list of things, thusly:
public interface IThingRepository
{
public IEnumerable<IThing> GetThings();
}
Surely at least one implementation of this interface will have to instantiate some Thing's? And it doesn't seem so bad being allowing ThingRepository to new up some Things as they are related anyway.
I could instead pass round a POCO instead, but at some point I'm going to have to convert the POCO in to a business object, which would require me to new something up.
This situation seems to occur every time I want a number of things which is not knowable in the Composition Root (ie we only find out this information later - for example when querying the database).
Does anyone know what the best practice is in these kinds of situations?
In addition to Steven's answer, I think it is ok for a specific factory to new up it's specific matching-implementation that it was created for.
Update
Also, check this answer, specifically the comments, which say something about new-ing up instances.
Example:
public interface IContext {
T GetById<T>(int id);
}
public interface IContextFactory {
IContext Create();
}
public class EntityContext : DbContext, IContext {
public T GetById<T>(int id) {
var entity = ...; // Retrieve from db
return entity;
}
}
public class EntityContextFactory : IContextFactory {
public IContext Create() {
// I think this is ok, since the factory was specifically created
// to return the matching implementation of IContext.
return new EntityContext();
}
}
Mark tells me that I am not allowed to use the 'new' keyword to instantiate objects
That's not what Mark Seemann tells you, or what he means. You must make the clear separation between services (controlled by your composition root) at one side and primitives, entities, DTOs, view models and messages on the other side. Services are injectables and all other types are newables. You should only prevent using new on service types. It would be silly to prevent newing up strings for instance.
Since in your example the service is a repository, it seems reasonable to assume that the repository returns domain objects. Domain objects are newables and there's no reason not to new them manually.
Thanks for the answers everybody, they led me to the following conclusions.
Mark makes a distinction between stable and unstable dependencies in the book I am reading ( "Dependency injection in .NET"). Stable dependencies (eg Strings) can be created at will. Unstable dependencies should be moved behind a seam / interface.
A dependency is anything that is in a different assembly from the one that we are writing.
An unstable dependency is any of the following
It requires a run time environment to be set up such as a database, web server, maybe even the file system (otherwise it won't be extensible or testable, and it means we couldn't do late binding if we wanted to)
It doesn't exist yet (otherwise we can't do parallel development)
It requires something that isn't installed on all machines (otherwise it can cause test difficulties)
It contains non deterministic behaviour (otherwise impossible to test well)
So this is all well and good.
However, I often hide things behind seams within the same assembly. I find this extremely helpful for testing. For example if I am doing a complex calculation it is impossible to test the entire calculation well in one go. If I split the calculation up into lots of smaller classes and hide these behind seams, then I can easily inject any arbirtary intermediate results into a calculating class.
So, having had a good old think about it, these are my conclusions:
It is always OK to create a stable dependency
You should never create unstable dependencies directly
It can be useful to use seams within an assembly, particularly to break up big classes and make them more easily testable.
And in answer to my original question, it is ok to instatiate a concrete object from a concrete factory.

Why does one use dependency injection?

I'm trying to understand dependency injections (DI), and once again I failed. It just seems silly. My code is never a mess; I hardly write virtual functions and interfaces (although I do once in a blue moon) and all my configuration is magically serialized into a class using json.net (sometimes using an XML serializer).
I don't quite understand what problem it solves. It looks like a way to say: "hi. When you run into this function, return an object that is of this type and uses these parameters/data."
But... why would I ever use that? Note I have never needed to use object as well, but I understand what that is for.
What are some real situations in either building a website or desktop application where one would use DI? I can come up with cases easily for why someone may want to use interfaces/virtual functions in a game, but it's extremely rare (rare enough that I can't remember a single instance) to use that in non-game code.
First, I want to explain an assumption that I make for this answer. It is not always true, but quite often:
Interfaces are adjectives; classes are nouns.
(Actually, there are interfaces that are nouns as well, but I want to generalize here.)
So, e.g. an interface may be something such as IDisposable, IEnumerable or IPrintable. A class is an actual implementation of one or more of these interfaces: List or Map may both be implementations of IEnumerable.
To get the point: Often your classes depend on each other. E.g. you could have a Database class which accesses your database (hah, surprise! ;-)), but you also want this class to do logging about accessing the database. Suppose you have another class Logger, then Database has a dependency to Logger.
So far, so good.
You can model this dependency inside your Database class with the following line:
var logger = new Logger();
and everything is fine. It is fine up to the day when you realize that you need a bunch of loggers: Sometimes you want to log to the console, sometimes to the file system, sometimes using TCP/IP and a remote logging server, and so on ...
And of course you do NOT want to change all your code (meanwhile you have gazillions of it) and replace all lines
var logger = new Logger();
by:
var logger = new TcpLogger();
First, this is no fun. Second, this is error-prone. Third, this is stupid, repetitive work for a trained monkey. So what do you do?
Obviously it's a quite good idea to introduce an interface ICanLog (or similar) that is implemented by all the various loggers. So step 1 in your code is that you do:
ICanLog logger = new Logger();
Now the type inference doesn't change type any more, you always have one single interface to develop against. The next step is that you do not want to have new Logger() over and over again. So you put the reliability to create new instances to a single, central factory class, and you get code such as:
ICanLog logger = LoggerFactory.Create();
The factory itself decides what kind of logger to create. Your code doesn't care any longer, and if you want to change the type of logger being used, you change it once: Inside the factory.
Now, of course, you can generalize this factory, and make it work for any type:
ICanLog logger = TypeFactory.Create<ICanLog>();
Somewhere this TypeFactory needs configuration data which actual class to instantiate when a specific interface type is requested, so you need a mapping. Of course you can do this mapping inside your code, but then a type change means recompiling. But you could also put this mapping inside an XML file, e.g.. This allows you to change the actually used class even after compile time (!), that means dynamically, without recompiling!
To give you a useful example for this: Think of a software that does not log normally, but when your customer calls and asks for help because he has a problem, all you send to him is an updated XML config file, and now he has logging enabled, and your support can use the log files to help your customer.
And now, when you replace names a little bit, you end up with a simple implementation of a Service Locator, which is one of two patterns for Inversion of Control (since you invert control over who decides what exact class to instantiate).
All in all this reduces dependencies in your code, but now all your code has a dependency to the central, single service locator.
Dependency injection is now the next step in this line: Just get rid of this single dependency to the service locator: Instead of various classes asking the service locator for an implementation for a specific interface, you - once again - revert control over who instantiates what.
With dependency injection, your Database class now has a constructor that requires a parameter of type ICanLog:
public Database(ICanLog logger) { ... }
Now your database always has a logger to use, but it does not know any more where this logger comes from.
And this is where a DI framework comes into play: You configure your mappings once again, and then ask your DI framework to instantiate your application for you. As the Application class requires an ICanPersistData implementation, an instance of Database is injected - but for that it must first create an instance of the kind of logger which is configured for ICanLog. And so on ...
So, to cut a long story short: Dependency injection is one of two ways of how to remove dependencies in your code. It is very useful for configuration changes after compile-time, and it is a great thing for unit testing (as it makes it very easy to inject stubs and / or mocks).
In practice, there are things you can not do without a service locator (e.g., if you do not know in advance how many instances you do need of a specific interface: A DI framework always injects only one instance per parameter, but you can call a service locator inside a loop, of course), hence most often each DI framework also provides a service locator.
But basically, that's it.
P.S.: What I described here is a technique called constructor injection, there is also property injection where not constructor parameters, but properties are being used for defining and resolving dependencies. Think of property injection as an optional dependency, and of constructor injection as mandatory dependencies. But discussion on this is beyond the scope of this question.
I think a lot of times people get confused about the difference between dependency injection and a dependency injection framework (or a container as it is often called).
Dependency injection is a very simple concept. Instead of this code:
public class A {
private B b;
public A() {
this.b = new B(); // A *depends on* B
}
public void DoSomeStuff() {
// Do something with B here
}
}
public static void Main(string[] args) {
A a = new A();
a.DoSomeStuff();
}
you write code like this:
public class A {
private B b;
public A(B b) { // A now takes its dependencies as arguments
this.b = b; // look ma, no "new"!
}
public void DoSomeStuff() {
// Do something with B here
}
}
public static void Main(string[] args) {
B b = new B(); // B is constructed here instead
A a = new A(b);
a.DoSomeStuff();
}
And that's it. Seriously. This gives you a ton of advantages. Two important ones are the ability to control functionality from a central place (the Main() function) instead of spreading it throughout your program, and the ability to more easily test each class in isolation (because you can pass mocks or other faked objects into its constructor instead of a real value).
The drawback, of course, is that you now have one mega-function that knows about all the classes used by your program. That's what DI frameworks can help with. But if you're having trouble understanding why this approach is valuable, I'd recommend starting with manual dependency injection first, so you can better appreciate what the various frameworks out there can do for you.
As the other answers stated, dependency injection is a way to create your dependencies outside of the class that uses it. You inject them from the outside, and take control about their creation away from the inside of your class. This is also why dependency injection is a realization of the Inversion of control (IoC) principle.
IoC is the principle, where DI is the pattern. The reason that you might "need more than one logger" is never actually met, as far as my experience goes, but the actually reason is, that you really need it, whenever you test something. An example:
My Feature:
When I look at an offer, I want to mark that I looked at it automatically, so that I don't forget to do so.
You might test this like this:
[Test]
public void ShouldUpdateTimeStamp
{
// Arrange
var formdata = { . . . }
// System under Test
var weasel = new OfferWeasel();
// Act
var offer = weasel.Create(formdata)
// Assert
offer.LastUpdated.Should().Be(new DateTime(2013,01,13,13,01,0,0));
}
So somewhere in the OfferWeasel, it builds you an offer Object like this:
public class OfferWeasel
{
public Offer Create(Formdata formdata)
{
var offer = new Offer();
offer.LastUpdated = DateTime.Now;
return offer;
}
}
The problem here is, that this test will most likely always fail, since the date that is being set will differ from the date being asserted, even if you just put DateTime.Now in the test code it might be off by a couple of milliseconds and will therefore always fail. A better solution now would be to create an interface for this, that allows you to control what time will be set:
public interface IGotTheTime
{
DateTime Now {get;}
}
public class CannedTime : IGotTheTime
{
public DateTime Now {get; set;}
}
public class ActualTime : IGotTheTime
{
public DateTime Now {get { return DateTime.Now; }}
}
public class OfferWeasel
{
private readonly IGotTheTime _time;
public OfferWeasel(IGotTheTime time)
{
_time = time;
}
public Offer Create(Formdata formdata)
{
var offer = new Offer();
offer.LastUpdated = _time.Now;
return offer;
}
}
The Interface is the abstraction. One is the REAL thing, and the other one allows you to fake some time where it is needed. The test can then be changed like this:
[Test]
public void ShouldUpdateTimeStamp
{
// Arrange
var date = new DateTime(2013, 01, 13, 13, 01, 0, 0);
var formdata = { . . . }
var time = new CannedTime { Now = date };
// System under test
var weasel= new OfferWeasel(time);
// Act
var offer = weasel.Create(formdata)
// Assert
offer.LastUpdated.Should().Be(date);
}
Like this, you applied the "inversion of control" principle, by injecting a dependency (getting the current time). The main reason to do this is for easier isolated unit testing, there are other ways of doing it. For example, an interface and a class here is unnecessary since in C# functions can be passed around as variables, so instead of an interface you could use a Func<DateTime> to achieve the same. Or, if you take a dynamic approach, you just pass any object that has the equivalent method (duck typing), and you don't need an interface at all.
You will hardly ever need more than one logger. Nonetheless, dependency injection is essential for statically typed code such as Java or C#.
And...
It should also be noted that an object can only properly fulfill its purpose at runtime, if all its dependencies are available, so there is not much use in setting up property injection. In my opinion, all dependencies should be satisfied when the constructor is being called, so constructor-injection is the thing to go with.
I think the classic answer is to create a more decoupled application, which has no knowledge of which implementation will be used during runtime.
For example, we're a central payment provider, working with many payment providers around the world. However, when a request is made, I have no idea which payment processor I'm going to call. I could program one class with a ton of switch cases, such as:
class PaymentProcessor{
private String type;
public PaymentProcessor(String type){
this.type = type;
}
public void authorize(){
if (type.equals(Consts.PAYPAL)){
// Do this;
}
else if(type.equals(Consts.OTHER_PROCESSOR)){
// Do that;
}
}
}
Now imagine that now you'll need to maintain all this code in a single class because it's not decoupled properly, you can imagine that for every new processor you'll support, you'll need to create a new if // switch case for every method, this only gets more complicated, however, by using Dependency Injection (or Inversion of Control - as it's sometimes called, meaning that whoever controls the running of the program is known only at runtime, and not complication), you could achieve something very neat and maintainable.
class PaypalProcessor implements PaymentProcessor{
public void authorize(){
// Do PayPal authorization
}
}
class OtherProcessor implements PaymentProcessor{
public void authorize(){
// Do other processor authorization
}
}
class PaymentFactory{
public static PaymentProcessor create(String type){
switch(type){
case Consts.PAYPAL;
return new PaypalProcessor();
case Consts.OTHER_PROCESSOR;
return new OtherProcessor();
}
}
}
interface PaymentProcessor{
void authorize();
}
** The code won't compile, I know :)
The main reason to use DI is that you want to put the responsibility of the knowledge of the implementation where the knowledge is there. The idea of DI is very much inline with encapsulation and design by interface.
If the front end asks from the back end for some data, then is it unimportant for the front end how the back end resolves that question. That is up to the requesthandler.
That is already common in OOP for a long time. Many times creating code pieces like:
I_Dosomething x = new Impl_Dosomething();
The drawback is that the implementation class is still hardcoded, hence has the front end the knowledge which implementation is used. DI takes the design by interface one step further, that the only thing the front end needs to know is the knowledge of the interface.
In between the DYI and DI is the pattern of a service locator, because the front end has to provide a key (present in the registry of the service locator) to lets its request become resolved.
Service locator example:
I_Dosomething x = ServiceLocator.returnDoing(String pKey);
DI example:
I_Dosomething x = DIContainer.returnThat();
One of the requirements of DI is that the container must be able to find out which class is the implementation of which interface. Hence does a DI container require strongly typed design and only one implementation for each interface at the same time. If you need more implementations of an interface at the same time (like a calculator), you need the service locator or factory design pattern.
D(b)I: Dependency Injection and Design by Interface.
This restriction is not a very big practical problem though. The benefit of using D(b)I is that it serves communication between the client and the provider. An interface is a perspective on an object or a set of behaviours. The latter is crucial here.
I prefer the administration of service contracts together with D(b)I in coding. They should go together. The use of D(b)I as a technical solution without organizational administration of service contracts is not very beneficial in my point of view, because DI is then just an extra layer of encapsulation. But when you can use it together with organizational administration you can really make use of the organizing principle D(b)I offers.
It can help you in the long run to structure communication with the client and other technical departments in topics as testing, versioning and the development of alternatives. When you have an implicit interface as in a hardcoded class, then is it much less communicable over time then when you make it explicit using D(b)I. It all boils down to maintenance, which is over time and not at a time. :-)
Quite frankly, I believe people use these Dependency Injection libraries/frameworks because they just know how to do things in runtime, as opposed to load time. All this crazy machinery can be substituted by setting your CLASSPATH environment variable (or other language equivalent, like PYTHONPATH, LD_LIBRARY_PATH) to point to your alternative implementations (all with the same name) of a particular class. So in the accepted answer you'd just leave your code like
var logger = new Logger() //sane, simple code
And the appropriate logger will be instantiated because the JVM (or whatever other runtime or .so loader you have) would fetch it from the class configured via the environment variable mentioned above.
No need to make everything an interface, no need to have the insanity of spawning broken objects to have stuff injected into them, no need to have insane constructors with every piece of internal machinery exposed to the world. Just use the native functionality of whatever language you're using instead of coming up with dialects that won't work in any other project.
P.S.: This is also true for testing/mocking. You can very well just set your environment to load the appropriate mock class, in load time, and skip the mocking framework madness.

DI Container and custom-scoped state in legacy system

I believe I understand the basic concepts of DI / IoC containers having written a couple of applications using them and reading a lot of stack overflow answers as well as Mark Seeman's book. There are still some cases that I have trouble with, especially when it comes to integrating DI container to a large existing architecture where DI principle hasn't been really used (think big ball of mud).
I know the ideal scenario is to have a single composition root / object graph per operation but in a legacy system this might not be possible without major refactoring (only the new and some select refactored old parts of the code could have dependencies injected through constructor and the rest of the system using the container as a service locator to interact with the new parts). This effectively means that a stack trace deep within an operation might include several object graphs with calls being made back and forth between new subsystems (single object graph until exiting into an old segment) and traditional subsystems (service locator call at some point to code under DI container).
With the (potentially faulty, I might be overthinking this or be completely wrong in assuming this kind of hybrid architecture is a good idea) assumptions out of the way, here's the actual problem:
Let's say we have a thread pool executing scheduled jobs of various types defined in database (or any external place). Each separate type of scheduled job is implemented as a class inheriting a common base class. When the job is started, it gets fed the information about which targets it should write its log messages to and the configuration it should use. The configuration could probably be handled by just passing the values as method parameters to whatever class needs them but if the job implementation gets larger than say 10-20 classes, it doesn't seem very handy.
Logging is the larger problem. Subsystems the job calls probably also need to write things to the log and usually in examples this is done by just requesting instance of ILog in the constructor. But how does that work in this case when we don't know the details / implementation until runtime? Since:
Due to (non DI container controlled) legacy system segments in the call chain (-> there potentially being multiple separate object graphs), child container cannot be used to inject the custom logger for specific sub-scope
Manual property injection would basically require the complete call chain (including all legacy subsystems) to be updated
A simplified example to help better perceive the problem:
Class JobXImplementation : JobBase {
// through constructor injection
ILoggerFactory _loggerFactory;
JobXExtraLogic _jobXExtras;
public void Run(JobConfig configurationFromDatabase)
{
ILog log = _loggerFactory.Create(configurationFromDatabase.targets);
// if there were no legacy parts in the call chain, I would register log as instance to a child container and Resolve next part of the call chain and everyone requesting ILog would get the correct logging targets
// do stuff
_jobXExtras.DoStuff(configurationFromDatabase, log);
}
}
Class JobXExtraLogic {
public void DoStuff(JobConfig configurationFromDatabase, ILog log) {
// call to legacy sub-system
var old = new OldClass(log, configurationFromDatabase.SomeRandomSetting);
old.DoOldStuff();
}
}
Class OldClass {
public void DoOldStuff() {
// moar stuff
var old = new AnotherOldClass();
old.DoMoreOldStuff();
}
}
Class AnotherOldClass {
public void DoMoreOldStuff() {
// call to a new subsystem
var newSystemEntryPoint = DIContainerAsServiceLocator.Resolve<INewSubsystemEntryPoint>();
newSystemEntryPoint.DoNewStuff();
}
}
Class NewSubsystemEntryPoint : INewSubsystemEntryPoint {
public void DoNewStuff() {
// want to log something...
}
}
I'm sure you get the picture by this point.
Instantiating old classes through DI is a non-starter since many of them use (often multiple) constructors to inject values instead of dependencies and would have to be refactored one by one. The caller basically implicitly controls the lifetime of the object and this is assumed in the implementations (the way they handle internal object state).
What are my options? What other kinds of problems could you possibly see in a situation like this? Is trying to only use constructor injection in this kind of environment even feasible?
Great question. In general, I would say that an IoC container loses a lot of its effectiveness when only a portion of the code is DI-friendly.
Books like Working Effectively with Legacy Code and Dependency Injection in .NET both talk about ways to tease apart objects and classes to make DI viable in code bases like the one you described.
Getting the system under test would be my first priority. I'd pick a functional area to start with, one with few dependencies on other functional areas.
I don't see a problem with moving beyond constructor injection to setter injection where it makes sense, and it might offer you a stepping stone to constructor injection. Adding a property is usually less invasive than changing an object's constructor.

Resources