Rewind! (was Re: Back to the issue... (was RE: Squeak coding style...))

Markus Gaelli gaelli at emergent.de
Mon Mar 8 15:45:12 UTC 2004


Hi Göran,

> Now, *forget* my ideas. I want to hear creative good ideas from you! 
> How
> do we improve the quality of the standard packages? Think broad now,
> don't only think about code conventions or class comments.
>
> I know for example Steph will rightly so push unit tests :) but before
> you do that Steph - don't just say "We should all write tests!" :) Try
> to come up with some idea, mechanism, tool or proposal that actually
> would have a chance of *moving us* in that direction.

One little thing which could have great impact on the quality of the 
code, would
be to use the little Object>>assert: mechanism, which is there since 
long time,
waiting to be used in all kinds of pre- and postconditions and 
invariants.

I did a little counting and while we have more than 1000 unit tests 
(great) in the image
right now we have only 23 (!) occurrences of assert: sent somewhere 
outside a unit test.
Romain Robbes digged out an assert: mechanism of Vassili Bykov
http://www.smalltalkchronicles.net/edition2-1/st_compiler.htm
which won't do any time penalty if switched off. Romain will introduce 
that soon
(sorry Romain, hope I did not spoil too much here ;-)

Enhancing the current implementation
Object >> assert: aBlock
	"Throw an assertion error if aBlock does not evaluates to true."

	aBlock value ifFalse: [AssertionFailure signal: 'Assertion failed']

with something like

assert: aBlock
	"Throw an assertion error if aBlock does not evaluates to true."
	(UseAssertions ifFalse: [^self].
	aBlock value ifFalse: [AssertionFailure signal: 'Assertion failed']

would not take too much time from our programs also, if one set 
UseAssertions to false.

In my experience from industry, to have invariants, pre- and 
postconditions can be really
powerful. Enhancing some classes which have strong invariants can 
really be an interesting
challenge... :-)

A concrete "Todo" would be to move as many assertions of our 1000 unit 
tests into the
code as possible. It's interesting what you can abstract here. The 
trick is, to _keep_ the tests,
though they don't have any assertions inside them, as long as their 
directly tested methods have
some assertions, they are still tests.
And suddenly one test might not only test one but several assertions. 
And our assertions are called
in somehow unexpected circumstances. And they document the code.

An example where one might want to move an already abstract assertion 
from the test in the
code could be

Random >> next
	"Answer a random Float in the interval [0 to 1)."
	^ (seed _ self nextValue) / m

One could replace the comment with some active code from

RandomTest >> testNext
	10000 timesRepeat: [
			| next |
			next := gen next.
			self assert: (next >= 0).
			self assert: (next < 1)].

and end up with:

Random >> next
	|aResult|
	aResult:=	(seed _ self nextValue) / m.
	self assert: [aResult >= 0].
	self assert: [aResult < 1].
	^aResult

and

RandomTest >> testNext
	10000 timesRepeat: [gen next]

Cheers,

Markus



More information about the Squeak-dev mailing list