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.
Related
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).
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.
Something that has been bugging me since I read an answer on another stackoverflow question (the precise one eludes me now) where a user stated something like "If you're calling the Service Locator, you're doing it wrong."
It was someone with a high reputation (in the hundred thousands, I think) so I tend to think this person might know what they're talking about. I've been using DI for my projects since I first started learning about it and how well it relates to Unit Testing and what not. It's something I'm fairly comfortable with now and I think I know what I'm doing.
However, there are a lot of places where I've been using the Service Locator to resolve dependencies in my project. Once prime example comes from my ModelBinder implementations.
Example of a typical model binder.
public class FileModelBinder : IModelBinder {
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
ValueProviderResult value = bindingContext.ValueProvider.GetValue("id");
IDataContext db = Services.Current.GetService<IDataContext>();
return db.Files.SingleOrDefault(i => i.Id == id.AttemptedValue);
}
}
not a real implementation - just a quick example
Since the ModelBinder implementation requires a new instance when a Binder is first requested, it's impossible to use Dependency Injection on the constructor for this particular implementation.
It's this way in a lot of my classes. Another example is that of a Cache Expiration process that runs a method whenever a cache object expires in my website. I run a bunch of database calls and what not. There too I'm using a Service Locator to get the required dependency.
Another issue I had recently (that I posted a question on here about) was that all my controllers required an instance of IDataContext which I used DI for - but one action method required a different instance of IDataContext. Luckily Ninject came to the rescue with a named dependency. However, this felt like a kludge and not a real solution.
I thought I, at least, understood the concept of Separation of Concerns reasonably well but there seems to be something fundamentally wrong with how I understand Dependency Injection and the Service Locator Pattern - and I don't know what that is.
The way I currently understand it - and this could be wrong as well - is that, at least in MVC, the ControllerFactory looks for a Constructor for a Controller and calls the Service Locator itself to get the required dependencies and then passes them in. However, I can understand that not all classes and what not have a Factory to create them. So it seems to me that some Service Locator pattern is acceptable...but...
When is it not acceptable?
What sort of pattern should I be on the look out for when I should rethink how I'm using the Service Locator Pattern?
Is my ModelBinder implementation wrong? If so, what do I need to learn to fix it?
In another question along the lines of this one user Mark Seemann recommended an Abstract Factory - How does this relate?
I guess that's it - I can't really think of any other question to help my understanding but any extra information is greatly appreciated.
I understand that DI might not be the answer to everything and I might be going overboard in how I implement it, however, it seems to work the way I expect it to with Unit Testing and what not.
I'm not looking for code to fix my example implementation - I'm looking to learn, looking for an explanation to fix my flawed understanding.
I wish stackoverflow.com had the ability to save draft questions. I also hope whoever answers this question gets the appropriate amount of reputation for answering this question as I think I'm asking for a lot. Thanks, in advance.
Consider the following:
public class MyClass
{
IMyInterface _myInterface;
IMyOtherInterface _myOtherInterface;
public MyClass(IMyInterface myInterface, IMyOtherInterface myOtherInterface)
{
// Foo
_myInterface = myInterface;
_myOtherInterface = myOtherInterface;
}
}
With this design I am able to express the dependency requirements for my type. The type itself isn't responsible for knowing how to instantiate any of the dependencies, they are given to it (injected) by whatever resolving mechanism is used [typically an IoC container]. Whereas:
public class MyClass
{
IMyInterface _myInterface;
IMyOtherInterface _myOtherInterface;
public MyClass()
{
// Bar
_myInterface = ServiceLocator.Resolve<IMyInterface>();
_myOtherInterface = ServiceLocator.Resolve<IMyOtherInterface>();
}
}
Our class is now dependent on creating the specfic instances, but via delegation to a service locator. In this sense, Service Location can be considered an anti-pattern because you're not exposing dependencies, but you are allowing problems which can be caught through compilation to bubble up into runtime. (A good read is here). You hiding complexities.
The choice between one or the other really depends on what your building on top of and the services it provides. Typically if you are building an application from scratch, I would choose DI all the time. It improves maintainability, promotes modularity and makes testing types a whole lot easier. But, taking ASP.NET MVC3 as an example, you could easily implement SL as its baked into the design.
You can always go for a composite design where you could use IoC/DI with SL, much like using the Common Services Locator. You component parts could be wired up through DI, but exposed through SL. You could even throw composition into the mix and use something like the Managed Extensibility Framework (which itself supports DI, but can also be wired to other IoC containers or service locators). It's a big design choice to make, generally my recommendation would be for IoC/DI where possible.
Your specific design I wouldn't say is wrong. In this instance, your code is not responsible for creating an instance of the model binder itself, that's up to the framework so you have no control over that but your use of the service locator could probably be easily changed to access an IoC container. But the action of calling resolve on the IoC container...would you not consider that service location?
With an abstract factory pattern the factory is specialised at creating specific types. You don't register types for resolution, you essentially register an abstract factory and that builds any types that you may require. With a Service Locator it is designed to locate services and return those instances. Similar from an convention point of view, but very different in behaviour.
When using dependency injection which dependencies do you inject?
I have previously injected all dependencies but have found when doing TDD there are typically two types of dependency:
Those which are genuine external dependencies which may change e.g. ProductRepository
Those which exist purely for testability e.g. Part of the behaviour of the class that has been extracted and injected just for testability
One approach is to inject ALL dependencies like this
public ClassWithExternalDependency(IExternalDependency external,
IExtractedForTestabilityDependency internal)
{
// assign dependencies ...
}
but I've found this can cause dependency bloat in the DI registry.
Another approach is to hide the "testability dependency" like this
public ClassWithExternalDependency(IExternalDependency external)
: this (external, new ConcreteClassOfInternalDependency())
{}
internal ClassWithExternalDependency(IExternalDependency external,
IExtractedForTestabilityDependency internal)
{
// assign dependencies ...
}
This is more effort but seems to make a lot more sense. The downside being not all objects are configured in the DI framework, thereby breaking a "best practice" that I've heard.
Which approach would you advocate and why?
I believe you're better off injecting all of your dependencies. If it starts to get a little unwieldy, that's probably an indication that you need to simplify things a bit or move the dependencies into another object. Feeling the "pain" of your design as you go can be really enlightening.
As for dependency bloat in the registry, you might consider using some sort of conventional binding technique, rather than registering each dependency by hand. Some IoC containers have convention-based type-scanning bindings built into them. For example, here's part of a module I use in a Caliburn WPF application that uses Ninject:
public class AppModule : NinjectModule
{
public override void Load()
{
Bind<IShellPresenter>().To<ShellPresenter>().InSingletonScope();
BindAllResults();
BindAllPresenters();
}
/// <summary>
/// Automatically bind all presenters that haven't already been manually bound
/// </summary>
public void BindAllPresenters()
{
Type[] types = Assembly.GetExecutingAssembly().GetTypes();
IEnumerable<Type> presenterImplementors =
from t in types
where !t.IsInterface
&& t.Name.EndsWith("Presenter")
select t;
presenterImplementors.Run(
implementationType =>
{
if (!Kernel.GetBindings(implementationType).Any())
Bind(implementationType).ToSelf();
});
}
Even though I have dozens of results and presenters running around, I don't have to register them explicitly.
I certainly won't inject all dependencies, because were to stop? Do you want to inject your string dependencies? I only invert the dependencies that I need for unit testing. I want to stub my database (see this example for instance). I want to stub the sending of e-mail messages. I want to stub the system clock. I want to stub writing to the file system.
The thing about inverting as many dependencies as you can, even those that you don't need for testing, is that make unit testing a lot harder and the more you stub out the less you really test how the system really acts. This makes your tests much less reliable. It also complicates your DI configuration in the application root.
I would wire all my non-external dependencies by hand and 'register' only external dependencies. When I say non-external, I mean the objects which belong to my component and which were extracted out to interfaces just for the sake of single responsibility/testability I would never have any other implementations of such interfaces ever. External dependencies are stuff like DB connections, web services, interfaces which don't belong to my component. I would register them as interfaces because their implementations can be switched to stubbed ones for integration testing. Having a small number of components registered in a DI container makes the DI code easier to read and bloat free.
On this AutoFac "Best Practices" page (http://code.google.com/p/autofac/wiki/BestPractices), they say:
Don't Pass the Container Around
Giving components access to the container, or storing it in a public static property, or making functions like Resolve() available on a global 'IoC' class defeats the purpose of using dependency injection. Such designs have more in common with the Service Locator pattern.
If components have a dependency on the container, look at how they're using the container to retrieve services, and add those services to the component's (dependency injected) constructor arguments instead.
So what would be a better way to have one component "dynamically" instantiate another? Their second paragraph doesn't cover the case where the component that "may" need to be created will depend on the state of the system. Or when component A needs to create X number of component B.
To abstract away the instantiation of another component, you can use the Factory pattern:
public interface IComponentBFactory
{
IComponentB CreateComponentB();
}
public class ComponentA : IComponentA
{
private IComponentBFactory _componentBFactory;
public ComponentA(IComponentBFactory componentBFactory)
{
_componentBFactory = componentBFactory;
}
public void Foo()
{
var componentB = _componentBFactory.CreateComponentB();
...
}
}
Then the implementation can be registered with the IoC container.
A container is one way of assembling an object graph, but it certainly isn't the only way. It is an implementation detail. Keeping the objects free of this knowledge decouples them from infrastructure concerns. It also keeps them from having to know which version of a dependency to resolve.
Autofac actually has some special functionality for exactly this scenario - the details are on the wiki here: http://code.google.com/p/autofac/wiki/DelegateFactories.
In essence, if A needs to create multiple instances of B, A can take a dependency on Func<B> and Autofac will generate an implementation that returns new Bs out of the container.
The other suggestions above are of course valid - Autofac's approach has a couple of differences:
It avoids the need for a large number of factory interfaces
B (the product of the factory) can still have dependencies injected by the container
Hope this helps!
Nick
An IoC takes the responsibility for determining which version of a dependency a given object should use. This is useful for doing things like creating chains of objects that implement an interface as well as having a dependency on that interface (similar to a chain of command or decorator pattern).
By passing your container, you are putting the onus on the individual object to get the appropriate dependency, so it has to know how to. With typical IoC usage, the object only needs to declare that it has a dependency, not think about selecting between multiple available implementations of that dependency.
Service Locator patterns are more difficult to test and it certainly is more difficult to control dependencies, which may lead to more coupling in your system than you really want.
If you really want something like lazy instantiation you may still opt for the Service Locator style (it doesn't kill you straight away and if you stick to the container's interface it is not too hard to test with some mocking framework). Bear in mind, though that the instantiation of a class that doesn't do much (or anything) in the constructor is immensely cheap.
The container's I have come to know (not autofac so far) will let you modify what dependencies should be injected into which instance depending on the state of the system such that even those decisions can be externalized into the configuration of the container.
This can provide you plenty of flexibility without resorting to implementing interaction with the container based on some state you access in the instance consuming dependencies.