[MUD-Dev] Object Models
John Buehler
johnbue at msn.com
Mon Nov 27 21:36:49 CET 2000
> Travis Casey writes:
> Monday, November 27, 2000, 1:44:49 AM, John Buehler
> <johnbue at msn.com> wrote:
> > Loose contracts give you room to add behaviors, but it also limits the
> > things that the client of a contract can rely on. If you have
> a component
> > that has temperature and a component that doesn't, yet the 'sharpen'
> > contract makes no statement about the need for temperature
> information, you
> > may get some unusual behaviors that you don't want.
>
> I think this is getting to a different point than I was talking about.
> Let me see if I can be clearer:
>
> A contract specifies what must be supplied and what must be returned
> -- but there's nothing in the idea of a contract that requires that
> everything that is supplied be explicitly passed as a parameter. This
> leaves room for later revision of contracts without necessarily
> changing the code interfaces.
I agree that a contract does not implicitly require that everything be
available as a parameter. But a strict contract will usually make as useful
a statement about what the method does as is possible, regardless of where
the method goes for its information.
> For example, the original "sharpen" contract might have been something
> like what follows.
[example snipped]
The contracts that we were writing were very precise. English language only
explained the intent of the precise contract, which was actually expressed
in a kind of contract code language. All components are represented by a
logical data structure (regardless of the actual implementation), and the
contracts expressed themselves as a series of preconditions and
postconditions to its operation. The actual algorithm used by the method
was very intentionally left out. That's because the way that the component
does its thing is the very crux of why we want components - we want to swap
out one way of doing that something with another way. We want to be able to
change the way that something is accomplished, without changing the before
and after, which are assumed to be stable by the system designer. Changing
the before and after means a change of contract.
I'm still leery of getting into the design of a skill system as an example.
I'm not sure how I'd structure it.
Some comments on your example:
1. You have an error handling case where an object cannot be sharpened.
This is an example where strict contracts and strong typing prevent the
possibility of that happening. A component that cannot be sharpened can't
even represent itself to the sharpener. The sharpen method requires that
the component passed to it be an 'edge' component. This would be checked at
compile time, not runtime. This is one reason why weakly typed languages
are a pain in the backside. Error handling was called "One of the four
unsolved problems in software engineering" by one of our consultant types.
I forget what the other three are ;)
2. As I mentioend above, specifying the algorithm used by a method is
generally a very restrictive thing to do. If there's a standard algorithm
that must be used, that's more of a process issue with your development
organization. A contract might impose space or performance restrictions on
the algorithm, but rarely would you want to say that a specific algorithm
must be used. If the algorithm has observable (and required) side-effects,
then those side-effects should be part of the contract.
> I would think that this is a "tight contract" for the sharpening
> method -- it specifies what will be passed in, what will be passed
> out, and what will be done, with no exceptions or changes allowed.
> However, there is still "looseness" in the interface -- if, for
> example, the contract were changed so that the sharpener's Dexterity
> score were also required, it would be accessed through the pointer to
> the sharpener, so a new parameter in the method call would not be
> necessary. Similarly, adding the temperature requirement does not
> affect the calling interface.
Querying for additional information from a parameter is really really
dangerous. Meaning 'related' information. The question is one of whether
you can represent the availability of that additional information in the
static type of that parameter. Is the type of the parameter 'Object', where
you go querying it for possible capabilities, or is the type of the
parameter 'ObjectWithRelatedDescriptor'. In the latter case, you MUST have
that related descriptor. Eliminating the runtime querying and possibility
of failure ensures that the system doesn't start degrading when you forget
to upgrade such-and-such a component. Sure, the system keeps working in a
degraded fashion. Lots of people think that's the cat's meow - I have a
system that isn't built correctly, but it still runs. Oh goodie. Just what
I wanted to deploy to my customers. Wouldn't you rather know that your
system isn't going to work the way you thought it was?
> This is what I meant -- that sometimes, changing what's done does not
> require changing the interface that's exposed to other modules. This
> is true even with a tight contract.
That statement alone is certainly one I can agree with. The line of what is
significant to the contract and what is not is far too subtle to discuss in
a mailing list.
> Exactly -- but a tight contract doesn't require that all values used
> be passed in as parameters via the standard calling interface -- they
> may be accessed through calls to objects that are passed in, like the
> "sharpening" skill and "sharpening-assist" value in the above
> contract.
Agreed.
JB
_______________________________________________
MUD-Dev mailing list
MUD-Dev at kanga.nu
https://www.kanga.nu/lists/listinfo/mud-dev
More information about the mud-dev-archive
mailing list