About use of specific error

Markus Gaelli gaelli at emergent.de
Fri Mar 17 15:42:12 UTC 2006


On Mar 17, 2006, at 3:49 PM, ncellier at ifrance.com wrote:

> Once you have put these exceptions at critical low levels, it is in  
> some cases (i do not say all cases) far more comfortable to squeeze  
> higher level precondition/postcondition tests and use exception  
> handling instead. This is where i am speaking of programming style.
>
> Lost of performance come not only from low level defense, but also  
> from testing several times the same assertion in the call chain.  
> Removing second half is not risky.

Ah...ok. Sure, I don't like checking the same stuff over and over again.
To quote myself from earlier in this thread:
>
> Example: I have a method to solve the quadratic equation f(x)=axx+bx+c
>
> Array >> #solveQuadraticEquation
> 	|a b c discriminant solutions |
> 	self precondition: [self size = 3 and: [self allSatisfy: [:each |  
> each isNumber]]].
> 	"Do I have to state here that the discriminant should be >= 0? I  
> do not think so."
> 	a:= self first.
> 	b:= self second.
> 	c:= self third.
> 	discriminant:=(b*b)-(4*a*c).
> 	solutions := Set new.
> 	solutions
> 		add:((0-b+discriminant sqrt)/(2*a));
> 		add:((0-b-discriminant sqrt)/(2*a)).
> 	^solutions
>
> If the discriminant<0 the precondition of sqrt should fail. I do  
> not want to state that here also as I am lazy and as I have not  
> computed the discriminant in the beginning.
>

Meanwhile I came to the conclusion that a better style for above  
method would certainly be to always return a collection of solutions,  
in the case of a negative discriminant the collection should just be  
empty.
So it better looked like:

Array >> #solveQuadraticEquation
	|a b c discriminant solutions |
	self precondition: [self size = 3 and: [self allSatisfy: [:each |  
each isNumber]]].
	a:= self first.
	b:= self second.
	c:= self third.
	discriminant:=(b*b)-(4*a*c).
	discriminant < 0 ifTrue: [^#()].
	solutions := Set new.
	solutions
		add:((0-b+discriminant sqrt)/(2*a));
		add:((0-b-discriminant sqrt)/(2*a)).
	self postcondition: [
		(solutions size between: 1 and: 2)  and: [
			solutions allSatisfy: [:each | ((a*each*each)+(b*each)+c) abs <=  
1.0e-10]]].
	^solutions

A typical case for a predictable situation which can be handled  
perfectly well without having to deal with any exceptions.

I still fail to see why I would have to introduce exception handling  
at a higher level due to not stating the same assertion over and over  
again:
I did not understand your NaN example, could you elaborate on that or  
send another example?

Note that I added a post condition, so here come a

PRICE QUESTION: (the person answering to this one last gets a beer  
(or bounty?) next time we meet personally... ;-)

Would test cases for that method still need to state the expected  
outcome?
Sth. along the line of

ArrayTest >> testSolveQuadaticEquation
	self assert: (#(1 -4 4) solveQuadraticEquation asArray = #(2.0))
	(...)

Or would it be sufficient to just provide examples a la:

ArrayTest >> testSolveQuadaticEquation
	#(1 -4 4) solveQuadraticEquation.
	(...)

as the postcondition here is already basically an inverse function,  
and "nothing" should go wrong....
Any opinions on that?

Cheers,

Markus





More information about the Squeak-dev mailing list