From: kk_oop on
Hi. I'm working on an architecture consisting of a group of
interacting components. By a component, I mean a cohesive group of
classes that offer their behavior to other components through a well
defined interface. Aside from the interface, all other details are
hidden from external components.

I'm defining an approach to make the component interfaces "well
defined." To do this, I'm using "design by contract" ideas. The
contracts are being defining in terms preconditions and
postconditions. These are defined in terms of a notional domain model
for each component. It's essentially the technique described in Craig
Larman's Applying UML and Patterns: An Introduction to Object-Oriented
Analysis and Design and Iterative Development.

For instance, a Widget Factory component may offer an allocateWidget
service. To define the behavior of allocateWidget, I'd create a class
diagram with a notional domain class called Widget and one called
Widget Factory. I'd show a relationship between these classes. Then,
taking Craig Larman's approach, I'd define an allocateWidget post
condition stating that a Widget instance was created and an instance
of the relationship between WidgetFactory and Widget was created.
This contract and the domain class diagram would be made available as
part of the component's "black box" documentation.

So that's the general approach.

My question is this. Should I be defining contracts for a component's
periodic behavior if it impacts the domain model? Technically, a
periodic is not visible to a client, so it can be seen as an
implementation detail. However, if that periodic is changing the
domain model in such a way that it can impact other services'
preconditions, it seems to me that the periodic contract should be
made visible to clients. For instance, in the example component
above, if a periodic were deleting a Widget under certain conditions,
it seems to me that this should be made visible to clients, and a way
to make it visible would be to make the periodic's contract visible to
the clients.

Any opinions would be greatly appreciated!

Thanks,

Ken

From: H. S. Lahman on
Responding to Kk_oop...

> My question is this. Should I be defining contracts for a component's
> periodic behavior if it impacts the domain model? Technically, a
> periodic is not visible to a client, so it can be seen as an
> implementation detail. However, if that periodic is changing the
> domain model in such a way that it can impact other services'
> preconditions, it seems to me that the periodic contract should be
> made visible to clients. For instance, in the example component
> above, if a periodic were deleting a Widget under certain conditions,
> it seems to me that this should be made visible to clients, and a way
> to make it visible would be to make the periodic's contract visible to
> the clients.

I'm not quite sure what you mean by "a periodic". Do you mean some
object is doing things concurrently according to a fixed time schedule?

Assuming that is the case, then how does that object delete the Widget?
Surely it must use the same Facade interface the other objects use to
interact with the encapsulated objects. If so, then there may be a
dependency between the interface methods. For example, one might not be
able to invoke allocateWidget if there is already one there so one must
wait until after deleteWidget is invoked.

If that is the case you will have to somehow define that contract
constraint for the Facade class you are using as an interface. That gets
tricky because the precondition will be based on the internals (i.e.,
whether a Widget exists) that the client is not supposed to know
anything about.

So what one needs to do is convert the constraint into semantics that is
meaningful in the client context. IOW, there must already be some
conditions in the external context that determine when deleteWidget and
allocateWidget need to be invoked. One needs to define a condition for
the external context that captures the sequencing constraint. That might
be as simple as an isWidgetAvailable attribute in an object outside the
Facade that is set when allocateWidget is called and reset when
deleteWidget is called (i.e., the precondition on calling allocateWidget
becomes "isWidgetAvailable = FALSE").


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl(a)pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info(a)pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH



From: kk_oop on
On Mar 1, 12:20 pm, "H. S. Lahman" <h.lah...(a)verizon.net> wrote:
> Responding toKk_oop...
>
<snip>
>
> I'm not quite sure what you mean by "a periodic". Do you mean some
> object is doing things concurrently according to a fixed time schedule?
>

Thanks for you response!

Here's what I mean. A component service like allocateWidget starts a
timer and gives it a callback method. The callback method is not a
blackbox component service. It is a method on an implementation class
inside the component. Eventually when the timer expires (long after
allocateWidget has completed), the callback method checks some
condition then, based on that condition, deletes the Widget.

Now let me distinguish between the domain class Widget from the
implementation class Widget. In the implementation, Widget may be
implemented by a number of classes, especially if a state pattern or
something like that is being used. The domain class Widget is purely
notional. It is only meant to represent the concept of Widget and its
possible states (shown as notional attributes). It and the rest of
the domain model exists just to represent the main concepts
manipulated by the component--and thus to be referenced by the
component's service's contracts. As Larman recommends, a
postcondition is deletion/creation of a domain class instance,
deletion/creation of a relationship between two domain class
instances, or the change of state of a domain class instance.

So let's say that allocateWidget has a precondition that no Widgets
exist. That means that the behavior of the periodic is significant
because it will delete the Widget domain instance. In reality, that
may mean that 10 classes got deleted (if the state pattern was used
and the Widget had 8 states). But from an external component client
point of view, he only cares that the Widget domain instance got
deleted, since that now means he can call allocateWidget.

Now, as you suggest, if the component offered a doesWidgetExist()
service, the client could just check that before calling
allocateWidget, but it just seems like good practice to let clients
now what events may lead to a change in a component's domain model.

Based on all that, do you think the periodic's postcondition should be
exposed to the client?

<snip>

Thanks in advance!

Ken

From: H. S. Lahman on
Responding to Kk_oop...

> Here's what I mean. A component service like allocateWidget starts a
> timer and gives it a callback method. The callback method is not a
> blackbox component service. It is a method on an implementation class
> inside the component. Eventually when the timer expires (long after
> allocateWidget has completed), the callback method checks some
> condition then, based on that condition, deletes the Widget.
>
> Now let me distinguish between the domain class Widget from the
> implementation class Widget. In the implementation, Widget may be
> implemented by a number of classes, especially if a state pattern or
> something like that is being used. The domain class Widget is purely
> notional. It is only meant to represent the concept of Widget and its
> possible states (shown as notional attributes). It and the rest of
> the domain model exists just to represent the main concepts
> manipulated by the component--and thus to be referenced by the
> component's service's contracts. As Larman recommends, a
> postcondition is deletion/creation of a domain class instance,
> deletion/creation of a relationship between two domain class
> instances, or the change of state of a domain class instance.

Alas, I am confused about what you mean by "domain class". It seems like
we are talking about objects here and they are either instantiated or
they are not. What you seem to be describing is a GoF Facade pattern
where some group of objects (your implementation objects for the Widget
functionality) is encapsulated behind a Facade "wrapper" object (the
public Widget). So external clients talk to Widget and Widget
re-dispatches to its "internal" implementation objects.

But in that scenario Widget and all the rest of the objects have
concrete instantiations. So...

>
> So let's say that allocateWidget has a precondition that no Widgets
> exist. That means that the behavior of the periodic is significant
> because it will delete the Widget domain instance. In reality, that
> may mean that 10 classes got deleted (if the state pattern was used
> and the Widget had 8 states). But from an external component client
> point of view, he only cares that the Widget domain instance got
> deleted, since that now means he can call allocateWidget.

Also, who owns allocateWidget? If allocateWidget creates a Widget object
(and the "contained" implementation classes), then it has to be owned by
an object outside Widget. Or is this just intended to be a 3GL
constructor for Widget? Or does one instantiate Widget and then invoke
allocateWidget to create the implementation objects?

I don't like the last because it opens opportunities for referential
integrity problems, especially in a concurrent environment. I would make
sure Widget and its implementation objects were all instantiated in the
same method scope to make life easier for managing referential integrity.

I don't like it as a constructor if it also instantiates the
implementation objects. Constructors are inherently fragile and should
be kept as simple as possible.

Who owns the callback? Is it one of the implementation objects, Widget
itself, of some external object?

It sounds like the Widget Facade object gets deleted by the callback,
which also deletes all of the implementation objects. If so, then any
relationships between external clients and Widget will have to be
removed at that time to ensure referential integrity. So....

> Now, as you suggest, if the component offered a doesWidgetExist()
> service, the client could just check that before calling
> allocateWidget, but it just seems like good practice to let clients
> now what events may lead to a change in a component's domain model.

I'm afraid that was not what I suggested. In a concurrent environment
that just opens up the possibility of race conditions.

I argued that the callback provided should not be an internal
implementation. It should be a responsibility of the domain Widget so it
is visible to external clients. That's because the timer /is/ an
external client. If one does that, then one has a "visible" dependency
between public behaviors and one can define a precondition contract to
enforce it.

But in this case I think there is an obvious state variable to access
for the precondition: the existence of a relationship to Widget. IOW,
the precondition for allocateWidget is that the relationship is not
instantiated.

> Based on all that, do you think the periodic's postcondition should be
> exposed to the client?

I think it is necessarily exposed because the relationships to Widget
must be de-instantiated and that will affect the potential clients.

BTW, the only exception I can think of would be a Singleton pattern.
There might be a business rule that no more than one Widget can exist at
a time so the client /always/ invokes allocateWidget as a static class
method. The Singleton pattern then actually creates only when necessary
because it knows <internally> if there is one yet. (The implementation
objects just have their life cycles tied to the Widget Singleton.) Then
the callback is just a static class method of Widget. If that is the
case, then it is a matter of private implementation of the pattern so,
consequently, its postcondition is not relevant to clients.


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl(a)pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info(a)pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH