The Persistence Concern in JHotDraw
A crosscutting concern that pops out clearly through a high
fan-in is persistence. Persistence and resurrection of figures are
performed by methods inherited from the
The two are pair concerns: the
classes implement the
methods to write/read themselves to/from a
object, which is basically a specialized
Persistence is a crosscutting concern spread over 36 classes. The concrete figures implement the
interface that encapsulates the concern.
is what we call a secondary
interface -- an interface that does not
define the primary role of the implementing class but only adds some
The methods ensuring the persistent
behavior create a high fan-in for several members of the
A refactoring solution, using the features of the AspectJ
language, would use
introduction to isolate the persistence concern from the figure classes. Better modularity
properties can be achieved by having all the code relating to the storable functionality
in the aspect construct. The figures will implement no persistence-specific code
but will be extended with this functionality through inter-type declarations.
Because the persistence concern is already distinguished in the
original design, refactoring it to an aspect is fairly
straightforward. The aspect can use introductions
in order to
have the persistent elements of a drawing (e.g., figures) implement
interface. If not all variables comprising the
state of the class are accessible through public getters and setters,
the aspect will need access to private members as well. The AspectJ
way to achieve this is by declaring the aspect
The concern corresponds to a generic type of crosscutting functionality, Role Superimposition
and its refactoring mainly consist of Extracting Interface Implementation
, the AspectJ
persistence implementation can be found in
When refactoring persistence to an aspect we run a number of risks:
The first is that in our aspect, we accidentally introduce a read or
write method body for a given figure in the wrong class.
The second is that we make an error when copy-pasting the body of
a method to an aspect.
Last but not least, our removal of the persistence code from, e.g.,
figures may be incomplete.
In order to test persistence we proceed as follows: First, we create a
class, which has a test method that
- creates a
Storable (typically a figure),
- writes it to a stream,
- reads it back into a different object, and
- checks the equivalence between the two.
Next, the creation of the actual figure
is deferred to subclasses of the
class using a
virtual factory method. Thus, the test hierarchy mimics the hierarchy
of classes to be stored.
Finally, our equivalence checking method
should be based on structure, not on object identity. Such a method is
not included in the JHotDraw
implementation. We injected this method
into the class hierarchy using an aspect. Observe that a collection of
static equivalence methods included in, for example the test class,
would not work, since the equivalence method must be polymorphic --
which can be achieved by means of introductions in an aspect but not
by means of static methods.
, the tests can be found under
The equivalence methods can be found in