Article: Programmatic DI with Abstract Factories

Discussions

News: Article: Programmatic DI with Abstract Factories

  1. "Programmatic Dependency Injection with an Abstract Factory," by Danny Hui, discusses the strength and weakness of applying Dependency Injection (DI) with a variant of Abstract Factory design pattern. This approach is especially suitable for such scenarios as creating local stateful objects with dynamic parameters, handling checked exceptions thrown during object creation, and dynamically wiring up objects. IoC frameworks, such as Spring IoC container, PicoContainer and Guice, do not offer good solutions for these issues or simply unable to address them. Read Article
  2. It reminds me a recent work that I did on Tiles:
  3. Purpose of the article?[ Go to top ]

    I really wonder what the purpose of the article is? An IoC Container usually is an abstract factory because one can change its configuration. And you can only create objects within the boundaries of the particular product, which is, why, naturally, an IoC container in itself is not a candidate for a strategy pattern implementation.
  4. Re: Purpose of the article?[ Go to top ]

    The purpose of this article is to demonstrate that IoC container cannot solve all dependency injection problems in a simple way. Actually after years of experiences and erperiments with different IoC containers, my conclusion is that IoC or Dependency Injecttion is a great idea since it helps promote the good practice of POJO-based design and testable code. BUT IoC container - XML-based or programmatic, is NOT such a good idea. I do not see a compelling reason for using a IoC container and you get dependent on yet another API no matter which IoC container you choose. We use conariners or frameworks only when they solve the common concerns that need special expertise such as transaction management, security, O-R mapping, etc. I do not see any expertise needed for Dependency Injection. You simply need to know how to create and wire up objects in a designated factory object (instead of spreading the object creation and wiring-up everywhere) and then instantiate the factory object in a designated object (client code, for instance. similarly to what IoC containers do). Then you enjoy all the benefits of DI. I do not see that object creation and wiring-up by a IoC container makes a big didfference.
  5. Re: Purpose of the article?[ Go to top ]

    Then you enjoy all the benefits of DI. I do not see that object creation and wiring-up by a IoC container makes a big didfference.
    Huh? But from your article you are constantly referencing unit testing. Which you will usually only do by changing *some* of the implementation classes within your factory. So, for unit testing you go about changing some of the code in your factories or writing a couple (several permutations may be possible) of designated testing factories, or you make your factories configurable which in effect creates just another IoC container. No, DI is not hard (and in my opinion it is grossly overrated), but its not worth being reinvented yet again either.
  6. Re: Purpose of the article?[ Go to top ]

    You have a abstract factory class (or interface). In you application code, you have an implementation of that factory. To do unit test, you simply extends/implement the abstract factory as a mock object and inject into the object under testing. This mock factory object just depends on other mock objects, not any concrete class in your application code.
  7. Re: Purpose of the article?[ Go to top ]

    No, DI is not hard (and in my opinion it is grossly overrated), but its not worth being reinvented yet again either.
    In your factory implementation class, you have ComponentA compA = new ComponentAImpl(); ComponentB compB = new ComponentBImpl(); compB.setComponentA(compA);//inject dependent object In the client code (or whereever you instantiate Spring/PicoContainer/Guice container), instantiate your concrete factory class. then just call the appropriate method from the factory to get the wired objects, similarly to calling the IoC container for objects. It is simple enough for me. Nothing but the very basic OO programming. There is no wheel to reinvent here.
  8. This approach is especially suitable for such scenarios as creating local stateful objects with dynamic parameters, handling checked exceptions thrown during object creation, and dynamically wiring up objects. IoC frameworks, such as Spring IoC container, PicoContainer and Guice, do not offer good solutions for these issues or simply unable to address them.
    This is 100% incorrect with regard to Guice. I have no idea about Spring and Pico. Not to mention, the article links to Guice's user guide at the bottom as if the author read it, but Guice's user guide does a better job of explaining dependency injection by hand using the factory pattern, and it also explains why you shouldn't bother with it.

  9. This approach is especially suitable for such scenarios as creating local stateful objects with dynamic parameters, handling checked exceptions thrown during object creation, and dynamically wiring up objects. IoC frameworks, such as Spring IoC container, PicoContainer and Guice, do not offer good solutions for these issues or simply unable to address them.


    This is 100% incorrect with regard to Guice. I have no idea about Spring and Pico.

    Not to mention, the article links to Guice's user guide at the bottom as if the author read it, but Guice's user guide does a better job of explaining dependency injection by hand using the factory pattern, and it also explains why you shouldn't bother with it.
    I do not see anywhere in Guice User Guide that mentions how the application specific checked exception is handled. As for local stateful objects with dynamic parameters, you do offer a solution (How do I pass a parameter when creating an object via Guice? http://code.google.com/p/google-guice/wiki/Guice10Recipes). However, the programmer still has to write a static factory class -- you simply cannot configure it in the regular Module class. Why the solution (Guice + Factory) is better than a pure abstract fatcory plus its subclass (or implementation if a factory interface is used)? Dynamically wiring up objects is not mentioned in Guice user Guide either (please correct me if I'm wrong). See this example: public void aMethod() { Integer i = somemethod(); ComponentA comA = null; if (i > 0) { compA = factory.getComponentAImpl1(); } else { compA = factory.getComponentAImpl2(); } ComponentB compB = anotherFactory.getComponentB(); //Implementation of ComponentA is determined at run time. compB.setComponentA(compA); ... } Can you give us a Guice solution simpler than the above? I assume you have to use factory -- again what's the benefit of using Guice + factory instead of just factory for this scenario?
  10. I do not see anywhere in Guice User Guide that mentions how the application specific checked exception is handled. As for local stateful objects with dynamic parameters, you do offer a solution (How do I pass a parameter when creating an object via Guice? http://code.google.com/p/google-guice/wiki/Guice10Recipes).
    However, the programmer still has to write a static factory class -- you simply cannot configure it in the regular Module class.
    We squeeze as little as possible into Guice core. Check out AssistedInject for example.
    Why the solution (Guice + Factory) is better than a pure abstract fatcory plus its subclass (or implementation if a factory interface is used)?
    Because you shouldn't throw the baby out with the bathwater. Just because you need to handle a couple cases by hand doesn't mean you should manually write everything.


    Dynamically wiring up objects is not mentioned in Guice user Guide either (please correct me if I'm wrong). See this example:

    public void aMethod() {
    Integer i = somemethod();
    ComponentA comA = null;

    if (i > 0) {
    compA = factory.getComponentAImpl1();
    } else {
    compA = factory.getComponentAImpl2();
    }

    ComponentB compB = anotherFactory.getComponentB();
    //Implementation of ComponentA is determined at run time.
    compB.setComponentA(compA);
    ...
    }

    Can you give us a Guice solution simpler than the above?
    I assume you have to use factory -- again what's the benefit of using Guice + factory instead of just factory for this scenario?
    It's hard to provide a "simpler" solution than that because I have no idea what your code is doing. For example, I probably wouldn't use a setter, but I don't have an actual use case to fall back on and try to solve.
  11. Bijection[ Go to top ]

    Doesn't the idea of bijection totally solve this problem? :)
  12. Re: Bijection[ Go to top ]

    The issue is whether a IoC container/framework is necessary for independency injection. In other words, is using third-party frameworks - XML-based or programmatic, a better solution than manually injecting dependency with the help of design pattern like Abstract factory? I do not have deep understanding of Gavin's bijection idea and would not like to comment too much right now. However, similar to independency injection, bijection also faces the question of whether it is better implemented with the help of a framework like Seam or just by hand. As I said in my article - it is also the opinion of many other developers, that we must have compelling reasons to use a framework for solving a common problem.
  13. "Maybe the problem with both Spring and Guice is a flaw in the Dependency Injection pattern itself. It looks nice in the simple UML diagrams used to describe the concept, but it gets harder when the number of classes and components increases." http://lateralprogramming.wordpress.com/2008/04/07/why-use-spring-if-you-have-a-hashmap-at-hand/
  14. Dependency Injection Without Frameworks http://www.supplesoftware.com/articles/2006/04/16/dependency-injection-without-frameworks
  15. We went down the exact same track and created a programmatic Dependency Injection that also provides a tiny framework for the 'exposed POJO model' pattern and to put the icing on the cake it provides an wrapper around the key transparent persistence technologies JDO and Hibernate. I think the time it took to write was less than the time it takes most people to get their head around Spring plus it has the added bonus of being measured in KB instead of MB and the massive benefit of having ZERO XML config. When something goes wrong your compiler or your IDE will point you right to the scene of the accident - you won't be wondering where to hunt for the problem in a sea of XML kludgery. It's been used in large enterprise apps and simple prototype apps. It's open source and will take about 10 minutes to grasp the simple concepts: http://expojo.com
  16. yes, you have abstract factory as part of your design, but you are using Factory Method DP. In order to have Abstract Factory DP, you have to have at least 2 different factories implementations of same abstract class and then separate manager class is trying to abstract the process of factory creation.
  17. The main difference between Factory Method DP and Abstract Factory DP is that the former creates objects of the same type (i.e. one product), while the latter creates objects of different types (i.e. multiple products). I use Abstract Factory DP in this article due to the obvious reason -- I need the concrete factory to create different types of objects, including their dependency, and hook them up, i.e. inject dependency. Yes we do need a separate manager class (Facade) to instantiate the concrete factory class -- that's where you would create the IoC container if you are using it. That's why I view the IoC container as a general-purpose factory.
  18. As I just began to read this article, I just stopped how the author is given an exemple about the implementation of a singleton: public class Module1ServiceFactoryImpl implements ... { private Module1Servicefactory instance; ... public static synchronized Module1ServiceFactory getInstance() { if (null == instance) { instance = new Module1ServicefactoryImpl(); componentA = new ComponentAImpl(); componentB = new ComponentBImpl(); componentA.setComponentB(componentB); } return instance; } ... } Implementing a singleton like this is a big error! and it has been proven it does not work in a multi-threaded environment... How is it possible to still publish articles containing this specific error. The goog way to implement a singleton is: public class ASingleton { private static ASingleton _instance=new ASingleton(); private ASingleton() {} public static ASingleton getInstance() { return _instance; } } In the article, we can also find the instance variable is not static, which is also an error. Nervertheless, I will continue to read it... Regards.