Today at work a collegue and I had a discussion about the following:
Basically we have a rule engine which works in the following way:
RuleExecutor
Gets all rules to execute in the constructor like
public RuleExecutor(ICollection<IRule> rulesToExecute) { ... }
Executes all rules by calling
rule.ApplyRule();
for each rulesToExecute
Rules
- Provide method ApplyRule(); which executes the rule
Now we want the RuleExecutor to be executed in a cron job.
We had a discussion about how to retrieve an instance of the RuleExecutor.
I think the "correct way" is via constructor injection
public RuleCronJob(IRuleExecutor ruleExecutor) { ... }
My collegue wants to use a "IocFactory" which has a static method GetInstance<>.
So in the "execute method" of the cron job he would do something like var ruleExecutor = IocFactory.GetInstance<IRuleExecutor>();
public static TType GetInstance<TType>(params Tuple<string, object>[] constructorParameters)
{
if (constructorParameters.Any())
{
var constructorArgs = new Collection<ConstructorArgument>();
foreach (var parameter in constructorParameters)
{
constructorArgs.Add(new ConstructorArgument(parameter.Item1, parameter.Item2, true));
}
return Kernel.Value.Get<TType>(constructorArgs.Cast<IParameter>().ToArray());
}
return Kernel.Value.Get<TType>();
}
Kernel is a StandardKernel of Ninject.
I think the constructor injection is better because it allows for easier tests (mocking) etc. but I couln't convince him to use it because he thinks that the IocFactory "works as well so why not use it"...
- What would be some arguments to convince him to use constructor injection instead of the IocFactory?
-
4What your collegue wants to use is actually called a "service locator". Reams have been written about service locator vs. dependency injection, so searching google or this site is your best bet.Ben Aaronson– Ben Aaronson2015年06月17日 12:45:38 +00:00Commented Jun 17, 2015 at 12:45
2 Answers 2
Well, for a start, the IOCFactory, or rather the way you described it being used, is a bold-faced lie, because it involves no inversion of control. If you continue calling getInstance() yourself, you should a least rename the alleged IOCFactory.
As Ben Aaronson pointed out, a container without inversion of control is just a Service Locator. A lot has been written about Dependency Injection vs. Service Locators, over ten years ago by Martin Fowler on his blog, or five years ago on stackoverflow: https://stackoverflow.com/questions/1557781/whats-the-difference-between-the-dependency-injection-and-service-locator-patte
but I couln't convince him to use it because he thinks that the IocFactory "works as well so why not use it"...
Because it's more complicated?
Rather by definition, code that is doing more things has more things that can go wrong. For IoC containers, that often means lots of things going on under the covers to discover the various dependencies, resolve them, inject them... IoC containers are the nuclear option for dependency injection. They'll solve your problem, but are almost always overkill, and will leave nasty lingering effects around regardless.
Explore related questions
See similar questions with these tags.