From: ulf on 2 Sep 2006 21:35 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 3 Sep 2006 04:45 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 3 Sep 2006 11:44 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 3 Sep 2006 13:18 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 3 Sep 2006 13:34
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 |