Opinion: Why I prefer constructor-based dependency injection

Discussions

News: Opinion: Why I prefer constructor-based dependency injection

  1. Simon Harris has written an opinion piece on why he prefers constructor-based dependency injection, compared to the set*() method approach. The main point revolves around "restricting the number of parameters you may declare for a method".

    Excerpt
    "On the current project I'm on, and no doubt on many of yours, we have restrictions on the number of parameters you may declare for a method. This, hopefully, forces developers to re-evaluate what they are passing around. For example, use a DateRange instead of dateFrom and dateTo.

    Unfortunately there is a simple way to subvert that process by simply declaring everything as "setters" which typically have only one parameter. Then all the lovely detail becomes much harder to see as it's hidden in the morass of the aptly name mutators (yet another reason I dislike getters and setters).

    Declaring service dependencies in constructors allows me to see them all in one go. It immediately becomes apparent if a class depends on "too many". Something that is much harder to see when you use setters. It also allows us to construct objects in a valid state with all the obvious benefits.

    Another advantage to using a constructor is that only the creator need know about the dependencies. In our case it's our ServiceRegistry. Once an object has been constructed (either by the registry configuration for singleton services defined by interfaces or by calling ServiceRegistry.newInstance(Class) allowing the construction of any class that depends on a service) client code is unaware of the dependency."
    Read Simon Harris in Why I prefer constructor-based dependency injection

    ps. Check out the interesting comments

    Threaded Messages (56)

  2. I found constructor-based dependency injection bad choice when you have class hierarchies of the componenets (beans, POJOs, etc...). Passing all the parameters to the super method is a boring bloat and error prone. Also setter based dependency injection has its downsides too.

    I found that for classes that need to be configure with a lot of parameters and which need reconfiguration facility, the following dependency injection pattern is prefreable:

    - create a separate configuration bean (named XXXComponentConfig for example) consisting of all rquired configuration parameters for you component (named XXXComponent). The been itself should be populated with setter methods for easier subclassing.
    - provide a configure method in your component:
    public void configure(XXXComponentConfig config);

    Whether your XXXComponent will store a reference to XXXComponentConfig instance or will store all configuration properties separately is implementation specific.

    The advantages of this approach are following:
    - your component is reconfigurable (important in dynamic environments) as oposed to constructior dependency injection which is not well suited for reconfiguration.
    - your component is configured in one method (in one place), thus more readable then setter based dependency injection.
    - configure method can be synchronized thus providing the consistency to the component configuration state (when reconfiguring), as oposed to setter based dependency injection which cannot easily be reconfigured without sacrifacing consistency of the configuration state.

    I do not know if there is a name for this dependency injection approach.

    Mileta
  3. There are other benefits to using the constructor rather than set methods (cue Effective Java style rant) - it means you can maximise the number of immutable objects. Saying that it makes inheritance more difficult is not such a big problem if you're using data objects - mostly you end up using composition rather than inheritance anyway.

    Of course as usual it all depends what you're trying to do...
  4. And another thing...[ Go to top ]

    Oh yeah, and I forgot to add, it makes exception handling neater, since all your data validation happens in the constructor.
  5. I see both ways have limitations, probably one of good ways to configure app is
    to configure it without any injection.
  6. I used to prefer constructor based initialisation but the problem comes when your object grows to need a new property.
    If you provide a sensible default then your contract with the original code is unchanged.
    Otherwise you must update the constructor and also update every piece of code that uses the object. Then you have to regression test it.

    I have finally come back to the conclusion that default constuctors and getters/setters are better.

    Constructor based intialisation should still be used when the order of initialisation matters but for simpel objects this does not apply.
  7. I used to prefer constructor based initialisation but the problem comes when your object grows to need a new property.If you provide a sensible default then your contract with the original code is unchanged.Otherwise you must update the constructor and also update every piece of code that uses the object. Then you have to regression test it.I have finally come back to the conclusion that default constuctors and getters/setters are better.Constructor based intialisation should still be used when the order of initialisation matters but for simpel objects this does not apply.
    This is a + for constructor-based dependency injection IMHO. If there's no good choice for a default value, you just change the constructor and you'll get an exception when your application. If you simply add a new setter you'll need to remeber to change your configuration files.

  8. I used to prefer constructor based initialisation but the problem comes when your object grows to need a new property.
    If you provide a sensible default then your contract with the original code is unchanged.
    Otherwise you must update the constructor and also update every piece of code that uses the object. Then you have to regression test it.


    If you use getters / setters, you'll either need to:
    -provide sensible defaults, because the setter won't be called.
    -find all statements that create an instance of that class, which is much more likely to be done wrong, as the compiler won't complain.
  9. Constructors too Constricting[ Go to top ]

    Come on, guys, I really appreciate the value of immutability and all, but it takes about ten minutes of actual work to see the limitations of contructor-based dependency injection.

    Try:

    public TaxBasis( String customerId )

    and

    public TaxBasis( String companyId )

    Uh... OOPS! I'm sure that there are some people that will advocate refactoring my dependencies and creating artifical construction signatures to try and avoid duplication. No, thank you. I am willing to sacrifice some level of immutability (or introduce an extra instance variable to enforce it if necessary) to avoid redesigning my architecture around the technical limitations of constructors.
  10. Constructor Syntax[ Go to top ]

    Try:

    public TaxBasis( String customerId )a

    and

    public TaxBasis( String companyId )
    Actually this won't compile. You can't have two constructors with the same signature. The type or number of parameters has to be different. Perhaps this was a typo?
  11. Constructor Syntax[ Go to top ]

    Actually this won't compile. You can't have two constructors with the same signature. The type or number of parameters has to be different.
    That was my point. This is one of the limitations introduced by contructor-based injection.
  12. Ah, sorry. Haven't finished my morning coffee yet.

    Good point. In cases like that, I still don't rely on the client invoking a setter. Instead I create two static factory methods:

    class TaxBasis {
      public TaxBasis createCustomerTaxBasis(String customerId);
      public TaxBasis createCompanyTaxBasis(String companyId);

      private TaxBasis() {}
    }

    That ensures that the object is always created in a valid state, and I can make it immutable if I want to. But of course this won't work with either style of dependency injection. Perhaps we need 'static factory method based injection'?

    In this particular case, perhaps Customer and Company need to be explicit types. I.e.:

    public TaxBasis(Customer customer);

    public TaxBasis(Company company);

    If you have two different constructors with the same signature, it could be a sign of a missing type (or subclass). But not always. And of course one shouldn't have to redesign one's code for the sake of the container (either by adding setter methods or an artificial constructor).

    I'm not arguing that a container shouldn't support setter based injection. But for me at least, constructor based injection is less invasive. I'd have to change more of my code to support the container with setter based injection, than I would with constructor based injection. So I reach for constructor based injection first, and only use setter injection when that doesn't work (usually with objects I don't control and don't instantiate.)
  13. Meant to make the factory methods static:

    class TaxBasis {
      public static TaxBasis createCustomerTaxBasis(String customerId);
      public static TaxBasis createCompanyTaxBasis(String companyId);

      private TaxBasis() {}
    }

    Still haven't finished my coffee.
  14. Instead I create two static factory methods: (...) That ensures that the object is always created in a valid state, and I can make it immutable if I want to. But of course this won't work with either style of dependency injection. Perhaps we need 'static factory method based injection'?
    Spring provides means to invoke static factory methods via its MethodInvokingFactoryBean class, offering the method invocation result for bean references: A collaborating object just needs to expose a constructor argument or bean property setter of the result type.
    And of course one shouldn't have to redesign one's code for the sake of the container (either by adding setter methods or an artificial constructor).
    Completely agreed. A container should support your style of development (as far as possible) rather than enforce its own, and allow for easy migration between different styles.

    Juergen
  15. Spring provides means to invoke static factory methods
    > via its MethodInvokingFactoryBean class, offering the
    > method invocation result for bean references

    Why do you need spring at all to do such a simnple thing?
    If you have service accessors then whomever constructs
    an object can just pass in the correct references.
    There's no need for a separate confusing framework.
  16. >Spring provides means to invoke static factory methods > via its MethodInvokingFactoryBean class, offering the > method invocation result for bean references. Why do you need spring at all to do such a simnple thing? If you have service accessors then whomever constructs an object can just pass in the correct references. There's no need for a separate confusing framework.
    The point is that this mechanism allows you to pass the factory method result to constructor arguments or property setters of other components in a declarative fashion. Of course, you can invoke the factory method yourself and do whatever you want with the returned object, but then you implement programmatic configuration code which depends on a specific factory method. Not to say that this is a bad thing in general, but it is not what IoC is about.

    As a side note, MethodInvokingFactoryBean is just a convenience implementation of the FactoryBean interface, which is Spring's generic mechanism to plug in *any* object into its IoC wiring namespace. Other examples are JndiObjectFactoryBean and LocalSessionFactoryBean, looking up a specific JNDI object respectively setting up a local Hibernate SessionFactory instance.

    FactoryBean is a simple interface: If you have some object that needs special setup, implement a FactoryBean for your custom needs, exposing the desired object via the getObject() method. You'll then configure the FactoryBean as Spring bean definition, which will expose your desired object for bean references rather than itself - the main characteristic of a FactoryBean.

    Juergen
  17. In this particular case, perhaps Customer and Company need to be explicit types. I.e.:
    public TaxBasis(Customer customer);
    public TaxBasis(Company company);
    I think you are missing the point. How do you cover the following case with constructor-based injection:

    public TaxBasis(Customer payingCustomer);
    public TaxBasis(Customer invitedCustomer);

    ?

    If you have two different constructors with the same signature, it could be a sign of a missing type (or subclass).

    Once again, there is simply no silver bullet. You have three choices:

    - Constructor-based injection
    - Setter-based injection
    - No injection (default constructor and invoke setters yourself)

    All three have their use and if you tell me you should only ever use one of them, I am sure I can come up with an example to prove you wrong :-)

    --
    Cedric
    http://beust.com/weblog
  18. I'm not arguing that constructor based injection is a silver bullet. There are certainly cases where setter based injection is more appropriate. But I think the point the author of the article was trying to make is that he finds construction injection *preferable". I think construction injection should be ones first choice. Coming up with examples of where constructor injection doesn't work does not invalidate that preference / recommendation.
    I think you are missing the point. How do you cover the following case with constructor-based injection:

    public TaxBasis(Customer payingCustomer);

    public TaxBasis(Customer invitedCustomer);
    I think I got the point. (I've had my coffee now. ;) ) Again, I think introducing creator factory methods would be preferable to introducing setter methods:

        public static TaxBasis createForPayingCustomer(Customer customer);

        public static TaxBasis createForInvitedCustomer(Customer invitedCustomer);

    The explict names remove any ambiguity, and the object is constructed in a valid state.

    I guess you would need to use something like Spring's MethodInvokingFactoryBean for this. This seems like a variation on constructor injection to me, working around the fact that Java doesn't have named constructors.
  19. I guess you would need to use something like Spring's MethodInvokingFactoryBean for this. This seems like a variation on constructor injection to me, working around the fact that Java doesn't have named constructors.
    Pico container allows registering component factories by using ComponentAdapters if necessary. They can call static methods, work as cache, or return cached proxies of an object and switch implementations at rintime.
  20. Good point.

    One of the things I like about PicoContainer is the ComponentAdapter concept. As soon as you say "You can't do 'X' in Pico," you soon realize that you can quickly write a little ComponentAdapter to do 'X'! They're very easy to write.

    PicoContainer has a very clean, minimalistic, elegant and extensible design.

    (Which is not do say that Spring doesn't! Don't want to start a flame war; I'm just more familiar with Pico's design.)
  21. XML[ Go to top ]

    What about passing some XML to the CSTR?

    It's flexible, but doesn't have static type checking.
  22. Constructor Syntax[ Go to top ]

    Try:public TaxBasis( String customerId )aandpublic TaxBasis( String companyId )
    Actually this won't compile.
    ...
    Voila !
  23. Re: Constructor Syntax[ Go to top ]

    Try:public TaxBasis( String customerId )aandpublic TaxBasis( String companyId )
    Actually this won't compile. You can't have two constructors with the same signature. The type or number of parameters has to be different. Perhaps this was a typo?
    I believe that was his point.
  24. Constructors too Constricting[ Go to top ]

    The method I descirbed (the separate configure method with XXXConfig bean) has 'the best of both worlds' (best of the setter injection and the constructor injection approaches):
    Pros:
    - configuration is held in one plase (XXXConfig bean) and is separate from other instance fields of our component which are not configuration specific.
    - configuration process is done at one place, thus easily synhronized.
    - reconfiguration is easy.
    - exception handling is easy.
    - configuration order is maintenable.
    Cons:
    - separate config class is required. But, this may not be a con. because you anyway has to provide getters to access the configuration attributes in the component class for setter and constructor based injection.

    Mileta
  25. Constructors too Constricting[ Go to top ]

    The method I descirbed (the separate configure method with XXXConfig bean) has 'the best of both worlds'
    It also suffers from a few fatal flaws:

    - All that you have accomplished is push back the problem further (now it's your Config beans that needs to validate your arguments and not your real class).

    - If the business logic in your real class changes its semantic or adds a new parameter, you need to remember to update your Config class as well (and no static typing nor refactoring will help you there, you are completely on your own).

    Your code has just become a lot more fragile and harder to maintain.

    --
    Cedric
    http://beust.com/weblog
  26. Constructors too Constricting[ Go to top ]

    - All that you have accomplished is push back the problem further (now it's your Config beans that needs to validate your arguments and not your real class).

    I do not see what is the problem with this. The basic validation could be done by the container (based on property type). If you need more sophisticated validation you can write it in configure method of the main component of in the config bean itself.

    >> - If the business logic in your real class changes its semantic or adds a new parameter, you need to remember to update your Config class as well (and no static typing nor refactoring will help you there, you are completely on your own).

    If you keep the reference to the config bean in you main component you do not have to duplicate configuration properties twice.

    Mileta
  27. Constructors too Constricting[ Go to top ]

    >> - All that you have accomplished is push back the problem further (now it's your Config beans that needs to validate your arguments and not your real class).

    I do not see what is the problem with this.
    Now you have two classes to keep in synch.
    If you keep the reference to the config bean in you main component you do not have to duplicate configuration properties twice.Mileta
    I think you missed my point.

    Imagine that you create a PersonConfig to create a Person. One day, you decide that on top of firstName and lastName, a Person needs to be created with a socialSecurityNumber as well, and that it's mandatory.

    You add this field to Person but you need to remember to add it to PersonConfig as well or your code will break.

    You are duplicating your work all over the place, as opposed to keeping the validating logic inside Person, where it belongs.

    --
    Cedric
  28. Constructors too Constricting[ Go to top ]

    Cedric,

    With a non dependency injection scheme (Wallet creates Currency rather than having it injected)..

    .. How do you test the Wallet in isolation (without dragging along a concrete implementation of Currency)?

    I'm a bit disappointed that the testing aspect of CDI has been completely ignored in this thread.

    In fact, CDI is closely related to TDD and mocking and they all complement each other. I'm not saying that you should all go out and use this happy trio, but those of you who do will have a pleasant surprise.
  29. CDI and TDD[ Go to top ]

    I agree, one of the main benefits of CDI is how well it aligns with TDD. With a test-first design, you typically end up passing hard-to test dependencies to the constructor, via interfaces. CDI is the most naturall way to inject the dependent components in run-time. If you start with a TDD design for a component, and then figured out how to write a component container to inject the dependencies, you'd end up with a simple CDI injection based container.

    Of coures not all components are written test first in the real world, and we need to integrate with stuff we can't control. So setter injection is also important to support legacy components, and for interesting esoteric cases where CDI is not so pratical (deeply nested inheritance hierachies, reams of parameters, etc.). But if you really design your components TDD style, I think you'll find that CDI is the most elegant and least invasive way to go *most* (not all) of the time.
  30. OO Without Inheritance[ Go to top ]

    My counter to this is simple: don't have deep and/or wide class hierarchies. I rarely find the need for them and they're usually a code smell.

    Aaargh! This is what always annoys me: "If you have a valid issue with [technical approach that I am advocating], the problem is actually with your design. I have never seen your project before, but I can tell you that you need to redesign your architecture to work around the non-existent limitations of [technical approach that I am advocating]."

    When you work on enterprise systems of a certain size of reasonably complex business logic, deep or wide class hierarchies are not a bad code smell. They are almost always necessary to eliminate bad code smells, particularly cut-and-paste code across large number of classes and poor readability.

    General advice: If you are convinced that X technology is perfect, but the problem lies with people who use inheritance, or require multithreading, or need to keep more than 32 megs of data in memory at a time, or who need a throughput of greater than 2 transactions per second, the problem may actually lie with technology X.
  31. OO Without Inheritance[ Go to top ]

    "When you work on enterprise systems of a certain size of reasonably complex business logic, deep or wide class hierarchies are not a bad code smell. They are almost always necessary to eliminate bad code smells, particularly cut-and-paste code across large number of classes and poor readability.
    I couldn't disagree more. Reuse by inheritance is in my experience a much poorer form of reuse than that of delegation.

    With a delegation model you have the flexibility of dynamic composition, whereas with inheritance you are statically bound to the class hierarchy.

    You can have a lot more fun with a Wallet that has-a Currency than a DollarWallet that is-a Wallet.
    General advice: If you are convinced that X technology is perfect, but the problem lies with people who use inheritance, or require multithreading, or need to keep more than 32 megs of data in memory at a time, or who need a throughput of greater than 2 transactions per second, the problem may actually lie with technology X.
    That's unfair. Technology is not a remedy for bad design. However, Good design is an enabler for good code.
  32. OO Without Inheritance[ Go to top ]

    I couldn't disagree more. Reuse by inheritance is in my experience a much poorer form of reuse than that of delegation.
    I can agree with this, in cases where inheritance or composition/delegation are equally capable of solving the problem. But my experience is that for complex problems, delegation works better for 'wide' hierarchies, and inheritance works better for 'deep' hierarchies.
    That's unfair. Technology is not a remedy for bad design.
    No, what's unfair is making dismissive statements like 'all inheritance is bad design' in order to justify a particular technical advocacy position.
  33. OO Without Inheritance[ Go to top ]

    No, what's unfair is making dismissive statements like 'all inheritance is bad design' in order to justify a particular technical advocacy position
    And who did this?

    I think the word used was "usually"... as in "they're usually a code smell"...

    -Nick
  34. OO Without Inheritance[ Go to top ]

    I couldn't disagree more. Reuse by inheritance is in my experience a much poorer form of reuse than that of delegation.With a delegation model you have the flexibility of dynamic composition, whereas with inheritance you are statically bound to the class hierarchy.
    You seem to imply that delegation and inheritance can be freely substituted for each other, that it's just an arbitrary choice by the developer.

    Nothing could be further from the truth.

    They are very different and come with different trade-offs.

    Granted, delegation has a few good properties (less coupling) but the price is that you lose type substitution. And sometimes, you really need your subclasses to obey the LSP.
     
    I agree with Mike: while deep hierarchies should be avoided, they are sometimes unavoidable and a better choice than any alternative. Even if this alternative is delegation.
    You can have a lot more fun with a Wallet that has-a Currency than a DollarWallet that is-a Wallet.
    Perfect illustration of what I was saying earlier: if I have a method

    stuffWallet(Wallet w)

    I can invoke

    stuffWallet(new MikeWallet())

    but not

    stuffWallet(new AslakWallet())

    And you do want to stuff this wallet, don't you?

    --
    Cedric
  35. OO Without Inheritance[ Go to top ]

    but the price is that you lose type substitution
    Unless you use interfaces. There is not much point to composition if you dont have type substitution... (as the winforms users are finding out)

    -Nick
  36. Silliness[ Go to top ]

    'Constructor-based dependency injection' has to be one of the silliest phrases I've heard in a while. Why not just call them 'constructors'? Seriously, this emperor has no clothes. Constructors aren't for 'declaring service dependencies' either. It is a seriously bonehead thing to do; it's a brittle, non-OO hack. Constructors should initialize an object into some known state and that's it. Trying to force them to do anything else is just wrong. It's really that simple. Also, two more things. Using a ServiceRegistry to construct all your objects (a la Spring) is a serious anti-pattern. As your codebase grows the SR just becomes more and more complex (a la Spring). This kind of centralization also confuses things since you literally have to decode how an object is being constructed. Finally, passing instances of the SR around (or using a static singleton) If object A needs to construct B and you need to hide B's configuration logic from A then use a Factory. On the other hand, giving a bean a configure(Config) method also seems like a bad idea. More than likely you want (1) the State pattern to completely externalize the parameters (2) the Prototype pattern so constructing an object is as simple as cloning it and then customizing it with a few setters (3) the factory pattern.
  37. Silliness[ Go to top ]

    More than likely you want (1) the State pattern to completely externalize the parameters (2) the Prototype pattern so constructing an object is as simple as cloning it and then customizing it with a few setters (3) the factory pattern.

    I think you miss the point about dependency injection. The dependency injections is all about moving configuration state handling OUT of your business logic components. With dependency injection you do not have to write code to read from configuration file (or other configuration state sources) because it is generic and already implemented in the container. Also constructor dependency injection and 'configure method injection' clearly separates configuration state from other component state that may or may not be transient.
  38. Silliness[ Go to top ]

    Agree, it is an antipattern. Probably some comprimise like
    "init.js/destroy.js" scripts can be a good way to configure "global" objects.
  39. For me the advantages of constructor based injection come down to the following:

    1. Immutable objects. Not possible with setters.
    2. No temporal coupling. Once constructed, the object is good to go.
    3. No need to change my code for the sake of the container.

    OK, #3 cuts both ways. If used aggresively, immutable objects can eliminate a whole category of bugs, and simplify (or to be precise, make unnecessary) copying/cloning. It would annoy the heck out of me if I had to add setters to all my immutable objects for the sake of the container. Since I try to avoid #2, most of my classes do have constructors that take all the dependencies.

    But of course there are exceptions, especially with code you don't control or objects you don't instantiate (i.e. Struts actions). So both styles need to be supported, but I always reach for constructor injection first.
  40. It would annoy the heck out of me if I had to add setters to all my immutable objects for the sake of the container.
    Good point. The container should not enforce its world view on you: If you prefer constructor injection, there should be non-intrusive ways to apply it. On the other hand, there might be objects that naturally have bean properties with setters (for example because of numerous optional settings); the container should provide sophisticated means for initializing those too. It's all about choice (true choice, that is, not checked options for marketing purposes).

    Juergen
  41. <blockquoteThe container should not enforce its world view on you: If you prefer constructor injection, there should be non-intrusive ways to apply it. On the other hand, there might be objects that naturally have bean properties with setters (for example because of numerous optional settings); the container should provide sophisticated means for initializing those too. It's all about choice (true choice, that is, not checked options for marketing purposes).JuergenCouldn't agree more! I think (hope) that the discussion here is about which to reach for first, constructor or setter DI, and which situations call for one approach over the other. There are definitely cases where constructor injection is more than a preference; often it's the only way to achieve a sound design with immutable objects and no temporal coupling. But sometimes the reverse is true and you do need setter injection.
  42. Using a framework like spring, you can define and object with setters and an interface with no setters. Simply use the interface and you have an immutable object with setter injection
  43. To be precise: Immutable interfaces to a mutable object are possible. The object itself is still mutable. Someone can still do:

    MyInterface i = new MyImpl();
    i.someMethod(); // whoops - forgot to initialize properly
  44. Question...[ Go to top ]

    Pardon the possibly ignorant question, but why the concern for immutability. Is this a problem with our service objects? Take this code for example:

    public class SomeWebLayerThingy {
        private SomeServiceInterface service;
        public void setSomeServiceInterface(SomeServiceInterface service) {
            this.service = service;
        }
        // code that does stuff goes here
    }

    Why should SomeWebLayerThingy be concerned that its instance of SomeServiceInterface is immutable. Shouldn't it just be concerned that it just does its job?

    Also, couldn't immutability of service ojbect be a bad thing? What if we have a CacheProvider interface that provides some properties to "tune" the cache. Let's say the load of our application has been growing significantly and we want to expand the size of the cache. Why shouldn't we be able to have a way (JMX?) to call setCacheSize on our CacheProvider at run time, thus mutating our CacheProvider service object. Provided that that CacheProvider implementation handles that run time change robustly, any of the CacheProvider clients will be using a mutable bean.

    This is a simplified example, but I can see a real use case for this. Perhaps I am missing something. I can see the use for immutability for value objects that comprise our model - we don't want outsiders mucking with our data without notifying our objects:

    someBean.setDate(date); // setDate does not make a defensive copy!
    date.setTime(0L); // oops!

    But service objects that do not offer a means to manage their properties except through a constructor seems limiting to me.

    Ryan
  45. Question...[ Go to top ]

    We might be talking about two different things - but I'm not sure if I understood you correctly. The issue is whether the *client* of the service (SomeWebLayerThingy) can be immutable or not. The service itself could have set methods, or not. But if you use setter based injection to supply SomeWebLayerThingy with its SomeServiceInterface, then SomeWebLayerThingy has to have a setService method. You can't make SomeWebLayerThingy immutable.

    Now maybe you don't want to make SomeWebLayerThingy immutable. Obviously not everything can or should be immutable. But with setter injection, you don't have a choice. You just can't make it immutable. Construction injection works with both mutable and immutable objects. You can remove the set methods later and your still OK.

    Setter injection can introduce a subtle dependency on the container. The setter methods have to be there for the container to do its magic.
  46. Question...[ Go to top ]

    Actually, in my example I was talking about making the service immutuable. I'll go back the CacheProvider example. Let's say our CacheProvider is really simple and has one property - size. If we are going to manage this CacheProvider with an IoC container, we can set the size two ways - by constructor or by setter. An argument for constructor injection is that when I instantiate my CacheProvider implementation by passing my cache size, it is now it a valid state and (if no setCacheSize method) immutable.

    My question is, why is this good? Is mutablility bad? Why? To me, it seems that immutability eliminates run time configurability. Again, I can see the value for mutability for value object. I don't see it buying much in the realm for dependency management. In a well behaved application, I can't see the fact that my object's dependencies are mutable will ever get me into trouble.
    Setter injection can introduce a subtle dependency on the container. The setter methods have to be there for the container to do its magic.
    How is this different than constructor injection? *Something* has to create/inject the object in either scenario. The fact that the container has to instatiate and inject separately in the setter case is really of no concern to me. As long as the container allows me an easy way to express my dependencies, I don't see much difference (auto wire rocks here!).

    The other question I have is what to you do with components that have lots of configurable properties, like a connection pool. Do you have many constructors? One monolythic constructor? What if there are twelve different configurable properties for a service (very possible for a connection pool - min/max connection, idle time, user name, password, URL, driver, etc). A twelve argument constructor would look a little unwieldly, no?

    Ryan
  47. Question...[ Go to top ]

    An argument for constructor injection is that when I instantiate my CacheProvider implementation by passing my cache size, it is now it a valid state and (if no setCacheSize method) immutable.
    The first argument, guaranteeing the service is in a valid state, still applies even if you don't require immutability. Well, not if the only dependency is 'size'; the default no-arg constructor could just fill in the default. But sometimes services depend on other services. Supplying dependent services in the constructor guarantees that the object is created in a valid state, even if you do allow clients to change parameters afterwords.

    I don't think anyone is arguing that mutability is always a bad thing. But it's nice to have the immutability option. I actually do make most services immutable, and only configurable at creation time. But of course there are exceptions.

    Take a DAO service. I usually don't want clients swapping out SQL strings, data sources, etc. at run time, after the object is created. At creation time sure, but after that usually no. I could imagine cases where I would want that, but usually I don't. And when I don't, it's safer and provides a smaller interface to make those properties immutable.

    If you need to supply 12 constructor parameters to support construction injection, sure that's a pain. Maybe you reach for setter injection in that case. But configuring those 12 parameters in the container config is going to be a pain too. Maybe things need to be refactored and broken up a bit.

    I'm not saying there's never a need for setter injection. But when you do need setter injection, it's often, *but not always*, an indication of a code smell.

    Steve
  48. temporal resolution is an issue[ Go to top ]

    Not all services are available at the time
    of construction or stay valid during the life
    time of an application, or i would say always use
    construction based configuration because
    it is the simplest, clearest, most obvious approach.

    By temporal resolution i mean an application may
    have a dependency tree of service references that
    can only be satisfied by the running of multiple
    state machines that can't run prior to construction.

    Applications that have distributed forms of calculations
    have the issue all the time. As an application i need
    to provide different sets of services at different points
    in my state machine. In each state i need different other
    services to provide my services. Thus they can't be
    satisified only at construction.
  49. We found that the biggest value of IoC design is usually attained when dealing with legacy objects, something that was created before and needs to be integrated into new or another application. In many cases to use these objects you will need to:
    • Create object with constructor
    • Set certain JavaBean and non-JavaBean properties into it
    • Call one or several initialization methods with various signatures
    ...and after that object is considered “logically” created and initialized. To support this behavior we had to come with much more advanced IoC implementation, one that has generalized invocation capability additionally to ctor-based injection.

    Regards,
    Nikita Ivanov.
    xTier - Service Oriented Middleware
  50. What's all the fuss about? This is basic OO coding. It's not a design pattern. It's not something new. For as long as I've been coding in OO languages it's been considered good coding practice to provide constructors that create well-formed instances of your objects. You pass in whatever parameters are needed to create well-formed instances.

    At the same time it's always been considered to be bad coding practice to create zero argument constructors and set all the attributes with individual "setter" methods.

    People argue in the abstract that it's too difficult to create "proper" constructors in practice - that you end up with too many variations of sets of parameters for different constructors. In practice, I've never found this to be the case.

    And in today's world of IDE's with built in Refactorings, is it really a big deal to add an additional parameter to a constructor if your object changes over time?
  51. For as long as I've been coding in OO languages it's been considered good coding practice to provide constructors that create well-formed instances of your objects. You pass in whatever parameters are needed to create well-formed instances.At the same time it's always been considered to be bad coding practice to create zero argument constructors and set all the attributes with individual "setter" methods.People argue in the abstract that it's too difficult to create "proper" constructors in practice - that you end up with too many variations of sets of parameters for different constructors. In practice, I've never found this to be the case.And in today's world of IDE's with built in Refactorings, is it really a big deal to add an additional parameter to a constructor if your object changes over time?
    Couldn't agree more with that. What is new is how IoC containers like Pico and Spring provide extra support for this coding style. Instead of instantiating dependent objects directly in your code, the container instantiates them for you, providing the correct implementation of an interface based on a configuration. This allows you to separate configuration from implementation. Here's a good intro article:

    http://www.martinfowler.com/articles/injection.html

    You may or may not like it, but it is something new.
  52. Imagine you have two components which are dependend to each other (e.g. think about a GUI and a controller component which are interacting together). How will you do this with Constructor Injection? Pico will give you a CyclicDependencyException...
  53. The problem that I have with Constructor Based Injection is the concept of well formed objects. When the object is coded and designed with a constructor based injection you have a already determined the business rules for the object. These rules are applied to the constructor and are immutable.

    Now this object is directly tied to a certain set of business rules to determine well-formedness and cannot be reused cleanly for disparate solutions. Even some of the most basic rules you can come up with for a bean validation may not apply to all solutions.

    I prefer to apply a combination of constuctor based and setter based injection. By that, I tend to have a number of limited parameter constuctors available as well as some business rules based constuctors using constructor based injection. Therefore I can apply to object to multiple solutions.

    The devil in these details occurs when having a team member that does not fully understand the code base. Then, a number of coding errors can occur because of developers not looking fully into the compositon of an object that they are using. Assuptions are made that the object is made well formed because the developer hasn't read the Javadoc or other supporting documentation.

    I have applied this philosophy to JavaBeans, POJOs, and complex objects such as JNDI, SQL, DAO, JMS factories. It provides the greatest flexabilty and reuse, but requires displine.
  54. Oh no "dependency injection"....[ Go to top ]

    The terms "dependency injection" or "inversion of control" are probably two of the most bloated terms I came across in my entire carreer (and it's been going on for some time). The dependencies in "dependency injection" are actually in the classes more often than not. There is no "dependency" injected. You either depend on an interface in your "bean" or "business object" or on a class. That is it. By configuring a particular object No dependency is injected. What is injected (if anything) is a reference.

    Much the same with "inversion of control". How about calling it "configuration" as this exposes what is done. But then nothing would be inversed, would it, because "configuration" has been done on the outside for ages. And the actual business processes are not "inversed" in any way. They are still pretty much linearly driven.

    Now really.....
  55. Oh no "dependency injection"....[ Go to top ]

    Either you are missing the point, or you are trying to be difficult :-)

    When you read "dependency injection", read "dependency instance injection".
    When you read "inversion of control", read "inversion of control of instantiation"

    The whole point is that the a component does not instantiate its dependancies. Therefore, it doesnt know what concrete types these are - nor where they came from - nor what their dependancies are.

    Now, for some people, this is Nothing New TM. (Most people doing proper unit testing would have discovered this by themselves - maybe not even realising it)

    However, for many people this is a big shift. They are used to their component instantiating its dependancies (in fact, knowing what to instantiate is deemed part of the encapsulation)

    In the end, though, its a very, very useful pattern.

    So.... yes... really!
  56. (Most people doing proper unit testing would have discovered this by themselves - maybe not even realising it)However, for many people this is a big shift. They are used to their component instantiating its dependancies (in fact, knowing what to instantiate is deemed part of the encapsulation)In the end, though, its a very, very useful pattern.So.... yes... really!
    I think most people do what I did for several years, instead of writing true unit tests which test methods in isolation, most people write "integration tests" which test objects and their dependencies. I see this all the time and I recognize it now that I've learned how to write Mock Objects (using jMock). A quick example: A coworker wanted to test his wrapper for the Apache commons HttpClient. So he coded up unit tests hitting yahoo.com and other websites. I was running the unit tests on my notebook on the train and they failed (obviously). His "unit tests" were in fact testing not only his "unit" but also HttpClient. This is a really simple example but it's very common. Another example is testing database access code.

    Michael Mattox
  57. Either you are missing the point, or you are trying to be difficult :-)

    When you read "dependency injection", read "dependency instance injection".
    When you read "inversion of control", read "inversion of control of instantiation"
    Well, to be precise, "inversion of control" refers to a characteristic common to frameworks. In the procedural paradigm, you had a set of function libraries, and when you write your system, generally you are responsible to design and code the flow of processing ('control'). Frameworks put it upside down, taking care of the main flow of processing and leaving the responsibility of the low-level (or business-specific) coding to you ('inversion of control'). This is often refered as 'the hollywood principle', or 'don't call us, we call you', because it's not your code that calls library functions, but the framework that calls YOUR functions/objects.

    This principle allows the configuration/customization of the framework (general) to fit our needs (specific).

    So, Karl isn't completely wrong about the configuration stuff, but the way this configuration is done is completely different. Pure configuration assumes that all code needed is already there, and you just need to set some flags to change the portion of code used. 'Inversion of Control' is a principle that allows customization of behavior by coding replaceable modules.

    You may say 'But I've done callbacks for ages as well'. OK, callbacks are made, but it is the 'concrete' term (implementation). 'Inversion of Control' would be the 'abstract' term (concept).

    Then, Nick, you are almost correct, just that those terms don't refer only to object instantiation, but to flow control (processing) as well. (or maybe I'm trying to be difficult?) =)