2

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?

marked as duplicate by Doc Brown c# Sep 10 '18 at 1:56

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • So it wouldn't violate single responsibility? I understand its a judgement call, just curious if it counts as still respecting single responsibility. The collections instances is a good point too. – WDUK Sep 9 '18 at 3:19
  • In c#, you usually "instantiate a class" or "create an object" from a class but you don't "create a class" at run-time. Creating an object from constructor is valid since you may need the new object values as initial values in your new "object". – NoChance Sep 9 '18 at 3:30
  • Whats the difference between create a class and instantiate a class ? Not sure what create a class would mean in any other context? – WDUK Sep 9 '18 at 3:33
  • A class is the blue print of an object. It is a definition and as such it is "defined" or "created" at design time. At run-time, the class, which is the definition, can't be created or changed or deleted. However, you can use the class definition that has been compiled to generate objects from it (for example by using new keyword if it is not static). The example that is often used is "cookie cutter" for a class. – NoChance Sep 9 '18 at 3:37
9

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.

  • There are also exceptions for developer logic. For example, a class is allowed to create its own log (object and/or file) in its constructor, provided the log is exclusively internally used by this class. That's not bad design, the log is simply not a part of the application's intended flow. It's added information for the developer's sake. Note that when a given log is shared between multiple classes, this does not apply and the log should then be injected. – Flater Sep 10 '18 at 8:53
3

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).
1

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.

  • So the first approach is an example of dependency injection? Always thought it was more complicated than that lol – WDUK Sep 9 '18 at 5:42
  • 1
    It is. The name is harder than the actual idea behind it. You do yourself a big favor if you inject an interface IClassB into Class A instead of the real implementation. That way you even have the possibility of using a mock. Google it and read some blogs if you want to know more about it. :—) – selmaohneh Sep 9 '18 at 6:49

Not the answer you're looking for? Browse other questions tagged or ask your own question.