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), IocFactory is actually a "ServiceLocator" which I think is an anti pattern and the IocFactory adds another dependency to the cronjob which isn't necessary... 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 rather than the IocFactory?
Thanks in advance
This is how you can answer his "works well" (and non-technical) argument.
If anything, his approach with
params Tuple<string, object>
is horrendous at best: maintenance nightmare, zero support from refactoring tools. Service Locator is effectively Singleton in disguise.Using proper IoC you can leveage whatever advanced functionality your container of choice provides: different lifetimes, constructor and property injection, support for
Func<>
andLazy<>
, etc. With Service Locator, you get none of that.