The Object Teams Blog

Adding team spirit to your objects.

Posts Tagged ‘delegation

Compare Object Teams to AOP?

with 7 comments

In response to our “Hello Eclipse” I was asked about “the distinction between OT, AOP and delegation
and also Wayne suspected some overlap. So here’s an attempt at answering.

What OT/J is not

If the only problems you see with pure Java are of the kind as non-invasively adding
tracing/logging to a system, than you’re probably fine with AspectJ and OT/J does not
compete for a better solution in this discipline. This is because AspectJ is specialized
at defining sophisticated pointcuts: use powerful patterns and wildcards to capture
a large set of joinpoints that shall trigger your aspect.

I’m personally not enthusiastic about targeting problems of this category because
the focus is too narrow for my taste. So in this league where AspectJ performs best
OT/J is not applying as a replacement for AspectJ.

Goals for OT/J

Positively speaking, let’s call five toplevel goals for OT/J:

  1. powerful modules
  2. powerful ways of connecting modules
  3. maximum support for re-use
  4. evolvable architectures
  5. intuitive metaphors

Most of these goals are so broad and common place, that we’ll soon agree that
we all scream for ice cream. For (1) classes, objects and bundles are a pretty good
starting point. Not much need to improve. For (3) & (4) the proof of the pudding is
only in the eating. You can’t directly boil them down to specific language features.
(5) is what makes a language suitable for manipulation by humans, it’s the least
technical goal in the list and thus ‘difficult’ to discuss among geeks 🙂

The issue of connecting modules (2) is, however, extremely interesting and creates
the backbone for anything we can say about an architecture. And this is where OT/J
excels in my view, based on three kinds of relations:

  • OT/J takes inheritance to the extreme
  • OT/J introduces a real meaningful containment relation
  • OT/J introduces the role playing relation

Mentioning inheritance lets me add that we pay very close attention to not
side-step object orientation, but rather to put object orientation on steroids.

As I’m zooming in I will leave inheritance and containment aside for now
so as to focus on the role playing relation.

Role playing

The way role playing is defined in OT/J it is actually very similar to inheritance
with three decisive differences

  • role playing is a dynamic thing happening among runtime instances
  • role playing separates two sides of inheritance: acquisition and overriding
  • control is more fine grained as individual methods (and fields) can be acquired
    and overridden selectively

This dynamism is one of the strongest points in OT/J: roles can be added to specialise
existing instances at any point during runtime and multiple roles can specialise the same
base instance simultaneously. Neither is possible if inheritance is defined between
classes rather than instances. Yet, OT/J is not careless about possible runtime effects,
so in order for a role instance to be attached to a base instance the role’s class must
statically declare a playedBy relation to the corresponding base class. The ensures that
possible runtime effects are analysable from the source code.

Ingredients to role playing

Separating acquisition from overriding yields the following pictures of possible
communications between a role and its base
– in all pictures assume a role class with this header:

public class ARole playedBy ABase { ...
 

Here we go:

Forwarding a call due to a callout binding

Here class ABase implements baseMethod() which ARole would like to “inherit”.
It does so by this little callout declaration:

void roleMethod() -> void baseMethod(); // make baseMethod known under a new name
 

Now when a client sends a roleMethod() call to the :ARole instance, this is
automatically forwarded to the associated base instance, invoking its baseMethod().

Great, so a role may acquire individual methods from its base using callout.
No big deal so far.

Here’s the opposite direction:

This time the client talks to the :ABase instance saying “baseMethod()”.
Assume that the role has defined this callin binding:

void roleMethod() <- replace void baseMethod();
 

Now the original method call is intercepted and redirected to the role.
This has the same effect as overriding has in traditional inheritance.

The full glory only shines when both directions are involved in the same control flow:

This picture shows the role version of the template&hook pattern: :ARole inherits the
template method baseMethod2() which issues a self call to the hook method baseMethod1().
Even during this self call, method dispatch may be aware of the overridingM() in the role,
which intercepts the self call.

This situation is what is widely termed as delegation in the literature:
forwarding with the option to still override methods called within this control flow.

Comparison

Now that I have elaborated on the role playing relation in OT/J, how does it compare?
To AOP? To delegation?

Role playing vs. delegation

Role playing supports full delegation with overriding. In OT/J delegation is configured
selectively for individual methods whereas the declarative style of method bindings
keeps the effort at a minimum.

Furthermore, the effect of callin bindings can be controlled by several mechanisms
which I haven’t shown here (“team activation“, “guard predicates“), which means you
have the free choice between the weaker forwarding and the stronger delegation.

Delegation usually doesn’t imply overriding when directly addressing the base instance
as in the second picture. In OT/J you can freely choose, whether or not overriding
is effective in this situation.

Additionally, OT/J takes away the burden to manually manage the additional instances
involved in delegation. That’s what a team as the container for roles does for you.

Role playing vs. AOP

My explanation didn’t sound much like AOP, did it? The only connection here is in
the term “interception”. That’s the core mechanism that is used in both approaches.
Other than that I see little similarity.

In the same way as all languages providing dynamic method dispatch can solve a
similar set of design issues, also all languages providing method call interception
can solve similar issues. In OT/J we blend interception into the general concept
of dynamic dispatch as best as we can, so that it doesn’t stick out from other
concepts of object oriented programming. So, instead of featuring three new
concepts (“join point”, “pointcut”, “advice”) , OT/J only has callin bindings to declare
method call interception.

Two examples for those who like the details of what I mean by
“blend with other concepts”: “advice” in AspectJ is an oddish animal,
it is, e.g., impossible to override inherited advice.
Callin bindings refer to methods, which can be overridden like normal.
Also “aspects” are limited regarding inheritance: it is illegal to extend a
non-abstract aspect. Roles in OT/J have no such restriction.

All the rest

OK, role playing is key for re-using (and adapting) existing things.

Remember, role playing is only one of three strong ways in OT/J to specify connections
between modules. The enhanced inheritance and the strong containment relation
are both unrelated to AOP and delegation, but add even more value as they help to
create evolvable architectures.
It’s a major contribution of OT/J that these three ways of connecting things are not added
as isolated language features but in a way that creates the best synergy among them.

I even think that roles and teams are great metaphors representing the mechanisms
at hand in an intuitive way, but before you actually tried eating the pudding,
you may perhaps not feel this way – yet 🙂

Advertisements

Written by Stephan Herrmann

February 13, 2010 at 19:36