home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!mcsun!fuug!demos!kiae!glas!demos!ucc.su.oz!extro.ucc.su.OZ.AU!maxtal
- From: maxtal@extro.ucc.su.OZ.AU
- Newsgroups: comp.lang.c++
- Date: 18 Jul 92 10:19 MDT
- Subject: Re: many set/get member functions in a
- Sender: Notesfile to Usenet Gateway <notes@glas.apc.org>
- Message-ID: <1992Jul18.061906.29676@ucc.su.oz>
- References: <1992Jul08.121838.13948@jho.com>
- Nf-ID: #R:1992Jul08.121838.13948@jho.com:2043735141:1992Jul18.061906.29676@ucc.su.oz:-850869296:001:8090
- Nf-From: extro.ucc.su.OZ.AU!maxtal Jul 18 10:19:00 1992
- Lines: 219
-
-
- In article <rmartin.711379395@thor> rmartin@thor.Rational.COM (Bob Martin) writes:
- >maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller) writes:
- >
- >
- >|If, however, the SEMANTICS
- >|that there be an unconstrained 'variable' in the class,
- >|then making a public variable or function returning a reference
- >|ensures AT COMPILE time that this contract is kept by the
- >|class.
- >
- >It seems very unlikely to me that any properly thought through
- >abstraction would demand that a variable be exposed through its
- >interface.
-
- Yes. And no.
-
- Yes: when I think up abstractions, they're usually
- of the form that has no unsconstrained variables.
-
- No: in practical programming, many things are
- quite concrete, and the program might be a one-off.
- So a simple struct is often the easiest way.
- Sometimes *I* claim, it is correct too.
-
- >
- >An object is an encapsulation of state and behavior, exposed through
- >an interface. The interface has the task of insuring that the
- >invariants of state are maintained. If internal variables can be
- >manipulated from the outside, these invariants may be violated without
- >the object's knowledge, leaving the object in an invalid state.
-
- I do not disagree with this philosophy, although I
- never think in terms of 'behaviours'.
-
- The interface is but ONE aspect of the semantics.
- The semantics, including the interface, should be immutable.
- If I could also specify a class invariant, or even better,
- some axioms, THAT would be the semantics and it would be
- immutable.
-
- >
- >"But", you say, "I have a variable which has no invariants, so it is safe
- >to expose this variable to my clients."
-
- No, I don't say "it is safe". On the contrary, I say
- its exposure in C++ is one of the few ways that one can also
- specify semantics completely and get a guarrantee that
- the semantics cannot be violated.
-
- >
- >Is it indeed? Let me tell you a little story.
- >
- >I once wrote an object oriented application for manipulating icons on
- >a screen. I created a "Point" class which encapuslated a single
- >cartesian coordinate. In my naivete I thought, as you think now, that
- >I should expose the 'x' and 'y' variables.
-
- Hold on, dont jump to conclusions! I would NEVER advocate
- that the x and y coordinates of a point be exposed publically.
- I would ALSO say set_x and set_y functions were naughty.
- I would require you to set BOTH coordinates simultaneously.
-
- >After all, I did not want
- >to have to write a set of accessor functions, that was too much work!
- >Little did I know!
-
- I agree you did it wrong: but NOT for the reasons you
- outline below. I will explain why.
- >
- >Much later, when the project was nearly complete, I decided to add the
- >concept of a constraining grid to the screen. I am sure you have seen
- >constraining grids, they separate the screen into a grid with a
- >spacing of 5-10 pixels or so, and force any positional change of any
- >object on the screen to align to this grid. This makes it easy for
- >the user to line up his icons in staight horizontal or vertical rows.
- >
- >Anyway, I realized that this would be remarkably simple to do, if I
- >created the concept of a ConstrainedPoint, derived from Point. This
- >new abstraction would automatically adjust its coordinates to the
- >grid. The rest of the application could remain blissfully ignorant of
- >the contraining grid. But alas, it was not to be. All through my code
- >there were direct accesses to the x and y variables of class Point.
- >THere was no way for me to insert the constraint in a single place.
-
- But there is. You just didn't think of it.
-
- class ConstrainedPoint : private Point {
- ContstrainedPoint(int x, int y);
- };
-
- >
- >Thus, I created bad situtation for myself. I had to search through
- >the code, finding every use of x and y, and apply the contraint
- >locally. Worse, I created a maintenance nightmare for the company,
- >since now the maintainer must always remember that when they
- >manipulate an x or x they must check for, and apply, the contraint.
-
- Absolutely necessary for you to do this running through
- the code. No way out. You HAVE to change you program
- to use constrained points where desired. Here's why:
-
- I also used your point class.
-
- I dont ALWAYS want constrained points.
-
- I have rectangles: (ICONS for example) and have
- cached all 4 corners.
-
- Now assume you had use set_x and set_y.
-
- Suddenly, my corners are all wrong. (Only the left
- corner of an icon snaps to the grid, the others can't because
- the sieze of the icon is fixed).
-
- But if you used the public variables YOU COULD NOT
- DO THIS NAUGHTY CHANGE TO THE SEMANTICS AND DESTROY MY CODE.
- >
- >Blech!
- >
- >I don't want to hear that the semantics of Constrained_Point were
- >different than the semantics of Point, and so the application should
- >have been changed at every place which used Point.
-
- Well, that is exactly what I am telling you must be done.
-
- >That argument is
- >absurd. I didnt want the rest of the application to know about
- >Constrained_Point.
-
- But I have shown you that SOME parts of the application
- RELY ON THE POINTS NOT BEING CONSTRAINED.
-
- Your idea that you can magically change the semantics
- by using polymorphism is absurd.
-
- >I wanted the semantics of contrainment to be
- >hidden.
-
- I'm glad you used a public variable because that
- PREVENTED YOU HIDING THE SEMANTICS and stuffing up MY
- piece of code.
- >
- >Also, I don't want to hear that I should have anticipated the need for
- >contrainment. That is a useless argument too. If OOP forces me to
- >think of everything in advance, then it is a worthless concept.
-
- Yes, I agree. In class based languages like C++
- the requirement is alleviated: you MUST GET THE SEMANTICS
- EXACTLY CORRECT AND NOT DEVIATE FROM THEM, and then if
- you obey the above rule you are allowed to derive
- new classes.
-
- IF YOU CHANGE THE SEMANTICS (just like if
- you change the interface) THEN YOU MUST REEXAMINE EVERY
- USE. It is best to add a NEW unrelated class sometimes,
- since that leaves all existing code working, esepcially
- MY piece of code that relied on points having unconstrained
- coordinates.
- >
- >But fortunately, when properly applied, OOP does not force you to
- >anticpate every need of the application. By hiding semantics, you can
- >create a system which is flexible enough to withstand many
- >unanticipated changes.
- >
-
- NO. You hide the IMPLEMENTATION.
- You hide irrelevant detail.
-
-
- Constrained points are NOT semantically equivalent
- to unconstrained ones.
-
- HAD you used Constrained points FIRST and then derived
- Unconstrained ones from them as a special case, you would
- have had no problem.
-
- Since you did not have the foresight to do this,
- you had to rework your code. This is as it should be,
- indeed, as it must be, and the fact that it ISNT in practical
- languages is a DISADVANTAGE of the language.
-
- In short: OOP rewards foresight.
-
- In C++ especially, you really MUST get the design
- exactly right and stick to it. In C++ there is a
- MASSIVE shift of effort from programming to design.
- Your reward for working under such stringent constraints
- is run-time correctness.
-
- Each weakening of the constraints leads to decreased
- ability of the compiler to provide guarrantees.
-
- Thus, in smalltalk, you can design anything, but only
- your customers know if it works. At least in C++
- the COMPILER knows something, when a program
- has been compiled *I* have some sense of security
- I could never have in sta.
-
- I would like to see better language support for
- semantics: Eiffel has shown one way.
-
- Then my cached points would have invariants:
- "Distance between two top points equal width of rectangle"
- and I could detect at run-time that you broke your
- contract with me to provide unconstrained points
- EVEN if you had set_x and set_y methods.
-
- As it happens, a public variable would provide that very
- guarrantee even better (although I would not utilise
- that feature in the case of a point)
-
-
- --
- ;----------------------------------------------------------------------
- JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
- Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
- ;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
-
-