Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What things are best not done in a constructor?

I started off by drafting a question: "What is the best way to perform unit testing on a constructor (e.g., __construct() in PHP5)", but when reading through the related questions, I saw several comments that seemed to suggest that setting member variables or performing any complicated operations in the constructor are no-nos.

The constructor for the class in question here takes a param, performs some operations on it (making sure it passes a sniff test, and transforming it if necessary), and then stashes it away in a member variable.

I thought the benefits of doing it this way were:

1) that client code would always be certain to have a value for this member variable whenever an object of this class is instantiated, and

2) it saves a step in client code (one of which could conceivably be missed), e.g.,

$Thing = new Thing;
$Thing->initialize($var);

when we could just do this

$Thing = new Thing($var);

and be done with it.

Is this a no-no? If so why?

like image 467
PartialOrder Avatar asked Feb 07 '09 21:02

PartialOrder


2 Answers

My rule of thumb is that an object should be ready for use after the constructor has finished. But there are often a number of options that can be tweaked afterwards.

My list of do's and donts:

  • Constructors should set up basic options for the object.
  • They should maybe create instances of helper objects.
  • They should not aqquire resources(files, sockets, ...), unless the object clearly is a wrapper around some resource.

Of course, no rules without exceptions. The important thing is that you think about your design and your choises. Make object usage natural - and that includes error reporting.

like image 144
gnud Avatar answered Oct 03 '22 05:10

gnud


This comes up quite a lot in C++ discussions, and the general conclusion I've come to there has been this:

If an object does not acquire any external resources, members must be initialized in the constructor. This involves doing all work in the constructor.

  • (x, y) coordinate (or really any other structure that's just a glorified tuple)
  • US state abbreviation lookup table

If an object acquires resources that it can control, they may be allocated in the constructor:

  • open file descriptor
  • allocated memory
  • handle/pointer into an external library

If the object acquires resources that it can't entirely control, they must be allocated outside of the constructor:

  • TCP connection
  • DB connection
  • weak reference

There are always exceptions, but this covers most cases.

like image 24
Tom Avatar answered Oct 03 '22 05:10

Tom