No “new”s is good news

"New" is the new "goto". As mock object testing frameworks and inversion of control containers are becoming more commonplace, we are encouraged to avoid having objects directly create other objects.

Why is "new" a bad word?
When a line of code includes the "new" keyword, it must also include the name of a concrete class. This line of code will appear within a different class (unless you are writing a singleton, in which case you have even bigger problems). You have just created a compile-time dependency between two classes.

The dependency inversion principle states that we should depend upon abstractions (i.e. interfaces and abstract base classes), rather than concrete classes. The "new" keyword immediately violates this principle because it forces us to depend upon a concrete class. The name after the "new" cannot be an interface or abstract base class, but a concrete packet of implementation.

Without dependency inversion, it is difficult or impossible to change units of behavior. If a class uses "new" to get access to a service component, you must change that code to replace it with a different service. If the change is a design-time decision, then recompiling the code just means more testing is required. But if the change is a run-time decision, then recompiling the code is not an option.

Without dependency inversion, it is difficult or impossible to mock objects for testing. If the code that you are testing is invoking "new", then the mock framework cannot intercept that and replace it with a test harness. The dummy object is there to observe the calls that leak out of the object that you are testing, and make sure that they are the ones that the test expects to induce. If those calls go into a concrete class, then the scope of the test is bigger than intended, and visibility is lost.

Building blocks
I once had a manager who compared good software component design to Legos. A complete solution can be built from interchangeable pieces. If you are using "new", your components are more like a puzzle pieces than building blocks. You create a solution out of pieces, but those pieces fit together in only one way.

As a rule of thumb, critically examine every "new" in your software. See if you can find a way to push it up through dependency injection. If you can, push it all the way out of your code and into an IoC container. The fewer "new"s, the better.

Leave a Reply

You must be logged in to post a comment.