Abstract Interactions

[ComponentDesignPatterns | CategoryPattern]

Please see the following link for the most updated version of the AbstractInteractions pattern:

http://jerry.cs.uiuc.edu/~plop/plop99/proceedings/Eskelin1/ComponentInteractionPatterns.pdf

This is the PLoP'99 version of this pattern.


Old version using canonical form below.

Context

The context in which one uses a component includes the other components with which it communicates. If a component makes assumptions about how those components are implemented, it becomes hard to reuse in combination with different components.

Problem

How can you reduce a component's dependence on other components in its context?

Solution

Known Uses

JavaBeans announce events through event listener interfaces. Individual beans have no knowledge of how those interfaces are implemented.

The CommonObjectRequestBrokerArchitecture defines object interfaces using an abstract InterfaceDefinitionLanguage (IDL). This defines an abstract protocol between client and the server that is independent of programming language and other implementation details. More complex protocols, such as event dissemination or transactions, are defined in terms of IDL interfaces.

The same holds for DistributedCom, JavaRemoteMethodInvocation, DCE RPC and many other middleware platforms.

Darwin/Regis defined component interfaces in terms of provided and required services, where services were typed. Each service type defined an interaction protocol to be used between communication endpoints at the components interfaces.

Example

(This sounds like the approach that the Eclipse IDE uses to talk to plug-ins)

Related Patterns

ComponentGlue can be used to implement an interface that is part of an AbstractInteraction?, in terms of methods of a concrete component type. .

AbstractInteractions are vital for supporting TransparentDistribution. If components interact only through abstract interfaces, a component is unaware whether it is invoking operations of a component in the same address space or a proxy for a component in a different address space.


I have a few questions about the scope of this pattern:

Does a single, named abstract interaction refer only to one primary interface, or does an "abstract interaction" refer to a set of interrelated interfaces?

Am I right in thinking that these interactions can involve bidirectional control and data flows? (For example, the callbacks used in the Observer design pattern.)

NatPryce: Unless very simple, AbstractInteractions are codified as a related set of interfaces. Different components can each implement interfaces of the interaction and control and data flow can occur in any direction between the components, not just as request/reply transactions from clients to a server. Observer-style callbacks are a good example of this.

For example, ActiveX defines several interfaces to support in-place embedding of objects. These interfaces define how a container object queries a contained object for its required size, how a contained object informs its container that its size required has changed, how a container can serialize its sub-objects and so on.

As another example, I have implemented a framework for implementing transport protocols in terms of lightweight components. AbstractInteractions are used to define how protocol layers pass data between each other (ie: they communicate through abstract interfaces). Protocol layers can pass data down the stack through "transmission" interfaces for transmission over the network or up the stack through "delivery" interfaces for delivery to the application. A "device" component would implement the transmission interface and a communication endpoint used by an application would implement the delivery interface. An intermediate protocol component, such as a multiplexor, would implement both the transmission interface and the delivery interface. Components are composed into stacks by pairing interfaces: a layer receives data from a lower layer through its own delivery interface and transmits data via that lower component's transmission interface. But both interfaces together comprise the abstract interaction that defines how protocols communicate and can be connected.

In addition there are further AbstractInteractions that define how parameters of layers can be configured and how they notify higher layers about important state changes.


BradAppleton: This one sounds a lot like the underpinnings of a framework. In my Patterns and Software paper [3], Im so bold as to proffer my own definition for the term "framework":

A software framework ... provides the generic structure and behavior for a family of software abstractions, along with a context of memes/metaphors which specifies their collaboration and use within a given domain. The framework accomplishes this by hardcoding the context into a kind of "abstract machine" (or "virtual engine"), while making the abstractions open-ended by designing them with specific plug-points .... Thus, a framework supplies the infrastructure and mechanisms that execute a policy for interaction between abstract components with open implementations.

AbstractInteractions sounds like this "virtual engine" or "abstract machine" which defines the protocol of this "policy for interaction between abstract components with open implementations." It also seems related to GOF patterns like "Strategy", "Template Method", "Adapter", and "Facade" which encapsulate such policies and/or their pluggable mechanisms. Could you elaborate on that a bit here (particularly upon these connections and similarities)?

NatPryce: Yes, I think AbstractInteractions are one of the important underpinnings of a framework in defining the "policy of interaction" between components. I'm not sure of whether AbstractInteractions are a "virtual engine" or "abstract machine". Those terms seem to indicate (to me) that the functionality has been implemented. AbstractInteractions define how components are meant to interact but don't implement any mechanisms to perform those interactions - that is left up to component implementors.

A framework will typically implement certain roles of its AbstractInteractions, or provide components or ComponentGlue that implement them, so as to help programmers quickly build upon the framework. Is that what you mean by "virtual engine"? If so that is not the main intent of AbstractInteractions. In fact, that could be another pattern for framework designers, named something like PrebuiltFunctionality.

I think that "Strategy" and "Facade" and, especially, "Template Method" are orthogonal to AbstractInteractions since they are concerned with the implementation of components rather than the interactions between them. "Adapter" is useful in combination with AbstractInteractions as ComponentGlue.

BradAppleton: Rest assured that the terms "abstract machine" and "virtual engine" most definitely do not imply the functionality has been implemented. If that were so, there would be no need for the words "virtual" or "abstract" in their name. They mean precisely what you say above, that the rules/protocol for interaction and collaboration are implemented (the policy), but the specifics of how they go about implementing the details which conform to those rules are not implemented (the mechanism). That's where the term "open implementations" come into play.

The component interaction policies are hardwired into the framework, but the mechanisms implementing them, and the components themselves need not be. The "machine" is "abstract", because only the skeleton is there, while the details are deferred. That's also why its like a virtual "engine" of sorts, because the main "driver" of control flow is embodied by the interaction policy, but you can plug in any working components that comply with the policy to implement whatever is possible within the confines of the protocol and its rules. They specify, and codify, only the policy, not the implementation mechanisms.

Many frameworks also supply some default or basic implementations (e.g. PrebuiltFunctionality) but its far from being a prerequisite for a framework, and many of them simply don't do this at all. Even when they do, its not the main service they provide. The predefined defaults are merely a convenience, the real power is in the composability and extensibility and adaptability of the codified collaboration "rules engine" that lets you plug in any and every component you want, so long as its willing to "work and play nice" with others by complying with the interaction policy.

So don't even bother to concern yourself with thinking that these terms might somehow imply implementation of component mechanisms. They don't do that at all (honest ;-) They are not ComponentGlue, they are what the ComponentGlue has to adapt the component to. I think this abstract interaction policy which defines the protocol but leaves open the implementation is exactly what AbstractInteractions seems to be about.

Its not the objects or the components that are being codified, its their associations. Its like taking an object model and erasing all the blocks/circles but leaving all the lines intact. That's what a framework is doing for you (often with abstract base classes or interfaces playing the roles of the "erased" objects) and that's what I perceive AbstractInteractions to be specifying.

The main difference I see here between this and a framework is that AbstractInteractions does not necessarily imply a dominant flow of control ("pull" or "push" for example) whereas a framework tends to use an inverted flow of control (e.g., the Hollywood Principle: "Don't call us, we'll call you"; or the Greyhound Principle: "Leave the driving to us."). I think this is key to understanding how a component architecture can still be a framework of sorts, but can be very different from (and more adaptable/reusable than, though perhaps with more "gluing" effort) an inheritance-based framework that prefers inheritance over composition/delegation. And the better you can flesh out this difference in AbstractInteractions, the better a pattern I think you will have.

I would suggest that patterns like Strategy and Adapter and Template Method and Facade are strongly related here (which is not the same thing is saying they are somehow equivalent). Strategy and Template Method are related because they give specific ways of specifying only the interaction policy while divorcing it from the implementation mechanism. The process of specifying and codifying the AbstractInteractions may well involve the use of Strategies and Template Methods to define where the "hot spots" are and how the interacting components might "plug in" to them. They define what and where the "plug points" are.

Adapter is related not because its a way of realizing AbstractInteractions (it clearly is not) but because its a way of realizing ComponentGlue to "plug-in" other components to these "plug-points". Facade can be used for the very same thing. It can also be used to adapt entire frameworks or collaboration clusters to other frameworks or collaboration clusters and their own sets of AbstractInteractions.

Each set of AbstractInteractions forms a coherent policy or protocol for how things should collaborate. The AbstractInteractions define a sort of micro-world where things interact according to a certain style or metaphor that is related to the contextual or domain-specific goal the framework is trying to achieve. Strategy and Template Method, and Adapter and Facade are related to this because they will typically follow from it, once the policy/protocol has been fleshed out. AbstractInteractions may define a micro-world with a conceptual frame for collaborative work; but Strategy and Template Method help establish the connection-points (or "wormholes" if you want to get Star Trek about it ;-) between those worlds; and Adapter and Facade (and others) are used to bridge those worlds via those communication outposts.

These patterns are related to AbstractInteractions, not because they are similar in result or intent (they aren't), but because they can all work together to achieve the larger result (of full-blown component frameworks and beyond). Im craving to see more details about how to weave them (and the other ComponentDesignPatterns) together in such a manner. And I think getting the AbstractInteractions right may well be the fundamental crux of the matter (so more patterns and guidelines for exactly how to do that are desirable IMHO). -- BradAppleton

NatPryce: Thanks for an excellent commentary. You have described exactly what this pattern is about and exactly how, at least in my experience, it is used in designing frameworks. In my experience, getting the AbstractInteractions right is most important, but also very difficult. More patterns will be added as these discussions stir up and crystallize ideas about how we go about doing this.

I will think about how to integrate your description of the difference between frameworks based on AbstractInteractions and PrebuiltFunctionality with those based on inheritance and inverted flow of control.

PhilipEskelin: Brad, great comments! You frequently amaze me in your ability to articulate yourself. (It's as if you're the Dylan of the patterns community but we can understand you!) One thing I think about is some of the other roles or patterns that can be played in the context of ComponentFrameworks?, which contain AbstractInteractions.

I completely agree with the way you distinguish Template Method and Strategy as being connection-point patterns, Adapter and Facade as being communication outpost bridges, and ComponentGlue's role as an adapter. But what about ComponentGlue being a mediator? The glue isn't comprised of a mediator god object, but it promotes loose coupling since components don't need to refer to each other explicitly and allows you to vary their interaction separately.

ComponentGlue plays more of a structural role as an adapter, and more of a behavioral role as a mediator. A simple mediator example is when an click event comes from a button component. The framework provides the means for event delivery to the point where the glue implements the resulting behavior that is not implemented in the framework or components themselves. Am I off-course on this? I know this is more of a framework thing, but could apply to AbstractInteractions.

BradAppleton: I think ComponentGlue can be any mechanism that bridges the gap between a component, and the "plug-points" provided by the framework with its AbstractInteractions. CORBA pretty much autogenerates adaptor-objects on the fly with proxy stubs as part of the generated code. But Mediator, Subject-Observer, or Publish-Subscribe can bridge this gap as well IMHO.

These patterns not only effect specific communication styles, but I think they can be used (albeit perhaps with other patterns) to help plug-in a component to a framework when the two have seemingly incompatible communications styles. They might be used to "adapt" something that expects a "pull" interaction model (where Mohammad has to come to the mountain ;-) so it can be plugged into a framework that is expecting a "push" interaction model (where the mountain comes to Mohammed ;-)

Nat - you talked about the importance of getting the abstract interactions "right"; well I think JimCoplien's latest book, MultiParadigmDesign for C++ may be of some help here. It talks about commonality, and variability, and types of variability (positive and negative), and performing CommonalityAndVariabilityAnalysis?. And it proposes some methods for how to conduct such an analysis for a domain. Part of getting the interactions "right" is identifying where the hot (soft) and cold (hard) spots need to be.

This is an exercise in determining what aspects of the subsystem or component and their interactions may change versus what may stay the same (the candidate variants and invariants if you will). You can apply this to Phil's mention of Mediator (as well as Adaptor) for ComponentGlue. Adapter is bridging a variance gap between two things. How do they differ: In structure? In protocol? In behavior? What about Mediator? Is the variance to be bridged here concerned with modes of communication or collaboration rather than in structure or behavior? And what part is staying the same? Is it protocol? Is it underlying semantics? Furthermore, when does the variance need to occur (when is it "bound"): is it as coding-time, compile/link-time, load-time, run-time? And where does it happen, or how is it distributed: on the client? on the server? in the network layer? (in the virtual machine?)

Asking these questions and making intelligent answers as to what varies, and what stays the same, and when and where is key to figuring out not only where the hard and soft spots need to be that the AbstractInteractions need to navigate through (playing connect the "hot-spots" instead of connect the dots ;-); It also is key to figuring out the appropriate features and mechanisms for designing and implementing their realization in the software. -- BradAppleton

NatPryce: I don't think that Mediator can really be used as ComponentGlue. The idea of ComponentGlue is to make it easy to perform "non-functional" adaption almost-compatible roles of AbstractInteractions. That is, it should not be used to implement algorithmic functionality (a.k.a. application functionality) because ComponentGlue is less visible, from the architectural view, than the components it glues together. Something that is performing application-specific mediation between components should probably, itself, be a component. As with all design issues, this is IMHO, and your mileage may vary.


I think consideration of WorkAccomplishedThroughDialogs ("WATD") may be useful here. Are we describing the same thing as WATD here or is WATD more concrete? (If WATD is more concrete, we could distill our AbstractInteractions from instances of WATD.)

What do you think?

PhilipEskelin: I'm not sure I understand how you feel WATD applies to AbstractInteractions or ComponentBasedDevelopment in general. Part of the nature of CBD is loose coupling and high cohesion. Therefore, components, frameworks, and instances of AbstractInteractions seem to stay coherent to its purpose, and do their best not to have unwanted or hidden dependencies.

As discussed earlier, AbstractInteractions can utilize the Strategy or Template Method DesignPatterns to basically act as connection point themes, and Adapter and Mediator can be utilized via ComponentGlue to adapt or mediate between components in the context of a framework. How would you envision WATD fitting into this where adaptation or mediation don't? Can you elaborate on your thoughts?

NatPryce: The WATD pattern is describing something similar to AbstractInteractions. The difference between WATD and AbstractInteractions is the abstract nature of AbstractInteractions. WATD shows that objects often need to have a conversation in order to collaborate - pure client/server request/reply relationships are often inadequate. However, it is not saying that those conversations should be codified as a "well defined" protocol separately from the objects communicating. The objects that are taking part in a dialog might know each others exact types, or they might not.

On the other hand, AbstractInteractions explicitly encode such dialogs (or interaction protocols) as abstract interfaces in order to reduce dependence between the communicating components. A component is dependent on the protocol in which it has a role but not on the exact types of the other participants with which it is collaborating.

(Aside: AbstractInteractions are only encoded as abstract interfaces because that is all current languages allow one to do. Maybe in the future, programming languages will allow one to defines interaction protocols in the same way one now defines abstract interfaces...)

The caveats of the WATD pattern - dialogs which include more than two components are a maintenance problem - are reduced if you use ThirdPartyBinding to make the dependencies between components explicit. An ArchitectureDescriptionLanguage can improve matters further, and an architecture visualization even more. A dialog only involving two components is quite rare in my experience.


PhilipEskelin: Another related pattern for AbstractInteractions is the Observer DesignPattern. Component frameworks and components can be plugged into each other applying the Observer pattern for subject-observer notification. It can be implemented via ConnectionPoints in the world of COM. Constrained and bound properties in JavaBeans can achieve a similar concept, but is less flexible.


PhilipEskelin: Brad, way up above in your first comment, you talked about open implementations. Do you mean Xerox Parc Open Implementation [4]? If so, it's interesting you bring it up. I don't want to go insane on theory, since this pattern language is focusing on practice, but one thing I've been wanting to address is base interface/meta interface concepts and things like Meta Object Protocol (MOP) in CBD, specifically in the JavaBeans/EJB, CORBA, and COM worlds.

BradAppleton: Actually, I didn't mean the OI stuff at Xerox Parc, though it did occur to me when I was writing the above. The successor of Gregor Kiczale's and friends Open Implementation project is AspectOrientedProgramming (AOP). Interestingly enough, there are some connections between AOP and AP (AdaptiveProgramming?, as defined by the DemeterProject?). Also, Christine Videira Lopes (sp?) has done research papers for both AOP and AP (and a cross-over paper or two).

These things have some very interesting ties to AbstractInteractions, but they are a bit at the "head in the clouds" or "pie in the sky" level. Id recommend looking to them for possible ideas/inspiration, but don't go too far while your still fleshing these patterns out. Try to stay grounded in what you can feasibly practice today with your industry-available tools and technology. After you've fleshed them out more, you might explore AOP and AP in more depth. (Just my $0.02 of course ;-)

As for MetaObjectProtocol (MOPs) in relation to JavaBeans/EJB, CORBA, and COM/DCOM, I think you might first want to look back at NickJacobs?' Garden of Applications paper from PLOP98 and see where those fit in to your current set of ComponentDesignPatterns. Some of Nick's patterns regarding "bootstrap applications" and "lifecycle management" layers and "application object" are a bit closer to where the rubber meets the road for some of these issues, and Id love to see them incorporated (or at least referenced) and woven together with what you guys have done here. -- BradAppleton

PhilipEskelin: I will follow your suggestion to look more in-depth at NickJacobs?' paper. While I workshopped it with you, I only had like 30 minutes in the back of the Allerton mansion to skim through it. His focused more on Java itself, where perhaps here in the context of this language we will be able to adapt his work to cross-flavor CBD.

AbstractInteractions is great, and a very interesting subject, but what about planned and accidental life and death of components both in the domestic and foreign spaces? Interesting area to pursue next. I just got ClemensSzyperski's seminal Component Software book from Amazon, so I'll see what it contains in this area as well. -- PhilipEskelin

BradAppleton: I think you will find good things in ClemensSzyperski's book. Nick's patterns also address some issues of planned and accidental life & death (that's what is meant by "lifecycle management" in CORBAservices, and also in Nick's PLOP98 paper, though I think he needs to delve into it a bit more. This also gets into issues of naming and naming services and how the names are left or cleaned up from server registries (and also gets into things like JavaSpaces, if you want to meander in that direction).

And I don't know why I failed to mention it before (Nat - you might be most interested in this), but TedFaison?'s PLOP98 paper was all about different kidns of fundamental patterns of interaction that occur not only in software, but in everyday life as well. This might be good for classifying the various types or modes of basic interactions and how to mingle them (and maybe even serve as a basis for CommonalityAndVariabilityAnalysis?).

Whew! I think Im pretty much all "tapped out" on this subject. Feel free to borrow/steal anything Ive said and work it into this pattern so you can factor out much of my ramblings. -- BradAppleton

PhilipEskelin: Brad, your contribution to this discussion has revitalized AbstractInteractions - you're the killer app. Thanks much for participating. Nat, I would agree with looking at Ted's work. It's a paper on "Interaction Patterns". The patterns use a very high-level format, but they are very concise, very comprehensive, and have diagrams that help communicate it well. Check the PLoP 98 Proceedings page at:

http://jerry.cs.uiuc.edu/~plop/plop98/final_submissions/

-- PhilipEskelin


EditText of this page (last edited April 10, 2012) or FindPage with title or text search