Question

Is it ever good or bad to have a constructor create new instances of classes that it needs versus passing in a reference that you want the new class to have ?

So basically it's the difference between:

A classA = new A();
B classB = new B(classA);

and have class B constructor assigning classA to its field/property.

compared with:

B classB = new B();

and

public class B{
   A classA {private set; get;}
   //constructor
   public B(){
     classA = new A();
   }
}

Does the latter example violate single responsibility since its creating and assigning? Is this too much magic in that its doing stuff the programmer is not aware of? Should a constructor ever even do that?

Was it helpful?

Solution

I think it depends on what A is actually doing and which role it has in the lifetime of B. For example it is totally okay to create an instance of A in B's constructor if A is just an ArrayList or some other object encapsulating B's state.

On the other hand if the instance of A may have a lifecycle not governed by B or if you may want to change A's implementation (for example during tests) you should inject it via the constructor.

There are many resources on when to use dependency injection, for example this one. There are also existing StackOverflow questions like this one.

OTHER TIPS

Constructors routinely construct other objects. In some languages it is even unavoidable. For example, in C++ a constructor will construct all the member objects of a new object.

So it's per se neither good or bad. It depends on the semantics:

  • It's a bad practice that a constructor creates an object that is not owned by the constructed object. So if A is meant to survive B, the new B() is not a good option.
  • It's also a bad practice if the "sub-construction" would introduce an unwanted dependency (for example if the sub-object could be polymorphic and have different specialisations). In this case the dependency injection shall be preferred (providing either the object or a factory as parameter).
  • Finally, it's a terrible idea, if the sub-constructed object would require a reference to the constructed object (because you don't know what the created object will do with that reference to an object still not completely constructed).

The main problem with the second approach is that it is very hard to test.

If you write a test that verifies a specific behavior of ClassA it is always dependent on ClassB. If you create ClassB in the constructor of ClassA you have no control over it. If ClassA reads the property Foo of ClassB in order to do some conditional work, how do you check the different cases? You have no easy way to setup you test, i.e. set the Foo property to the value you need.

If you inject ClassB into the constructor of ClassA instead it suddenly gets a lot more simple. In your test you can now construct am instance of ClassB, specify a value for Foo, construct an instance of ClassA and verify the correct behavior. Test done. Repeat for other Foo values...

This pattern is called dependency injection and should be preferred over your other approach. Construction dependencies of a class directly in their constructors is an antipattern since it leads to side effects and makes testing way harder.

Licensed under: CC-BY-SA with attribution
scroll top