Introduction to ObjectTeams/Java, a Role-Based Approach to Modularity With AOP

I've recently stumbled upon an interesting Eclipse project called ObjectTeams/Java (OT/J), which promises improved reusability and maintenance and support for evolvable architectures by creating well-encapsulated bundles of behavior - modules - that can be applied to existing classes (via AOP), when they are in the appropriate context of interaction (and not simply always, as is the case with AOP). An example application is the addition of NonNull constraint to JDT via an OT/Equinox plugin, without the necessity to modify JDT's base classes. I've decided to write down my discoveries as the project is missing a clear and brief introduction (though it has otherwise very good documentation). This blog borrows heavily from [1].

Disclaimer: By no means do I claim to understand OT/J completely :-)

So what is OT/J about?

The key concepts are roles, contexts in which an entity is being used ("teams"), modules, and separation of concerns.

Roles are traditionally used in domain modeling: the role Customer may be played by a physical person, by a company, ... . OT/J adds explicit support for roles so that behavior that is only relevant to a particular role is implemented in the class representing the role, which is than applied on the base entity class. We can see below in Fig. 1 that the entity Professor can play the roles Supervisor for some PhDs and also Lecturer in some courses, in this particular example Prof. Smith lectures OOP and Software Engineering. The lecturing-related behavior, such as "write neatly on the blackboard" (PhDs are there long enough to read his natural hand writing) and handing over of slides and handouts, is implemented in the Lecturer role class. Thanks to this separation of concerns, as the number of roles a particular entity may play grows, the base class doesn't get more and more bloated. Roles may modify or reuse behavior  of their base classes and may expose or hide any properties and methods of the base classes.
Fig. 1 (Source: A Precise Model for Contextual Roles: The Programming Language ObjectTeams/Java.)
Contexts of interaction, called Teams in the OT/J terminology, are the space where roles live, for a role is only meaningful in a particular context, such as teaching a course or participating in the PhD program - you may also think of high-level use cases. Teams serve basically two purposes in OT/J: First, they group related roles together (think of a package). Second, they make it possible to activate or deactivate all the roles at once - e.g. when a Professor and a bunch of Students enter a course room then the behavior defined by the Lecturer and Participant roles will activate and will modify/enhance their behavior for the duration of the lesson. This ability to switch on/off modifications of behavior based on the context where a class is used is pretty nice. Additionally a Team may have its own set of methods and properties because it is represented by a class.

Modularity and reusability are achieved by implementing independent behaviors as roles grouped into teams and applied to base classes at the run-time. OT/J offers a middle road for modularization between white-box frameworks and black-box components and makes it possible to evolve and adapt a system while avoiding lot of changes to the base classes. One of the examples I've seen uses an abstract Team with a Subscriber, which collects credit for some BonusItems. The team is then specialized with a concrete FlightBonus team, which applies this behavior to the existing entity classes Passenger and Flight, where the "credit" being collected are bonus miles. The same abstract Team could be applied to a shop customer shopping with a customer card and collecting some bonus for each purchase.

What is it good for?

OT/J makes it possible to implement systems in a more natural way by supporting explicitly the notion of role, narrowing thus the gap between the business, business analysts and the developers. At the same time it helps to remove unnecessary coupling and to structure functionality in a better, more reusable way.

The authors themselves have experienced these benefits:
At a technical level applying OT/J for the implementation of its own tools Herrmann & Mosconi (2007) has demonstrated significantly improved maintainability of components that re-use and adapt existing components.

How is it implemented?

OT/J extends Java syntax to support natively the concepts of a team, role, and extension/modification of existing behavior of base classes. You compile it with a special OT/J compiler and it then applies load-time weaving to actually enable the application of roles to their base classes. Teams and their roles are activated either implicitly when you call a method on a Team class, the activation lasting for the duration of the call, or explicitly, so that a role may apply even if the client of the entity is unaware of it (for instance a flight reservation system doesn't perhaps need to know or care that there is some support for collecting bonus miles).

An example of the syntax, showing a team and replacement of a method in the base class Main (an around advice in the AOP language):


public class Main { public String sayMore() {...} }
...
public team class MyTeam {

protected class MyRole playedBy Main { callin static void sayMore() { System.out.println("callin begins ..."); base.sayMore(); System.out.println("callin ends ..."); } sayMore <- replace sayHello; } }


Summary
  • Role is a class, which explicitly refers to the class that it modifies/enhances. At run-time, the modifications it introduces are injected into the base class when it is in the appropriate context.
    • Methods of the base class may be modified in the around-advice style ("callin-binding") using "aRoleMethod <- replace aBaseClassMethod"
    • Methods of the base class may be exposed by the role ("callout-binding"): "aDelegatingRoleMethod -> aBaseClassMethod"
    • Also properties of the base class may be exposed via getters/setters: "getARoleGetter -> get aBaseClassField"
  • Team is a class, which may contain roles - either as nested classes or in a package-style folder/file structure - and its own methods and properties. Roles have a link to their Team. When a team is activated then OT/J tries to automatically apply its roles to the eligible interacting objects based on their types (the programmer may tune that with "guard predicates").

What's the difference between AOP and OT/J?

AOP deals only with code injection and usually the same code (advice) is applied to multiple methods in multiple classes. OT/J is much more than that with its explicit support for roles and teams and their context-sensitive activation. Also a method in a Role normally only modifies one method in one base class, so the mapping isn't 1:N as in AOP but 1:1.

OT/J also supports the traditional modification of multiple joint points but this should be avoided as much as possible because it makes it more difficult to understand the runtime behavior and to refactor the code, OT/J is on purpose more explicit.

See [2] for a deeper discussion.

Conclusion

Separation of concerns is not always easy because we often need to apply the same - or very similar - behavior at several places and OOP doesn't always lend itself to extraction and reuse of the behavior. AOP can help here by injecting the behavior defined at one place to all the places where it is needed but when its power is overused then it is very difficult to understand the runtime structure of a program from just looking at its source codes. OT/J makes a very good compromise here by allowing Roles to modify existing classes but making the application explicit and 1:1 (further reusability is possible by defining common functionality in an abstract team and binding it to different set of entities via concrete sub-teams, as in the FlightBonus example). By using the language of business analysis such as Roles, OT/J makes it easier to understand and apply this technique to real projects.

OT/J certainly looks very interestingly and can benefit a complex project greatly provided that it is applied correctly. Certainly it tends to be less obscure than low-level AOP with e.g. AspectJ.

OT/J ss currently in incubation due to its recent move to Eclipse, but the project is alive since around 2003, so it should be pretty mature. There is also tooling supporting it, for example a set of Eclipse plugins.

According to the developers, the project delivers what it promises:
During several case studies we have collected data about code sizes, about structural properties of the code as well as about the development process regarding productivity and maintainability. All these data support our approach, ...

Resources


Tags: architecture java library tool


Copyright © 2024 Jakub Holý
Powered by Cryogen
Theme by KingMob