On Aug 20, 2009, at 14:49, Gary Wright wrote:
> I would argue that this is also the wrong approach because it
> confuses responsibilities.  To use programming by contract  
> terminology,
> the requirement that the actual arguments to calculate_bounding_box
> be numeric (or more specifically that they respond to ceil) is a
> pre-condition and pre-conditions should be guaranteed by the caller,
> not the callee.

If you're writing calculate_bounding_box() as a bit of library code  
that will be used by other programmers, it is nice to provide helpful  
error messages.

Someone using the method calculate_bounding_box() has no way of  
knowing that you're calling "ceil" internally, so getting an error  
back saying "NoMethodError: undefined method `ceil' for "2343":String"  
will be confusing.

If you are nice enough to catch that error and throw a more useful  
error: "ArgumentError: width and height must be numeric" it will make  
debugging much easier.

This doesn't mean it's not the responsibility of the caller to make  
sure it provides proper arguments, it just means that in the event the  
caller doesn't, you get clearer error messages.

> Also, the example as written doesn't really solve the problem since
> the caller will have to deal with ArgumentError instead of
> NoMethodError.

That depends on what you mean by "solve the problem".  If the problem  
is "my program isn't working", solving the problem will involve  
looking at the traceback and figuring out what went wrong.  In which  
case "ArgumentError: width and height must be numeric" is more helpful  
than "NoMethodError: undefined method `ceil'..."

> In either case it indicates that the *caller* is
> shirking its duty to guarantee the pre-conditions.  Adding code in
> the caller to guarantee numeric arguments is probably clearer than
> arranging to respond to NoMethodError or ArgumentError.

There's no reason not to do both.  Clearly, whatever calls  
calculate_bounding_box() should make sure the parameters it supplies  
are what the method expects, but there's no reason  
calculate_bounding_box() can't anticipate a common exception, catch it  
then raise a more accurate and more helpful exception of its own.

Ben