From: maxtal@extro.ucc.su.OZ.AU
Newsgroups: comp.lang.c++
Date: 18 Jul 92 08:27 MDT
Subject: Re: many set/get member functions in a 
Nf-ID: #R:1992Jul08.121838.13948@jho.com:2043735141:1992Jul18.042727.20354@ucc.su.oz:-176646010:001:7670
Nf-From: extro.ucc.su.OZ.AU!maxtal    Jul 18 08:27:00 1992


In article <rmartin.711378328@thor> rmartin@thor.Rational.COM (Bob Martin) writes:
>maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller) writes:
>
>|In article <9219706.1120@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) writes:
>|>maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller) writes:
>|>
>|>>	I would claim that
>|>>
>|>>	1) private variable, public get and set routines
>|>>	2) public variable
>|>>
>|>>	have the same interface.(Except for syntactic sugar).
>|>
>|>Yes, the interface is the same, but (2) puts rather severe constraints on the
>|>implementation :-)
>
>|	No, it puts severe constraints on the SEMANTICS and does
>|so visibly and publicly. This has the DESIRABLE effect of PREVENTING
>|the sorts of changes to semantics without warning that you outline
>|below.
>
>John:  It is the semantics that we want to hide.  We don't always want
>the clients to know the semantics of the objects it is dealing with.

	How can they use them if they don't know what their semantics are?
>
>Having said that, let me define "semantics" as I have just used it.
>
>     The semantics of an object is the combination of its behavior and
>     interface.  Any change to the interface of an object, changes
>     that object's semantics.  
	
	Yes.

>Any change to the behavior of an
>     object, whether visible 

	Yes

>or invisible 

	No. Contradiction. If the behaviour changes invisibly,
it hasn't changed at all because you can't tell. Please
see Skinner, behaviourism REQUIRIES that behaviour be
observable.

	Semantics is meaning.

>to its clients, changes it's
>     semantics. 
>
>You have claimed that clients wan't to know when the semantics of the
>objects they use change.  This protects them from changes sneaking in
>that they are not prepared to handle.
>
>I strenuously disagree with this assertion.  

>benefits of OOP/OOD is that changes in behavioral semantics can be
>made utterly irrelevant to clients.  This is what abstraction is all
>about.  

	I do NOT agree. Quite the contrary, the idea of abstract
classes, and abstraction in general is to provide a model
with FIXED IMMUTABLE SEMANTICS.

	Consider for example the definitions in mathemtaics
of VECTOR SPACE, or if you like COMPLEX NUMBER or again GROUP.

	These are abstractions. If the behaviour of a class
representing a group changed at the level of the abstraction
it WOULD NO LONGER BE A GROUP.

	Some languages, like C++ provide almost no way of
enforcing semantics. Eiffel has rudimentary provision
for it:
	INVARIANT
	PRE-CONDITION
etc

	These facilities are still not 'semantics' but they
do help in its definition.
>
>An abstraction, is an object whose behavioral semantics are not
>entirely known.  That's why it is abstract.  

	Yes. So the abstract class is use TO FACTOR OUT THE
PUBLICLY VISIBLE BEHAVIOUR which meets some semantic criteria.
All else is either irrelevent or implementation detail.

	Here is a characterisation:

	Implementations present some private set of states
and implement operations on them, precisely what the
public interface and spec does.

	The operations at the public level on the public 
states are constrained in some way by invariants,
laws of behaviour, etc. 

	Those constraints ARE the abstraction and ARE
the semantics and MUST be immutable.

	If you change the representation and the relationship
to the publkic states appropriately, you might get
a more efficient representation and you WANT to be able
to do that without the public knowing right?

	You must keep the contract: you can change the
implementation details but NOT the public meanings
of the operations on the public state.

	C++ is capable only of detecting changes in
semantics at the interface level. Eiffel can detect
at run time admittedly, changes in declared class
invariants which is much better than nothing.
IF we had a super language that could detect
ANY change in meaning it would be great.
You could then ENSURE that all derived objects,
whether newly added or changes to old ones,
implementated the SAME semantics at the base level.

	There is ONE case C++ can do just this,
and that is by using a public variable: here the
semantics ARE GUARRANTEED BY THE LANGUAGE.
[const is the only other case, and the guarrantee
is weakened by ability to cast the const away]


>If the client knew all
>the behavioral semantics, it would not be dealing with an abstraction.
>
>The ability to deal with objects as abstract interfaces without
>knowing their behavioral semantics is at the root of polymorphism.  

	NO. The ability to deal with abstractions KNOWING FOR
SURE that all the objects have the same semantics is the root
of polymorphism. The interface is just a special case of
the semantics.


	Consider a vector class, suppose you have + and -.

	If without changing the interface, I swapped the 
	MEANINGS (semantics) of + and -, your programs would fail.

	That is obvious. You MUST conform to the semantics for vectors.


	Now suppose you derive a new class normed-vector.
	You add a function 'norm' giving the vectors length.

	This is a NEW behaviour. But my routines dot know
	or care about normed-vector when dealing with
	plain jane vector. 

>An
>object can be polymorphic precisely because its client makes no
>assumptions about its behavior.

	NO, on the contrary: it is because the client and
the server object have a CONTRACT on PRECISELY what the
behaviour will be, hopefully a contract kept by
all derived classes :-) that polymorphism works.

	If there are some undefined bits of the behaviour,
great, THAT IS PART OF THE SEMANTIC SPECIFICATION 
exactly what bits can change and what can't.

>
>So, back to the point.  Using get/set functions is always preferable
>to exposing a variable through a public interface, because the get/set
>functions provide the ability for abstraction, and hide the semantics
>of the underlying implementation.  A good thing!

	No, the public interface hides implementation details.
Behaviour at the implementation is not relevant, it HAD BETTER
CONFORM to the public behaviour expected.
>
	Lets take an example.
	We have 

	class Animal;
	class Mammal : Animal;

OK? Now when dealing with an array of Animals, you are dealing
with abstractions right? (Even Mammal is still an abstraction).

The detailed behaviours of animals are different. For example

	kilos eat(kilos)

will change each animals weight in a different way, by a different
amount.

I dont care: the SEMANTICS is "on eating, animals weight
changes by some amount". Actually, I might also expect:
the weight of the animal cannot increment by more than the
amount of food eaten. That prescription is ALSO part of
the semantics (but not the interface).


The actual details of how this
happens might be different for mammals than reptiles.
Their interfaces might be different, the semantics
might be different for Mammal and Reptile.

In other words: "Semantics" must be QUALIFIED by specifying
the level of abstraction, and at that level, it MUST NOT
CHANGE IN PRIVATE.

Changing the semantics is like changing the interface: if you
do EITHER you ought to reexamine all uses in your code.
The latter is ENFORCED by C++, the former cannot be in
any language.

So: If you do experiments and refine the formula for how
Mammal put on weight, then clients of ANIMAL don't care.
Clients of Mammal, on the other hand, might
(depending on how you make the change I suppose).

-- 
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
	Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------

Newsgroups: comp.lang.c++,comp.std.c++