[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Why would anyone want opacity?



> Jeff Dalton wrote:
> 
> > [doesn't matter -- jd]
> 
> I have no idea what he meant by this.
>
> No one has proposed write-only records.  The whole point of
> having opaque records is to allow the implementation of an
> ADT to look inside instances of that ADT while preventing
> client code from doing so.

Humm.  I don't know how anyone could have thought I was saying
anything about write-only records, so I'm not sure what it is
I need to explain to make my meaning clearer.

Perhaps I misunderstood what people meant by "opaque".  I
thought it meant the fields of the record could be accessed
(and modified) only via the proper accessors (and mutators).
With a non-opaque record, OTOH, there would be some other
way to "look inside" (a metaphorical way of speaking that
I thought would fit with the metaphor behind "opaque").
For instance, maybe (record-length rec) tells me the number
of slots, (record-ref rec i) gives me the contents of the
i-th slot, and (record-set! rec i value) puts a new value
in the i-th slot.  (At least that looks like the kind of
abstraction-breaking mechanism someone might object to.)

Now, in most cases no one is going to use record-ref and friends.
It's not like ADT implementations would normally use them all over
the place instead of calling the proper accessors (and mutators).
Nor would someone writing client code be likely to use them.
Neither of these things would happen except in fairly unusual
cases.

Now consider the problem Will Clinger identified in the message
I was replying to:

> It isn't the similarity of the  words that causes the problem.
> The problem comes from forgetting whether you're an implementor
> of the ADT (in which case it's ok to depend upon the representation)
> or a client of the ADT.  This is a conceptual problem that most
> inexperienced programmers seem to have, particularly when they
> spend their morning implementing the ADT and their afternoon
> writing client code (and switching back and forth between the
> two to fix bugs).
> 
> It's a special case of the well-documented problem of switching
> between two cognitive contexts.  It's not a lexical problem at all.

Since the ADT implementor probably won't use record-ref (and friends),
the likelihood of the ADT implementor calling those procedures by
accident (because of a problem in changing cognitive context) when
switching to writing client code should be fairly small -- because the
ATD implementor wouldn't have been using them in the 1st place.  And
students and other inexperienced programmers can stay out of trouble
just by not using record-{length,ref,set!}.

Moreover, if the records are opaque -- if record-ref and friends
don't exist or can't be called on these records -- then neither
the ADT implementation nor the client code can use record-ref.
It's not like the ADT implementation can while the client code
cannot.  [So if opacity lets the ADT implementation do something
client code cannot, it doesn't provide this difference directly.
On the contrary, the ADT implementation and th client code seem to
be in pretty much the same boat.]

So the significance of the ADT "cognitive context switch" issue to
the question of opacity seems at least somewhat limited.

Here's another way to get there.  If "ADTs" were implemented using
ordinary lists or vectors, then there might well be a significant
"cognitive context switch" problem.  Inside the ADT implementation,
there would be lots of calls to ordinary list or vector operations,
and such operations would be common in other parts of the code as
well.  So a programmer might well apply them to instances of the
ADT by accident (e.g. writing MAP instead of SET-MAP).  That seemed
to be the kind of thing Will Clinger was talking about.  But that
problem can be dealt with fairly well just by having record types 
that are disjoint from other types (and using them when defining
ADTs).

That's as far as I went in my earlier message.  But there's
another way ADTs might be relevant, so I expected that someone
might reply as follows:  No, that's not it at all.  The ADT
implementor would define the record inside a lexical scope.
The "proper accessors" (and mutators) would not be visible 
outside that scope unless the ADT implementor made them visible
by assigning them to some more-global variables.  That is how
the implementation of an ADT could look inside instances of that
ADT while preventing client code from doing so.  But if the
records are not opaque -- if something like record-{length,ref,set!}
can be used -- then the client code is not prevented after all,
because, even when the client code cannot get at the (hidden)
"proper accessors", the client code can still look inside another
way.

Well, yes; but would the client code do this by accident?
I think that will be pretty rare.  If it's thought that, say,
record-ref looks like something meant to be used, a different
name might be chosen.  For instance, abstraction-breaking-record-
ref-that-you-should-call-only-if-you-are-sure-you-know-what-you-
are-doing.

Whether or not records are opaque, the ADT implementation can
control the visibility of the proper accessors (and mutators).

> Or at least I thought that was the whole point.  What other
> point could there be?

Well, we are in a thread with the subject "Why would anyone
want opacity?"  ^_^

-- jd