From: ulf on
H. S. Lahman wrote:
>
> The OO paradigm is /designed/ to eliminate the hierarchical
> specification dependencies that plagued maintainability in traditional
> SA/D/P. If an OO application does not do that, then it is poorly formed
> by definition.

Can I rephrase: An OO application is poorly formed if its architectural
style is client-server - It is well formed only if its architectural
style is event-based?
["architectural style" according to Garlan et.al. Eg. in Shaw, Garlan:
Software architecture: perspectives on an emerging discipline.]

It appears to me you are talking about an OO paradigm designed quite
differently compared to the original OO paradigm(s) of
Jacobson/Meyer/Booch/Rumbaugh in the 1990s, where client-server
relationships played a major role.

> [...]
>
> Yes, it is a good solution from a maintainability viewpoint because it
> completely eliminates the hierarchical dependence on what other methods
> do from the original examples. That allows each method to be
> exhaustively unit tested in complete isolation.

But note that besides this advantage, event-based architectures also
have their disadvantages. Cf. Shaw and Garlan.


> [...]
>
> > 1. Reading this again: If you can define methods before messages, does
> > this mean the level of abstraction of message exchange is below the
> > level of methods (How), which is below responsibilities (What)?
>
> No, it is well above it.

Good. I was hoping for this answer.
Could I say: Methods are specified self-contained. [And somehow also
link instantiation is specified.] After I have done that, I can look at
the specified system and visualize - describe, not prescribe - how that
objects in it are interacting qua method specification [and link
instantiation]?

> [...]
>
> <elided possible contents of preconditions>
> <elided the example of possible control flows derived from dependencies>

Thanks for the clarification.


UIf Schünemann

From: Dmitry A. Kazakov on
On Sat, 02 Sep 2006 14:19:03 GMT, H. S. Lahman wrote:

> Responding to Kazakov...
>
>> To me when the type S delegates its Foo to the Foo of the type T, then
>> equivalently S inherits Foo from T, and equivalently, S is a subtype of T
>> in Foo.
>
> That may be a helpful view when dealing with 3GL types systems, but it
> is not the OOA/D view.

OK, as always, we are on different pages. (:-))

>>>No, it is not a relation between types; the types are completely
>>>independnet in a delegation. A delegation just results in a
>>>reallocation of responsibilities among multiple peer objects rather than
>>>a single object.
>>
>> => types are related. You have identified a group of objects sharing some
>> behavior, this is either a type or a class of types to me.
>
> Once the delegation is identified the resulting object abstractions are
> independent peers. There is no sharing.

How so? Clearly T::Foo is shared between T and S. After all, the ultimate
goal of delegation is re-use. How could that happen without sharing?

>> ... presently, in a languages that has no proper support for delegation. In
>> a better language you wouldn't care how S::Foo is routed to T::Foo, exactly
>> as you don't when you call to a virtual method.
>
> Actually, you don't want to do that. The client wants to talk directly
> with the delegatee via relationship navigation rather than using the
> delegator as a middleman.

That is upside down to me. The whole idea is to abstract navigation by
presenting an integral interface instead.

> IOW, objects collaborate on a peer-to-peer basis.

OK, that's the same disagreement between us. There is no peers at the
abstraction level of types. You won't get me back down to the ad-hockery of
individual objects... (:-))

> The problem with using the delegator as a middleman is that the
> delegator no longer has the responsibility so it has no business knowing
> anything about it semantics. That is manifested by maintenance when new
> requirements demand that the interface to the delegatee change. If
> there is no middleman, then only the client and delegatee are affected.
> If there is a middleman, then all three have to change because the
> middleman does a pass-through of the delegatee's interface (i.e., the
> delegatee's properties must be defined in the middleman's interface for
> the client to access the properties). That is a major no-no in OOA/D.

That is why delegation has to be language supported, that is why it must be
inheritance. Because then the language would automatically enforce
necessary semantics on the middlemen.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: H. S. Lahman on
Responding to Ulf...

>>>Yes, *each* method/behavioral-property can be specified self-contained
>>>and in terms of its own input-to-output transformation [at least for
>>>the issue at hand].
>>>But a class can say more about its instances than specify all their
>>>self-contained
>>>knowledge/behavior properties. It can also *relate* several of these
>>>self-contained properties eg. by an invariant. Such an relating
>>>invariant cannot be reduced to the self-constained specification of any
>>>of the object's knowledge/behavior properties.
>>>
>>>How do invariants fit into your presentation of OOA/D founded on
>>>self-constained responsibilities?
>>
>>Per the above, knowledge invariants are part of the precondition for a
>>behavior responsibility and they only apply to input state variable
>>values. In abstracting behavior responsibilities to be intrinsic and
>>self-contained the developer <methodologically> ensures that invariants
>>between behaviors do not exist.
>
>
> OK. Let me rephrase: Don't we need, besides responsibilities for
> behavior and for knowledge also a category of responsibilties for
> (knowledge) invariants? By my understanding of invariants and
> subclassing (cf. DbC), invariants in a class X cannot be completely
> reduced to preconditions of the behaviors in the same class, because
> invariants should also bind subclasses' behaviors, while preconditions
> of X's behaviors have no bearing on the (necessary) preconditions of
> new behaviors in X's subclasses.

Such invariants can be expressed as preconditions, invariant conditions,
and/or postconditions for behaviors under DbC. In an OOA/D context one
relies on method scope to bound the notion of "at the same time", so
invariant conditions on how the method actually executes would be rather
rare. But including knowledge invariants (aka data integrity
constraints) in method preconditions and postconditions is common when
applying DbC to OO development.

At another level I would argue that DbC itself is based on a fundamental
distinction between behavior and knowledge. That is, DbC assumes one
can specify what a behavior does purely in terms of the state variable
values it accepts and what state variable values it modifies. IOW,
there is no demonstrable behavior unless state variable values are
modified. Thus constraints like dependent variables can be expressed in
terms of DbC pre- and postconditions.

Note that this view is quite similar to the view represented by
functional programming where all procedures are standalone functions
that modify inputs to produce outputs. Though the OO approach manages
state data quite differently, the underlying notions of self-contained
behaviors that can be specified purely in terms of changes to state data
are essentially the same.

>>[...]
>>
>>
>>>In model-based specifications, data/state-variables are passive. ...
>>>
>>>In responsibility-based specifications, invariants can be added to the
>>>[few] knowledge properties related by the invariant, ...
>>
>>...
>>
>>My only quibble here is with model-based vs. responsibility-based. The
>>OO paradigm is responsibility-based. OTOH, the OOA/D notation (UML) is
>>model-based. So I am not sure I would contrast the approaches that way.
>
>
> "Model-based [formal] specification"
> cf. http://www.google.de/search?hl=de&q=model-based+specification
> is a standing technical term. UML + OCL (as well as a DbC-contract) is
> such a model-based specification in this sense for the instances of a
> class. UML regards its attributes as passive. They are not given
> responsibilities (other than linking ["knowing" ;^)] a value/object of
> a certain type/class).

And UML was originally designed as an OOA/D notation and is currently
the standard OOA/D notation. One can also argue that the entire OO
paradigm is model-based because it is based upon abstracting (modeling)
some set of problem spaces. So OOA/D is clearly model-based. Hence I
have a problem with contrasting vs. responsibility-based.

OTOH, OOA/D abstracts the essence of an entity in terms of
responsibilities. That is done to keep the definition of what an object
/is/ separate from its implementation. But I see that as more of a
methodological tool to avoid foot-shooting. So I see it as being
characteristic of the OO paradigm, but not in the same league with a
characterization of being model-based.

<hot button>
At the risk of getting off on yet another tangent, OCL is really not
necessary to OOA/D specification. In the MDA profile I use for
translation OCL is very rarely used and then only as static constraints
on relationship participation. Since translation does full code
generation from OOA (MDA PIM) models, the specification is demonstrably
complete, precise, and unambiguous without OCL. (Personally in two
decades of OOA modeling I have never needed an OCL constraint.)

IMO, making OCL an integral part of the UML meta model was a serious
mistake. OCL is just one of many possible constraint languages and I
have no doubt that someday there will be better ones available (if not
already). OMG should have been content to define the necessary meta
semantics of a constraint language rather than anointing a particular
one as The Constraint Language.
</hot button>


*************
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: H. S. Lahman on
Responding to Ulf...

>>The OO paradigm is /designed/ to eliminate the hierarchical
>>specification dependencies that plagued maintainability in traditional
>>SA/D/P. If an OO application does not do that, then it is poorly formed
>>by definition.
>
>
> Can I rephrase: An OO application is poorly formed if its architectural
> style is client-server - It is well formed only if its architectural
> style is event-based?
> ["architectural style" according to Garlan et.al. Eg. in Shaw, Garlan:
> Software architecture: perspectives on an emerging discipline.]

Using "client-server" here carries far too much IT baggage. [Note that
40 years ago the only context where I saw "client/server" referred to
applications talking to reentrant device drivers. B-)]

Also, messages in the OO paradigm do not have to be events. Nor does an
OO application need to be inherently asynchronous. The OOA/D
specification just needs to be implementable in either an asynchronous
or synchronous environment without change. It is serendipity that
asynchronous communications among collaborating state machines happens
to rigorously enforce good OOA/D practices.

However, it would be fair to say the OOA/D (as opposed to OOP) is
message-based.

>
> It appears to me you are talking about an OO paradigm designed quite
> differently compared to the original OO paradigm(s) of
> Jacobson/Meyer/Booch/Rumbaugh in the 1990s, where client-server
> relationships played a major role.

I don't think so. They all advocate peer-to-peer collaboration,
message-based communications, abstraction of intrinsic properties,
implementation hiding (if you don't know it, you can't depend on it),
self-contained methods, etc., etc.. Show me an OOA/D author who does
not regard "god object" as a pejorative.

Even Jacobson's use of "controller" objects was quite different than
Mellor's use in a famous quote:

"The first rule of partitioning control is you do not make controller
objects.

The second rule of partitioning control is YOU DO NO MAKE CONTROLLER
OBJECTS."

Jacobson's "controller objects" are not hierarchical middlemen in a
functional decomposition and they do not coordinate behaviors in other
objects. They simply provide behavior (as opposed to interface and
entity objects) and they collaborate with one another on a peer-to-peer
basis.

Controller objects in Mellor's sense (aka god objects) are higher level
nodes in a functional decomposition tree whose implementations
"hard-wire" rules and policies about how other objects interact and the
overall flow of control of the problem solution. Their behavior cannot
be specified without also specifying what the controlled objects do (or
how they interact). Such hierarchical specification dependencies are
always a no-no in OO applications, regardless of which OOA/D author one
reads.

<aside>
This thread has been going on so long I don't recall whether I have
already mentioned this... The problem with hierarchical structures was
not the structure itself. The problem was that, in practice, they
tended to have a lot of redundancy (i.e., the lower level nodes,
especially at the leaves, were reused in different limbs of the tree).
That redundancy was bad because if a change was needed in a leaf that
appeared in multiple places one needed to do multiple edits.

So instead of simply defining what the fundamental (leaf) processes were
and the sequence in which they were executed, the tree itself became
part of the structure as higher level nodes were created to encapsulate
the common leaf sequences so that they could be defined once and
inserted into the tree in multiple places. IOW, the higher level nodes
were logically implemented in order to provide reuse o shared sequences
of fundamental operations in multiple contexts. That elimination of
redundancy (or tedious sequence specification) solved a lot of
maintenance problems that had plagued software development since the BAL
Days.

However, the reuse of higher level nodes in the hierarchy introduced a
new problem: spaghetti code. That's because the hierarchy was really a
lattice due to the reuse of the same lower level nodes in different
contexts. (That is, if one never duplicated leaf nodes, the lower parts
of the tree would necessarily connect like a lattice as each shared leaf
needed to connect to every higher level node that used it.) If a change
needed for one context was not relevant to another context, one had a
problem. Fixing it in the reused node for one context would break the
other context. No big deal, make a new node just for the new context.

The problem with that was the hierarchical specification dependency.
The behavior that needed to change in a given context was that of the
higher level node, which was all that was visible to the context's
client. But what if the change actually had to be made in a leaf node
several levels lower in the tree? That was entirely possible because
the higher level node's specification to its client necessarily included
the specifications of all the descendent lower level nodes.

Now one is faced with two equally unattractive solutions. The first was
to duplicate the entire tree except for the lower level node. That was
unacceptable because it just reintroduced the redundancy that reusing
nodes was supposed to eradicate. The second was to make the change in
the lower level node. But doing so would break the other context
because that lower level node was essentially reused across contexts.
The only alternative was to reorganize the tree to eliminate the sharing
of the lower level node between the two contexts. That tended to result
in a massive refactoring that led to really ugly code because the
pristine functional decomposition tree would now have a lot of knots in it.

Enter stage left, dancing: the OO paradigm. The OO paradigm effectively
flattens the tree so everybody talks to one another at the leaf level on
a peer-to-peer basis. The paradigm gets around the tedium of sequencing
a plethora of "atomic" leaf operations by introducing the notion of
flexible logical indivisibility. Through abstraction and tailoring to
the problem context, one can define responsibilities that are logically
indivisible yet have arbitrarily complex implementations. Better yet,
the level of abstracti
From: H. S. Lahman on
Responding to Kazakov...

>>>>No, it is not a relation between types; the types are completely
>>>>independnet in a delegation. A delegation just results in a
>>>>reallocation of responsibilities among multiple peer objects rather than
>>>>a single object.
>>>
>>>=> types are related. You have identified a group of objects sharing some
>>>behavior, this is either a type or a class of types to me.
>>
>>Once the delegation is identified the resulting object abstractions are
>>independent peers. There is no sharing.
>
>
> How so? Clearly T::Foo is shared between T and S. After all, the ultimate
> goal of delegation is re-use. How could that happen without sharing?

As I illustrated in the Car example a couple of messages ago, A Drive
Train is not a Car by any stretch of the imagination. They are quite
different things and they share no properties. There is no relation
between their types; there is only a logical association between objects.

>>>... presently, in a languages that has no proper support for delegation. In
>>>a better language you wouldn't care how S::Foo is routed to T::Foo, exactly
>>>as you don't when you call to a virtual method.
>>
>>Actually, you don't want to do that. The client wants to talk directly
>>with the delegatee via relationship navigation rather than using the
>>delegator as a middleman.
>
>
> That is upside down to me. The whole idea is to abstract navigation by
> presenting an integral interface instead.

In OOA/D collaboration is on a peer-to-peer basis. Once the delegation
is done, the delegator no longer has the semantics the client needs. So
the client needs to talk to the delegatee who does have the semantics.

The reason is maintainability. If the Client continues to talk only to
the Delegator, then the Delegator must necessarily present the
Delegatee's properties in its interface. If requirements change such
that the Delegatee's properties must change, then clearly both the
Delegatee and Client must be modified to accommodate the change.
However, if the properties that are modified are also presented in the
Delegator's interface, then the Delegator must also change. Thus the
goal of peer-to-peer collaboration is to ensure one does not have to
also change the middlemen.

>>IOW, objects collaborate on a peer-to-peer basis.
>
>
> OK, that's the same disagreement between us. There is no peers at the
> abstraction level of types. You won't get me back down to the ad-hockery of
> individual objects... (:-))

Dmitry, I got to ask it: what are you doing on an OO forum if you refuse
to accept the most fundamental tenets of OOA/D?


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