[comp.lang.smalltalk] Access methods - New feature ?

brian@vuse.vanderbilt.edu (Brian Antao) (04/22/91)

Hi,
	Having been a moderately heavy user of Smalltalk-80 (ParcPlace sys,
Objectworks), I had a suggestion that may be fairly easy to implement and
would save some programming effort. Often one needs to define access methods
with each Class definition, these methods simply return the current value of
an instance variable. The suggested feature would be, that the compiler/
interpreter, by default inserts these methods corresponding to each instance
variable specified in the Class definition. Each time the Class definition is
recompiled, the appropriate access methods should be added/deleted if any
instance variables are added/deleted. One could also argue for a similar
feature to also support class variable access. 
I vaguely remember that some of the earlier Smalltalk-80 versions, 1.xx or
2.2 that did something on the lines of the above functionality.
Do other smalltalk-80 users feel positively about this ?
	 

ParcPlace Objectworks developers:  would you take up on this ?? or is this
feature available as an addOn like the BOSS, with the ObjectKit ?



 


-- 
-------------------------------------------------------------------------------
Brian Antao,                               |FAX: 615-343-6449
Vanderbilt University,                     |INET: brian@vuse.vanderbilt.edu
Department of Electrical Engg.,            |UUCP: ...!uunet!vuse!brian

dawg6844@uxa.cso.uiuc.edu (Race Bannon) (04/22/91)

brian@vuse.vanderbilt.edu (Brian Antao) writes:
>an instance variable. The suggested feature would be, that the compiler/
>interpreter, by default inserts these methods corresponding to each instance
>variable specified in the Class definition. Each time the Class definition is
>recompiled, the appropriate access methods should be added/deleted if any
>instance variables are added/deleted. One could also argue for a similar
>feature to also support class variable access. 

This would not be difficult to add, just aesthetically unpleasant.  Why?
One of the primary ideas behind 'objects' is the encapsulation of data with
the code that manipulates it.  Why is this good?  If used properly, it 
minimizes the 'side-effects' that can occur with other programming paradigms.
In SmallTalk, no object can manipulate another's state unless you 
'do it on purpose',  by constructing the access methods to do so.
If access methods were automatically generated for every private variable, 
then this breaks down; every object can diddle with the state of every other.
Yes, frequently you need to write several access methods for several private
variables of an object, but if you are finding that you need to make ALL of
your instance variables public, then perhaps you need to rethink your design.
--
_______________________________________________________________________________
Dan Walkowski                          | To understand recursion, 
Univ. of Illinois, Dept. of Comp. Sci. |   you must first understand recursion.
walkowsk@cs.uiuc.edu                   |

pkr@media03.UUCP (Peter Kriens) (04/22/91)

Dan Walkowski writes:
> If access methods were automatically generated for every private variable,
> then this breaks down; every object can diddle with the state of every other.
> Yes, frequently you need to write several access methods for several private
> variables of an object, but if you are finding that you need to make ALL of
> your instance variables public, then perhaps you need to rethink your design.

I basically agree with this statement, but I have found that it is much more
tru in technical software then information technology. The last moths{ I have
been trying several times to build a program that uses a SQL database as
backend and a smalltalk front end. The problem is that in those environments
you basically need access to most instance variables.(the origininal database
fields). 

Eiffel has a very nice solution for this. It allows an instance variable
to be exported in the header (Smalltalk could also do that in the
class definition, you could for example place a colon behinde the 
definition of the instance variable). So in Eiffel you can easely access those often
used instance variables. The good thing is that if you decide later on
to replace the instance access with a procedure, because the implementation
changes, nobody notices because the syntax stays the same. Sounds like
a feature I could love in Smalltalk. Unfortunately you cannot access the
compiler in Digitalk smalltalk, otherwise it could be done.

Peter Kriens
pkr@media01

voss@cs.uiuc.edu (Bill Voss) (04/22/91)

In article <1991Apr21.221149.8057@vuse.vanderbilt.edu> brian@vuse.vanderbilt.edu (Brian Antao) writes:

>  Often one needs to define access methods
>  with each Class definition, these methods simply return the current value of
>  an instance variable. The suggested feature would be, that the compiler/
>  interpreter, by default inserts these methods corresponding to each instance
>  variable specified in the Class definition. 

	Methods such as these are the Smalltalk equivalent of the GOTO statement.
Yes I have written and used such methods.  They are especially useful during
the early exploratory/debugging stages.  However, they violate the fundamental
principles of encapsulation which make OOP so useful.  I definitely do NOT
want such a "feature" added as a standard part of the language.

	I am not saying don't use such methods.  I am saying that until
you finish eliminating such methods from a design, you should know you are
not finished creating your design.  Exception: Objects which exist solely
to "encapsulate" external interfaces must frequently violate this rule, 
until you can redesign the external part of the interface.

	This is in large part a religious/style question, and I am obviously
a "purist" on this one.  Some heretic ;-) will probably post a goodie which 
does almost exactly what you want.  It looks like a rather simple problem 
(at least in st80).

Bill Voss <voss@cs.uiuc.edu>

boissier@irisa.fr (franck boissiere) (04/22/91)

From article <2270@media03.UUCP>, by pkr@media03.UUCP (Peter Kriens):
> Dan Walkowski writes:

[stuff deleted]

> a feature I could love in Smalltalk. Unfortunately you cannot access the
> compiler in Digitalk smalltalk, otherwise it could be done.
> 
You do not need to modify the compiler to do this (unless you want to
change the syntax which is what Peter proposes).

The key is to define a new class definition message which allow you to
specify which variables are to be exported. The key issue is to track
all class modification to add/remove the methods according to instance
variable additions/removals.

In fact when you do an accept in the Browser text pane the Compiler
simply evaluate the expression printed.


-- 
Franck BOISSIERE                        boissier@irisa.irisa.fr
C.C.E.T.T.   B.P. 59                    boissiere@ccett.fr
35512 CESSON SEVIGNE CEDEX  FRANCE    

knight@mrco.carleton.ca (Alan Knight) (04/22/91)

In article <2270@media03.UUCP> pkr@media03.UUCP (Peter Kriens) writes:
>Dan Walkowski writes:
>> If access methods were automatically generated for every private variable,
>> then this breaks down; every object can diddle with the state of every other.
>> Yes, frequently you need to write several access methods for several private
>> variables of an object, but if you are finding that you need to make ALL of

<stuff omitted>

>Eiffel has a very nice solution for this. It allows an instance variable
>to be exported in the header (Smalltalk could also do that in the
>class definition, you could for example place a colon behinde the 
>definition of the instance variable). So in Eiffel you can easely access those often
>used instance variables. The good thing is that if you decide later on
>to replace the instance access with a procedure, because the implementation
>changes, nobody notices because the syntax stays the same. Sounds like
>a feature I could love in Smalltalk. Unfortunately you cannot access the
>compiler in Digitalk smalltalk, otherwise it could be done.
>
>Peter Kriens
>pkr@media01

A nearly equivalent feature, and one which preserves a little more
encapsulation than automatically writing all acces methods is to allow
them to be written on command, one at a time.  i.e. have a menu item
which writes access methods for a single instance variable.  I've seen
this done in Smalltalk/V, and it could easily be done in Smalltalk-80.
  
   The disadvantage of this method is that it discourages comments,
particularly a problem in /V where there are no class comments.
Coming across the automatically written message

glorch: aValue
   "Set the value of the instance variable glorch to aValue"

    glorch := aValue.

is annoying (to say the least), when there is no indication what kind of
a thing glorch is or what it is used for.

-- 
--
  Alan Knight   knight@mrco.carleton.ca  +1 613 788 5783   Support
  Dept. of Mechanical and Aeronautical Engineering         the
  Carleton University, Ottawa, Ontario, Canada, K1S 5B6    LPF

dawg6844@uxa.cso.uiuc.edu (Race Bannon) (04/22/91)

boissier@irisa.fr (franck boissiere) writes:

>From article <2270@media03.UUCP>, by pkr@media03.UUCP (Peter Kriens):
>> Dan Walkowski writes:

>[stuff deleted]

>> a feature I could love in Smalltalk. Unfortunately you cannot access the
>> compiler in Digitalk smalltalk, otherwise it could be done.
>> 

please pay attention to how you quote in the future.  I did NOT say the above.
I was arguing _against_ automatic accessing methods.  I have never even used
DigiTalk.  (I use PP)
--
_______________________________________________________________________________
Dan Walkowski                          | To understand recursion, 
Univ. of Illinois, Dept. of Comp. Sci. |   you must first understand recursion.
walkowsk@cs.uiuc.edu                   |

nvi@mace.cc.purdue.edu (Charles C. Allen) (04/22/91)

Actually, I think being able to tell the compiler that "private"
methods are just that would solve this and other problems relatively
cleanly.  I'm not so enamored of C++'s "protected", but others feel it
would be a good idea as well.

Charles Allen                           Internet: cca@physics.purdue.edu
Department of Physics                   HEPnet:   purdnu::allen, fnal::cca
Purdue University                       Bitnet:   cca@fnal.bitnet
West Lafayette, IN  47907-1396          talknet:  317/494-9776

brian@vuse.vanderbilt.edu (Brian Antao) (04/23/91)

In article <1991Apr22.003659.18658@ux1.cso.uiuc.edu> dawg6844@uxa.cso.uiuc.edu (Race Bannon) writes:
>brian@vuse.vanderbilt.edu (Brian Antao) writes:
>>an instance variable. The suggested feature would be, that the compiler/
>>interpreter, by default inserts these methods corresponding to each instance
>>variable specified in the Class definition. Each time the Class definition is
>>recompiled, the appropriate access methods should be added/deleted if any
>>instance variables are added/deleted. One could also argue for a similar
>>feature to also support class variable access. 
>
>This would not be difficult to add, just aesthetically unpleasant.  Why?
>One of the primary ideas behind 'objects' is the encapsulation of data with
>the code that manipulates it.  Why is this good?  If used properly, it 
>minimizes the 'side-effects' that can occur with other programming paradigms.

There is a limitation in smalltalk, in that one cannot explicitly classify
instance variables to be public or private. If this feature  exists, such as
in C++, then the access methods would be generated only for those instance 
variables designated as public, and need access methods anyway. This would
satisfy the encapsulation constraints as well.

>In SmallTalk, no object can manipulate another's state unless you 
>'do it on purpose',  by constructing the access methods to do so.
>If access methods were automatically generated for every private variable, 
>then this breaks down; every object can diddle with the state of every other.

An object would be able to access the state of another object only if it
has been instructed to do so. ie via explicit coding. In such cases you need
some aspects of an object that is maintained in an instance variable. Th only
way to acces and update/modify the state is via an access method.

>Yes, frequently you need to write several access methods for several private
>variables of an object, but if you are finding that you need to make ALL of
>your instance variables public, then perhaps you need to rethink your design.

At the current status of smalltalk, there is no way of seperating private and
public internal (instance variables), hence the default notion of access 
methods for all. 

Which also bring up the issue, DO we need to distinguish Private and Public
instance variables in smalltalk ?,


-- 
Brian Antao,  Dept. of Electrical Engg.,     |INET: brian@vuse.vanderbilt.edu
Vanderbilt University, Nashville, TN, USA 37235 
Disclaimer:      "Artificial Intelligence" - an oxymoron ? 
-------------------------------------------------------------------------------

voss@cs.uiuc.edu (Bill Voss) (04/23/91)

Teach me to be careless when I post. ;-)  Naah..

>I wrote:
>	   I am not saying don't use such methods.  I am saying that until
>   you finish eliminating such methods from a design, you should know you are
>   not finished creating your design.  Exception: Objects which exist solely
>   to "encapsulate" external interfaces must frequently violate this rule, 
>   until you can redesign the external part of the interface.

I still maintain that using access methods is a strong indication that the programmer 
has goofed (or not finished).  However I forgot the BIG exception.

The "private" method category is almost always filled with "access" methods,
and I tolerate this (in MY code) PROVIDED all methods in the "private" category 
are only used by other methods in the SAME CLASS (or maybe reluctantly subclasses).
[NOTE: Access methods in the "private" category can also almost always
       be avoided by using double dispatching.  I generally prefer to use
       double dispatching, but consider a more direct interface acceptable
       when confined to PRIVATE methods.]

My objection is not an algorithm, but it is in my experience a very good heuristic.
When I call another class's access methods, I almost always find I should have 
opened another browser, and started adding methods to the other class instead.

Thus as a "purist" on this question, I consider access methods similar to
the goto statement.  Occasionally needed, but usually abused.

Bill Voss - the purist - <voss@cs.uiuc.edu>

knight@mrco.carleton.ca (Alan Knight) (04/23/91)

--  A couple of people have talked about the undesirability of access
methods for instance variables, including:

In article <VOSS.91Apr22183834@laslo.cs.uiuc.edu> voss@cs.uiuc.edu (Bill Voss) writes:
>My objection is not an algorithm, but it is in my experience a very good heuristic.
>When I call another class's access methods, I almost always find I should have
>opened another browser, and started adding methods to the other class instead.
>
>Thus as a "purist" on this question, I consider access methods similar to
>the goto statement.  Occasionally needed, but usually abused.
>
>Bill Voss - the purist - <voss@cs.uiuc.edu>


I think that this is a rather extreme position.  Gratuitously
accessing the representation of another class is undesirable, but
often that representation corresponds to information about the class
that a client might legitimately want to know.
  If access methods are usually an indication that the programmer has
goofed then what about

  Point     x, y
  Rectangle origin, corner, extent
  Line      slope, or Line coefficients

All of these represent information that I might reasonably want to
know about an object, but they may easily correspond to pieces of
the representation.  Then again, they may not, and that's the point of
encapsulation.  

   
-- 
--
  Alan Knight   knight@mrco.carleton.ca  +1 613 788 5783   Support
  Dept. of Mechanical and Aeronautical Engineering         the
  Carleton University, Ottawa, Ontario, Canada, K1S 5B6    LPF

mjohnson@sirius.acs.calpoly.edu (Mark S. Johnson) (04/23/91)

As a relative newcomer to Smalltalk, I am very interested in this
debate. I'd like to start some serious coding in the near future and
I'd like to get off on the right foot "stylistically." I tend to agree
with the folks who oppose access methods, but what about when using
simple "readonly" methods to extract information from a "record-like"
object? If the object Mark below is a "record-like" object containing
personal information about me, what's wrong with this type of access

                           Mark eyeColor 

to check my eye color? Note that Mark does not necessarily have an
instance variable named eyeColor.

Am I being a dope about this?

As an aid to me learning Smalltalk in a vacuum, can anyone recommend a
Smalltalk "style guide" which addresses these issues?

Thanks for listening,
Mark
                  
-- 
Mark S. Johnson        mjohnson@stn9.me.calpoly.edu      (129.65.19.9)

dawg6844@uxa.cso.uiuc.edu (Race Bannon) (04/23/91)

Because Smalltalk lacks syntax for describing 'public' and 'private'
variables does not mean it lacks these concepts.  ALL instance variables
are 'private' unless explicitly made otherwise by adding an access method.
--
_______________________________________________________________________________
Dan Walkowski                          | To understand recursion, 
Univ. of Illinois, Dept. of Comp. Sci. |   you must first understand recursion.
walkowsk@cs.uiuc.edu                   |

voss@cs.uiuc.edu (Bill Voss) (04/24/91)

>    but what about when using
>    simple "readonly" methods to extract information from a "record-like"
>    object? 

	My objection to access methods is in part because they do encourage 
	"record-like" objects, instead of more active objects.

	The use of access methods tends to indicate that the programmer
	is using a Class the way a Pascal programmer would use a Record.
	Instead of having the object do the work, the programmer has the
	object store information, then regurgitate raw information which
	code outside of the object manipulates.

>   If the object Mark below is a "record-like" object containing
>   personal information about me, what's wrong with this type of access
>
>			      Mark eyeColor 
>
>   to check my eye color? Note that Mark does not necessarily have an
>   instance variable named eyeColor.

	Maybe alot, maybe nothing.  To answer your question I need
	to know WHY you want to know Mark's eyeColor.

	Do you want to see if Mark has the same color eyes as Bob?
	Then you should use
		Mark sameColorEyesAs: Bob
			ifTrue:.....
	instead of
		m <- Mark eyeColor.
		b <- Bob eyeColor.
		m = b
			ifTrue:.....

	Do you want to draw a picture of Mark's eyes?
	Then you should use
		Mark drawEyesOn: someDisplayable at: somePoint andSoOn:....
	instead of
		m <- Mark eyeColor.
		blaBlaBla... color: m.

	The key point is that code which needs to know about Mark's
	eye color should be INSIDE the class which keeps track of
	Mark's eye color.  This could be the class Human, or Human could
	contain two instances of class Eye.  In that case the class Human
	would split up "drawEyesOn:" for example into two "drawYourselfOn:" 
	messages, one for each eye.  The code which needs to know about 
	Mark's eyes should almost never be located in some external method 
	which simply send's Mark an "eyeColor" message.

	Thus in my (never humble ;-) opinion, if Mark is a "record-like"
	object, you have already made a fundamental mistake.  You should
	have used Pascal/.... which directly supports Records instead.
	(but please don't Smalltalk is much nicer.  :-)

>   As an aid to me learning Smalltalk in a vacuum, can anyone recommend a
>   Smalltalk "style guide" which addresses these issues?

	I don't think such a book exists.  Just monitor comp.lang.smalltalk
	for messages containing words like "extreme" "wrong" .... ;-)


Exercise: Assume two equivalent systems, both need to determine in say twenty
	  different places wether or not Mark and Somebody have the same
	  color eyes.  One system uses my "sameColorEyesAs:" method, and
	  one system uses the "eyeColor" method.

	  Your job (should you choose to accept it) is to change one
	  of the two systems to support people with different color eyes.
	  (Someone with a brown left eye, and a green right eye does NOT 
	   have the same color eyes as someone with TWO green eyes.)

	  Which system would you rather change?  
	  Then (try to) write your code that way to begin with.

Bill Voss -- voss@cs.uiuc.edu

dawg6844@uxa.cso.uiuc.edu (Race Bannon) (04/24/91)

mjohnson@sirius.acs.calpoly.edu (Mark S. Johnson) writes:
>object? If the object Mark below is a "record-like" object containing
>personal information about me, what's wrong with this type of access

>                           Mark eyeColor 

>to check my eye color? Note that Mark does not necessarily have an
>instance variable named eyeColor.

>Am I being a dope about this?

I'm much more of a moderate than my esteemed colleague Mr. Voss.  I don't
advocate having NO accessing methods, just as few as possible.  


--
_______________________________________________________________________________
Dan Walkowski                          | To understand recursion, 
Univ. of Illinois, Dept. of Comp. Sci. |   you must first understand recursion.
walkowsk@cs.uiuc.edu                   |

kentb@argosy.UUCP (Kent Beck) (04/24/91)

I don't wish to flame the original poster, but I think automatic compilation
of access methods makes it entirely too easy to fall back into "rape and
plunder" mode, where are object are expensive data structures.  As Dave
Ungar has pointed out, objects are nothing more than their behavior.  If
part of their behavior is to return another object, fine, but I like the
way the annoyance of defining an instance variable access method forces
me to stop and think, "Should this object be doing more, so that other
objects would no longer need access to this variable?"  This flies in the
face of the "access method for all variables" camp, but to me the 
value of added encapsulation far outweighs the minor hassle of changing
instance variable references to messages if such a change becomes
necessary.

Kent

voss@cs.uiuc.edu (Bill Voss) (04/24/91)

I wrote a few messages ago:
 >When I call another class's access methods, I almost always find I should have
 >opened another browser, and started adding methods to the other class instead.

Alan Knight argues the following are counter examples
>     Point     x, y
>     Rectangle origin, corner, extent
>     Line      slope, or Line coefficients

>   All of these represent information that I might reasonably want to
>   know about an object, but they may easily correspond to pieces of
>   the representation.  Then again, they may not, and that's the point of
>   encapsulation.  

	Point is a particular favorite of mine, because I goofed BIG
	using class Point when I started using Smalltalk.  Back then I 
	was very very new to Smalltalk, and very very timid/reluctant to 
	alter/extend the existing code.

	So I was writing something which needed a Point.  Hey I thought to
	myself, I'll bet a class Point already exists.  Search for "Point"
	yep, sure does.  Lets see how this works....ah ACCESSING methods
	x x: y y: thats great.  I understand these methods.  I can read and 
	set the x and y values for a point, just what I need.  Wow they were
	right, you can reuse code in Smalltalk.  This is great.  :-)

	For the next few weeks, if I needed the distance between two
	points, I'ld go
		x1 <- point1 x.
		y1 <- point1 y.
	and so forth, plugging my temporary variables into the distance 
	formula we learned in High School.  I was using Point as a simple
	two element array.

	Obviously I should have been using "point1 dist: point2." instead.
	However, NOT because dist: already exists.  I should have been using
	dist: EVEN IF I NEEDED TO WRITE IT.  Unlike my code, the "dist:"
	method was in the right place.  It needs to know about the internals
	of a Point, so it is located INSIDE the class Point.  The method "dist:" 
	is in my opinion a very GOOD example of how to do things.  However,
	the class Point is not such a good class.  The Point class seems to
	encourage programmers to break encapsulation.

Exercise 1:  Make a wild guess as to how frequently code in the Smalltalk-80
	     image needs to determine the distance between two points.
		invoke "senders" on the method "dist:"
		invoke "senders" on the method "x"
	     How are programmers doing it?

Exercise 2:  A new faster way of computing the distance between two
	     points has been found.  Change all existing code in the
	     Smalltalk-80 hierarchy to use the new method.

Exercise 3:  Comment on the results of Exercise 1 based on your experience
	     in Exercise 2.

	So I have shown that accessing the x and y instance variables
	of class Point MAY be wrong.  Hopefully we can all at least agree
	on that much?  :-)
-------------------------------------------------------------------------------
	Now is it ALWAYS wrong to use access methods?  
	I do NOT contend that it is ALWAYS wrong.
	I think it must be judged on a case by case basis.
	However, I do contend that it is USUALLY wrong.

	I have not yet seen anyone post a good counter example.
	They say this or that instance variable is "obviously"
	an exception, but they don't show WHY they need to
	access that particular variable.  Without knowing WHY
	I can't tell wether they are correct or not.

	(Hmm looks like rain... I might even get flooded now. ;-)
-------------------------------------------------------------------------------
	The next obvious question is "What do you do instead?"
	;-) So glad you asked. ;-)

	It is my contention that instead of using something like

voss@cs.uiuc.edu (Bill Voss) (04/24/91)

	For some reason GNUS/nntpd keeps dropping the tail of my posting
	with the message "writing to process: no more processes, nntpd"
	So here is that final section, ONE MORE TIME.
-Bill
-------------------------------------------------------------------------------
	The next obvious question is "What do you do instead?"
	;-) So glad you asked. ;-)

	It is my contention that instead of using something like

			x1 <- point x.
			y1 <- point y.
			anObject myThingX: x1 Y: y1.
	or in one line
			anObject myThingX: (point x) Y: (point y).

	in those cases where you legitimately need to know x and y,
	outside of Point, you should instead write a Point method:

		doMyThingOn: anObject

			^anObject myThingX: x Y: y.

	I consider this CLEANER, more READABLE, more MAINTAINABLE, and
	much harder to abuse than a straight ACCESS technique.

	The fact that it usually involves both less programmer typing, 
	and fewer runtime message sends is a nice bonus.

-Bill Voss <voss@cs.uiuc.edu>

knight@mrco.carleton.ca (Alan Knight) (04/24/91)

In article <VOSS.91Apr23194435@laslo.cs.uiuc.edu> voss@cs.uiuc.edu (Bill Voss) writes:
>I wrote a few messages ago:
> >When I call another class's access methods, I almost always find I should have
> >opened another browser, and started adding methods to the other class instead.
>
>Alan Knight argues the following are counter examples
>>     Point     x, y
>>     Rectangle origin, corner, extent


Lots of stuff with some very good points omitted to try and reduce
length.  I'll summarize what I thought the good points were.
Summaries begin with --, quotes start each line with >, plain text is
my comments.

-- Lots of people access x and y values for points when they really
--shouldn't, either using point as an array of two values or to compute
--things that should have been made into methods for Point, with dist:
--being the example.
>	Obviously I should have been using "point1 dist: point2." instead.
>	However, NOT because dist: already exists.  I should have been using
>	dist: EVEN IF I NEEDED TO WRITE IT.  Unlike my code, the "dist:"
>	method was in the right place.  It needs to know about the internals
>	of a Point, so it is located INSIDE the class Point.

Absolutely.  A good example of when access methods are abused and code
duplicated for no good reason.


-- The class Point encourages programmers to break encapsulation.
>Exercise 2:  A new faster way of computing the distance between two
>	     points has been found.  Change all existing code in the
>	     Smalltalk-80 hierarchy to use the new method.

Yes, but this unlikely for this particular example.  Far more likely
is that you will decide you want to use a different metric for some of
your code, in which case isn't nearly as easy.  e.g. This UI code
doesn't really need precise distances, a Manhattan metric is fine to
test if the mouse is "close enough".  The method dist: should have
been used anyway, but as much to avoid duplication of code as to avoid
accessing representation.
   It also seems to me that the representation part is somewhat of a
side issue.  If points were represented in polar coordinates would x,
y, x:, y: suddenly become all right to use?  Does caching a previously
computed property inside an object make it wrong to access that
property?  It seems as if the issue is whether objects should return
properties of themselves, or if objects should always be dealt with as
an indivisible whole, where most messages don't return anything more
complex than a boolean.


>	I do NOT contend that it is ALWAYS wrong.
>	I think it must be judged on a case by case basis.
>	However, I do contend that it is USUALLY wrong.
>
>	I have not yet seen anyone post a good counter example.
>	They say this or that instance variable is "obviously"
>	an exception, but they don't show WHY they need to
>	access that particular variable.  Without knowing WHY
>	I can't tell wether they are correct or not.
>

OK, here are some examples, still using x and y.
Suppose that I have a set of points, and that I want to sort them.
There's no canonical sorting order for points, so I have to define
one.  I could define my sortBlock as 

   [ :point1 :point2 | point1 x <= point2 x]
OR [ :point1 :point2 | point1 y <= point2 y].

On the other hand, to avoid accessing the representation, I could
write
   [:point1 :point2 | point1 xIsLessThanOrEqualXFor: point2]


I contend that there is no additional encapsulation in the second
example, and no good reason to use it.  Of course for generality there
should really be a single sort block.
   [:point1 :point2 | (point1 componentInDirection: aVector) <=
	(point2 componentInDirection: aVector)]
which is no longer really an access method, but the efficiency gain is
significant enough that I believe a lot of people would write one of
the preceeding forms.


Another, and perhaps a better example is where one needs to know about
internals of more than one class at a time.  For example, suppose that
I have a geometric object and I need to do some mathematics on it (I'm
specifically looking at code for doing finite element analysis as I
write this, but think of it in general).  This mathematics probably
involves plugging x and y coordinates of some or all of the points
into some fairly complicated equations.
  Right now this code is in the finite element, which is (IMHO) where
it belongs, since it has to know a lot more about the details of the
finite element than about the particular points, but it does need to
know x's and y's.  I certainly don't think that having the methods

    Point>> findBasisFunctionsForEightNodeBrick: aBrick
            findBasisFunctionsForFourNodeQuad: aQuad
            findBasisFunctionsForTetrahedron: aTetrahedron

	etc. etc. is in any way a cleaner solution.


>	It is my contention that instead of using something like
>                        x1 <- point x.
>                        y1 <- point y.
>                        anObject myThingX: x1 Y: y1.
>        in those cases where you legitimately need to know x and y,
>        outside of Point, you should instead write a Point method:
>
>                doMyThingOn: anObject
>
>                        ^anObject myThingX: x Y: y.
>
>        I consider this CLEANER, more READABLE, more MAINTAINABLE, and
>        much harder to abuse than a straight ACCESS technique.
>
>        The fact that it usually involves both less programmer typing, 
>        and fewer runtime message sends is a nice bonus.

  Well, I have to admit that I don't consider this CLEANER, more
READABLE, or more MAINTAINABLE, although it might arguably be harder
to abuse.  Its main advantage seems to be that it gives you an idea of
who might be getting at the representation of point with a little more
detail than might be seen from senders of x or y.  It doesn't seem to
answer my previous example where I want x and y values for several
points without a great deal of convolution.
  I can see circumstances where this would be useful, but I think it
can wind up adding a lot of extraneous methods to Point.

  In summary, I don't think we disagree qualitatively.  Access to the
representation should be carefully watched, and you should always
think twice before doing it.  That doesn't mean that it's usually a
mistake, or that you should put methods in the "wrong" place to get
around it.  A method should be put in the class where it needs to know
the most about the internals, and knowledge of the internals of other
classes should be minimized, but cannot always be avoided.

-- 
--
  Alan Knight   knight@mrco.carleton.ca  +1 613 788 5783   Support
  Dept. of Mechanical and Aeronautical Engineering         the
  Carleton University, Ottawa, Ontario, Canada, K1S 5B6    LPF

eat@helmut.scs.carleton.ca (Eric Arseneau) (04/25/91)

In article <VOSS.91Apr23201829@laslo.cs.uiuc.edu>, voss@cs.uiuc.edu (Bill Voss) writes:
|> 
|> 	For some reason GNUS/nntpd keeps dropping the tail of my posting
|> 	with the message "writing to process: no more processes, nntpd"
|> 	So here is that final section, ONE MORE TIME.
|> -Bill
|> -------------------------------------------------------------------------------
|> 	The next obvious question is "What do you do instead?"
|> 	;-) So glad you asked. ;-)
|> 
|> 	It is my contention that instead of using something like
|> 
|> 			x1 <- point x.
|> 			y1 <- point y.
|> 			anObject myThingX: x1 Y: y1.
|> 	or in one line
|> 			anObject myThingX: (point x) Y: (point y).
|> 
|> 	in those cases where you legitimately need to know x and y,
|> 	outside of Point, you should instead write a Point method:
|> 
|> 		doMyThingOn: anObject
|> 
|> 			^anObject myThingX: x Y: y.
|> 
|> 	I consider this CLEANER, more READABLE, more MAINTAINABLE, and
|> 	much harder to abuse than a straight ACCESS technique.
|> 
|> 	The fact that it usually involves both less programmer typing, 
|> 	and fewer runtime message sends is a nice bonus.
|> 
|> -Bill Voss <voss@cs.uiuc.edu>


This goes without saying.   But saying that access methods are a no-no
is absolutely wrong.  This is easy to show by simply stating that a user
of an object has absolutely no way to know what is being returned, an 
instance variable or a function of some other objects.  This is what 
encapsulation gives you, and it suppors CLEANER, READABLE and MAINTAINABLE
as the users do not know ho they are implemented.

If a function makes sense to do on a particular object, then you add it to
that object's class.  If myThingOn: is something that is general for a point
then it is totally obvious that you shoudl implement it under Point, but
this does not rule out access methods.  If at a later point I change the 
representation of my objects, then I still have to provide the accessing
methods I had before, so if a method used to return an instance variable, and
it no longer does, who's to know the diference.  The point is that the method
still has to be supported in the new representation because it was part ofg
the public interface to your objects before, and you're still repsonsible
for supporting all of the previous operations, even if the representation
chenages.

When I am writing a class, I write an access method for all of my instance
variables, making some private and some public.  Instead of referencing
an instance variable directly, I will send myself the accessor message`
to get it's value.  That way when I change the representation of my class
later on, all of my other operations will still work as long as I still
support the old accessor messages, but mapped to something appropriate.
This makes it much easier for the implementor (not the user) of a class
to change his represenation and still have things working somewhat, maybe
not as efficient as it should be, but he can go back later and replace the
senders of the old accessors and update them to the new representation.

THE POINT:  Acessor methods are definitely OK !!!

voss@cs.uiuc.edu (Bill Voss;;;356-4652;jerry.cs.uiuc.edu) (04/25/91)

Trying again with a different machine.  Sorry if the other one made it
part way out. -- HUGE SIGH.
------------------------------------------------------------------------------
First let me say thanks to all my fellow debate partners in this string, both
the posters, and the emailers.  This is definitely the most fun I've had in
comp.lang.smalltalk for months.  We have even managed to disagree without
slipping into a flame war, in my opinion this string is an example of USENET
at its finest.

Now replying to Alan's reply to my.......

>   OK, here are some examples, still using x and y.

I wish I'ld never accepted Point as an example.  SIGH.

>   Suppose that I have a set of points, and that I want to sort them.
>   There's no canonical sorting order for points, so I have to define
>   one.  I could define my sortBlock as 
>
>      [ :point1 :point2 | point1 x <= point2 x]
>   OR [ :point1 :point2 | point1 y <= point2 y].
>
>   On the other hand, to avoid accessing the representation, I could
>   write
>      [:point1 :point2 | point1 xIsLessThanOrEqualXFor: point2]
>
>   I contend that there is no additional encapsulation in the second
>   example, and no good reason to use it.  Of course for generality there
>   should really be a single sort block.
>      [:point1 :point2 | (point1 componentInDirection: aVector) <=
>	   (point2 componentInDirection: aVector)]
>   which is no longer really an access method, but the efficiency gain is
>   significant enough that I believe a lot of people would write one of
>   the preceeding forms.

PP.R4 class "Point" method category "comparing" method "<= aPoint" method
comment says "Answer whether the receiver is 'neither below nor to the right'
of aPoint."  So you can stick PP.R4 Point's directly into a sorted collection.

If you need a different canonical sorting order, then yes I most definitely
would suggest adding a simple method "xyzCompare:" to class point.  Then use
the simple and readable sort block [:p1 :p2 |p1 xyzCompare: p2].  Both methods
will obviously work, but there is an implicit difference in encapsulation.

>      [ :point1 :point2 | point1 x <= point2 x]
Would you use that sort block if you KNEW that the internal representation of
a Point was NOT based on instance variables X and Y?  I like my code to run as
fast as possible, so I would try to avoid converting Points needlessly.  As an
external user asking for x and y, I have no business worrying about a Point's
internal representation.  As an xyzCompare: method inside of Point I can
legitimately take Point's internal representation into consideration.  Thus
using xyzCompare: I can legitimately make efficiency decisions based on
Point's internal representation.

I`ld also either name xyzCompare: something like
	orderByGodzilianSpiral: 
in this case I've already written my GodzilianSpiral code when I need it again
OR
	projectHack12BSorter:
in which case WHEN I later decide I didn't really need that infinite precision
asymptotically corrected aglutinated comparison, and could instead get by with
an 8 way truncated fast shuffle I only need to change code in ONE PLACE.  
(I can also find all such users quickly with "senders".)
==============================================================================
>   Another, and perhaps a better example is where one needs to know about
>   internals of more than one class at a time.  For example, suppose that
>   I have a geometric object and I need to do some mathematics on it (I'm
>   specifically looking at code for doing finite element analysis as I
>   write this, but think of it in general).  This mathematics probably
>   involves plugging x and y coordinates of some or all of the points
>   into some fairly complicated equations.
>     Right now this code is in the finite element, which is (IMHO) where
>   it belongs, since it has to know a lot more about the details of the
>   finite element than about the particular points, but it does need to
>   know x's and y's.  I certainly don't think that having the methods
>
>       Point>> findBasisFunctionsForEightNodeBrick: aBrick
>	       findBasisFunctionsForFourNodeQuad: aQuad
>	       findBasisFunctionsForTetrahedron: aTetrahedron
>
>	   etc. etc. is in any way a cleaner solution.

I've never done any finite element analysis, I don't think I could even tell
you what it is used for.  (My, my, the state of my education.... ;-)

That said, it sounds as though you are treating Points as simple Records here.
Extracting out the raw data they contain, and plugging that data into a
mathematical formula.  There is nothing apriori wrong with doing this.  In
such a situation the difficult portion is usually the mathematics, not the
programming.  However, I wouldn't describe it as object oriented programming
either, it is programming in an imperative style using an object oriented
language.  I know if someone gave me a problem which involved complex
mathematical formulas I'ld do the same thing.  I'ld simply plug the formulas
into my program.  Not all problems require a hammer, and not all problems
require object oriented programming.  This seems to be one of those cases
where imperative is better, and imperative programming definitely DOES work
better with access methods.

So I need to update my exceptions list.

    Using ACCESS methods is almost always undesirable EXCEPT:
    1) As class "private" methods.
    2) To encapsulate an external interface you can't easily change.
    3) To implement something not easily expressed in an object oriented style.
		Such as a complex mathematical formula better expressed
		in an imperative style.

Bill Voss -- voss@cs.uiuc.edu -- Graduate Student in Computer Science

P.S.
Thinking about it a wee bit more, perhaps you could handle a mathematical
formula in a rather object oriented style by making the formula itself a
class.  You feed it what it needs at instance creation, and then eventually
ask it for its value.  You would build the big formula with instances of
smaller formulas....  hmmm.
If anyone out there has an OBJECT ORIENTED way of handling complex
mathematical formulas, please start another string and tell us about it.

--
Bill Voss     INTERNET: billvoss@uiuc.edu    UUCP: uunet!uiucuxc!uiucdcs!voss

tma@m5.COM (Tim Atkins) (04/25/91)

Seems to be a lot of hype around this question so I'll post my own. 
One point that has been neglected somewhat is that well designed classes
tend to have named instance variables that clearly encapsulate data-ish
parts of the problem domain.  Sending a message to get at this held
data via a request to its encapsulator is perfectly ok.  If the 
encapsulator did not want to allow access (read only here) to this
data that class would not have done so.  From an external point of
view it is not knowable whether a particular method just returns
the value of an instance variable or computes its result.  This is
encapsulation!  To me it has nothing whatsoever to do with what in
fact is the implementation of the method.  Also it would be silly
to make up some new name for the method that was not the instance
variable name.  I believe most posters grant this.   There is a valid
point that over-reliance on such data-ish features often fails to 
produce a good design.  But this is more a design viewpoint issue
than an implementation guideline.  It is all too easy to view the
world as a bunch of data structures like we learned back in the 
dark ages instead of as a set of "objects" capable of responding
to methods.   For this reason I tend to get a bit frustrated with
OOD and OOA tools that concentrate early on data relationships in
the design.

Another point that has not been made is that good OO programming 
style asserts that instance variables should always be accessed
indirectly through methods, even by methods of the same class and
its subclasses.  One reason is that any other approach makes the
system very fragile and hard to modify.  Given that this is so,
it makes a great deal of sense to have automatically generated
access methods available.


- Tim Atkins

pkr@media03.UUCP (Peter Kriens) (04/25/91)

voss@cs.uiuc.edu (Bill Voss) writes (after giving an example about point
not using x,y for calculating the distance between two points)

        Now is it ALWAYS wrong to use access methods?
        I do NOT contend that it is ALWAYS wrong.v:Soon
        I think it must be judged on a case by case basis.
        However, I do contend that it is USUALLY wrong.
 
1: I think a basic quality of object oriented design is defining a
"functionality" only in place. Calculation of the distance between 
points should therefore be placed in one location and that is the
Point class. Your example violates this first rule. I cannot in the
world see what this example has to do by accessing through a method
of the instance variable. 

2: Instance variables have a natural tendenncy to contain the most
relevant information regarding an object. So it seems quite natural
to me that they should be accessible outside the object. What I dont
want is that once I change the implementation (e.g. change a Point
from x,y to polar coordinates) that my clients break. As long as
the instance variables are accessed through methods (and i dont seen another
way to do it in Smalltalk) I can always keep the same interface. So
what is wrong in have the instance variable access methods?

3: I do not promote to make EACH instance variable automatically
accessible, but I think it would be very nice to allow variables
to be exported like in Eiffel.

Peter Kriens
pkr@media01.uucp

knight@mrco.carleton.ca (Alan Knight) (04/25/91)

In article <VOSS.91Apr24215444@jerry.cs.uiuc.edu> voss@cs.uiuc.edu (Bill Voss;;;356-4652;jerry.cs.uiuc.edu) writes:
>------------------------------------------------------------------------------
>First let me say thanks to all my fellow debate partners in this string, both
>the posters, and the emailers.  This is definitely the most fun I've had in
>comp.lang.smalltalk for months.  We have even managed to disagree without
>slipping into a flame war, in my opinion this string is an example of USENET
>at its finest.

Thank you.  I agree that this thread is remarkably civil and
thought-provoking by USENET standards.

(me)
>>   Suppose that I have a set of points, and that I want to sort them.
>>   There's no canonical sorting order for points, so I have to define

>PP.R4 class "Point" method category "comparing" method "<= aPoint" method
>comment says "Answer whether the receiver is 'neither below nor to the right'
>of aPoint."  So you can stick PP.R4 Point's directly into a sorted collection.

This is not a total order.  Try 
  (0 @ 3) <= (3 @ 0)        ==>  false
  (3 @ 0) <= (0 @ 3)        ==>  false

You can put them into a sorted collection, and you will get an answer
back, but it isn't really sorted.  For example, you get.

   (Array with: (3@0) with: (0@3)) asSortedCollection  ==>
        SortedCollection (0@3 3@0 )
   (Array with: (0@3) with: (3@0)) asSortedCollection  ==>
        SortedCollection (3@0 0@3 ) 

(This is also in PP.R4, but is not likely specific to that version).

>
>If you need a different canonical sorting order, then yes I most definitely
>would suggest adding a simple method "xyzCompare:" to class point.  Then use
>the simple and readable sort block [:p1 :p2 |p1 xyzCompare: p2].  Both methods
>will obviously work, but there is an implicit difference in encapsulation.
>
I will agree that there is no particular harm done by using
xyzCompare: p2, but I don't think it gains you very much over the
other approach.  It might be better style though, so I'll concede you
this one.

>>      [ :point1 :point2 | point1 x <= point2 x]
>Would you use that sort block if you KNEW that the internal representation of
>a Point was NOT based on instance variables X and Y?  I like my code to run as

If I wanted to sort by x-coordinate I don't see that I would have any choice.


>I`ld also either name xyzCompare: something like
>	orderByGodzilianSpiral: 
>in this case I've already written my GodzilianSpiral code when I need it again
>OR
>	projectHack12BSorter:
>in which case WHEN I later decide I didn't really need that infinite precision
>asymptotically corrected aglutinated comparison, and could instead get by with
>an 8 way truncated fast shuffle I only need to change code in ONE PLACE.  

  The code for sorting should already be in one place.  The sort block
does not implement a sorting routine, just a comparison, and in the
instances where the comparison was trivially based on a property of
the object which could be considered a key (whether this is part of
the representation or not).  In the case of an even moderately complex
comparison function I would definitely put it in a method.
e.g. 
  aPoint leqInClockwiseRadialOrderWithOrigin: anOriginPoint than: anotherPoint

Although, with regard to the efficiency you like (which I think I just
deleted) for an ordering by key which is expensive it is considerably
more efficient to calculate the property once at the beginning and
then compare keys.
  e.g.  allPoints do: [:eachPoint |
            eachPoint associateProperty: (eachPoint
                GodzilianSpiralNumberWRT: anOrigin)].

(Pretend points have property lists hanging of them.  One could also
use a dictionary or some other mechanism to do this).
This efficiency, however, breaks encapsulation somewhat in that you need to use
a different sorting routine depending on how expensive your ordering is.


>I've never done any finite element analysis, I don't think I could even tell
>you what it is used for.  (My, my, the state of my education.... ;-)
  Doing physical calculations about objects.  e.g. to analyze heat
flow in a weld, break the object being welded into a number (often
large) of regularly shaped elements, and then evaluate your heat
functions at the corners of these objects discretely rather than
continuously throughout the object.  

>
>That said, it sounds as though you are treating Points as simple Records here.
>Extracting out the raw data they contain, and plugging that data into a
>mathematical formula.  There is nothing apriori wrong with doing this.  In
>such a situation the difficult portion is usually the mathematics, not the
>programming.  However, I wouldn't describe it as object oriented programming
>either, it is programming in an imperative style using an object oriented
>language.  I know if someone gave me a problem which involved complex
>mathematical formulas I'ld do the same thing.  I'ld simply plug the formulas
>into my program.  Not all problems require a hammer, and not all problems
>require object oriented programming.  This seems to be one of those cases
>where imperative is better, and imperative programming definitely DOES work
>better with access methods.

Good analysis of the situation.  In fact, IMHO, a lot of the
difference in style between OOP and non-OOP programming is in the
difference in difficulty between different parts of the program.
  Imperative programming assumes that the difficult parts are the
functions, and that data is some other stuff that functions work on.
The important mental shift in OOP is that usually the data are more
important, and that they should be treated as primary with functions
dependent on them.
  However, this is not true in all domains, and certain kinds of
mathematics are examples of this.  For example, there are a great many
integer functions in math (factorial, catalan, fibonacci, etc. etc.).
The natural impulse is to add these as methods in class Integer.
However, these can be very expensive to evaluate, so it's probably
worth caching them, or intermediate results (e.g. for catalan it's a
big win to cache intermediate C(n,k) values).  These could be added as
class variables in class Integer, but pretty soon this gets awfully
messy.
   What's happening is that the mathematical functions and their
associated data are becoming "heavier" than the functions strictly
associated with single integers, and IMHO the correct approach is to
split these functions out into a separate class or classes.  This
sounds a bit like what you are proposing in your P.S.
i.e. 
>P.S.
>Thinking about it a wee bit more, perhaps you could handle a mathematical
>formula in a rather object oriented style by making the formula itself a
>class.


>
>So I need to update my exceptions list.
>
>    Using ACCESS methods is almost always undesirable EXCEPT:
>    1) As class "private" methods.
>    2) To encapsulate an external interface you can't easily change.
>    3) To implement something not easily expressed in an object oriented style.
>		Such as a complex mathematical formula better expressed
>		in an imperative style.

  This sounds reasonable, although it has the potential to be
dangerous given the common mentality that "object-oriented" means good
and "not object-oriented" means bad.  
   "To implement something not easily expressed in an OO style" also
sounds a bit like a "To handle cases where you need to" catchall, but
perhaps that's what it amounts to.


Unrelated P.S.  I definitely think that a Vector should be a subclass
somewhere under Magnitude.  In PPS, probably under ArithmeticValue,
but not Number.  In a number of places Smalltalk treats points like
Vectors of size 2 (e.g. (3@2) * 5), but they're not well-integrated.

-- 
--
  Alan Knight   knight@mrco.carleton.ca  +1 613 788 5783   Support
  Dept. of Mechanical and Aeronautical Engineering         the
  Carleton University, Ottawa, Ontario, Canada, K1S 5B6    LPF

kentb@argosy.UUCP (Kent Beck) (04/26/91)

Alan Knight makes a good point about operations becoming "heavier" than
data.  The image has a good example of this in BitBlt. 

If the "function" becomes so important or hairy that it doesn't seem to
fit in any existing class, make it an object.  Then all the benefits of 
objects accrue.  If you thought that graphics operations should be in 
Form (probably as primitives) you would have locked out all the neat, 
nasty efficiency hacks that having BitBlt be its own object enable, 
like scrolling Strings in a terminal emulator.

Kent

kentb@argosy.UUCP (Kent Beck) (04/26/91)

Peter Kriens says "Instance variables have a natural tendenncy (sic) to contain 
the most relevant information regarding an object. So it seems quite natural
to me that they should be accessible outside the object."  My point on 
accessing methods is that objects are much more about behavior than about
structure.  Thinking about any message send as an instance variable
accessing method allows assumptions about the structure of one object to
leak into others.  In a perfectly disciplined world this wouldn't happen,
but realistically I have seen too many cases of "highlighted: aBoolean"
methods to tell beginners anything but "don't create accessing methods
unless you absolutely need them, and even then think about what behavior
the object might be able to offer to eliminate the need to disclose 
structure".  The answer may be that the object cannot deliver the needed
functionality itself and so it has to allow itself to be plundered from
the outside, but access methods are not near the top of coding
strategies.

Kent

kentb@argosy.UUCP (Kent Beck) (04/27/91)

Tim Atkins writes: "Another point that has not been made is that good OO 
programming style asserts that instance variables should always be accessed
indirectly through methods, even by methods of the same class and
its subclasses."

This is only true in the presence of private methods.  In Smalltalk if you
choose to use the above style in a class and its subclasses you cannot
reasonable prevent external reliance on the same structure information.
I choose to accept the occasional hassle of doing an inst var refs and
adding a few "self "s rather than expose all of my instance variables
to raping and plundering.  Purists will say that Smalltalk should have
private methods- well the one I make my living on now doesn't, so I
make do with what I have.

Kent

klimas@iccgcc.decnet.ab.com (05/01/91)

In article <1264@argosy.UUCP>, kentb@argosy.UUCP (Kent Beck) writes:
> Tim Atkins writes: "Another point that has not been made is that good OO 
> programming style asserts that instance variables should always be accessed
> indirectly through methods, even by methods of the same class and
> its subclasses."
> 
> This is only true in the presence of private methods.  In Smalltalk if you
> choose to use the above style in a class and its subclasses you cannot
> reasonable prevent external reliance on the same structure information.
> I choose to accept the occasional hassle of doing an inst var refs and
> adding a few "self "s rather than expose all of my instance variables
> to raping and plundering.  Purists will say that Smalltalk should have
> private methods- well the one I make my living on now doesn't, so I
> make do with what I have.
> 
> Kent
	Please folks, read the excellent article "Variables Limit Reusability"
	by Allen Wirf-Brock and Brian Wilkerson in the May/June 89 JOOP.
	Basically ALL instance variables (PUBLIC & PRIVATE) should be 
	manipulated via getter and setter methods because it becomes 
	SIGNIFICANTLY easier to do maintenance on the system later.  
	Through actual industrial experience, this advice has proven to be 
	exceptionally sound!  

	BTW some claim that this practise wastes
	CPU resources whereas even in a tight loop. Profiling will show
	that the CPU overhead is miniscule when used in getter/setter methods
	(i.e. using
	anInstanceVariable
		^self anInstanceVariable

	anInstanceVariable: aValue
		anInstanceVariable := aValue
	).

johnson@cs.uiuc.EDU (Ralph Johnson) (05/01/91)

I bet Allan and Kent were arguing about this back in 1986 or 1987
when they worked together at Tektronix.  I take Kent's side, and
argue about it with Allan when I see him.  The claim that all
variable access should be made through messages is nice in theory,
but the current Smalltalk environment gives the advantage to directly
accessing variables.

I generally look down my nose at anybody who chooses Smalltalk 
programming style on the basis of efficiency, so I pay little
attention to the relative speed of direct access or message
sending unless I am optimizing a program.  The reasons that I
like direct access are because I think it makes programs a
little easier to read and it is certainly a lot easier to figure
out where a variable is getting changed by doing an "inst vars"
than by doing a "senders".  Thus, I think that direct access to
instance variables makes programs easier to maintain.

I don't buy the argument that Wirfs-Brock and Wilkerson made
that it is easier to eliminate variables or to replace a variable
with an algorithm to compute the value when all variable accesses
are made using access methods.  I have never seen an instance
variable that I couldn't eliminate in 5 minutes using "inst vars"
and intelligent cut and pasting.  Of course, this is in Smalltalk-80.
Perhaps the Smalltalk-V environment changes the balance of power.
My argument (which is really the same as Kent's argument--I haven't
said anything new) is based on the programming environment, not the
programming language.

This is a classic argument that never seems to end.  It must be like
the argument between vi and emacs users on Unix, a matter of taste.

Ralph Johnson -- University of Illinois at Urbana-Champaign

objtch@extro.ucc.su.OZ.AU (Peter Goodall) (05/14/91)

knight@mrco.carleton.ca (Alan Knight) writes:

[Even more stuff about automatically generating access methods omitted]
><stuff omitted>

>A nearly equivalent feature, and one which preserves a little more
>encapsulation than automatically writing all acces methods is to allow
>them to be written on command, one at a time.  i.e. have a menu item
>which writes access methods for a single instance variable.  I've seen
>this done in Smalltalk/V, and it could easily be done in Smalltalk-80.
>  
>   The disadvantage of this method is that it discourages comments,
>particularly a problem in /V where there are no class comments.
>Coming across the automatically written message

>glorch: aValue
>   "Set the value of the instance variable glorch to aValue"

>    glorch := aValue.

>is annoying (to say the least), when there is no indication what kind of
>a thing glorch is or what it is used for.

>-- 
>--
>  Alan Knight   knight@mrco.carleton.ca  +1 613 788 5783   Support
>  Dept. of Mechanical and Aeronautical Engineering         the
>  Carleton University, Ottawa, Ontario, Canada, K1S 5B6    LPF

You can always enforce some sort of comment using a request for input.
If you are automatically generating access, the method is unlikely
to be complex.

-- 
------------------------------------------------------------------------
Peter Goodall - Smalltalk Systems Consultant - objtch@extro.ucc.su.oz.au
      ObjecTech Pty. Ltd. - Software Tools, Training, and Advice
162 Burns Bay Rd, LANE COVE, NSW, AUSTRALIA. - Phone/Fax: +61 2 418-7433

vernak@cateye.LABS.TEK.COM (Verna Knapp) (05/18/91)

In article <1991May1.042952.6876@m.cs.uiuc.edu> johnson@cs.uiuc.EDU (Ralph Johnson) writes:
>I bet Allan and Kent were arguing about this back in 1986 or 1987
>when they worked together at Tektronix.  I take Kent's side, and
>argue about it with Allan when I see him.  The claim that all
>variable access should be made through messages is nice in theory,
>but the current Smalltalk environment gives the advantage to directly
>accessing variables.
>
(Good argument eliminated here)

>Ralph Johnson -- University of Illinois at Urbana-Champaign

I agree with Kent and Ralph on this one, and I have written several
million bytes of Smalltalk code (Tektronix Smalltalk-80, PPS Smalltalk-80
through V2.5, and the OTI version of Smalltalk/V). At least half of this
code has been maintenance and modification of existing code. I find 
that getter and setter methods actually slow down my understanding of
existing code...I have to go an extra step or two to find out who is
using them and why. I much prefer to modify code which uses direct
access of variables. It is easier to see what is going on. I think 
this "change in only one place" mentality is actually a hangover from
the days when we had to code without browsers. I found it quite useful
when I was programming in assembly language. However, we have a much
more powerful environment now, and that particular standard is a handicap,
not an advantage. 

Verna Knapp
vernak@crl.labs.tek.com