Google's Go & Exceptions

Justin Johansson no at spam.com
Tue Jan 26 16:07:37 PST 2010


dsimcha wrote:
> == Quote from Walter Bright (newshound1 at digitalmars.com)'s article
>> Justin Johansson wrote:
>>> (1) For some reason (possibly valid only in an historic context), I have
>>> this great aversion to throwing exceptions from inside C++ constructors.
>>>  From memory, I once threw an exception from inside a constructor
>>> with an early C++ compiler and wound up with stack corruption or
>>> something like that, and consequently I developed the practice of
>>> forever more avoiding throwing from inside a C++ constructor.
>> I'm a believer in the methodology that a constructor should be "trivial"
>> in that it cannot fail (i.e. cannot throw). I'm probably in the minority
>> with that view, but you shouldn't feel like you're doing the wrong thing
>> when you stick to such a style.
> 
> I've never understood the recommendation not to put complex logic in the
> constructor.  If you need complex logic to establish the class's invariant, or
> need to initialize complicated immutable data structures, where else is that logic
> supposed to go?

I do (especially when working with immutable value classes).  A good
use of OO classes is to bind/glue/cement a few pieces of your
programming task jigsaw puzzle together.  This you do with a
constructor meaning that once you have a few pieces of the puzzle
nutted out (and prevalidated), you use a constructor to associate
the pieces together under the umbrella of a single object which
can be thought of as a tuple of values or a row in a table.

It would be unusual in relational DB terms to create a new row in
a table and validate the columns after the event.  Forms are filled
out, fields validate and only when all's good does one commit that
to a database (by creating a new row in a table).  The same
philosophy holds in an OO programming language.

At best, it's a hint of code that could be better refactored,
and, at worse, it's a sure sign of a bad design to check any
of the following after the event (that's is after deciding to
create a new instance of a class, tuple or row as the case may
be):

   (1) parameters passed to a constructor inside constructor
   (2) individual values in a constructed tuple
   (3) columns in the row of a DB table
   (4) attribute values of an object inside constructor

This argument is programming language agnostic, and leans
on the acknowledged benefits of immutable structures and
functional programming.

Furthermore, and I think this is the most compelling point
for not throwing exceptions in constructors is when a class
is declared with const members.

When declaring such a class, the const members of the class
need to be assigned up front from the arguments passed to the
constructor.  This means that there would not be any
opportunity to throw an exception anyway until execution
enters the body of the constructor code.  In C++ it's done
like this (and surely in D it's similar .. I forget not having
D for six months) ...

class Foo
{
public:
   Bar const bar;	// const means need to write
                         // : bar( aBar) after constructor
                         // argument list.
                         // cannot write bar = aBar in ctor body


   Foo( Bar aBar)
   :  bar( aBar)
   {
      // Do "complex logic" here and
      // check Bar value now for validity (after
      // it's already been assigned to member)
      // and throw an exception now if it's no
      // good the devil asks?
   }

}

Cheers
Justin Johansson












More information about the Digitalmars-d mailing list