Interfaces in Ruby

[… socket example elided …]

So you end up adding predicates to the public API of objects to track
the progress of the protocols used to interact with those object. Often
this also requires adding data members to keep track of the current
state of the object.

This is a good example and you raise a good point. Classes that make
their clients overly aware of their internal state is bad coupling for
several reasons, and this adds another reason to that list.

I found that when writing code that had a lot of composition, rather
than inheritance, contracts of classes would end up mirrored in the
interface of other classes that contained them, and in containers of
containers, and so on. If you changed the contract of a component
class, then the change would ripple through the containers. In very
compositional code, it became quite expensive to change contracts.

Interesting. I’ve not noticed this effect in my own code. I generally
think of objects that use composition as a firewall against changes. If
an internal object changes its behavior, then the composing object
should compensate to provide consistent behavior to the client. Of
course, these are general statements and not always possible, so your
point is a valid one.

Hmmm… I wonder if it would be feasible to create a deferred class that
contained the contract. Then the composing class could inherit the
contract and changes to the contract could be automatically propagated.

Thanks for your insights.

···

On Mon, 2002-10-21 at 11:12, Nat Pryce wrote:


– Jim Weirich jweirich@one.net http://w3.one.net/~jweirich

“Beware of bugs in the above code; I have only proved it correct,
not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)

“Nat Pryce” nat.pryce@b13media.com schrieb im Newsbeitrag
news:1035212081.3359.22.camel@ballsup…

[…] Also, in my experience, DbC ends up polluting the class
interface with a lot of predicates, because it doesn’t support the
idea
of protocols, […]

I’m not sure I understand the above comment.

i think i understand the comment but i am not sure whether i can agree the
implications:

Often, when designing classes you define a protocol by which calls can
be made to the object. A simple example, a Socket object has methods to
connect, read and write data, shutdown the read or write stream, or
close both streams. You must call connect before calling read, write,
shutdown or close. Once you’ve called close, you cannot call read or
write again until you call connect again. Once you’ve shutdown the read
stream you cannot read, and similarly for write shutdown.

yepp.

Client code that uses a socket keeps track of the socket state by its
own control flow. A socket can only be in a closed state if it has been
closed by the client code (ignoring errors in this example).

that’s true.

However, to specify this protocol in DbC you have to define
preconditions on whether the socket is open, and those preconditions
have to be defined in terms of public methods. E.g. the read method
might be:
[snip]
So you end up adding predicates to the public API of objects to track
the progress of the protocols used to interact with those object.

is this really that bad? i mean, the pre- and postconditions are a way of
representing the protocol. you could argue that it is not as readable as an
uml sequence diagram. however, my impression is that the protocol is a by
product of a class’s semantics, which are reflected in the contract.

Often
this also requires adding data members to keep track of the current
state of the object.

is this really the case? i mean, taking your socket example your class will
have to store a file descriptor anywhere or something equivalent. if that
descriptor is ni, NULL, -1 or whatever other special value this corresponds
to being closed. the read method has to be able to determine whether the
stream is open anyway. so, to me it seems there is no additional state
necessary.

more abstract: if there is no state already present in a class representing
some protocol state, of which use would a protocol condition be then? if,
from the semantics of the class at hand, there is no distinction which sense
does a special protocol state make? (i’m awfully struggling to find the
right words, so please bear with me.)

i conclude, it is never necessary to add state to support the
protocol.

I found that when writing code that had a lot of composition, rather
than inheritance, contracts of classes would end up mirrored in the
interface of other classes that contained them, and in containers of
containers, and so on. If you changed the contract of a component
class, then the change would ripple through the containers. In very
compositional code, it became quite expensive to change contracts.

the same story for adding / removing method arguments and exceptions.

regards

robert
···

On Sun, 2002-10-20 at 04:12, Jim Weirich wrote:

On Fri, 2002-10-18 at 14:08, Nat Pryce wrote:

I think it’s possible to maintain this illusion, provided:

  1. No two modules mixed into the same class provide two methods with
    the same name
  2. Mixins do not carry any state (and therefore have no initialize()
    method); this is a special case of the first requirement.

I have not yet decided whether I think it is always a good idea to
strictly adhere to these requirements.

Paul

···

On Fri, Oct 18, 2002 at 11:21:17PM +0900, Chris Gehlker wrote:

I consider mixins to be a form of MI. I would go so far as to say
that it is the only form that I’ve actually seen usefully employed even
in C++ code. Your example below and your previous example with is_a
show that it passes the duck test. But even if you want to consider the
it to be “the illusion of multiple inheritance” it’s important to
maintain the illusion. Which is why I think it important to use class
clusters as well as mix-ins.

I was wondering… If you made the contracts “Delegate” classes that are
called at runtime and they had the contract, then any time you changed the
contract, all those who were delegating would get the change, not by
propagation, but just by the link existing. Now how would you implement
those “Delegate Contract” classes. It seems to me that they would be
implemented in the MVC style. They express the contract, but to get the
values, they do a call back to the registered class that they are a delegate
for.

Does this make sense?

···

On 10/22/2002 7:27 AM, in article 1035289773.8156.27.camel@traken, “Jim Weirich” jweirich@one.net wrote:

On Mon, 2002-10-21 at 11:12, Nat Pryce wrote:

[… socket example elided …]

So you end up adding predicates to the public API of objects to track
the progress of the protocols used to interact with those object. Often
this also requires adding data members to keep track of the current
state of the object.

This is a good example and you raise a good point. Classes that make
their clients overly aware of their internal state is bad coupling for
several reasons, and this adds another reason to that list.

I found that when writing code that had a lot of composition, rather
than inheritance, contracts of classes would end up mirrored in the
interface of other classes that contained them, and in containers of
containers, and so on. If you changed the contract of a component
class, then the change would ripple through the containers. In very
compositional code, it became quite expensive to change contracts.

Interesting. I’ve not noticed this effect in my own code. I generally
think of objects that use composition as a firewall against changes. If
an internal object changes its behavior, then the composing object
should compensate to provide consistent behavior to the client. Of
course, these are general statements and not always possible, so your
point is a valid one.

Hmmm… I wonder if it would be feasible to create a deferred class that
contained the contract. Then the composing class could inherit the
contract and changes to the contract could be automatically propagated.

Thanks for your insights.


Sam Griffith Jr.
email: staypufd@mac.com
Web site: http://homepage.mac.com/staypufd/index.html