About KCP and automatic initialize

Richard A. O'Keefe ok at cs.otago.ac.nz
Mon Sep 15 06:01:34 UTC 2003


Richard Staehli <rastaehli at mac.com> wrote:

	Pattern 1:  Canonical Initializer
	
	Problem:  How to establish a single method for an object that 
	initializes to a well defined state.  Users with minimal training 
	should be able to discover this method and use it reliably to 
	initialize the object.
	
	Solution:  Require that every object have a method named with the 
	prefix 'initCanonical' and taking a set of arguments that completely 
	define the state of the object.  If the object inherits state from a 
	superclass, the 'initCanonical' method is responsible for initializing 
	this state and this is easily accomplished by calling the superclass' 
	canonical initializer.
	
This invites the obvious questions:
(1) Why SHOULD a method have a single "best" initialisation method?

    For example, suppose one has

	File openForInput: aFileName
	File openForReplacement: aFileName
	File openForAppending: aFileName

    There might in fact *be* a common method,

	File pvtOpen: aFileName method: rwa    
	
    which they all share, but you might have excellent reason to keep
    that method private.  (Not least so you don't have to worry about
    unexpected values for the rwa argument.)

    One of the big differences between Smalltalk and Simula 67 was that
    in Simula 67 a class was basically a procedure that returned its
    (heap-allocated) activation record, so there _could_ only be one
    constructor for a class, whereas Smalltalk lifted this restriction.

(2) I don't like the sound of "users with minimal training".

(3) If there _is_ a preferred instance creation method, even users with
    minimal training *ought* to be able to find it in the class comment,
    no?  Isn't insisting that class comments be filled out even better
    than insisting on twisted method names?

    Really, anyone who can't look for 'instance creation' in the browser
    and maybe read one or two method comments is so minimally trained that
    they shouldn't be using Squeak yet.  One hour of instruction should
    fix that.  If there _aren't_ any method comments, _nothing_ is going
    to help; there isn't any guarantee that the default method is the
    right one and there never can be.

(4) "initCanonical" violates several good naming practices.  Why is
    "init" abbreviated by not "Canonical"?  Why not just say that it
    should begin with "initialize"?  Even then, "init" isn't _quite_
    intention-revealing.  The important thing to do is to establish the
    class invariant, and that may involve updating other objects entirely,
    and it might _not_ involve initialising any instance variables at all.

(5) The "initialize" method will normally be of no interest to clients
    at all; they will be interested in some flavour of "new".

(6) Just because an object inherits state from a parent class, it does
    NOT follow that the right way that shared state is to use the parent's
    initialiser.  Often it is, often it isn't.  The way Java forces me to
    do this is one of the things I dislike about Java, and the way Eiffel
    *doesn't* is one of the things I like about Eiffel.

	Pattern 2:  Convenience Method
	
	Problem:  Commonly repeated sequences of code increase the chance of 
	error and obscure more important aspects.
	
	Solution:  Define a method that aggregates the repeated sequence into a 
	single message send.  For example, if a canonical initializer is 
	frequently called with the same value for many of its arguments, 
	replace these calls with a call to a convenience method that 
	encapsulates these invariant values.  The invocation of the convenience 
	method is syntactically shorter because it takes only the arguments 
	that vary.
	
This is just factoring.
	
	Pattern 3:  Default Constructor
	
	Problem:  Users frequently need to obtain new objects with well
	defined state, but cannot be expected to understand how to reliably
	initialize that state.
	
WHAAAAAAAAAT?

If "users" cannot "cannot be expected to understand how to reliably
initialise" an object, then they cannot be expected to understand
how to do ANYTHING with an object.

	Solution:  Require every class to have a method named
	'defaultNew' that takes no arguments, but that creates a basic
	new instance and calls the canonical initializer for the object
	with default arguments.
	
I have recently explained at some length why this is HIGHLY UNDESIRABLE,
leading to poor design, or the exposure of incompletely initialised
objects, or both.
	
My whole contribution to this thread is a protest against this
absurd and dangerous idea that there *ought* to be a default parameterless
way of initialising every kind of object and a plea that indulging in such
a dangerous practice should be made *harder*, not easier.

To repeat an example I've used before, there is *NO* set of default
arguments which could make "Point new" reasonable.

To put it in pattern terms:

    "No #'new's is good news"

    Problem:
	For many classes a parameterless #new (and correspondingly
	a parameterless #initialize) makes no sense.  The automatic
	inheritance of Object>>new, and the recent proposal to make
	that automatically invoke #initialize, make it far too easy
	for people to create incompletely initialised objects and
	encourage bad design.

    Solution:
	Change the browser so that when you create a new class
	the class method "new   self shouldNotImplement" with a
	suitable comment is automatically added, requiring explicit
	programmer action to *remove* this protection.

Finally:

	It would seem to be a good idea to agree on  a "canonical initializer" 
	prefix and "default constructor" name for squeak.

We *have* a default constructor name for Squeak, it's #new, and we had
better live with it rather than try to invent something different.

The problem is not the *name* of the method, but it's very *existence*.
Adopting the "No #'new's is good news" pattern would fix the problem.

	



More information about the Squeak-dev mailing list