Paul Hemmers lingo OOP Style Guide


[ Zettels Traum ] [ search / suche ]

von dp am 23.August 98 um 18:20:23:

From: Paul Hemmer
Subject: Re: To Me or not to Me

To: DIRECT-L@UAFSYSB.UARK.EDU

Ok, Irv's response on the use of 'me' when referencing properties in
ancestor objects was right on.

However, and for what it's worth, there is another, more subtle problem
with your code. You are referencing specific global variables within a
parent script.. This just doesn't make sense, and violates good OOP
technique.

This is bad because :
1) Objects should be fully self contained.. That is, they should not
rely on the existence of a specific
object to function. I say "specific" because a system should not be
required to have (in your case) a global
variable called "aObj" in order for your object to work with it.
This restricts its use to the system at hand, and
means in order for you or somebody else to reuse it, they have to
declare a variable called "aObj" in their
system. Which leads to ...

2) Objects should be portable (re-usable) in other systems with *no*
modification. In the case of descendant
classes (objects with an ancestor) or a "chain" of objects (an
object which has an ancestor that has it' own
ancestor, which has its own ancestor etc. etc. ) it would seem that
this violates the rule. Not so. This is the
distinction between "is-a" and "has-a" relationships. When an object
(A) has an ancestor (B) then A *is* B,
and the two together can be considered as "virtually" one in the
same. However, one should be able to take A
and stick it into another system with no modification. When a set of
objects are in a "has-a" relationship, there
isn't a violation of the rule. If an object has a property which is
going to be an instance of some other object, the
object will have a method to set the value of that property via a
paramater, or if it's private, will set it in the new()
method, via a paramater.

If you find that these rules don't really hold up in your system, then
your design needs to be re-evaluated
to make sure you have fully abstracted the OO design. By abstraction, I
mean, fully discovering all the classes your system needs, making sure
each one has a _concise purpose and function_ and as few dependencies as
possible. (Dependencies are the elements of "is_a" and "has_a"
relationships)

For example, consider the following simple system, with say a MAN and a
WOMAN with the following properties :

(some of the property names are kind of rediculous, all I could think
of to make the point obvious.)
===============
classMan
property name, height, weight, beardLength
methods : getName, getHeight, getWeight, getBeardLength

classWoman
property name, height, weight, gestationPeriod, childrenBeared
methods getName, getHeight, getWeight, getGestationPeriod,
getChildrenBeared
===============
You might think "sure, man, woman.. two classes for two distinct things"
But, this can be further abstracted as follows (and as I'm sure is
quite clear to you)

===============
classPerson
property name, height, weight
methods : getName, getHeight, getWeight

classMAN
property ancestor, beardLength
(ancestor will be a PERSON)
methods : getBeardLength

classWOMAN
property ancestor, gestationPeriod, childrenBeared
(ancestor will be a PERSON)
methods : getGestationPeriod, getChildrenBeared
===============
This abstracts all which is common to both MAN and WOMAN into it's own
class, PERSON which is more abstract, and further re-usable. (For
example, if you decided to have a classChild, classTeacher, classBoss
they would all extend from classPerson rather than having to give the
PERSONs functionality (through recoding) to each of the new classes
(child, teacher, boss) Taking the time to properly design and abstract
your system will result in an easier to follow structure, which is
highly re-usable. Functionality which is *hightly specific* to the
system at hand, and will not have any other uses will be kept at a
minimum. These are the classes at the lowest level of abstraction.
Another hint that your system isn't fully abstracted could be that you
find you are cutting and pasting code from one class into another class.
This is a sure sign that functionality can be abstracted into its own
class, thereby further abstracting your design.

So, in reference then to your code, I'm assuming you instanced an object
into global aObj somewhere along the lines. Then you wanted to create
another object, which uses aObj as its ancestor. To do this you put a
specific reference to a global variable within your parent script.
(Alarms should be going off in your head right about now!)

While that will work just fine, and Director won't complain about it,
it's not good OOP style (as I have hopefully described)

What you should do, is one of the following :

1) Have the new() method in your parent script create the instance of
whatever parent script aObj was instanced from :

property ancestor
on new me
set ancestor = new(script "whatever your global aObj was instanced
from)
return me
end

-OR-

2) If the ancestor object already exists :

property ancestor
on new me, dAncestorObject
set ancestor = dAncestorObject
return me
end

You still have your global aObj, only you would pass it into the new()
method of your script, rather than directly referencing it from within
the new() method of your script.

That way, your object is not relying on a global variable, called aObj,
existing within the system to work, it only needs to be told at time of
birth, what it's ancestor should be.

Well, sorry to ramble, hopefully some of this made some sense to you
(and anybody else reading this post)

good luck
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Paul Hemmer - Multimedia Software Developer



Dazu:























D. Plänitz