Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IoC Factory: Pros and contras for Interface versus Delegates

Any place where you need a run-time value to construct a particular dependency, Abstract Factory is the solution.

My qestion is: Why do many sources favor FactoryInterface over FactoryDelegate to implement this pattern? What are the pros and contras for both solutions?

Here is an example to understand what i mean

If you have a Service that needs a Repository with a certain Context then the Service constructor needs a factory to create or access its repository.

The common solution for this is to create a RepositoryFactoryInterface like this.

public IRepositoryFactory {     IRepository Create(ContextInformation context); }  public class MyService {     private IRepositoryFactory repositoryFactory;     public MyService(IRepositoryFactory repositoryFactory)     {         this.repositoryFactory = repositoryFactory:     }      public void DoSomeService()     {         ContextInformation context = ....;          IRepository repository = this.repositoryFactory.Create(context);          repository.Load(...);         ...         repository.Save(...);     } } 

You also need to implement IRepositoryFactory interface some way

public MyEf4RepositoryFactory : IRepositoryFactory {     IRepository Create(ContextInformation context)     {         return new MyEf4Repository(context);     } } 

... and use it in the application

public void main() {     IRepositoryFactory repoFactory = new MyEf4RepositoryFactory();     IService service = new MyService(repoFactory);       service.DoSomeService(); } 

----- End of mainstream solution ------

Instead of the RepositoryFactoryInterface you can do the same with a factorydelegate that requires less coding like this.

public class MyService {     private Func<ContextInformation, IRepository> repositoryFactory;     public MyService(Func<ContextInformation, IRepository> repositoryFactory)     {         this.repositoryFactory = repositoryFactory:     }      public void DoSomeService()     {         ContextInformation context = ....;          IRepository repository = this.repositoryFactory(context);          repository.Load(...);         ...         repository.Save(...);     } } 

... and use it in the application

public void main() {     IService service = new MyService(context => new MyEf4Repository(context));       service.DoSomeService(); } 

In my opinion the factorydelegate context => new MyEf4Repository(context) is much more compact than declaring and implementing an interface IRepositoryFactory and MyEf4RepositoryFactory.

There must be a reason for this and i want to know why.

Here is one example source that uses the interface aproach: answer to is-there-a-pattern-for-initializing-objects-created-via-a-di-container

[Update]15 Months after asking this question and having more experience with the java universers i changed my mind: Now I prefer interfaces over delegates . But i cannot say why. It is just a feeling. Maybe because I am more used to it?

like image 755
k3b Avatar asked Mar 23 '11 10:03

k3b


People also ask

What are the roles of an IoC Inversion of Control container?

The IoC container is responsible to instantiate, configure and assemble the objects. The IoC container gets informations from the XML file and works accordingly. The main tasks performed by IoC container are: to instantiate the application class.

What is IoC example?

A great example of an implementation of IoC is Spring Framework. The Spring container instantiates and manages the lifecycle of the objects that are a part of the program. The user in the configuration file provides the information related to what objects and dependencies are required by the application.

Why do we need IoC container?

The IoC container that is also known as a DI Container is a framework for implementing automatic dependency injection very effectively. It manages the complete object creation and its lifetime, as well as it also injects the dependencies into the classes.

What is understood by Inversion of Control IoC?

Inversion of control is a software design principle that asserts a program can benefit in terms of pluggability, testability, usability and loose coupling if the management of an application's flow is transferred to a different part of the application.


1 Answers

Any place where you need a run-time value to construct a particular dependency, Abstract Factory is the solution.

I would argue against this. Dependencies should not be constructed using runtime data, as explained here. In summary the article states:

Don't inject runtime data into application components during construction; it causes ambiguity, complicates the composition root with an extra responsibility and makes it extraordinarily hard to verify the correctness of your DI configuration. Instead, let runtime data flow through the method calls of constructed object graphs.

When we let runtime data "flow through the method calls of constructed object graphs" instead, you'll see the usefulness of Abstract Factories decline. They might still be used when runtime data is used to choose from multiple dependencies (compared to injecting runtime data into a dependency), but even then Abstract Factories are typically not the best solution, as explained here. In summary the article states:

Generally, the use of a factory abstraction is not a design that considers its consumers. According to the Dependency Injection Principle (DIP), abstractions should be defined by their clients, and since a factory increases the number of dependencies a client is forced to depend upon, the abstraction is clearly not created in favor of the client and we can therefore consider this to be in violation of the DIP.

Instead, patterns such as Facade, Composite, Mediator and Proxy are generally a better solution.

That doesn't mean you can't have code in your application that produces dependencies, but it should not be defined as abstraction that is used by other application components. Instead, factory-like behavior should be encapsulated into adapters that are defined as part of your Composition Root.

When you only have these factory-like logic and dependencies as part of your Composition Root, it doesn't really matter whether you define an IRepositoryFactory or merely use an Func<IRepository> to construct such dependency, since the IRepositoryFactory would be defined in the Composition Root as well (since the application has no business in using such factory).

That said, in the rare case that an Abstract Factory is the right abstraction (which will typically happen when you are building a reusable framework), I do find the use of factory interfaces much more intend revealing than the use of delegates. It is a bit more verbose, but much clearer what the meaning is of such a thing. An IControllerFactory is more intend revealing than Func<IController>.

I would say this even more holds for factories that do not produce dependencies but data values instead. Take for instance the example of injecting a Func<DateTime> into a constructor. What does this actually mean and what value does it return? Is it intuitive that it returns a DateTime.Now, or does it return DateTime.Today, or something else? In that case it would be much clearer to define an ITimeProvider interface with a GetCurrentTime() method.

NOTE: This answer was updated on July 2017 to reflect my latest views.

like image 102
Steven Avatar answered Sep 22 '22 02:09

Steven