Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Should the usage of Dependency Injection and an Inversion of Control container remove all occurrences of the "new" keyword from your code?

In other words, should every object/dependency, no matter how simple or short-lived, be "registered" within your IoC container and injected into the method/class that needs to use them?

If no, where do you draw the line between which dependencies/objects get registered in the IoC container, versus what gets created "in-line" as a concrete reference, via the new keyword ?

share|improve this question
    
I've had the same thought, along the lines of "is 'new' a 4-letter word?" –  Michael Easter Aug 18 '11 at 16:31
add comment

6 Answers

up vote 20 down vote accepted

Avoid dogma. Do what feels right.

I prefer to use "new" for data structures which have no behavior.

If the class does have behavior, I then look at the scope of that behavior. If it is stateless and has no dependencies, I lean towards "new". I only begin refactoring towards DI when I need to add a dependency to stateful resources (such as a database or a file), or to other classes with such resources.

share|improve this answer
14  
+1 for "avoid dogma". Way too easy to fall into the trap of just following the motions without understanding what is happening or where it should be used properly. –  Wayne M Aug 18 '11 at 12:08
    
@Alex I like this. A very pragmatic approach. Funnily enough, I was going to add some code in my question showing a new'ed dependency in my own code that prompted my question. It was a simple class with no functionality or "behaviour" per-se, only simple properties. –  CraigTP Aug 18 '11 at 13:24
add comment

I would just like to add to the existing answers that were brought up earler, new is perfectly fine to create objects that are pure value objects (i.e. have only properties/getters/setters). See the Google Testing Blog for more detail.

share|improve this answer
    
+1 for the link. Point 9 in that blog posting answers the question and provides a pragmatic distinction between what should and should not be new'ed –  CraigTP Aug 19 '11 at 14:04
add comment

One word: No.

More words: Dependency injection is exactly that. It is a means by which you introduce resources that another object depends on, but shouldn't know the intricate details of, from another source. Using DI does not mean that NOTHING in your program should know how to create any other object; in fact, I posit that it is highly infeasible for a non-trivial program to avoid the "new" keyword (or reflection-based alternatives) entirely. However, DI does mean that objects that shouldn't HAVE to know how to create complex objects that require a lot of dependencies that will tightly couple this object to the other, shouldn't have all this tightly-coupling knowledge.

I would study the two major theories of O/O software design, GRASP and SOLID. GRASP will tell you to study the object's purpose, and ask yourself, "Should this object be responsible for creating new objects of this other type? Is that part of the 'job description' of this object?" SOLID goes one step further: The "S" stands for the "Single Responsibility Principle", which states unambiguously that an object should have one job, and it should be the only object in the program that does that specific job.

So, GRASP would generally encourage you to look through your existing classes for which creating these new objects, and find one for which the task of creating this object fits with what the object already does, while maintaining your desired level of "cohesion". SOLID will tell you that cohesion is key; the task of creating these objects should be given to some factory that should be injected into your class. I think you'll find, as the complexity of your program continues to grow, that adherence to either of these methodologies, with a willingness to refactor, will result in very similar architectures.

share|improve this answer
add comment

In my book, I provide the distinction between Stable and Volatile Dependencies. It's most important to use DI with Volatile Dependencies, but often you can achieve even looser coupling by also abstracting and injecting Stable Dependencies.

Keep in mind that the application of DI should not rely on a DI Container. In the case where Poor Man's DI is in use, no new keywords are removed - they are just moved to the Composition Root.

Some people actually prefer Poor Man's DI over DI Containers. The maintenance cost may be higher, but you get compile-time safety in return. As I recently heard Dan North say: "new is the new new" :)

What is meant by this is simply than instead of implementing the Composition Root with a DI Container, it'd just contain a whole bunch of nested new statements.

share|improve this answer
    
Mark, to expand a little on my Twitter comment, Programmers is the right place for conceptual, whiteboard-y questions that aren't dealing with a specific error in an implementation. –  Anna Lear Aug 18 '11 at 13:37
2  
Stack Overflow has 2000+ questions in the dependency-injection tag, and a lot of them are like this one. Programmers has 23 questions in the same tag. Based on these numbers, where should a developer go to have the biggest chance of getting an answer to a question like this? –  Mark Seemann Aug 18 '11 at 13:44
    
A lot of those questions predate Programmers entirely. This site was created to take conceptual questions off of SO and give them a dedicated home. And we're still growing. It's a work in progress, but ideally questions that don't involve specific implementation problems would get migrated here. We do what we can in the meantime. –  Anna Lear Aug 18 '11 at 13:59
add comment

"new" is not a forbidden keyword. My personal rules:

All "services" (I call a service a class designed to provide one or more methods related to one and only one thing ; for example: access the database, retrieve/update data related to a given domain) are registered in the IOC container. No class should have to make the decision on how to obtain the implementation of a given service it needs to use. Therefore, whenever you need to use an existing service, you should configure your class and the IOC container to provide it to you. Imagine that you are not aware how your implementation works, it could be a web service, you don't care.

All beans, or models are to be created with the "new" keyword or with an IOC-registered factory when I need them to have some default properties enabled. There is also the particular case of utility classes containing only static methods (for example: a mathematical utility service). If they are totally standalone and do not need any database connection or another IOC-registered service, I leave them out of the IOC and they are to be called statically. However, if one such class needs to use an existing IOC-registered service, I change it to a singleton class and register it in the IOC.

share|improve this answer
add comment

Clearly depends on the language you use. If your language forces you to use objects to represent both actual object and records (value object, structs), then the answer is most likely no.

Speaking purely of "real" objects, there is nothing wrong with creating an instance explicitly. What you must bare in mind however is, that all classes should follow the single responsibility principle. It should not be the responsibility of a class to choose the implementor of a service it relies on. However there are classes who's have that very responsibility, i.e. to provide implementors of certain services. An IoC might be such class. In fact any type of factory is such a class.

So to summarize: Only such classes should directly instantiate objects, who's responsibility it is to choose which classes to instantiate.
You might find these criteria helpful: http://en.wikipedia.org/wiki/GRASP_(object-oriented_design)#Creator

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.