Please see the following link for the most updated version of the AbstractInteractions
This is the PLoP'99 version of this pattern.
Old version using canonical form below.
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.
How can you reduce a component's dependence on other components in its context?
- Define protocols by which components interact separately from the components themselves.
- Codify these protocols as abstract interfaces
- Implement components that rely only on abstract interfaces. That is, components should refer only to abstract interfaces not to concrete classes that conform to the interfaces.
announce events through event listener interfaces. Individual beans have no knowledge of how those interfaces are implemented.
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
, 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.
like the approach that the Eclipse IDE uses to talk to plug-ins)
can be used to implement an interface that is part of an AbstractInteraction?
, in terms of methods of a concrete component type. .
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.)
: 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.
: This one sounds a lot like the underpinnings of a framework. In my Patterns and Software
paper , 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.
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)?
: 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
: 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
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
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
: 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
with those based on inheritance and inverted flow of control.
: 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.
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
: 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
: 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?
I'm not sure I understand how you feel WATD applies to AbstractInteractions
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?
: 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.
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.
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.
Brad, way up above in your first comment, you talked about open implementations. Do you mean Xerox Parc Open Implementation ? 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.
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
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.
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
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
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: