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.

I watched a Google Tech Talk presentation on Unit Testing, given by Misko Hevery, and he said to avoid using the new keyword in business logic code.

I wrote a program, and I did end up using the new keyword here and there, but they were mostly for instantiating objects that hold data (ie, they didn't have any functions or methods).

I'm wondering, did I do something wrong when I used the new keyword for my program. And where can we break that 'rule'?

share|improve this question
2  
Can you add a tag related with the programming language? New exists in many languages (C++, Java, Ruby to name a few) and has different semantics. –  faif Dec 11 '12 at 17:25
add comment

5 Answers

up vote 12 down vote accepted

This is more guidance than hard-and-fast rule.

By using "new" in your production code, you are coupling your class with its collaborators. If someone wants to use some other collaborator, for example some kind of mock collaborator for unit testing, they can't – because the collaborator is created in your business logic.

Of course, someone needs to create these new objects, but this is often best left to one of two places: a dependency injection framework like Spring, or else in whichever class is instantiating your business logic class, injected through the constructor.

Of course, you can take this too far. If you want to return a new ArrayList, then you are probably OK – especially if this is going to be an immutable List.

The main question you should be asking yourself is "is the main responsibility of this bit of code to create objects of this type, or is this just an implementation detail I could reasonably move somewhere else?"

share|improve this answer
1  
Well if you want it to be an immutable list, you should use Collections.unmodifiableList or something. But I know what you mean :) –  MatrixFrog Oct 24 '11 at 21:37
    
Yes, but you need somehow to create the original list which you then convert to being unmodifiable... –  Bill Michell Nov 3 '11 at 9:49
add comment

Objects that only hold data, or DTOs (data transfer objects) are fine, create those all day long. Where you want to avoid new is on classes that perform actions, you want the consuming classes to instead program against the interface, where they can invoke that logic and consume it, but not be responsible for actually creating the instances of the classes that contain the logic. Those action-performing or logic containing classes are dependencies. Misko's talk is geared towards you injecting those dependencies and letting some other entity be responsible for actually creating them.

share|improve this answer
add comment

The crux of this question is at the end: I'm wondering, did I do something wrong when I used the new keyword for my program. And where can we break that 'rule'?

If you are able to write effective unit tests for your code, then you did nothing wrong. If your use of new made it difficult or impossible to unit test your code, then you should re-evaluate your use of new. You could extend this analysis to interaction with other classes, but the ability to write solid unit tests is often a good enough proxy.

share|improve this answer
add comment

Others have already mentioned this point, but wanted to quote this from Uncle Bob's (Bob Martin) Clean Code because it might make it easier to understand the concept:

"A powerful mechanism for separating construction from use is Dependency Injection (DI), the application of Inversion of Control (IoC) to dependency management. Inversion of Control moves secondary responsibilities from an object to other objects that are dedicated to the purpose, thereby supporting the Single Responsibility Principle. In the context of dependency management, an object should not take responsibility for instantiating dependencies itself. Instead, it should pass this responsibility to another "authoritative" mechanism, thereby inverting the control. Because setup is a global concern, this authoritative mechanism will usually be either the "main" routine or a special-purpose container."

I think it is always a good idea to follow this rule. Others mentioned the more important one IMO -> it decouples your class from its dependencies (collaborators). Second reason is that it makes your classes smaller and terser, easier to understand and even reuse in other contexts.

share|improve this answer
add comment

In short, whenever you use "new", you are tightly coupling the class containing this code to the object being created; in order to instantiate one of these objects, the class doing the instantiating must know about the concrete class being instantiated. So, when using "new", you should consider whether the class in which you're placing the instantiation is a "good" place for that knowledge to reside, and you're willing to make changes in this area if the form of the object being instantiated were to change.

Tight coupling, that is an object having knowledge of another concrete class, is not always to be avoided; at some level, something, SOMEWHERE, has to know how to create this object, even if everything else deals with the object by being given a copy of it from somewhere else. However, when the class being created changes, any class that knows about the concrete implementation of that class must be updated to correctly deal with that class's changes.

The question that you should always ask is, "Will having this class know how to create this other class become a liability when maintaining the app?" Both major design methodologies (SOLID and GRASP) would usually answer "yes", for subtly different reasons. However, they are only methodologies, and both have the extreme limitation that they were not formulated based on knowledge of your unique program. As such, they can only err on the side of caution, and assume that any point of tight coupling will EVENTUALLY cause you a problem relating to making changes to either or both sides of this point. You must make a final decision knowing three things; the theoretical best practice (which is to loosely-couple everything because anything can change); the cost of implementing the theoretical best-practice (which may include several new layers of abstraction that will ease one type of change while hindering another); and the real-world probability that the type of change you are anticipating will ever be necessary.

Some general guidelines:

  • Avoid tight coupling between compiled code libraries. The interface between DLLs (or an EXE and its DLLs) is the main place where tight coupling will present a disadvantage. If you make a change to a class A in DLL X, and class B in the main EXE knows about class A, you have to recompile and release both binaries. Within a single binary, tighter coupling is generally more permissible because the entire binary must be rebuilt for any change anyway. Sometimes, having to rebuild multiple binaries is unavoidable, but you should structure your code so that you can avoid it where possible, especially for situations where bandwidth is at a premium (like deploying mobile apps; pushing a new DLL in an upgrade is far cheaper than pushing the entire program).

  • Avoid tight coupling between the major "logic centers" of your program. You can think of a well-structured program as consisting of horizontal and vertical slices. Horizontal slices may be traditional application tiers, like UI, Controller, Domain, DAO, Data; vertical slices might be defined for individual windows or views, or for individual "user stories" (like creating a new record of some basic type). When making a call that moves up, down, left or right in a well-structured system, you should generally abstract said call. For example, when validation needs to retrieve data, it should not have access to the DB directly but should make a call to an interface for data retrieval, which is backed by the actual object that knows how to do this. When some UI control needs to perform advanced logic involving another window, it should abstract the triggering of this logic via an event and/or callback; it doesn't have to know what will be done as a result, allowing you to change what will be done without changing the control that triggers it.

  • In any case, consider how easy or difficult a change will be to make, and how likely said change will be. If an object you are creating is only ever used from one place, and you do not foresee that changing, then tight coupling is generally more permissible, and may even be superior in this situation to loose coupling. Loose coupling requires abstraction, which is an extra layer that prevents change to dependent objects when the implementation of a dependency must change. However, if the interface itself must change (adding a new method call, or adding a parameter to an existing method call), then an interface actually increases the amount of work necessary to make the change. You have to weigh the likelihood of different types of change impacting the design, and it will be infeasible or even impossible to make a system that is closed to all types of change.

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.