25

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 ?

CraigTP
  • 1,554
  • 1
  • 17
  • 17

6 Answers6

36

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.

Alex Beynenson
  • 476
  • 4
  • 3
  • 16
    +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 Molina 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
14

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 that instead of implementing the Composition Root with a DI Container, it'd just contain a whole bunch of nested new statements.

Pang
  • 313
  • 4
  • 7
Mark Seemann
  • 3,860
  • 23
  • 27
4

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.

Jack
  • 141
  • 2
  • +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
3

"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.

Jalayn
  • 9,789
  • 4
  • 39
  • 58
2

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.

KeithS
  • 21,994
  • 6
  • 52
  • 79
1

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

back2dos
  • 29,980
  • 3
  • 73
  • 114