Catalog concept instead of complex constructors? - c#

In my current project my manager is forcing some design concept for dependency injection I would like to discuss because I’m curious what a specialists of dependency injection think about this approach. The ideas behind this is use of class called catalog that is implemented per each service (service in Service Fabric) and having all dependencies inside like this:
public interface IDepA
{
}
public interface IDepB
{
}
public interface IDepC
{
}
public class StandardConstructorInjectorService
{
private readonly IDepA _depA;
private readonly IDepB _depB;
private readonly IDepC _depC;
public StandardConstructorInjectorService(IDepA depA, IDepB depB, IDepC depC)
{
_depA = depA;
_depB = depB;
_depC = depC;
}
}
public class ServiceCatalog
{
private readonly Container _container;
public ServiceCatalog(Container container)
{
_container = container;
}
public IDepA DepA => _container.GetInstance<IDepA>();
public IDepB DepB => _container.GetInstance<IDepB>();
public IDepC DepC => _container.GetInstance<IDepC>();
}
public class ServiceWithCatalog
{
private readonly ServiceCatalog _catalog;
public ServiceWithCatalog(ServiceCatalog catalog)
{
_catalog = catalog;
}
}
From my perspective we have
Pros:
Code that is using catalog is simple
Dependencies can be used in Lazy mode so when code logic is not using them they will not be created – but on other hand I know that we should design classes in such way that they will use all dependencies
It is easy bootstrap those classes because they have one predefined catalog
Cons:
Dependencies to class is not directly visible
Smell for service locator but we use resolve only in catalog definition and not in business code so I’m not sure is this acceptable or maybe dependency injection police will hunt us down :)
What do you think about this approach?

Your ServiceCatalog class depends on the Container. This effectively makes this a Service Locator, which is an anti-pattern. The fact this this class is not 'business code' is irrelevant. The only thing that matters is that it is not part of the Composition Root, which makes this an anti-pattern.
Besides using an anti-pattern, the class exposes its dependencies, rather than hiding them, which is a bad idea as well. The main idea of this class is probably to group commonly used dependencies together, lowering the number of constructor dependencies a class has. Problem with this, however, is that it doesn't lower the complexity of a consuming class, but simply obscures the fact that a class has too many dependencies. A class with too many dependencies likely violates the Single Responsibility Principle.
Instead of using this service catalog 'pattern', stick to using Constructor Injection. When a class gets too many constructor dependencies, a code-smell called Constructor Over-Injection, action should be taken. There are many solutions for this, such as Facade Services, Decorators or Domain Events. A Facade Service hides its dependencies rather than exposing them.
All this information, and much more, can be read in this book, by Mark Seemann and myself.

Related

Does using DependencyResolver incur a performance hit?

I found a few articles outlining the reason why the DependencyResolver in C# MVC should be avoided
But I also found a pattern of injecting a "base dependency" into a constructor, and that class essentially hold all instances the app's dependencies, but obviously not in a sigleton, each time the dependencies are instantiated anew
// example possibly to be avoided
public interface IBaseDependencies
{
IClientRepo ClientRepo { get; }
IProductRepo ProductRepo { get; }
/// more here
}
..but while I love the simplicity of passing dependencies in this way, the problem is ALL the depencies will be instantiated but they may not all be required, so to avoid that performce hit, I thought to add C#'s Lazy<> class like so...
// Is this example any better?
public interface ILazyBaseDependencies
{
#region IClientRepo
private readonly Lazy<IClientRepo> ClientRepoLazy =
new Lazy<IClientRepo>(() => DependencyResolver.Current.GetService<IClientRepo>());
public IClientRepo ClientRepo => ClientRepoLazy.Value;
#endregion
/// more here
}
So now the dependency is only instantiated when it is called directly. The larger the project, the more the "base dependencies" approach becomes useful, but will it hurt performance to do this this way?
I wouldn't call that a pattern, but rather a code smell. At the very least, it violates the Interface Segregation Principle as well as the Dependency Inversion Principle.
Will it hurt performance? Only you can answer that question.

How to register collection of instances in Simple injector

In my project I have more than one database contexts, so I have created a provider for getting the context objects based on need.
My provider is looks like this.
public class DbContextProvider
{
public Func<AccountingContext> AccountingDbContextResolver { get; set; }
public Func<ActiveDirectryContext> ActiveDirectryDbContextResolver { get; set; }
public AccountingContext GetAccountingDbContext() =>
this.AccountingDbContextResolver();
public ActiveDirectryContext GetActiveDirectryDbContext() =>
this.ActiveDirectryDbContextResolver();
}
One ServiceBase class I have created for getting the provider
public class ServiceBase
{
public ServiceBase(DbContextProvider contextProvider)
{
this.ContextProvider = contextProvider;
}
protected DbContextProvider ContextProvider { get; }
public AccountingContext AccountingDbContext =>
this.ContextProvider.GetAccountingDbContext();
public ActiveDirectryContext ActiveDirectryDbContext =>
this.ContextProvider.GetActiveDirectryDbContext();
}
I am using simple injector and I need to create instance of both Database contexts.
For getting the instance I have created two static methods with delegate
private static DbContextProvider CreateActiveDirectryDbContextProvider(Container container)
{
return new DbContextProvider
{
ActiveDirectryDbContextResolver =
() => container.GetInstance<ActiveDirectryContext>();
};
}
private static DbContextProvider CreateAccountingDbContextProvider(Container container)
{
return new DbContextProvider
{
AccountingDbContextResolver = () => container.GetInstance<AccountingContext>();
};
}
And for registrations I have used the below code
var accountingProvider = CreateAccountingDbContextProvider(container);
container.RegisterInstance(accountingProvider);
var activeDirectryProvider = CreateAccountingDbContextProvider(container);
container.RegisterInstance(activeDirectryProvider);
If i run the code then I am getting an error like below
System.InvalidOperationException: 'Type DbContextProvider has
already been registered. If your intention is to resolve a collection
of DbContextProvider implementations, use the
Container.Collection.Register overloads. For more information, see
https://simpleinjector.org/coll1. If your intention is to replace the
existing registration with this new registration, you can allow
overriding the current registration by setting
Container.Options.AllowOverridingRegistrations to true. For more
information, see https://simpleinjector.org/ovrrd.'
But everything is working fine when I try with only one context that is ,
var accountingProvider = CreateAccountingDbContextProvider(container);
container.RegisterInstance(accountingProvider);
I have tried to register it using container.Collection.Register, no error is coming but I am not getting the instance in the service layer , I am getting a null reference exception there.
can someone help me to resolve this ?
You only have one type (DbContextProvider) that is responsible for constructing both AccountingContext and ActiveDirectryContext. From that perspective, it is really strange to create two DbContextProvider instances that are each partly initialized. A consumer would not expect GetAccountingDbContext() to return null or throw a NullReferenceException. So instead, you should create one single instance that can be used for both cases:
container.Register<ActiveDirectryContext>(Lifestyle.Scoped);
container.Register<AccountingContext>(Lifestyle.Scoped);
container.RegisterInstance<DbContextProvider>(new DbContextProvider
{
ActiveDirectryDbContextResolver = () => container.GetInstance<ActiveDirectryContext>(),
AccountingDbContextResolver = () => container.GetInstance<AccountingContext>()
});
Or better, make DbContextProvider immutable:
container.RegisterInstance<DbContextProvider>(new DbContextProvider(
activeDirectryDbContextResolver: () => container.GetInstance<ActiveDirectryContext>(),
accountingDbContextResolver: () => container.GetInstance<AccountingContext>()));
This fixes the problem, because there is no only one registration for DbContextProvider. This removes the ambiguity, prevents possible bugs, and is a simpler solution.
But while this would work, I would like to suggest a few changes to your design.
Composition over Inheritance
First of all, you should get rid of the ServiceBase base class. Although base classes are not bad per see, when they start to get dependencies of their own, they likely start to violate the Single Responsibility Principle, and their derivatives the Dependency Inversion Principle and the Open/Closed Principle:
Base classes with dependencies often become a hodgepodge of functionality—often cross-cutting concerns. The base class becomes an ever-growing class. Ever-growing classes are an indication of a Single Responsibility Principle violation.
When the base class starts to contain logic, the derivatives automatically depend on that behavior—A derivative is always strongly coupled to its base class. This makes it hard to test the derivative in isolation. In case you ever want to replace or mock the behavior of the base class, it means that its behavior is Volatile. When a class is tightly coupled with a Volatile Dependency, it means you are violating the Dependency Inversion Principle.
The base class's constructor dependencies need to be supplied by the derived class's constructor. This will cause sweeping changes when the base class requires a new dependency, because all derived constructors need to be updated as well.
Instead, of using base classes, do the following:
Instead of forwarding dependencies from the derived class to the base class constructor, the derived class should store the dependency itself in a private field. It can use that dependency directly.
In case the base class contains behavior besides code:
In case that behavior is Volatile, wrap the logic in a class, hide that class behind an abstraction and inject the class (through its abstraction) into the constructor of the derived class. When doing this, it becomes very easy to see what dependencies the derived class has.
In case the behavior is Stable, you can use static helper classes or extension methods to make the base class's behavior reusable.
In case the behavior concerns a cross-cutting concern, consider the use of Decorators or Dynamic Interception as an alternative to base classes.
When you follow this advice, what you end up with is a set of (derived) service classes that depend on a base class that is nothing more than an empty shell. This is when you can remove the base class altogether. What you now achieved is Composition over Inheritance. Composition typically leads to more maintainable systems than inheritance does.
Closure Composition Model
As JoostK mentioned, you can also inject the DbContext types directly into consumers. Whether or not you want to do this, however, depends on the type of composition model you decided to use. What this means is that, when you choose to apply the Closure Composition Model, you should typically inject the DbContext implementations directly into your consumers.
public class ProduceIncomeTaxService : IHandler<ProduceIncomeTax>
{
private readonly AccountingContext context;
// Inject stateful AccountingContext directly into constructor
public ProduceIncomeTaxService(AccountingContext context) => this.context = context;
public void Handle(ProduceIncomeTax command)
{
var record = this.context.AccountingRecords
.Single(r => r.Id == command.Id);
var tax = CalculateIncomeTax(record);
FaxIncomeTax(tax);
this.context.SaveChanges();
}
...
}
This simplifies the registrations of your system, because now you just register the DbContext implementaions and you're done:
container.Register<ActiveDirectryContext>(Lifestyle.Scoped);
container.Register<AccountingContext>(Lifestyle.Scoped);
// Of course don't forget to register your service classes.
Interface Segregation Principle
Your current DbContextProvider seems to designed around the Ambient Composition Model. There are advantages of both composition models, and you might have chosen deliberately for the Ambient Composition Model.
Still, however, the DbContextProvider exposes many (10) properties—one for each DbContext. Classes and abstractions with many methods can cause a number of problems concerning maintainability. This stems from the Interface Segregation Principle that prescribes narrow abstractions. So instead of injecting one wide provider implementation that gives access to a single DbContext type. Implementations would typically only require access to a single DbContext type. If they require multiple, the class should almost certainly be split up into smaller, more-focused classes.
So what you can do instead is create a generic abstraction that allows access to a single DbContext type:
public interface IDbContextProvider<T> where T : DbContext
{
T Context { get; }
}
When used in a consumer, this would look as follows:
public class ProduceIncomeTaxService : IHandler<ProduceIncomeTax>
{
private readonly IDbContextProvider<AccountingContext> provider;
// Inject an ambient context provider into the constructor
public ProduceIncomeTaxService(IDbContextProvider<AccountingContext> provider)
=> this.provider = provider;
public void Handle(ProduceIncomeTax command)
{
var record = this.provider.Context.AccountingRecords
.Single(r => r.Id == command.Id);
var tax = CalculateIncomeTax(record);
FaxIncomeTax(tax);
this.provider.Context.SaveChanges();
}
...
}
There are multiple ways to implement IDbContextProvider<T>, but you can, for instance, create an implementation that directly depends on Simple Injector:
public sealed class SimpleInjectorDbContextProvider<T> : IDbContextProvider<T>
where T : DbContext
{
private readonly InstanceProducer producer;
public SimpleInjectorDbContextProvider(Container container)
{
this.producer = container.GetCurrentRegistrations()
.FirstOrDefault(r => r.ServiceType == typeof(T))
?? throw new InvalidOperationException(
$"You forgot to register {typeof(T).Name}. Please call: " +
$"container.Register<{typeof(T).Name}>(Lifestyle.Scope);");
}
public T Context => (T)this.producer.GetInstance();
}
This class uses the injected Container to pull the right InstanceProducer registration for the given DbContext type. If this is not registered, it throws an exception. The InstanceProducer is then used to get the DbContext when Context is called.
Since this class depends on Simple Injector, it should be part of your Composition Root.
You can register it as follows:
container.Register<ActiveDirectryContext>(Lifestyle.Scoped);
container.Register<AccountingContext>(Lifestyle.Scoped);
container.Register(
typeof(IDbContextProvider<>),
typeof(SimpleInjectorDbContextProvider<>),
Lifestyle.Singleton);

Domain Driven Design - Singletons

It's a bad idea to create a singleton when we are using ddd?
I'm thinking of creating two of them, one for global settings (which are saved in the database) and the other for local settings (which are saved in the Windows Registry in my application windows forms).
If singletons in ddd is acceptable, where and when should I fill them with the stored values?
Singletons implemented as is (1) aren't acceptable in DDD based on your case(2) and even in any other modern software development paradigm. Note that DDD is more than a software architectural paradigm, but when I say that common singleton implementation isn't acceptable I'm talking about how to properly implement DDD in programming languages like C#.
For example, the following code sample is a possible simple implementation of singleton:
// Very simple singleton using a static field initializer
public class SimpleSingleton
{
private readonly static SimpleSingleton _instance = new SimpleSingleton();
public SimpleSingleton Instance => _instance;
}
They're not swappable, and this means that you can't inject them using dependency injection(3). That is, testing is harder to implement too (you should understand that a system that can't be tested or it's hard to test is a very bad idea).
What can be acceptable is using a dependency injection/inversion of control container that can define component implementations' life-style like Castle Windsor and others, which means that you can still use dependency injection and define that only a single instance will be created during the life of the application (i.e. you get an instance where you get an injected component implementation, but once one is created by the internal component factory, this is the one that's being injected during one application life-cycle).
At the end of the day, your system is designed to be agnostic about how component life-cycle works. It's defined by configuration. I would say that object life management is an aspect when your system is designed this way (see this Wikipedia article to learn more about aspect-oriented programming).
Delegating component life management to an aspect and define what kind of life will have your components is a great advantage: your code can work in many hosting environments and on each of them your code can work differently by configuration.
Think about an ASP.NET WebAPI. Maybe some components should be singletons during a single request, and each request should work with its own singleton. Same component used in another environment maybe shouldn't be a singleton, but just a transient object (i.e. each time you inject it, it's a completely new object). With common singleton implementations you won't get this flexibility.
Your requirement done right
There're many possible approaches to provide a good solution to your problem. I'll describe two of many possible solutions:
1. Instead of thinking about a global settings object, you should inject these settings as a class of settings into each component where you require these settings
For example:
public interface IDatabaseSettings
{
string Host { get; set; }
}
public class RegistryDatabaseSettings : IDatabaseSettings
{
// This property should get and set the setting from and
// against the Windows Registry. It's just a sample and dummy
// implementation
public string Host { get; set; }
}
public interface ISomeRepository
{
}
public class SomeRepositoryImpl : ISomeRepository
{
private readonly IDatabaseSettings _dbSettings;
// Inject IDatabaseSetttings as constructor's dependency
public SomeRepositoryImpl(IDatabaseSettings dbSettings)
{
_dbSettings = dbSettings;
}
public IDatabaseSettings DatabaseSettings => _dbSettings;
}
And using your favourite inversion of control/dependency injection container, you can define that IDatabaseSettings must be instantiated once per application cycle (i.e. singleton).
2. If settings are a cross-layer concern...
...maybe you can define a class called Settings where you define all settings as public properties and you inject a singleton instance into any component requiring it:
public interface IDatabaseSettings
{
string Host { get; set; }
}
public interface ISettings
{
IDatabaseSettings Database { get; }
}
public interface ISomeRepository
{
}
public class SomeRepositoryImpl : ISomeRepository
{
private readonly ISettings _settings;
// Inject Settings as constructor's dependency
public SomeRepositoryImpl(ISettings settings)
{
_settings = settings;
// Now you can access DatabaseSettings as follows:
// Settings.Database.Host
}
public ISettings Settings => _settings;
}
For me, the issue with this approach is you're going to inject settings to components that shouldn't access/write settings which are from other domains or they're just not desirable to be accessed everywhere. I'm talking about not breaking one of most important principles in object-oriented programming: encapsulation.
(1) When I talk about a singleton pattern implementation as is, I'm describing a common singleton pattern implementation where the whole singleton class implements the single object life instantiation/management.
(2) OP talks about a settings that should be stored in some database and in Windows Registry. It would be a bad idea not using dependency injection, because there would be no chance to unit test a component requiring the whole settings without also involving the database and Windows Registry. Setting fakes wouldn't be possible.
(3) Some inversion of control containers have support to configure components using custom factories, where you can define that an instance of some implementation can be taken from any custom source. For example, that factory can return SomeSingleton.Instance and get it injected as any regular component.

How to reduce amount of passing IUnityContainer object through constructors?

I have a big class hierarchy.
When my app starts, I initialize UnityContainer object and configure it.
After that I always passing it through constructors to another classes in hierarchy.
Something like this :
Unity container has these classes as Registrations: IClassA, IClassB, IClassC, IClassD
All concrete implementations of interfaces have constructor with IUnityContainer parameter.
For example,
public class ClassA : IClassA
{
public ClassA(IUnityContainer unityContainer)
{
}
}
So, every time when I'm creating a new instance of some class I must pass an object of IUnityContainer.
May I reduce amount of passing IUnityContainer object as constructor's parameter?
Maybe by using Dependency attribute ?
Yes, you should reduce it.
You should reduce it to 0.
Using DI container like this is a bad practice. Don't treat DI container as a magical super factory.
You should only use the container to make it easier to compose your application at the composition root: read this
Your code shouldn't be aware that it is composed with a DI container, container is just a technology while DI is a technic. You should be able to compose your application without a container too.
So, how you can reduce it? Like this:
public class ClassA : IClassA
{
public ClassA()
{
}
}
Then if your ClassA needs something (a dependency, an interface), then you should inject that via constructor for example.
public class ClassA : IClassA
{
private readonly IComponent _component;
public ClassA(IComponent component)
{
_component = component;
}
}
You can use another injection patterns too: property injection, method injection, ambient context.
If you use a container like in your question then you hide all the dependencies of the actual class. You can't figure out what that actual class needs to work because it will use the container to resolve something ad-hoc. It's completely againts dependency injection because you not inject dependencies, you just inject a generic factory (you can ask for anything) which is very dangerous and highly increases complexity for nothing.
I highly recommend this book: Dependency Injection in .NET - Mark Seemann
What you are doing is abusing the container as a ServiceLocator. This is considered an anti-pattern in modern application architecture.
Use proper Dependency Injection instead. Martin Fowler gives a good introduction on the pattern.
Mark Seemann wrote a very good book on the topic called Dependency Injection in .NET.
And as #PeterPorfy already pointed out the concept of Composition Roots is important. You register all dependencies with your container there and then kickoff by resolving the root object of your application or service there.
You never hand the container to a class outside that composition root!

how do IoC this?

I am looking to see how Ioc/Di can simplify wiring the following classes I use often.
Consider a library that has an abstract notion of an Entity and an interface for a data access object:
public abstract class EntityWithTypedId<TId> : IEntityWithTypedId<TId>{...}
public interface IDao<T, TId> where T : IEntityWithTypedId<TId>
For the dao, I have one implementation for NHibernate as well as a fake dao I find useful for testing:
// has an NHib implementation
public class Dao<T, TId> : IDao<T, TId> where T : EntityWithTypedId<TId> {...}
public class DaoFakeBase<T> : IDao<T, int>, IDisposable where T : IEntityWithTypedId<int> {...}
I currently do the following to define an Entity and Dao type for a given project:
/// <summary>
/// <see cref="IEntityWithTypedId{IdT}"/> with an int for an id
/// </summary>
[Serializable]
public abstract class Entity : EntityWithTypedId<int>
{
}
public class Dao<T> : Dao<T, int> where T : Entity
{
protected Dao(ISessionFactory sessionFactory) : base(sessionFactory) { }
}
Can I use a DI tool to define the Entity instead? Can someone show me a code sample of how to do it if so?
Can you also lay out how I might tell my test assembly to use DaoFakes and production to use NHib.Dao
I have been looking at Windsor, mostly because NHibernate contrib projects use it, but am also interested in MEF, AutoFac and Ninject, in that order. I realize that MEF is not an IoC container in the sense that Windsor is. From what I can see with Windsor I would use Installer classes, maybe an EntityInstaller and a DaoInstaller, although I might be missing a FActory type of object here too.
Cheers,
Berryl
UPDATE # KeithS
Are you saying to change something like:
class MyViewModel(IDao<MyClass, int> dao) {...}
becomes something like
class MyViewModel(Func<IDao<MyClass, int>, obj> getDaoFunc) {
_dao = getDaoFunc(this);
}
In your example...
class MyViewModel(IDao<MyClass, int> dao) {...}
...IDao would get resolved at runtime based on a previous registration within your container. The syntax for a Prism/Unity implementation is below...
IUnityContainer.RegisterType<IDao..., DaoFakeBase...>();
The RegisterType takes place within IModule.Initialize() of a given module as defined in the UnityBootstrapper class.
protected override IModuleCatalog GetModuleCatalog()
{
ModuleCatalog catalog = new ModuleCatalog();
catalog.AddModule(typeof(project.Init));
return catalog;
}
You can also register a given type based on a lifetime manager; to behave as a Singleton...
IUnityContainer.RegisterType<IShellController, ShellController>(new ContainerControlledLifetimeManager());
...where the IShellController resolved instance will remain the same returned instance throughout the lifetime of the IUnityContainer.
UPDATE:
Using your code the registration would look like this...
public interface IDao<T, TId> where T : IEntityWithTypedId<TId>
{ }
public class Dao<T, TId> : IDao<T, TId> where T : EntityWithTypedId<TId>
{ }
public class TId
{ }
public abstract class EntityWithTypedId<TId> : IEntityWithTypedId<TId>
{ }
public interface IEntityWithTypedId<TId>
{ }
IUnityContainer.RegisterType<IEntityWithTypedId<TId>, EntityWithTypedId<TId>>();
IUnityContainer.RegisterType<IDao<IEntityWithTypedId<TId>, TId>, Dao<IEntityWithTypedId<TId>, TId>>();
IDao<IEntityWithTypedId<TId>, TId> dao = IUnityContainer.Resolve<IDao<IEntityWithTypedId<TId>, TId>>();
I would not use IoC to register the relationship between DAOs and their types (which is basically what you'd be doing). This will lead to you using the IoC container as a "service locator", a known anti-pattern where you pass the IoC container into objects that will use it to get the DAO they need.
I think the best way to simplify this from a consumption perspective would be to define a strategy pattern, using a factory class or method:
public Dao<T, TId> GetDaoFor<T, TId>(T objectInstance) where T:EntityWithTypedId<TId>
{
//Here, you could use a Dictionary, Linq with some reflection, etc.
}
This one method can be injected as a delegate into classes dependent upon DAOs. The difference is that classes that need a DAO are dependent on a method that can give it to them, which can be provided by the IoC container; they are NOT dependent on the container itself (which is the primary source of evil inherent in the "service locator" pattern). This reduces the number of things you'd have to change if you re-wrote how you got these DAOs.
EDIT: A bit off-topic, but I opened the door:
The service location pattern is generally to be avoided, because it results in code that relies on the service locator. For instance, the following is common in code where the IoC has been exposed at child levels:
private IDependency _dependency;
public IDependency MyDependency
{
get {
_dependency = _dependency ?? IoC.Resolve<IDependency>();
return _dependency;
}
}
While this seems like a nice pattern (dependencies are lazily initialized, consuming code doesn't need to know about dependencies of the child, and you always* get a reference), this code will ALWAYS require the IoC singleton to exist. You can change the IoC framework behind it, you can remove the third-party tool altogether and roll your own, but this class will always require something on which to statically call Resolve<IDependency>().
You also don't ALWAYS get a reference; you get a reference only if you properly registered IDependency with IoC. This produces two more weaknesses; 1) you don't know what the class will need without opening it up, and 2) if/when the call fails, it will fail deep in the bowels of the dependent class' inner workings. If you develop a new class, and plug it into IoC, it may pass integration, and even work in production for a while, until you start getting weird "object reference set to null" errors in really weird places in code, which are, trust me, a nightmare to debug.
Lastly, unit-testing service-locator-pattern code is more difficult, for the simple reason that you must mock the service locator as well as the dependency provided by the service locator. You can leave the production service locator in use, and simply register mocked classes as the dependencies, but that's not a unit test; the test relies on, and thus to some extent tests, that the integration of the class and its service locator works as expected. That's an integration test.
By contrast, dependency injection patterns free you from any dependency on how dependencies are resolved. The only requirement (in constructor-injection) is that they be around when the class is created. This has several advantages:
If not using an IoC framework, you have to know what the class will need to instantiate it.
If using an IoC framework, you get a runtime error when attempting to instantiate the dependent class, not sometime later when the object actually gets resolved.
When testing a dependent class, you can more easily mock the dependency, because the dependency does not have to be fed in via the service locator.
You can in most IoC frameworks still lazily initialize dependencies by providing a factory method instead of the actual dependency to the constructor. The above pattern then calls that delegate, which could come from anywhere, instead of a static named method which is satisfied by one and only one construct in the entire codebase.

Categories

Resources