I have the following Unity related question. The code stub below sets up the basic scenario and the question is at the bottom.
NOTE, that [Dependency] attribute does not work for the example below and results in StackoverflowException, but the constructor injection does work.
NOTE(2) Some of the comments below started to assign "labels", like code smell, bad design, etc... So, for the avoidance of confusion here is the business setup without any design first.
The question seems to cause a severe controversy even among some of the best-known C# gurus. In fact, the question is far beyond C# and it falls more into pure computer science. The question is based on the well-known "battle" between a service locator pattern and pure dependency injection pattern: https://martinfowler.com/articles/injection.html vs http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/ and a subsequent update to remedy the situation when the dependency injection becomes too complicated: http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/
Here is the situation, which does not fit nicely into what is described in the last two but seems to fit perfectly into the first one.
I have a large (50+) collection of what I called micro services. If you have a better name, please "apply" it when reading. Each of them operates on a single object, let's call it quote. However, a tuple (context + quote) seems more appropriate. Quote is a business object, which gets processed and serialized into a database and context is some supporting information, which is necessary while quote is being processed, but is not saved into the database. Some of that supporting information may actually come from database or from some third-party services. This is irrelevant. Assembly line comes to mind as a real-world example: an assembly worker (micro service) receives some input (instruction (context) + parts (quote)), processes it (does something with parts according to instruction and / or modifies instruction) and passes it further if successful OR discards it (raises exception) in case of issues. The micro services eventually get bundled up into a small number (about 5) of high-level services. This approach linearizes processing of some very complex business object and allows testing each micro service separately from all others: just give it an input state and test that it produces expected output.
Here is where it gets interesting. Because of the number of steps involved, high-level services start to depend on many micro services: 10+ and more. This dependency is natural, and it just reflects the complexity of the underlying business object. On top of that micro services can be added / removed nearly on a constant basis: basically, they are some business rules, which are almost as fluid as water.
That severely clashes with Mark's recommendation above: if I have 10+ effectively independent rules applied to a quote in some high-level service, then, according to the third blog, I should aggregate them into some logical groups of, let's say no more than 3-4 instead of injecting all 10+ via constructor. But there are no logical groups! While some of the rules are loosely dependent, most of them are not and so artificially bundling them together will do more harm than good.
Throw in that the rules change frequently, and it becomes a maintenance nightmare: all real / mocked calls must be updated every time the rules change.
And I have not even mentioned that the rules are US state dependent and so, in theory, there are about 50 collections of rules with one collection per each state and per each workflow. And while some of the rules are shared among all states (like "save quote to the database"), there are a lot of state specific rules.
Here is a very simplified example.
Quote - business object, which gets saved into database.
public class Quote
{
public string SomeQuoteData { get; set; }
// ...
}
Micro services. Each of them performs some small update(s) to quote. Higher level services can be also built from some lower level micro services as well.
public interface IService_1
{
Quote DoSomething_1(Quote quote);
}
// ...
public interface IService_N
{
Quote DoSomething_N(Quote quote);
}
All micro services inherit from this interface.
public interface IQuoteProcessor
{
List<Func<Quote, Quote>> QuotePipeline { get; }
Quote ProcessQuote(Quote quote = null);
}
// Low level quote processor. It does all workflow related work.
public abstract class QuoteProcessor : IQuoteProcessor
{
public abstract List<Func<Quote, Quote>> QuotePipeline { get; }
public Quote ProcessQuote(Quote quote = null)
{
// Perform Aggregate over QuotePipeline.
// That applies each step from workflow to a quote.
return quote;
}
}
One of high level "workflow" services.
public interface IQuoteCreateService
{
Quote CreateQuote(Quote quote = null);
}
and its actual implementation where we use many of low level micro services.
public class QuoteCreateService : QuoteProcessor, IQuoteCreateService
{
protected IService_1 Service_1;
// ...
protected IService_N Service_N;
public override List<Func<Quote, Quote>> QuotePipeline =>
new List<Func<Quote, Quote>>
{
Service_1.DoSomething_1,
// ...
Service_N.DoSomething_N
};
public Quote CreateQuote(Quote quote = null) =>
ProcessQuote(quote);
}
There are two main ways to achieve DI:
Standard approach is to inject all dependencies through constructor:
public QuoteCreateService(
IService_1 service_1,
// ...
IService_N service_N
)
{
Service_1 = service_1;
// ...
Service_N = service_N;
}
And then register all types with Unity:
public static class UnityHelper
{
public static void RegisterTypes(this IUnityContainer container)
{
container.RegisterType<IService_1, Service_1>(
new ContainerControlledLifetimeManager());
// ...
container.RegisterType<IService_N, Service_N>(
new ContainerControlledLifetimeManager());
container.RegisterType<IQuoteCreateService, QuoteCreateService>(
new ContainerControlledLifetimeManager());
}
}
Then Unity will do its "magic" and resolve all services at run time. The problem is that currently we have about 30 such micro services and the number is expected to increase. Subsequently some of the constructors are already getting 10+ services injected. This is inconvenient to maintain, mock, etc...
Sure, it is possible to use the idea from here: http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/ However, the microservices are not really related to each other and so bundling them together is an artificial process without any justification. In addition, it will also defeat the purpose of making the whole workflow linear and independent (a micro service takes a current "state", then preforms some action with quote, and then just moves on). None of them cares about any other micro services before or after them.
An alternative idea seems to create a single "service repository":
public interface IServiceRepository
{
IService_1 Service_1 { get; set; }
// ...
IService_N Service_N { get; set; }
IQuoteCreateService QuoteCreateService { get; set; }
}
public class ServiceRepository : IServiceRepository
{
protected IUnityContainer Container { get; }
public ServiceRepository(IUnityContainer container)
{
Container = container;
}
private IService_1 _service_1;
public IService_1 Service_1
{
get => _service_1 ?? (_service_1 = Container.Resolve<IService_1>());
set => _service_1 = value;
}
// ...
}
Then register it with Unity and change the constructor of all relevant services to something like this:
public QuoteCreateService(IServiceRepository repo)
{
Service_1 = repo.Service_1;
// ...
Service_N = repo.Service_N;
}
The benefits of this approach (in comparison to the previous one) are as follows:
All micro services and higher-level services can be created in a unified form: new micro services can be easily added / removed without the need to fix constructor call for the services and all unit tests. Subsequently, maintenance and complexity decreases.
Due to interface IServiceRepository, it is easy to create an automated unit test, which will iterate over all properties and validate that all services can be instantiated, which means that there will be no nasty run time surprises.
The problem with this approach is that it starts looking a lot like a service locator, which some people consider as an anti-pattern: http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/ and then people start to argue that that all dependencies must be made explicit and not hidden as in ServiceRepository.
What shall I do with that?
I would just create one interface:
public interface IDoSomethingAble
{
Quote DoSomething(Quote quote);
}
And a Aggregate:
public interface IDoSomethingAggregate : IDoSomethingAble {}
public class DoSomethingAggregate : IDoSomethingAggregate
{
private IEnumerable<IDoSomethingAble> somethingAbles;
public class DoSomethingAggregate(IEnumerable<IDoSomethingAble> somethingAbles)
{
_somethingAbles = somethingAbles;
}
public Quote DoSomething(Quote quote)
{
foreach(var somethingAble in _somethingAbles)
{
somethingAble.DoSomething(quote);
}
return quote;
}
}
Note: Dependency injection doesn't mean, you need to use it everywhere.
I would go for a factory:
public class DoSomethingAggregateFactory
{
public IDoSomethingAggregate Create()
{
return new DoSomethingAggregate(GetItems());
}
private IEnumerable<IDoSomethingAble> GetItems()
{
yield return new Service1();
yield return new Service2();
yield return new Service3();
yield return new Service4();
yield return new Service5();
}
}
Everything else (which is not constructor injected) hides explicit dependencies.
As a last resort, you could also create some DTO object, inject every needed Service via the Constructor (But only one time).
This way you can request the ProcessorServiceScope and have all Service available without needing to create the ctor logic for every class:
public class ProcessorServiceScope
{
public Service1 Service1 {get;};
public ServiceN ServiceN {get;};
public ProcessorServiceScope(Service1 service1, ServiceN serviceN)
{
Service1 = service1;
ServiceN = serviceN;
}
}
public class Processor1
{
public Processor1(ProcessorServiceScope serviceScope)
{
//...
}
}
public class ProcessorN
{
public ProcessorN(ProcessorServiceScope serviceScope)
{
//...
}
}
It seems like a ServiceLocator, but it does not hide the depencies, so I think this is kind of ok.
Consider the various interface methods listed:
Quote DoSomething_1(Quote quote);
Quote DoSomething_N(Quote quote);
Quote ProcessQuote(Quote quote = null)
Quote CreateQuote(Quote quote = null);
Apart from the names, they're all identical. Why make things so complicated? Considering the Reused Abstractions Principle, I'd argue that it'd be better if you had fewer abstractions, and more implementations.
So instead, introduce a single abstraction:
public interface IQuoteProcessor
{
Quote ProcessQuote(Quote quote);
}
This is a nice abstraction because it's an endomorphism over Quote, which we know is composable. You can always create a Composite of an endomorphism:
public class CompositeQuoteProcessor : IQuoteProcessor
{
private readonly IReadOnlyCollection<IQuoteProcessor> processors;
public CompositeQuoteProcessor(params IQuoteProcessor[] processors)
{
this.processors = processors ?? throw new ArgumentNullException(nameof(processors));
}
public Quote ProcessQuote(Quote quote)
{
var q = quote;
foreach (var p in processors)
q = p.ProcessQuote(q);
return q;
}
}
At this point, you're essentially done, I should think. You can now compose various services (those called microservices in the OP). Here's a simple example:
var processor = new CompositeQuoteProcessor(new Service1(), new Service2());
Such composition should go in the application's Composition Root.
The various services can have dependencies of their own:
var processor =
new CompositeQuoteProcessor(
new Service3(
new Foo()),
new Service4());
You can even nest the Composites, if that's useful:
var processor =
new CompositeQuoteProcessor(
new CompositeQuoteProcessor(
new Service1(),
new Service2()),
new CompositeQuoteProcessor(
new Service3(
new Foo()),
new Service4()));
This nicely addresses the Constructor Over-injection code smell, because the CompositeQuoteProcessor class only has a single dependency. Since that single dependency is a collection, however, you can compose arbitrarily many other processors.
In this answer, I completely ignore Unity. Dependency Injection is a question of software design. If a DI Container can't easily compose a good design, you'd be better off with Pure DI, which I've implied here.
If you must use Unity, you can always create concrete classes that derive from CompositeQuoteProcessor and take Concrete Dependencies:
public class SomeQuoteProcessor1 : CompositeQuoteProcessor
{
public SomeQuoteProcessor1(Service1 service1, Service3 service3) :
base(service1, service3)
{
}
}
Unity should be able to auto-wire that class, then...
Unity supports property injection. Instead of passing all those values in to the constructor just have public setters available with the [Dependency] attribute. This allows you to add as many injections as you need without having to update the constructor.
public class QuoteCreateService : QuoteProcessor, IQuoteCreateService
{
[Dependency]
protected IService_1 Service_1 { get; public set; }
// ...
[Dependency]
protected IService_N Service_N; { get; public set; }
public override QuoteUpdaterList QuotePipeline =>
new QuoteUpdaterList
{
Service_1.DoSomething_1,
// ...
Service_N.DoSomething_N
};
public Quote CreateQuote(Quote quote = null) =>
ProcessQuote(quote);
}
I never thought that I would answer my own question, though a substantial part of the credit should go to https://softwareengineering.stackexchange.com/users/115084/john-wu - he was the one who had my mind set in a proper direction.
Nevertheless, nearly two year have passed since the time when I asked the question and while I built the solution to the question slightly after asking it (and thanks to everyone who replied), it took more than a year for most of the developers in the company that I work for to actually understand how does it work and what does it do (and yes, they all are well above average developers and yes, the code is written in pure C# with no external libraries). So, I think that it could be important for others who might have similar business scenarios.
As mentioned in the question, the root of our problem is that the parameter space that we are dealing with is too large. We have about 6-8 values of what we call workflow (call it W), about 30-40 values of what we call a state config (call it S) – this is a combination of US state code and two other parameters, though not all triples are possible (the actual content of what is that state config is irrelevant), and about 30-50 values of what we call a risk rule (call it R) - that value depends on the product but this is also irrelevant as different products are treated differently.
So, the total dimension of parameter space is N = W * S * R and it is around 10K (and I am not much concerned about a precise value). Which means that when the code runs, we need approximately the following: for each workflow (obviously only one is running at a time but all of them do run at some time) and each state config (again only one is running at a time but any of them could run at some time) we need to evaluate all risk rules, which are relevant for that workflow and that state config.
Well, if the dimension of parameter space is around some N, then the number of tests needed to cover the whole space is at least on the order of that N. And this is exactly what the legacy code and tests were trying to do and what resulted in the question.
The answer turned out to be in a pure math, rather than in a pure computer science and it is based on what is called separable spaces: https://en.wikipedia.org/wiki/Separable_space and what in the group theory terms is called irreducible representation: https://en.wikipedia.org/wiki/Irreducible_representation . Though I have to admit that the latter one was more like an inspiration rather than the actual application of the group theory.
If you already lost me, that’s fine. Just, please, read the math mentioned above before proceeding further.
The space separability here means that we can choose such a space N so that subspaces W, S, and R become independent (or separable). To the best of my understanding, this can always be done for finite spaces that we are dealing with in CS.
This means that we can describe N space as e.g. S lists (or sets) of some rules whereas each rule is applicable in some of W workflows by assigning a set of applicable workflows to each rule. And yes, if we have some bad rules that originally should be applied in some weird combinations of workflows and state configs then we can split them into more than one rule, which would then allow maintaining separability.
This, of course, can be generalized, but I will skip the details as they are irrelevant.
At this point, someone may wonder, what’s the point. Well, if we can split N dimensional space (and N is about 10K in our case) into independent subspaces, then the magic happens and instead of writing on the order of N = W *S * R tests to cover the whole parameter space we only need to write on the order of W + S + R tests to cover the whole parameter space. In our case the difference is about 100X.
But that’s still not all. As we can describe the subspaces in the notions of sets or lists (depending on the needs) that naturally brings us to the notion of useless tests.
Wait, did I just say useless tests? Yes, I did. Let me explain. A typical TDD paradigm is that if the code failed, then the first thing that we need to do is to create a test, which would’ve caught that bug. Well, if the code is described by a static list or set (== list or set that was hard coded in the code) and the test would be described by an identity transformation from that list/set, then this makes such a test useless as it would have to repeat the original list/set…
The state configs form a historical pattern, e.g., let say, that we had some set of rules for the state of CA some time in 2018. That set of rules might be slightly changed to some other set of rules in 2019 and into some set of rules in 2020. These changes are small: a set of rule might pick up or lose a few rules and/or the rule might be tweaked a little bit, e.g. if we are comparing some value to be above some threshold, then the value of that threshold might be changed at some point for some state config. And once the rule or collection of rules is changed, then it should stay as it is until it changed again. Meanwhile some other rules could be changed, and every such change requires introduction of what we call state config. So, for each US state we have ordered collection (list) of these state configs and for each state config we have a collection of rules. Most of the rules don’t change but some of them do sporadically change as described. A natural IOC approach is to register each rule collection and each rule for each state config with IOC container, e.g. Unity using a combination of unique “name” of the state config and name of rule / collection (we actually run more than one collection of rules during workflow), whereas each rule already has a collection of workflows where it should be applicable. Then when the code runs for a given state config and a given workflow we can pull the collection out of Unity. A collection then contains the names of the rules that should be run. Then combining the name of the rule with the name of state config we can pull the actual rule out of Unity, filter the collection to leave only the rules that are applicable for a given workflow and then apply all the rules.
What happens here is that rule names / collection names form some closed sets and they benefit greatly by describing them that way. We obviously don’t want to register each rule / collection for each state config by hands as that would be tedious and error prone. So we use what we call “normalizers”. Let’s say that we have a general rule – that’s a rule that is the same for all state config. Then we register it by name only and the normalizer will “automatically” register it for all state configs. The same goes with the historic versioning. Once we register a rule / collection with Unity by rule / collection name + state config, then the normalizer will fill in the gap until we change the rule at some later state config.
As a result, each rule becomes extremely simple. Most of them have either zero or one injected constructor parameter, a few of them have two, and I know only one rule that has three injected parameters. As rules are independent and very simple, the tests for rules become very simple as well.
We do have some ideas to make the core of whatever I wrote above open source, provided that it could bring some value to the community...
Let’s say I have some DDD service that requires some IEnumerable<Foo> to perform some calculations. I came up with two designs:
Abstract the data access with an IFooRepository interface, which is quite typical
public class FooService
{
private readonly IFooRepository _fooRepository;
public FooService(IFooRepository fooRepository)
=> _fooRepository = fooRepository;
public int Calculate()
{
var fooModels = _fooRepository.GetAll();
return fooModels.Sum(f => f.Bar);
}
}
Do not rely on the IFooRepository abstraction and inject IEnumerable<Foo> directly
public class FooService
{
private readonly IEnumerable<Foo> _foos;
public FooService(IEnumerable<Foo> foos)
=> _foos = foos;
public int Calculate()
=> _foos.Sum(f => f.Bar);
}
This second design seems better in my opinion as FooService now does not care where the data is coming from and Calculate becomes pure domain logic (ignoring the fact that IEnumerable may come from an impure source).
Another argument for using the second design is that when IFooRepository performs asynchronous IO over the network, usually it will be desirable to use async-await like:
public class AsyncDbFooRepository : IFooRepository
{
public async Task<IEnumerable<Foo>> GetAll()
{
// Asynchronously fetch results from database
}
}
But as you need to async all the way down, FooService is now forced to change its signature to async Task<int> Calculate(). This seems to violate the dependency inversion principle.
However, there are also issues with the second design. First of all, you have to rely on the DI container (using Simple Injector as an example here) or the composition root to resolve the data access code like:
public class CompositionRoot
{
public void ComposeDependencies()
{
container.Register<IFooRepository, AsyncDbFooRepository>(Lifestyle.Scoped);
// Not sure if the syntax is right, but it demonstrates the concept
container.Register<FooService>(async () => new FooService(await GetFoos(container)));
}
private async Task<IEnumerable<Foo>> GetFoos(Container container)
{
var fooRepository = container.GetInstance<IFooRepository>();
return await fooRepository.GetAll();
}
}
Also in my specific scenario, AsyncDbFooRepository requires some sort of runtime parameter to construct, and that means you need an abstract factory to construct AsyncDbFooRepository.
With the abstract factory, now I have to manage the life cycles of all dependencies under AsyncDbFooRepository (the object graph under AsyncDbFooRepository is not trivial). I have a hunch that I am using DI incorrectly if I opt for the second design.
In summary, my questions are:
Am I using DI incorrectly in my second design?
How can I compose my dependencies satisfactorily for my second design?
One aspect of async/await is that it by definition needs to applied "all the way down" as you rightfully state. You however can't prevent the use of Task<T> when injecting an IEnumerable<T>, as you suggest in your second option. You will have to inject a Task<IEnumerable<T>> into constructors to ensure data is retrieved asynchronously. When injecting an IEnumerable<T> it either means that your thread gets blocked when the collection is enumerated -or- all data must be loaded during object graph construction.
Loading data during object graph construction however is problematic, because of the reasons I explained here. Besides that, since we're dealing with collections of data here, it means that all data must be fetched from the database on each request, even though not all data might be required or even used. This might cause quite a performance penalty.
Am I using DI incorrectly in my second design?
That's hard to say. An IEnumerable<T> is a stream, so you could consider it a factory, which means that injecting an IEnumerable<T> does not require the runtime data to be loaded during object construction. As long as that condition is met, injecting an IEnumerable<T> could be fine, but still makes it impossible to make the system asynchronous.
However, when injecting an IEnumerable<T> you might end up with ambiguity, because it might not be very clear what it means to be injecting an IEnumerable<T>. Is that collection a stream that is lazily evaluated or not? Does it contain all elements of T. Is T runtime data or a service?
To prevent this confusion, moving the loading of this runtime information behind an abstraction is typically the best thing to do. To make your life easier, you could make the repository abstraction generic as well:
public interface IRepository<T> where T : Entity
{
Task<IEnumerable<T>> GetAll();
}
This allows you to have one generic implementation and make one single registration for all entities in the system.
How can I compose my dependencies satisfactorily for my second design?
You can't. To be able to do this, your DI container must be able to resolve object graphs asynchronously. For instance, it requires the following API:
Task<T> GetInstanceAsync<T>()
But Simple Injection doesn't have such API, and neither does any other existing DI Container and that's for good reason. The reason is that object construction must be simple, fast and reliable and you lose that when doing I/O during object graph construction.
So not only is your second design undesirable, it is impossible to do so when data is loaded during object construction, without breaking the asynchonicity of the system and causing threads to block while using a DI container.
I try as much as possible (until now I've succeded every time) to not inject any service that do IO in my domain models as I like to keep them pure with no side effects.
That being said the second solution seems better but there is a problem with the signature of the method public int Calculate(): it uses some hidden data to perform the calculation, so it is not explicit. In cases like this I like to pass the transient input data as input parameter directly to the method like this:
public int Calculate(IEnumerable<Foo> foos)
In this way it is very clear what the method needs and what it returns (based on the combination of class name and method name).
In a .Net application when using C# I have to make an expensive call to get some data to a third party API, and depends on this one sometimes it's slower that I would like.
Thing is, that data will be accurate but I can calculate it with less precision on my own. So I was thinking how would I be able to let's say keep track of the average request time during the last 5 minutes and if it's greater than my threshold change to use my own implementation.
A sketch of the method would be something like this:
public int GetMyData()
{
return isTooSlow() ? _ownImplementation.GetData() : thirdParty.GetData();
}
Even if ideally I would like to be able to wrap the third party in an interface which mine would implement and change it on runtime that would be a nice to have.
But the mainquestion would be how to keep that state in memory. I can only think of using a static class and I have read about ApplicationState but not sure if any of those are the best approaches.
Besides, not for my small project but how would any of those solutions scale out? If I had to think about several instances of my application running I think the only solution would be to use an external storage (redis or alike?) and query it when doing the check.
Sorry if the question is too generic but thought it was an interesting problem to solve and don't know exactly how to best approach it
Thanks
I would put the question of multiple application instances on the back burner. Not that it doesn't matter, but if you're programming against interfaces then at some point you could replace your implementation with something that's cached.
If you want average request times over a duration like five minutes then you'll need a list that ejects expired entries. Here's a stab at that:
internal class TimestampedEntry<T>
{
internal DateTimeOffset Timestamp { get; private set; }
internal T Value { get; private set; }
internal TimestampedEntry(T value)
{
Timestamp = DateTimeOffset.Now;
Value = value;
}
}
public class ExpiringList<T>
{
private readonly List<TimestampedEntry<T>> _list = new List<TimestampedEntry<T>>();
private readonly TimeSpan _expiration;
public ExpiringList(TimeSpan expiration)
{
_expiration = expiration;
}
public void Add(T item)
{
lock (_list)
{
_list.Add(new TimestampedEntry<T>(item));
}
}
public IReadOnlyCollection<T> Read()
{
var cutoff = DateTimeOffset.Now - _expiration;
TimestampedEntry<T>[] result;
lock (_list)
{
result = _list.Where(item => item.Timestamp > cutoff).ToArray();
_list.Clear();
_list.AddRange(result);
}
return new ReadOnlyCollection<T>(result.Select(item => item.Value).ToList());
}
}
That ensures that when you read from the list it only returns items stored within the specified interval and also deletes the rest. You could create an ExpiringList<TimeSpan>, add the elapsed time for each call, and then inspect the average as needed.
Where to store it? I'd put it in a class with a single instance. That could be a singleton or a static class. I prefer using a dependency injection container that returns a single instance (like Windsor's singleton lifestyle.) I don't like creating singletons. I'd rather create a "normal" class and then manage it to keep a single instance. DI containers like Windsor make that easy.
I think an important factor in an implementation like this is to keep the messy switching logic separate - hidden in some sort of factory as opposed to having an if/then with all the logic to check the average response times and call either API all in one big class.
For example, if you have an interface representing the call to get data, like IMyDataProvider, then you could define a factory like
interface IMyDataProviderFactory
{
IMyDataProvider Create();
}
Your classes just depend on that factory interface. An class that implements IMyDataProviderFactory checks your average response times and returns either the implementation of IMyDataProvider that calls the external API or an implementation that uses your calculation.
That way the complexity of that logic stays separate from whatever classes depend on the APIs.
Windsor is good with those abstract factories too. Other DI containers also make them easy, and this sort of functionality is built into ASP.NET Core. You weren't asking about dependency injection, but I recommend looking into it. It makes it easier to manage this sort of complexity and keep it maintainable.
Going back to multiple application instances and distributed caches - you can see how the factory pattern implementation makes this easier to manage. Let's say today this is one instance but tomorrow you want to share this data via a distributed cache. Where do you make that change? Most of the code that depends on this API won't need to change at all because it doesn't "know" about any of those implementation details. You would change the code that stores the timing of each API call and change the implementation of your factory.
I recently asked about doing DI properly, and got some links to blog posts about it. I think I have a better understanding now - separate object construction from logic, by putting it in factories. But all of the examples are for things like websites, and say to do all the wiring at startup. Call one large factory which news everything and passes in all the dependencies.
But what if I don't want to instantiate everything up front? I have an object which contains a list of other objects which it can delegate to, but they are expensive, and used one at a time, so I construct them when needed and let them get collected when I'm done. I don't want to put new B() inside the logic of A because I would rather use DI - but how? Can A call the factory? That doesn't seem much better, unless the factory is maintaining state including the current dependencies. I just don't want to pass the full list of Bs into A when it's constructed, since it would be wasteful. If you want, B doesn't necessarily have to be inside A, although it makes logical sense (A is a game level, B is a single screen), but in any case the logic of A dictates when B is created.
So, who calls the factory to get B, and when?
Clarification: I'm not using framework for DI. I wonder if the term DI implies that?
In Ninject, you can register Func<B> and request that in the constructor to A.
Autofac will automagically supply Func<B> if B is already registered.
Or, you can take the more straight forward approach and define an explicit factory for B, and request that factory in the constructor; its just more typing as you'd have to create a factory for every dependency you want to lazily initialize.
Here's another SO answer that shows Ninject style factory methods: How do I handle classes with static methods with Ninject?
#Not Using A Framework: If you can, I'd probably look into using one: a IoC/DI framework usually will handle delayed creation for you out of the box.
If you want to continue to roll your own, then just pass the factory that creates B to your A object. Or, if you just don't like raw Funcs and don't want to have to create explicit factories for all your objects, then you could look into using Lazy<B> for a more formalized solution.
There are typically two patterns for using rarely needed objects that are expensive to create. The first pattern is using a factory, as David Faivre suggests. The other is by using a proxy.
A proxy is -from a design perspective- probably the cleanest solution, although it might need more code to implement. It is the cleanest, because the application can be totally unaware of this, because you don't need an extra interface (as the factory approach needs).
Here is an simple example with some interface and an expensive implementation:
interface IAmAService
{
void DoSomething();
}
class ExpensiveImpl : IAmAService
{
private object x = [some expensive init];
void IAmAService.DoSomething() { }
}
No you can implement a proxy based on that interface, that can delay the creation of that implementation:
class ServiceProxy : IAmAService
{
private readonly Func<IAmAService> factory;
private IAmAService instance;
public ServiceProxy(Func<IAmAService> factory)
{
this.factory = factory;
}
void IAmAService.DoSomething()
{
this.GetInstance().DoSomething();
}
private IAmAService GetInstance()
{
// TODO: Implement double-checked lock only a single
// instance may exist per ServiceProxy.
if (this.instance == null)
{
this.instance = this.factory();
}
return this.instance;
}
}
This proxy class accepts a factory delegate as dependency, just as David Faivre described in his answer, but this way the application won't have to depend on the Func<IAmAService>, but can simply depend on IAmAService.
Now instead of injecting an ExpensiveImpl, you can inject a ServiceProxy into other instances:
// Create the proxy
IAmAService service =
new ServiceProxy(() => new ExpensiveImpl());
// Inject it into whatever you wish, such as:
var customerService = new CustomerService(service);
Assuming I have a list of financial transactions, I have a need to execute a list of validation rules against those transactions. An example would be I have a transaction to purchase a product, however first I need to validate that the account in the transaction has enough available funds, that the product is not sold out etc. As a result of these many rules the transaction will be marked as rejected, as well as an error code should be specified.
Naturally I am thinking towards fronting my rules with an interface, allowing the executing code to roll through the rules executing each one until the first one rejects the transaction.
Each rule will require to be configured with parameters (ex. ValidateMinimumBalance will need to know that minimumBalance = 30). The result of a rule executing can be as simple as settings the rejection code on the transaction object, and the error code; or it can be as complicated as automatically modifying multiple other properties of the transaction.
My basic understanding of design patterns points to me either Strategy or Command patterns, but I am not entirely sure which one is better suited for this scenario.
Command Pattern
Each command will implement some sort of IValidate interface
The constructor of the command will take an instance of the transaction as the receiver in order to be able to read/validate the transaction as well as modify aspects of it. The constructor will also take an array of key/value pairs as parameters for the validation logic.
When I try to picture how the Strategy Pattern fits this scenario it looks very similar. In most examples the strategy is a simple object with a single method, however in my case the strategy will need a reference to the transaction as well as validation parameters.
Strategy is more used to swap out algorithms, its not really used for chaining validations. If you are going to have a pattern where you have one validation per type then you could use the strategy, if you are finding your having to use multiple validators, or the need to reuse validators. I think you are going to have to either find a new way to do it (aka COR) or within your strategy use the COR.
I actually would answer other. I think a combination chain of responsibility pattern and the composite pattern, or decorator for validators is much more suited for your needs.
Typing up an example implementation now.. but at a high level
Chain of Responsiblity
The design would revolve around something like:
abstract class Handler
{
protected Handler next;
public Handler(Handler h){
this.next = h;
}
public abstract bool Validate(Request request);
public abstract void Handle(Request request);
}
class CoreLogic: Handler
{
public CoreLogic(Handler handle) : base(handle){
}
public override void Validate(Request request){
return True
}
public override void Handle(Request request){
if(this.Validate(request)){
if(next!= null){
next.Handle(request);
}
}
}
}
class ValidBalance: Handler
{
public ValidBalance(Handler handle) : base(handle){
}
public override void Validate(Request request){
return True
}
public override void Handle(Request request){
if(this.Validate(request)){
if(next!= null){
next.Handle(request);
}
}
}
}
class MainApp
{
static void Main(){
Handler h = new ValidateBalance( new CoreLogic(null));
h.Handle(new Request());
}
}
Other useful links:
Chain of Responsiblity wikipedia
A Strategy would be something use to 'parameterize' a Command (telling it how parts of the operation should be executed).
When I try to picture how the Strategy Pattern fits this scenario it looks very similar.
Similar? It should look identical.
The distinction is one of how the context and delegation works. In principle a Command is the "active" agent. A Strategy is injected into some active agent. That distinction is pretty subtle.
It barely changes the design. What does change is the expectation.
Command objects (more-or-less) stand alone. They're built to do their work, and then they can vanish. No one cares about them any more. Perhaps they also use the Memento pattern, and have some future life, but perhaps not.
Strategy objects (more-or-less) live with the object into which they're injected. A Strategy would be part of some larger object, and could be replaced by a different implementation without breaking or changing anything else.
But the essential interface is largely the same.
In most examples the strategy is a simple object with a single method,
Those are poor examples.
however in my case the strategy will need a reference to the transaction as well as validation parameters.
Not unusual. Nothing wrong with it.
but I am not entirely sure which one
is better suited for this scenario
Neither :)
I strongly recommend to look at Interpreter. Actually your validator rules are just predicates formulated for your transactions. It's quite possible that soon you will need to combine these rules with AND, OR, NOT, etc.