next up previous contents
Next: A. Maintance of the Up: Diploma Thesis: Utility Support Previous: 6. Summary   Contents

Subsections


7. Outlook

The results of this paper leave various directions for future work on the OCL toolkit. This chapter outlines the (in the author's opinion) most interesting ideas.

7.1 Inheriting Constraints

Inheriting constraints is completely neglected in the current version. This means, that a subclass does not inherit the constraints of its ancestors. At a glance this is an implementation problem only. But it is not that easy.

Simply promoting constraints of a class to all its descendants is not sufficient. This downward promotion implies a conjunction (logical AND) of inherited and own constraints. This is suitable for invariants and postconditions, but not for preconditions. Design by Contract (DbC) requires inheritance of contracts, not just constraints, thus preconditions cannot be strengthened. To make this sure, DbC suggests a disjunction (logical OR) of inherited and own preconditions.

This causes some uncomfortable effects. Consider a class representing a bank account. The account has an attribute balance and a method for drawing money. There is no debit allowed, and for some technical reason the amount to be drawn cannot exceed 10000 per transaction. This could be expressed like this: (Postconditions have been omitted for brevity).

context Account::drawMoney(amount:integer)

  pre: amount<=10000

  pre: balance-amount>=0

A subclass weakens the second precondition by allowing a debit of 1000.
context DebitableAccount::drawMoney(amount:integer)

  pre: balance-amount>=(-1000)

But what happened now? The effective precondition of DebitableAccount (ORing preconditions of both classes) is now just balance-amount>=(-1000). The upper limit for amount disappeared. This is perfectly compatible with DbC, but certainly not the intention of the developer.

A work-around is to repeat the upper limit for amount in the subclass. But this is not convenient, particularly when considering 10 such technical preconditions instead of just one.

A sensible solution should allow to inherit a precondition as such without repeating it in the subclass. A suitable solution could feature named preconditions and a ``per name'' disjunction of these:

context Account::drawMoney(amount:integer)

  pre max_amount:  amount<=10000

  pre min_balance: balance-amount>=0

 

context DebitableAccount::drawMoney(amount:integer)

  pre min_balance: balance-amount>=(-1000)

These considerations suggest, that there is still some investigation and development needed to make the OCL toolkit usable for supporting Design by Contract.

7.2 Integration with CASE Tools

7.2.1 Code Generation

The OCL toolkit works with arbitrary java source code. Thus, it is definitely compatible with java code generators of all CASE tools. Still, there are some issues to be mentioned.

7.2.1.0.1 Export of OCL.

If the CASE tool is able to store OCL constraints, there should be some export function for them as well. A sophisticated export function could even embed the constraints into javadoc comments (section [*]), providing a single source solution. This should be easy to implement for CASE tools with the source code available, otherwise the feasibility depends on API's of the CASE tool.

7.2.1.0.2 Export of Element Types.

Even more important is the export of @element-type javadoc tags (section [*]). These are needed for type checking of constraints. The feasibility of such an extension depends again on the availability of either the source code or suitable API's.

7.2.1.0.3 Superseding Name Adapters.

Code generators of Argo/UML [AU], Rational Rose [RSC] and Together [TSC] require the employment of name adapters. This is, since an association end called employers does not result in a collection attribute of the same name, as one would expect. Instead, the attribute is called myEmployers, theEmployers or lnkEmployers, depending on the CASE tool. The necessary translation is encapsulated in name adapters. It would be nice to make code generators use the original name. This would remove the need for name adapters, making the OCL toolkit and its application a bit less complex.

7.2.2 Reverse Engineering

The OCL toolkit provides support for inserting and validating @element-type javadoc tags into arbitrary source code. This information could be used for reverse engineering from Java to UML.

This significantly changes the way of reverse engineering: Up to now, a CASE tool analyses the source code, and wherever there is some information missing (particularly the element type of container attributes) it makes some simple assumptions. In a second step, the user is expected to review the results and adjust them where necessary.

The OCL toolkit can be used to swap the order of steps. First, the missing information is inserted into the source code in form of @element-type tags. This information is then used by the CASE tool to straightly produce a correct UML model. The advantage is, that the additional information can be verified using the runtime checks provided by the OCL toolkit.

Of course, the @element-type tag does not provide all the needed information. For instance bidirectional associations cannot be determined, since they cannot be distinguished from two independent one-way associations. This could be approached by introducing some kind of @reverse-direction tag. Given the infrastructure already provided, such extensions should be easy to implement.

These considerations suggest, that the OCL toolkit together with a CASE tool could be extended into a complete round trip engineering solution - with special support for starting the round trip at the ``java side'' of the circle.

7.3 Others

7.3.0.0.1 Reduce Observed Attributes.

Caching of invariants (section [*]) requires observing object attributes for modifications. Up to now, all attributes found in the java source code are observed, regardless whether they are used in some OCL expression or not. This could be reduced to those attributes, which are actually referred to in any of the constraints. This would significantly improve runtime efficiency of the instrumented code. For an implementation one would probably intercept the OCL type checker to get the necessary information.

7.3.0.0.2 Observing Queries.

Caching the results of invariants requires observing of both attributes and query methods. However, observing queries has not been implemented yet. The total approach to caching requires a significant memory overhead. Observing queries will make this even worse by introducing another step of indirection. This should not be attempted until this approach has shown to be functional for big projects with many and complex invariants.

7.3.0.0.3 Java Constraints.

Constraints could be expressed in Java instead of OCL. This may be useful for developers, who are unfamiliar with UML and OCL. An advantage is, that such a tool would be dramatically smaller and faster. A serious drawback is the loss of some quite comfortable functionality of OCL, such as universal and existential quantifiers and @pre modifiers. Furthermore, caching of invariants for java constraints requires much more implementation effort.

7.3.0.0.4 Enhancing Flexibility.

Simply put, this means more options and probably some kind of configuration file. A good example is iContract [RK98], which allows to enable constraints independently for packages, classes and methods using a configuration file. Additionally there could be a more flexible scope of invariants, as suggested in section [*].


next up previous contents
Next: A. Maintance of the Up: Diploma Thesis: Utility Support Previous: 6. Summary   Contents
Ralf Wiebicke 2005-11-25