views:

2829

answers:

22

When is it right for a constructor to throw an exception? (Or in the case of Objective C: when is it right for an init'er to return nil?)

It seems to me that a constructor should fail -- and thus refuse to create an object -- if the object isn't complete. I.e., the constructor should have a contract with its caller to provide a functional and working object on which methods can be called meaningfully? Is that reasonable?

A: 

ctors aren't supposed to do any "smart" things so throwing an exception is not needed anyway. Use a Init() or Setup() method if you want to perform some more complicated object setup.

EricSchaefer
+1  A: 

Because of all the trouble that a partially created class can cause, I'd say never.

If you need to validate something during construction, make the constructor private and define a public static factory method. The method can throw if something is invalid. But if everything checks out, it calls the constructor, which is guaranteed not to throw.

Michael L Perry
I'd say the opposite is the case - if we don't want partially created objects, the constructor _should_ throw when there's a problem - that way the caller will know something went wrong.
Blair Conrad
A: 

It's always pretty dodgy, especially if you're allocating resources inside a constructor; depending on your language the destructor won't get called, so you need to manually cleanup. It depends on how when an object's lifetime begins in your language.

The only time I've really done it is when there's been a security problem somewhere that means the object should not, rather than cannot, be created.

blowdart
I have no idea why anyone rated this down... To me it seems like this is a pretty good thing to consider when throwing an exception in a constructor. I'm sure there is more than a few projects out there with memory leaks because the destructor wasn't called after throwing an exception.
Scott S.
+22  A: 

The constructor's job is to bring the object into a usable state. There are basically two schools of thought on this.

One group favors two-stage construction. The constructor merely brings the object into a sleeper state in which it refuses to do any work. There's an additional function that does the actual initialization.

I've never understood the reasoning behind this approach. I'm firmly in the group that supports one-stage construction, where the object is fully initialized and usable after construction.

One-stage constructors should throw if they fail to fully initialize the object. If the object cannot be initialized, it must not be allowed to exist, so the constructor must throw.

Sebastian Redl
Classes with one stage constructors can not easily be used in unit test by subclassing.
EricSchaefer
Two-stage construction is for environments where exceptions don't work properly or aren't implemented. MFC uses two-stage construction because when it was originally written, Visual C++ didn't have C++ exceptions working. Windows CE didn't get C++ exceptions until v4.0, and MFC 8.0.
Mike Dimmick
@EricSchaefer: For unit testing, I feel it is better to mock dependencies, rather then use subclassing.
sleske
+3  A: 

See C++ FAQ sections 17.2 and 17.4.

In general, I have found that code that is easier to port and maintain results if constructors are written so they do not fail, and code that can fail is placed in a separate method that returns an error code and leaves the object in an inert state.

moonshadow
+2  A: 

It's reasonable for a constructor to throw an exception so long as it cleans itself up properly. If you follow the RAII paradigm (Resource Acquisition Is Initialization) then it is quite common for a constructor to do meaningful work; a well-written constructor will in turn clean up after itself if it can't fully be initialized.

Matt Dillard
A: 

I think it's OK to throw an Exception in a constructor. Let's say you throw an ArgumentException.

artur02
+1  A: 

Yes, if the constructor fails to build one of its internal part, it can be - by choice - its responsibility to throw (and in certain language to declare) an explicit exception , duly noted in the constructor documentation.

This is not the only option: It could finish the constructor and build an object, but with a method 'isCoherent()' returning false, in order to be able to signal an incoherent state (that may be preferable in certain case, in order to avoid a brutal interruption of the execution workflow due to an exception)
Warning: as said by EricSchaefer in his comment, that can bring some complexity to the unit testing (a throw can increase the cyclomatic complexity of the function due to the condition that triggers it)

If it fails because of the caller (like a null argument provided by the caller, where the called constructor expects a non-null argument), the constructor will throw an unchecked runtime exception anyway.

VonC
+1  A: 

Throwing an exception during construction is a great way to make your code way more complex. Things that would seem simple suddenly become hard. For example, let's say you have a stack. How do you pop the stack and return the top value? Well, if the objects in the stack can throw in their constructors (constructing the temporary to return to the caller), you can't guarantee that you won't lose data (decrement stack pointer, construct return value using copy constructor of value in stack, which throws, and now have a stack that just lost an item)! This is why std::stack::pop does not return a value, and you have to call std::stack::top.

This problem is well described here, check Item 10, writing exception-safe code.

Don Neufeld
+2  A: 

You absolutely should throw an exception from a constructor if you're unable to create a valid object. This allows you to provide proper invariants in your class.

In practice, you may have to be very careful. Remember that in C++, the destructor will not be called, so if you throw after allocating your resources, you need to take great care to handle that properly!

This page has a thorough discussion of the situation in C++.

Luke Halliwell
A: 

Speaking strictly from a Java standpoint, any time you initialize a constructor with illegal values, it should throw an exception. That way it does not get constructed in a bad state.

scubabbl
A: 

To me it's a somewhat philosophical design decision.

It's very nice to have instances which are valid as long as they exist, from ctor time onwards. For many nontrivial cases this may require throwing exceptions from the ctor if a memory/resource allocation can't be made.

Some other approaches are the init() method which comes with some issues of its own. One of which is ensuring init() actually gets called.

A variant is using a lazy approach to automatically call init() the first time an accessor/mutator gets called, but that requires any potential caller to have to worry about the object being valid. (As opposed to the "it exists, hence it's valid philosophy").

I've seen various proposed design patterns to deal with this issue too. Such as being able to create an initial object via ctor, but having to call init() to get your hands on a contained, initialized object with accesors/mutators.

Each approach has its ups and downs; I have used all of these successfully. If you don't make ready-to-use objects from the instant they're created, then I recommend a heavy dose of asserts or exceptions to make sure users don't interact before init().

Addendum

I wrote from a C++ programmers perspective. I also assume you are properly using the RAII idiom to handle resources being released when exceptions are thrown.

nsanders
A: 

The usual contract in OO is that object methods do actually function.

So as a corrolary, to never return a zombie object form a constructor/init.

A zombie is not functional and may be missing internal components. Just a null-pointer exception waiting to happen.

I first made zombies in Objective C, many years ago.

Like all rules of thumb , there is an "exception".

It is entirely possible that a specific interface may have a contract that says that there exists a method "initialize" that is allowed to thron an exception. That an object inplementing this interface may not respond correctly to any calls except property setters until initialize has been called. I used this for device drivers in an OO operating system during the boot process, and it was workable.

In general, you don't want zombie objects. In languages like Smalltalk with become things get a little fizzy-buzzy, but overuse of become is bad style too. Become lets an object change into another object in-situ, so there is no need for envelope-wrapper(Advanced C++) or the strategy pattern(GOF).

Tim Williscroft
A: 

Perhaps the underlying question here is how do you communicate that the state of the newly created object is invalid. Various frameworks I have used have enforced data validation like this through exceptions, which I really don't like. I prefer that the state of the object either be communicated to client software through a property or method call, or an exception thrown when business operations are conducted on the object.

For example, consider instantiating an object with an invalid value (C#).

MyClass myClass = new MyClass(invalidValueOne, validValueTwo); //no exception
Console.Write(myClass.IsValid); //writes out "false"
myClass.DoSomeBusinessOperationWithValueOne(); //throws exception
Jason Jackson
+9  A: 

Eric Lippert says there are 4 kinds of exceptions.

  • Fatal exceptions are not your fault, you cannot prevent them, and you cannot sensibly clean up from them.
  • Boneheaded exceptions are your own darn fault, you could have prevented them and therefore they are bugs in your code.
  • Vexing exceptions are the result of unfortunate design decisions. Vexing exceptions are thrown in a completely non-exceptional circumstance, and therefore must be caught and handled all the time.
  • And finally, exogenous exceptions appear to be somewhat like vexing exceptions except that they are not the result of unfortunate design choices. Rather, they are the result of untidy external realities impinging upon your beautiful, crisp program logic.

Your constructor should never throw a fatal exception on its own, but code it executes may cause a fatal exception. Something like "out of memory" isn't something you can control, but if it occurs in a constructor, hey, it happens.

Boneheaded exceptions should never occur in any of your code, so they're right out.

Vexing exceptions (the example is Int32.Parse()) shouldn't be thrown by constructors, because they don't have non-exceptional circumstances.

Finally, exogenous exceptions should be avoided, but if you're doing something in your constructor that depends on external circumstances (like the network or filesystem), it would be appropriate to throw an exception.

Jacob
So where does Argument[Null]Exception lie in this scheme? Is it a boneheaded exception, and so shouldn't be thrown? Or is it a fatal exception and is therefore ok to be thrown?
alastairs
I realize now that I didn't include a link to the original article, http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspxThings like ArgumentException/ArgumentNullException are boneheaded: just plain bugs in the calling code. He says "Fix your code so that it never triggers a boneheaded exception – an 'index out of range' exception should never happen in production code."
Jacob
@alastairs: You should definitely *throw* ArgumentExceptions, because the only alternative is to pretend that the arguments are valid when they're not. (Leading to NullReferenceExceptions, or possibly much worse things.) But like Jacob says, you should **never** catch them.
Joren
A: 

I can't address best practice in Objective-C, but in C++ it's fine for a constructor to throw an exception. Especially as there's no other way to ensure that an exceptional condition encountered at construction is reported without resorting to invoking an isOK() method.

The function try block feature was designed specifically to support failures in constructor memberwise initialization (though it may be used for regular functions also). It's the only way to modify or enrich the exception information which will be thrown. But because of its original design purpose (use in constructors) it doesn't permit the exception to be swallowed by an empty catch() clause.

mlbrock
+2  A: 

A constructor should throw an exception when it is unable to complete the construction of said object.

For example, if the constructor is supposed to allocate 1024 KB of ram, and it fails to do so, it should throw an exception, this way the caller of the constructor knows that the object is not ready to be used and there is an error somewhere that needs to be fixed.

Objects that are half-initialised and half-dead just cause problems and issues, as there really is no way for the caller to know. I'd rather have my constructor throw an error when things go wrong, than having to rely on the programming to run a call to the isOK() function which returns true or false.

Denice
A: 

Throw an exception if you're unable to initialize the object in the constructor, one example are illegal arguments.

As a general rule of thumb an exception should always be thrown as soon as possible, as it makes debugging easier when the source of the problem is closer to the method signaling something is wrong.

DeletedAccount
A: 

I'm just learning Objective C, so I can't really speak from experience, but I did read about this in apple's docs.

http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/chapter_3_section_6.html

Not only will it tell you how to handle the question you asked, but it does a good job of explaining it as well.

Scott S.
+6  A: 

There is generally nothing to be gained by divorcing object initialization from construction. RAII is correct, a successful call to the constructor should either result in a fully initialized live object or it should fail, and ALL failures at any point in any code path should always throw an exception. You gain nothing by use of a separate init() method except additional complexity at some level. The ctor contract should be either it returns a functional valid object or it cleans up after itself and throws.

Consider, if you implement a separate init method, you still have to call it. It will still have the potential to throw exceptions, they still have to be handled and they virtually always have to be called immediately after the constructor anyway, except now you have 4 possible object states instead of 2 (IE, constructed, initialized, uninitialized, and failed vs just valid and non-existent).

In any case I've run across in 25 years of OO development cases where it seems like a separate init method would 'solve some problem' are design flaws. If you don't need an object NOW then you shouldn't be constructing it now, and if you do need it now then you need it initialized. KISS should always be the principle followed, along with the simple concept that the behavior, state, and API of any interface should reflect WHAT the object does, not HOW it does it, client code should not even be aware that the object has any kind of internal state that requires initialization, thus the init after pattern violates this principle.

A: 

Using factories or factory methods for all object creation, you can avoid invalid objects without throwing exceptions from constructors. The creation method should return the requested object if it's able to create one, or null if it's not. You lose a little bit of flexibility in handling construction errors in the user of a class, because returning null doesn't tell you what went wrong in the object creation. But it also avoids adding the complexity of multiple exception handlers every time you request an object, and the risk of catching exceptions you shouldn't handle.

Tegan Mulholland
+1  A: 

If you are writing UI-Controls (ASPX, WinForms, WPF, ...) you should avoid throwing exceptions in the constructor because the designer (Visual Studio) can't handle them when it creates your controls. Know your control-lifecycle (control events) and use lazy initialization wherever possible.

iik