[MUD-Dev] Object Models

Travis Casey efindel at earthlink.net
Mon Nov 27 15:01:31 New Zealand Daylight Time 2000


Monday, November 27, 2000, 1:44:49 AM, John Buehler <johnbue at msn.com> wrote:
> Travis Casey writes:

[snip explanation of "tight" vs. "loose" contracts]

>> Thus, changing what all a low-level component will do (e.g., to add a
>> "temperature" variable and make the "sharpen me" behavior take it into
>> account) doesn't mean that you'll necessarily have to change all the
>> code that uses that component.

> 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.

For example, the original "sharpen" contract might have been something
like what follows.

All "edge" components will supply a "sharpen" method.  The "sharpen"
method will be passed the following parameters:

 - A pointer to the object that is doing the sharpening.  This object
   will have a "sharpening" skill value, accessible via the normal
   skill interface.  This object is referred to below as the
   "sharpener".

 - A pointer to the tool or toolset being used to perform the
   sharpening.  This may be the same pointer as the sharpener, in
   cases of machine sharpening or a creature using natural abilities
   to sharpen a weapon (e.g., an earth elemental).  This object will
   have one or more "sharpening-assist" values, indexed by material to
   be sharpened, accessible via the normal tool/toolset interface.
   This object is referred to below as the "sharpening tool".
   
 - An integer value indicating the degree of sharpness desired.  This
   value will be on the standard sharpness scale.  This value is
   referred to below as the "required sharpness".

 - No other parameters will be accepted.
   
It will return:

 - An integer value indicating the degree of sharpness achieved, or,
   in case of failure, the value -1 (object cannot be sharpened under
   current conditions) or -2 (object cannot be sharpened).  In either
   of the latter two cases, the method will issue an explanatory error
   message to the sharpener.  If the sharpener is not a player, the
   sharpener is responsible for passing the error message on to a
   player.

 - Nothing else will be returned.
   
The edge component to be sharpened will:

 - Have a standard "material" component, with appropriate values set
   for "hardness" and "brittleness".

 - Have a "sharpness" value.

The method's action is:
 
 - When applicable, use that material's hardness and brittleness to
   determine the degree of sharpness achieved.  This will be done by
   the standard sharpening algorithm, which is:  .....
   
   If sharpening was possible, the edge will then update its own
   sharpness value to be the result achieved by the prior algorithm
   when the sharpen method is called.  It will also return this value
   to the caller.

   If sharpening was impossible, the value -1 will be returned to the
   caller, and the error message set by the above algorithm will
   be issued to the sharpener via the standard error message
   mechanism.

 - When the sharpening algorithm is not applicable (e.g., for an
   energy blade or something else that cannot be sharpened), the
   value -2 will be returned to the caller, and the error message
   "[Item name with determinant] cannot be sharpened." will be
   issued to the sharpener via the standard error mechanism.

 - The method must do exactly one of the above two alternatives.
   
 - The method may request that the sharpening tool degrade its
   sharpening-assist value, using the standard interface for tool
   degradation, but this is not required.

 - The method may take no further action.
   
------

In this case, changing the contract to require the temperature of the
"material" component of the edge to be factored in would require a
change in code, but would not require a change in the programmatic
interface -- the same things are still being passed back and forth.
(The user interface might change, with a new error message or two
being added, but that's another story.)

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.

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.
   
> For example, some
> blades might sharpen more easily on a hot forge, while others will not.
> This will be confusing to users.  The value of tight contracts is knowing
> what you have - and knowing when you're making changes.  You have to
> acknowledge the fact that you're changing the relationship between
> components and to consider what impact that has on each element of your
> design.  Without it, you end up with screwy behaviors, which are bugs just
> as much as a crash or having the wrong texture on a surface is a bug.

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.

>> The usual problem that I've run into with adding things like that in
>> muds isn't updating objects that use those components -- it's going
>> back and changing everything that's already finished that *should*
>> have used those components.

In this case, if temperature is added correctly, any object that used
an edge component will automatically have its "sharpen" take advantage
of the new temperature support.

However, if some creator on the mud made a variant "sharpen" a while
back that worked a different way, and several creators used it in
different places, then that will cause a problem, since those will not
be updated.  That's the sort of problem I've had fun with.  It's
really more of a quality-control and standardization issue than a
coding issue, but it's still a problem.

--
       |\      _,,,---,,_    Travis S. Casey  <efindel at earthlink.net>
 ZZzz  /,`.-'`'    -.  ;-;;,_   No one agrees with me.  Not even me.
      |,4-  ) )-,_..;\ (  `'-'
     '---''(_/--'  `-'\_)   


_______________________________________________
MUD-Dev mailing list
MUD-Dev at kanga.nu
https://www.kanga.nu/lists/listinfo/mud-dev



More information about the MUD-Dev mailing list