This morning, I found a very interesting article by Misko Hevery on the use of the "new" operator for object instantiation. In his article, Hevery lays out some guidelines that can help keep your code cohesive and easy to test.
First, he asserts that you should try to avoid calling the "new" operator as much as possible within your code. Every time you call the "new" operator, you make your code harder to test because you have object-creation logic encapsulated in such a way that your testing framework cannot easily manipulate it. When possible, the "new" operator should be deferred to some sort of Factory that can use a Dependency Injection (DI) framework.
That said, there are types of objects that the dependency injection framework simply can't know about. He refers to these objects as "Newables." For this blog post, I'll refer to them as "Value" objects. And, I'll refer to the other objects (the ones the DI framework can know about) as "Service" objects. These Value objects must be created inline using the "new" operator.
In this context, Hevery lays down the following guidelines:
- A Service object can ask for other Service objects in its constructor.
- A Service object can never ask for a Value object in its constructor. This is because the dependency injection (DI) framework will not know how to create the required Value object.
- A Value object can ask for other Value objects in its constructor.
- A Value object can never ask for a Service object in its constructor.
- A Value object can be passed a Service object as part of a method call; however, that Service object cannot be stored in the state of the Value object. In other words, the Value object cannot retain a reference to the Service object.
I don't know enough about Object Oriented Programming (OOP) to know whether or not these guidelines make complete sense. I can understand that removing dependencies will probably make your classes more cohesive as the potential for "responsibility" has been limited. There are probably situations where these guidelines must be broken; but, like the Object Calisthenics exercise, leaning on these guidelines for "advice" will probably have beneficial effect on how you think about your code.
If nothing else, running into a situation that violates these guidelines might just give you pause to ask the question, "Is there a cleaner way to wire this together?" And, the more we question our status-quo, the more likely we are to find better ways of doing things.