Another newbie question

Mike Meyer mwm at mired.org
Sat Dec 10 16:32:42 EST 2005


aleax at mail.comcast.net (Alex Martelli) writes:
> Mike Meyer <mwm at mired.org> wrote:
>    ...
>> Well, the hard-core solution is to note that your class doesn't really
>> deal with the type Bar, but deals with a subtype of Bar for which x >
>> 23 in all cases. Since types are represented by classes, you should
>> subclass Bar so you have a class that represents this subtype. The
>> class is trivial (with Eiffel conventions):
>> class RESTRICTED_BAR
>>    inherits BAR
>>    invariant x > 23
>> END
> Yes, but then once again you have to "publicize" something (an aspect of
> a class invariant) which should be dealt with internally

Contracts are intended to be public; they are part of the the class's
short form, which is the part that's intended for public consumption.
If your vision of invariants is that they are for internal use only,
and clients don't need to know them, then you probably ought to be
considering another language.

> also, this approach does not at all generalize to "bar1.x>23 OR
> bar2.x>23" and any other nontrivial constraint involving expressions
> on more than attributes of a single instance's attribute and
> compile-time constants.  So, besides "hard-coreness", this is just
> too limited to serve.

I believe it's the best solution for the case at hand. It causes the
violation of the invariant to be caught as early as possible. As I
mentioned elsewhere, it's not suitable for all cases, so you have to
use other, possibly less effective, tools.

>> > So, one invariant that had better hold to ensure a certain instance foo
>> > of Foo is not about to crash, may be, depending on how Foo's detailed
>> > structual geometry is, something like:
>> >
>> >   foo.beam1.force_transferred_A <= foo.pier1.max_load_top AND
>> >   foo.beam1.force_transferred_B <= foo.girder1.max_load_A
>> >
>> > The natural place to state this invariant is in class Foo, by expressing
>> > 'foo' as 'self' in Python (or omitting it in languages which imply such
>> > a lookup, of course).
>> 
>> I don't think that's the natural place. It's certainly one place to
>> consider, and may be the best one. However, it might work equally well
>> to use preconditions on the methods that add the beam and pier to Foo
>> to verify that the beam and pier in question are valid. If the
>> attributes of the beam and pier can't change, this would be the right
>> way to do it.
>
> What ever gave you the impression that the loads on beams and piers (and
> therefore the forces they transfer) "can't change"?

Your incomplete specification of the problem. You didn't say whether
or not they could change, so I pointed out what might - key word, that
- be a better solution for a more complete specification.

>> > If I'm not allowed (because you think "it's silly"!) to express a class
>> > invariant in terms of attributes of the attributes of an instance of
>> > that class, I basically have to write tons of boilerplate, violating
>> > encapsulation, to express what are really attributes of attributes of
>> > foo "as if" they were attributes of foo directly, e.g.
>> [...]
>> > (etc).  Changing a lot of dots into underscores -- what a way to waste
>> > programmer time!  And all to NO advantage, please note, since:
>> If you knew it was going to be to no advantage, why did you write the
>> boilerplate? That's also pretty silly. Care to provide reasons for
>> your wanting to do this?
>
> If I had to program under a styleguide which enforces the style
> preferences you have expressed, then the stupid boilerplate would allow
> my program to be accepted by the stylechecker, thus letting my code be
> committed into the source control system; presumably that would be
> necessary for me to keep my job (thus drawing a salary) or getting paid
> for my consultancy billed hours.  Just like, say, if your styleguide
> forbade the use of vowels in identifiers, I might have a tool to convert
> such vowels into consonants before I committed my code.  I'm not saying
> there cannot be monetary advantage for me to obey the deleterious and
> inappropriate rules of any given arbitrary styleguide: it may be a
> necessary condition for substantial monetary gains or other preferments.
> I'm saying there is no advantage whatsoever to the organization as a
> whole in imposing arbitrary constraints such as, "no vowels in
> identifiers", or, "no access to attributes of attributes in invariants".

True. But if you think this is an arbitary constraint, why did you
impose it in the first place?

>> >> of. Invariants are intended to be used to check the state of the
>> >> class, not the state of arbitary other objects. Doing the latter
>> >> requires that you have to check the invariants of every object pretty
>> >> much every time anything changes.
>> > ...in the end the invariant DOES have to be checked when anything
>> > relevant changes, anyway, with or without the silly extra indirection.
>> No, it doesn't have to be checked. Even invariants that don't suffer
>> from this don't have to be checked. It would be nice if every
>> invariant was checked every time it might be violated, but that's not
>> practical. If checking relationships between attributes attributes is
>> the best you can do, you do that, knowing that instead of an invariant
>> violation raising an exception after the code that violates it, the
>> exception may raised after the first method of your class that is
>> called after the invariant is violated. That's harder to debug than
>> the other way, but if it's the best you can get, it's the best you can
>> get.
> Let's silently gloss on the detail that calling "invariant" something
> that is in fact not guaranteed not to vary (or at least not to vary
> without raising exceptions) is a recipe for semantic confusion;-)  The
> point remains that forcing me to define a beam1_load method, which just
> delegates to beam1.load, and use beam1_load in my invariant's code
> instead of beam1.load, is a silly rule -- yet it follows from the
> stylistic prohibition on using beam1.load directly there, which
> highlights the fact that said stylistic prohibition is silly in its
> turn.

Yes, it's a silly rule. Why did you impose it?

>> > But besides the wasted work, there is a loss of conceptual integrity: I
>> > don't WANT Foo to have to expose the internal details that beam1's
>> > reference point A transfers the force to pier1's top, etc etc, elevating
>> > all of these internal structural details to the dignity of attributes of
>> > Foo.  Foo should expose only its externally visible attributes: loads
>> > and forces on all the relevant points, geometric details of the
>> > exterior, and structural parameters that are relevant for operating
>> > safety margins, for example.
>> You're right. Choosing to do that would be a bad idea. I have no idea
>> why you would do that in any language I'm familiar with. I'd be
>> interested in hearing about the language you use that requires you to
>> do that.
> Eiffel PLUS your constraint against using attributes' attributes in an
> invariant (language + additional constraint you desire)

No, that's *your* constraint. I can think of no rational reason you
would want to impose it, but you have.
>> >> Invariants are a tool. Used wisely, they make finding and fixing some
>> >> logic bugs much easier than it would be otherwise. Used unwisely, they
>> >> don't do anything but make the code bigger.
>> > I disagree, most intensely and deeply, that any reference to an
>> > attribute of an attribute of self in the body of an invariant is
>> > necessarily "unwise".
>> So do I.
> Yet you called it "silly" -- which DOES imply "unwise" (and more).

No, I called one specific example silly. Yesterday, I fixed a bit of
python that did:

       datetime = str(datetime)
       year = int(datetime[x:y])
       # and so on to pull month, day, hour, and minute out

I'd call this use of str, int and slicing silly as well. You would
apparently therefore conclude that I think *any* use of str, int and
slicinng is silly. You'd be wrong to do so, just as you were wrong to
conclude from my thinking that one particular example of referencing
an attributes attribute in ann invariant that any use of an attributes
attribute in an invariant is silly. That particular straw man is
strictly *your* creation. If you want it justified, you're going to
have to do it yourself.

>> >> > I'm also quite dubious as to how you can then express some
>> >> > invariants that can be very important
>> >> Not all invariants, pre-conditions or post-conditions can be
>> >> expressed.
>> > Not all can be sensibly CHECKED, but most definitely all can be
>> > EXPRESSED.  Another one of my long-standing contentions with Eiffel is
>> > the inability to express invariants (and pre- and post- conditions)
>> > because the compiler is unable to figure out a decent way to check them;
>> > Z and the VDL, just to name very old design languages, show easy ways to
>> > allow full expression.  Of course, if a condition is of the form, say,
>> > "all items of potentially infinite iterable X satisfy predicate P", it
>> > may not be runtime-checkable -- big furry deal, I want to be able to
>> > EXPRESS it anyway, because apart from runtime checking there are other
>> > precious uses of such conditions (e.g., the compiler might be able to
>> > DEDUCE from such a condition some important optimization, or the
>> > compiletime proof of other assertions, when run in the appropriate
>> > mode).
>> 
>> So you think that a tool being imperfect means you shouldn't use it
>> all? So you don't test your code, because testing can't reveal all
>> bugs? That's odd - I always thought that testing was a critical part
>> of program development. I'd be interested in hearing about any
>> research that justifies doing development with testing, preferably
>> with URLs.
>
> Start with:
[...]
> and feel free to come back and ask for more once you've exhausted the
> wealth of pointers, articles, books and surveys these URLs will direct
> you to.

Sorry, I misspoke. I meant to ask you to justify your believe in doing
development *without* testing.

       <mike
-- 
Mike Meyer <mwm at mired.org>			http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.



More information about the Python-list mailing list