Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why not "instantiate a new object inside object constructor"?

Tags:

I answered a question (link) that I used a creation of the new object in another class' constructor, here the example:

class Person {   public $mother_language;    function __construct(){ // just to initialize $mother_language     $this->mother_language = new Language('English'); } 

And I got the comment from user "Matija" (his profile) and he wrote: You should never instantiate a new object inside object consturctor, dependencies should be pushed from outside, so anyone who uses this class knows what is this class dependent on!

Generally, I can agree with this, and I understand his point of view.

However, I used to do this this way very often, for example:

  • as the private properties other classes give me functionality that I can solve not duplicating the code, for example I can create a list (class implementing ArrayAccess interface) of objects), and this class would be used in another class, that has such a list of objects,
  • some classes use for example DateTime objects,
  • if I include (or autoload) dependant class, one should have no problem with errors,
  • because dependant objects can be very large number, passing all of them to the class constructor can be very long and not clear, example

    $color = new TColor('red'); // do we really need these lines? $vin_number = new TVinNumber('xxx'); $production_date = new TDate(...); ... $my_car = new TCar($color, $vin_number, $production_date, ...............); 
  • as I was "born" in Pascal, then in Delphi, I have some habits from there. And in Delphi (and FreePascal as its competitor) this practice is very often. For example, there is a TStrings class that handles array of strings, and to store them it does not use arrays but another class, TList, that provides some useful methods, while TStrings is only some kind of interface. The TList object is private declared and has no access from outside but the getters and setters of the TStrings.

  • (not important, but some reason) usually I am the one who uses my classes.

Please explain me, is it really important to avoid creating objects in constructors?

I've read this discussion but have still unclear mind.

like image 634
Voitcus Avatar asked Apr 09 '13 12:04

Voitcus


1 Answers

Yes it really is. You are then clear about what the object needs in order to be constructed. A large number of dependent objects being passed in is a code smell that perhaps your class is doing too much and should be broken in up in multiple smaller classes.

The main advantage of passing in dependent objects comes if you want to test your code. In your example, I cannot use a fake Language class. I have to use the actual class to test Person. I now cannot control how Language behaves to make sure that Person works correctly.

This post helps explain why this is a bad thing and the potential problems that it causes. http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/

UPDATE

Testing aside, passing in dependent objects also makes your code more explicit, flexible and extensible. To quote the blog post that I linked to:

When collaborator construction is mixed with initialization, it suggests that there is only one way to configure the class, which closes off reuse opportunities that might otherwise be available.

In your example, you can only create people that have "English" as a language. But what about when you are wanting to create someone who speaks "French". I can't define that.

As for creating the objects and passing them in, that is the whole purpose of the Factory pattern http://www.oodesign.com/factory-pattern.html. It would create the dependencies and inject them for you. So you would be able to ask it for the object that would be initialized in the manner that you want. The Person object should not have to decide what it needs to be.

like image 194
Schleis Avatar answered Sep 20 '22 13:09

Schleis