Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [cme-dev] Visiting Concerns

Hi Phil,

> In the end, I agree with you that Visitor should be replaced by
composition in
> cases where it is being used to support a kind of open-class pattern.  On
the
> other hand, I think it might be just the trick if you are trying to
> encapsulate traversal.
This makes a great deal of sense. Another limitation of using our
composition
for Visitor is that you can add to the state of the visited objects (which
regular visitor cannot), but there is nowhere to put traversal state - so
regular visitor wins out when you need that. Actually, perhaps the best
approach
of all to traversal is Karl Lieberherr's adaptive programming, which would
be
great to integrate with our composition one day!

Your project sounds really interesting, and I can see such views being
extremely
valuable. It's also great to see this sort of capability being done in the
CME
context. Please continue to ask questions and report problems. I look
forward
to seeing how this progresses.

As you saw from the note Peri sent, the "unloader" (perhaps to be called
"traverser") should fulfil your need for abstracted traversal. So you
shouldn't,
in fact, need composition for this purpose. If you are still interested in
experimenting with composition, let's talk on the phone to discuss what
you'd
like to do and what it will involve.

- Harold


Philip Quitslund <pq@xxxxxxxxxx> wrote on 12/14/2004 08:15:48 PM:

> Hi Harold,

> Thanks for responding!  I agree that composition is cleaner and more
flexible
> than visitor in a number of ways and so I'm sympathetic, philosophically,
to
> your case.  On the other hand, this has practical limitations.  You
mention,
> rightly, that composition does not manage traversal and in cases where
the
> datastructure is simple this is no problem but if it is complex it's a
bit
> burdensome for the client.  Moreover, there is the issue of
encapsulation.  It
> would be nice for the client not to *have to know* about the
> structure of data.
> Now admittedly even with a visitor we often do (I'm thinking of cases
where we
> might have nested visitors) but it is a *bit* more declarative seeming.
That
> is, I contend that:

> composite.accept(new CompositeVisitor() {
> void visit(BranchA b) {
> b.accept(new BranchAVisitor() {
> //...
> }
> void visit(BranchB b)
> b.accept(new BranchBVisitor() {
> //...
> }
> }
>
> is nicer than:

> Branches [] br = composite.getBranches();
> for (int i 0; i < br.length; ++i) {
> Branch branch = br[i];
> if (branch instanceof BranchA) {
> Nodes [] nodes = ((BranchA)branch).getNodes();
> //traverse nodes...
> }
> if (branch instanceof BranchB) {
> // do something else...
> }
> //...
> }

>
> In the end, I agree with you that Visitor should be replaced by
composition in
> cases where it is being used to support a kind of open-class pattern.  On
the
> other hand, I think it might be just the trick if you are trying to
> encapsulate
> traversal.  In my particular case, this is just what I was looking for
--- I
> didn't want to have to "look behind the curtain" to build my
representation of
> Concerns.

> Having said all this it would probably be useful for me to describe
> a bit of my
> motivation.  My interest in the CME is in the context of designing a
system
> (with Andrew Black) that enables programmers to view and manipulate their
> programs from a number of (equally first-class) perspectives.  Views in
this
> system are derived from Concerns and are reified into editable textual
> representations.  Edits to these representations directly effect
theunderlying
> model.  There are many details to work out here but in the short term we
are
> looking at a way to take extracted Concerns and transform them into
> the abstract
> syntax of a simple language that supports crosscutting views.  In this
> language an "implementers of ..." concern derived from the query:

> method * speak()(..)

> run over the 'feline' package might translate into abstract syntax
> that produces
> the following "row-centric" concrete view:

> String speak()
> case Feline { return "prrrrr..."; }
> case Tiger  { return "grrrrr"; }
> case Lion   { return "growl!"; }
>
> that when edited effects the methods in the underlying classes.

> Of course this just scratches the surface of the story but hopefully
> gives you a
> taste.  If you're interested, I'd be happy to tell you more.  As foryou
offer
> to help get me get set up using the ConMan composition mechanism, I'd
love to
> take you up on it.  I also agree that this would be mutually beneficial.
(And
> maybe my instincts about Visitors won't bear out!)  In any event, it
would be
> interesting to find out.

>
> Thanks again,

>
> phil

>
> Harold Ossher wrote:
> > Hi Philip,
> >
> > It's really interesting that you raised this. There is, as you
observed, no
> > visitor support for concern models. This is in large part because we
always
> > tend to think of composition as a better realization of visitors than
the
> > usual approach. Here's how it would work, illustrated with your
example.
> >
> > Typically, the visitor pattern is used to extend an interface - to add
some
> > new capability across an inheritance hierarchy (like the concern
model),
> > implement it separately for selected specific classes, and use dispatch
to
> > pick the right implementation, There's also the actual traversal, but
let's
> > ignore that for a moment.. So, using a composition approach, you write
an
> > extension to the interface, to the top-level abstract class (to do
nothing)
> > and to the classes you actually want to extend. These classes can be
> > top-level classes, or inner classes within a containing "visitor"
class, in
> > your own project. In your case:
> >
> > public interface ConcernModelElement {
> >       public void collectAdvice(Collection c);  // Additional method
> > }
> >
> > public class AbstractConcernModelElementImpl implements
> > ConcernModelElement, org.eclipse.cme.conman.ConcernModelElement {
> >       public void collectAdvice(Collection c) {} // Default
implementation
> > }
> >
> > public class Advice implements ConcernModelElement,
> > org.eclipse.cme.conman.Advice {
> >       public void collectAdvice(Collection c) {  // Specific
implementation
> >             c.add(this.getDefinition());
> >             // c.add(this.getAdviceArtifact);  There is not a special
> > method getAdviceArtifact, but this is how you'd use it if there were.
> >       }
> > }
> >
> > Now you can compose this extension with ConMan (or the cme jar), and
call
> > collectAdvice like any other method. So you would iterate over the
elements
> > you care about, calling this method. The same, or separate, extensions
> > could add other methods.
> >
> > Conceptually, this approach has some advantages over the standard
> > implementation of visitor, such as the ability to add methods with a
> > variety of parameters and return types and avoidance of double
dispatch. It
> > doesn't handle the traversal, through. You could do that by
implementing
> > the collectAdvice() method for GroupImpl, the top-level collection in
the
> > concern model hierarchy, to iterate over the elements. Unfortunately,
there
> > is no way to make this generic across all extensions, as the usual
visitor
> > pattern does, because a specific method name is involved (rather than a
> > visitor object).
> >
> > Unfortunately, we don't yet have the tool support to make the
composition
> > approach really convenient (some classpath manipulation, integration of
> > composition with the Eclipse build process, perhaps some
refactoring/code
> > generation to help set up the structure, ...). Still, I'd be interested
to
> > hear your thoughts on this approach, and if you have time and are
feeling
> > adventurous, we can help you set this up by hand using the lower-level
> > composition support we do have. Together we'd learn something about
what is
> > really needed to support this well. (We might hit some bugs or
limitations
> > in the course of this, which we'd be happy to work on, but our time is
> > limited so we should discuss your time constraints.)
> >
> > Regards, Harold
> >
> >
> >
> >
> >              Philip Quitslund
> >              <pq@xxxxxxxxxx>
> >              Sent by:
To
> >              cme-dev-admin@ecl         cme-dev@xxxxxxxxxxx
> >              ipse.org
cc
> >
> >
Subject
> >              12/13/2004 05:48          [cme-dev] Visiting Concerns
> >              PM
> >
> >
> >              Please respond to
> >                   cme-dev
> >
> >
> >
> >
> >
> >
> > Hi all.
> >
> > Forgive me if this is obvious (and it probably is!) but I'm puzzling
over
> > how to
> > best traverse the structure of Concerns.  What I'm driving at is a way
to
> > take a
> >   Concern and build my own abstract representation.  I was expecting
some
> > kind
> > of visitor scheme but haven't found anything...
> >
> > As a simple example, suppose I wanted to collect all the
AdviceArtifacts in
> > a
> > Concern.  I'd like to avoid code that looks like this:
> >
> >  /* final */ Collection adviceCollector = new ArrayList();
> >
> >  ConcernModelElement cme =
> >   /* ProxyConcernModelElement */ pcme.getConcernModelElement();
> >  if (cme instanceof ConcernImpl) {
> >   ConcernImpl concern = (ConcernImpl)cme;
> >   QueryableRead elems = concern.getElements();
> >   for (Iterator iter = elems.iterator(); iter.hasNext();) {
> >    Object o = iter.next();
> >    if (o instanceof AdviceUnit) {
> >     adviceCollector.add(((AdviceArtifact)o).
> >      getAdviceArtifacts());
> >    }
> >    ...
> >   }
> >   ...
> >  }
> >
> > preferring something more like this:
> >
> > cme.accept(new ConcernVisitor() {
> >   void visit(AdviceUnit advice) {
> >    adviceCollector.add(advice.getAdviceArtifact());
> >   };
> >  );
> >
> > (Admittedly this is an overly simple example, but you get the idea.)
> >
> > What's the best way to programmatically explore the structure of
Concerns?
> >
> > Any help would be greatly appreciated.  Thanks!
> >
> >
> >
> > -phil
> >
> >
> >
> >
> >
> > _______________________________________________
> > cme-dev mailing list
> > cme-dev@xxxxxxxxxxx
> > http://dev.eclipse.org/mailman/listinfo/cme-dev
> >
> >



Back to the top