Section 17.5. EVOLUTION


17.5. EVOLUTION

Support for evolution is crucially important in the development of computer software. A motivation for this is the well-known fact that somewhere between 60% and 80% of the cost of software stems from the maintenance phase of software development [83]. In addition, economic competitiveness is often dependent on the agility with which new versions of software can be released. Recent trends in software also highlight the importance of dynamic evolution, that is, supporting changes to software at runtime without taking the system out of action. This is particularly important in distributed systems, where the complexity and distributed nature of the system make it highly undesirable to stop the system and then build/redeploy the new system. Furthermore, with innovations in fields such as mobile and ubiquitous computing, it is often necessary to support dynamic reconfiguration whereby software configurations can be altered dynamically to match the requirements of the current operating context. An example of this would be to employ caching if a period of disconnection is anticipated. More radically, researchers are currently investigating self-healing systems, where software evolves itself to deal with detected faults in its operation [72].

In theory, AOSD should be well placed to address issues related to evolution (and certainly static evolution). In particular, the separation of concerns inherent in AOSD should facilitate the replacement or upgrading of particular aspects and the introduction of new aspects. Indeed, this is one of the most frequently quoted motivations for the AOSD approach. In practice, however, the state-of-the-art is less positive particularly when dealing with dynamic evolution.

In addressing the state-of-the-art, there are two key issues to consider:

  1. How do we support the dynamic evolution of aspects?

  2. Can aspects themselves be used to manage this evolutionary process?

In terms of the former, there is now considerable interest in the general area of dynamic aspects, that is, being able to weave aspects into a system at runtime (the static approach to weaving exemplified by most current approaches such as AspectJ). In order to understand this area, it is necessary, however, to appreciate the (often misunderstood) relationship between aspects and reflection.

Reflection is a technique to support the dynamic inspection and adaptation of a particular software system [51, 75]. The traditional approach to developing software is based on the principle of abstraction. For example, in the object-oriented paradigm, programmers deal in terms of abstract interfaces without being aware of the underlying implementation details. This is a powerful but ultimately flawed philosophy [50]. In particular, it is often necessary to access underlying details of a system, for example to fine-tune the implementation for a given context such as making space-time tradeoffs in the underlying algorithms/data structures. In a reflective system, access is provided to such internal details via a meta-interface (or meta-object protocol). This interface offers a causally connected self-representation of the underlying systemby changing the representation, you are making a change to the actual system implementation.

As a technique, reflection has now gained general acceptance with widespread use in areas such as programming languages [51, 84], operating systems [85], and middleware [9, 55]. From this work, a widespread portfolio of reflective mechanisms has emerged, including introspection mechanisms (as found for example in the Java reflection API), interception/ message reification (supporting for example the association of pre- and post-behavior with particular object invocations), and architectural reflection (supporting the discovery and subsequent adaptation of architectural structures in terms of components and their interconnections). At another level, tools such as Javassist [18] and JMangler [54] support the dynamic adaptation of bytecode.

One problem with reflection is that it can be a rather low-level and hence rather dangerous technique (in terms of maintaining the overall integrity of the system). This is the key to understanding the relationship between aspects and reflection. In particular, the implementation of dynamic aspects inevitably involves the use of particular reflective mechanisms. Aspects, however, provide a higher-level abstraction for the evolutionary process in order to protect the integrity of the application. For example, consider composition filters. The emphasis of this approach is on offering higher-level filtering patterns (e.g., dispatch filters, wait filters, error filters) with strong underlying semantics in order to have a precise understanding of the effects of composition. In order to support dynamic evolution, the approach would typically be implemented using a variation of interception. At this level, however, there is no formal basis to understand the resultant behavior of the system.

In terms of the classic AOP approaches, composition filters are the most advanced in terms of supporting dynamic evolution [8]. In addition, Orleans and Lieberherr report on a language called the DJ Framework, an extension to adaptive programming offering dynamic traversal strategies [60]. Finally, work is currently underway to incorporate dynamic aspects in AspectJ.

There are also a number of experimental languages under development. We feature two interesting examples, JAC and Lasagne:

JAC. JAC (Java Aspect Components) is one example of how reflective mechanisms can be used to construct dynamic aspects [64]. JAC is a component-based framework to support the construction of distributed applications. As with Enterprise JavaBeans, components reside in containers. More specifically, two styles of components are identified: business components containing the standard business logic and aspect components that define crosscutting concerns (the non-functional properties associated with a container). New aspect components can be introduced at runtime. The implementation of this feature exploits dynamic wrappers and also structural meta-data. JAC also features an interesting distributed pointcut mechanism for aspects that may span multiple hosts.

Lasagne. Lasagne is a higher-level component-based approach that supports "the dynamic and context-sensitive combination of aspects on a per collaboration basis" [81]. Like JAC, the approach is based on dynamic wrappers; indeed the current implementation of Lasagne is based on JAC. Each aspect is realized by a set of wrappers potentially hosted on different sites in a network. The key to the approach is the use of composition policies that specify the particular subset of aspects to be employed in different contexts. The approach carries a significant performance overhead and is recommended for use with relatively coarse-grained aspects such as a particular security policy. Lasagne has been applied in a variety of areas including the construction of an adaptive Object Request Broker [80].

A number of pure Java-based frameworks providing dynamic aspect weaving are also being developed. The most prominent amongst these are the JBoss AOP Framework [44], AspectWerkz [12], and PROSE [65]. While these approaches avoid Java language extension, they do require augmented JVMs. JBoss is a reflective and reconfigurable application server that uses the JBoss AOP frameworkaspects are implemented as interceptors to provide a set of crosscutting services (e.g., persistence, remote access, etc.), and load-time weaving is used for composition with the help of a custom classloader. The weaver introduces actual hooks, that is, only to a set of points of actual interest and not to every possible point of potential interest. AspectWerkz also supports load-time weaving based on introducing actual hooks. It uses a custom-enhanced core Java class loading architecture hooked in directly after the bootstrap classloader. In contrast, weaving in PROSE is based on a JIT compiler, and the weaving scope can be varied between actual hooks and every possible point of potential interest.

Other notable languages offering dynamic aspects include Handi-Wrap [6], AspectS [40], AOP/ST [11], and SMove [49]. Research at INRIA is also investigating efficiency issues in dynamic weaving using the technique of code injection [13].

Interestingly, there has been very little work on employing such (higher-level) techniques in a more language-independent setting, that is, in middleware. Schult and Polze report one technique based on .NET exploiting the underlying CLR to offer language (but not necessarily platform) independence [73]. In general, though, most work in this area simply exposes the underlying reflective mechanisms leaving it to higher layers, such as the application, to preserve consistency.

There is much less research on the second key issuewhether aspects themselves can be used to manage this evolutionary process. However, the authors believe this is potentially a very important approach. This observation stems from previous work by one of the authors on evolutionary mechanisms for databases, as described in Chapter 29.

In selecting from these evolution techniques, an interesting question is which AOP implementation languages support evolution. In terms of the classic AOP approaches, all techniques have the potential to support static evolution. Note however, that this potential will not be realized unless the resultant system has a good architecture/design. Certain language features can also result in undesirable behavior under evolution. One example is with the use of wildcards in AspectJ, where some join points that were previously matched might no longer match, while others might be matched when they should not.

In terms of dynamic evolution, it is clear that of the classic approaches, at present, composition filters offer the most comprehensive solution. An increasing number of experimental languages also supports dynamic aspects, typically employing a variation of wrappers and reflection to achieve the necessary level of dynamism. Of this class of language, we consider JAC to be the leading approach, as it is the most mature. Note that the techniques generally have a significant performance overhead because of the level of indirection involved. If this is an important concern, then techniques such as the code injection work mentioned previously should be considered. In general, though, what is required is consolidation of research in this area and for the most promising approaches to be included in the more mature aspect-oriented languages and systems.



Aspect-Oriented Software Development
Aspect-Oriented Software Development with Use Cases
ISBN: 0321268881
EAN: 2147483647
Year: 2003
Pages: 307

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net