Newsgroups: comp.lang.smalltalk
Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!wuarchive!m.cs.uiuc.edu!cs.uiuc.edu!voss
From: voss@cs.uiuc.edu (Bill Voss;;;356-4652;jerry.cs.uiuc.edu)
Subject: Re: Access methods - New feature ?
In-Reply-To: knight@mrco.carleton.ca's message of Wed, 24 Apr 1991 15:37:44 GMT
Message-ID: <VOSS.91Apr24215444@jerry.cs.uiuc.edu>
Sender: news@m.cs.uiuc.edu (News Database (admin-Mike Schwager))
Nntp-Posting-Host: jerry.cs.uiuc.edu
Organization: Typed Smalltalk Group, Dept of Comp Sci, Univ of IL in Urbana.
References: <VOSS.91Apr22183834@laslo.cs.uiuc.edu>
	<1991Apr23.010026.25098@ccs.carleton.ca>
	<VOSS.91Apr23194435@laslo.cs.uiuc.edu>
	<1991Apr24.153744.24049@ccs.carleton.ca>
Date: 24 Apr 91 21:54:44
Lines: 120

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
