Another newbie question

Alex Martelli aleax at mail.comcast.net
Fri Dec 9 10:44:06 EST 2005


Mike Meyer <mwm at mired.org> wrote:

> aleax at mail.comcast.net (Alex Martelli) writes:
> > Mike Meyer <mwm at mired.org> wrote:
> >> My standard object interface is modeled after Meyer's presentation in
> >> OOSC: an objects state is manipulated with methods and examined with
> >> attributes; manipulating attributes doesn't change the internal state
> >> of the object. This makes it possible to change the internal
> >> representation of a class without having to change all the clients of
> >> the class to match.
   ...
> On the other hand, Eiffel specifically forbids setting attributes
> directly, except for the object they belong to. This is done to
> enforce the design goals I stated above: attributes are the "readouts"

We must have a different meaning in mind for the word "goal"; I take it
to mean, as a web definition says, "the state of affairs that a plan is
intended to achieve".  By this definition, your second quoted sentence
identifies a goal, but the former one doesn't -- it's a MEANS, not an
END, as strongly confirmed by the words "This makes it possible to...".

Enabling internals' changes is a goal, and an important one; doing so by
forbidding the setting of attributes is one way to help achieve it, but
properties are another way, and as a matter of language design it
appears to me to be a better approach.  I haven't used Eiffel "in
anger", just evaluated and rejected it years ago for an employer, but I
have used other languages such as ObjectiveC which follow a similar
approach, so my preference is based on some experience (Ruby, though
strongly influenced by Smalltalk, does let you define attribute-setter
methods, with a net effect similar to Deplhi's or Python's properties).

> for an object, and methods are the knobs/dials/etc. This also ties in
> with the compiler having facilities to check class invariants. If you
> allow assignments to attributes in other classes, the assignments have
> to generate code to check the invariants every time you have such an
> assignment, otherwise a future attribute read may come from an object
> in an invalid state. If you only allow attributes to be set by the
> owning objects methods, then you only have to check the invariants on
> method exit.

What classes' invariants do you have to check in those cases?  E.g.,
consider zim.foo.bar.baz() -- you do have to check the invariants of
bar, foo AND zim, right?  And you must do it with code placed inline
after this specific call, since not all calls to that baz method must
check invariants in foo and zim.  So, what's different about having to
generate just the same inline code for, say, zim.foo.bar=baz ?  Since
your compiler must be ready to generate such checks anyway, forbidding
the second form appears to have no pluses.  Or, in other words, having
to spell zim.foo.bar=baz as zim.foo.set_bar(baz) [[and having to code
boilerplate to implement set_bar]] is a style-choice (common to Eiffel
and Smalltalk, and others) which I consider inferior to the alternative
choice you find in Ruby or Python [[allowing autogeneration of the
implied attribute-setter method if necessary]].

> Different idioms for different languages. Trying to write Python in
> Eiffel doesn't work any better than trying to write C++ in Python.

Absolutely, but here I was discussing language design, not usage of
languages whose design is an external "given".


Alex



More information about the Python-list mailing list