Preserving Design Patterns using Source Code

0 downloads 0 Views 1MB Size Report
Preserving Design Patterns using Source Code Annotations. Miroslav .... Whilst he uses them as medium for .... identification of a pattern in the source code, she.
Preserving Design Patterns using Source Code Annotations Miroslav Sabo and Jaroslav Porubän Department of Computers and Informatics, Technical University of Košice, Faculty of Electrical Engineering and Informatics, Letná 9, 04200 Košice, Slovak Republic, E-Mail: {miroslav.sabo, jaroslav.poruban}@tuke.sk

often first comes to mind as a solution. All the more surprisingly is that we find the tool support for design patterns in phase of maintaining the existing system the most insufficient. Other phases of system development life cycle are supported relatively well by tools furnished with features for defining, rearranging, modeling, interconnecting, applying and instantiating of design patterns. Design patterns are also recognized in non-object-oriented programming languages [12].

Abstract – Design patterns are abstract descriptions of established time-tested solutions to often recurring problems. They have proven to be very useful for the design of object-oriented systems as they elevate the level of abstractions by capturing a relationship among the language-level abstraction mechanisms. However, the traceability of a design pattern in source code is often lost over the time due to insufficient or out of date documentation. Moreover, the original intentions captured by design pattern may get lost as well due to inappropriate source code modifications. This paper presents an approach to preserving the correct form of design pattern application to source code during the whole process of system evolution by annotating the language constructs constituting design pattern. Annotations prescribe the correct structure of annotated constructs and if this does not comply, the programmer is notified that the pattern is broken and is given the recommendations how to fix it. For the purpose of defining correct form of pattern constructs, specific language is proposed.

It often happens that design patterns can not be identified in source code because the conceptual entity of pattern at the design level is scattered over different parts of an object or even multiple objects on the implementation level. Intentions of design pattern and system specific intentions are superimposed in implementation and without explicit distinguishing between sections implementing each of them, it becomes very difficult to identify the constructs constituing the pattern later. Due to inability to identify individual parts of pattern, they may be modified inadvertently which may result in breaking the pattern and losing the benefits gained by its application in the system.

Keywords: design patterns, annotations, Java, design pattern structure, structural checking

I. INTRODUCTION Design patterns have gone a long way since they were first introduced to computer science by Helm in 1995 [3]. Thenceforth much research has been conducted in this area and great effort has been put into enhancing the application of design patterns to source code, especially through tool support [1][2]. Nowadays there are numerous such tools which support the process of pattern-based design and implementation, available both as stand-alone development applications and plugins for integrated development environments. A.

Motivation

The application of design patterns to object-oriented software development has already brought positive results in practice. Reported benefits include significant increases in quality and productivity. Most design patterns also make software more modifiable and maintainable. The reason for this is that they are timetested solutions. Therefore, they have evolved into structures that can handle change more readily than what

Fig. 1 – Comparison of the Pattern concept on design level and Pattern implementation interleaved with an application specific functionality on implementation level.

53

B.

includes built-in annotations and also supports custom annotations which can be written by programmer himself. Our approach makes use of custom annotations for labeling the pattern constituents which enables the identification of them in code further in time.

Problems & Objectives

Problems discussed in previous section can be formulated as follows: 1) Traceability of design patterns in implementation – information about design pattern constituents is usually lost in early phases of system development after the source code has been generated from design models. This problem has been also identified by Soukup [10]. Traceability of design patterns is important also in the context of semi-automatic program refactoring [11].

@AbstractFactory( role = Role.CONCRETE_FACTORY, id = 3) public class AfricanFauna extends ContinentalFauna { private static int lionCount = 0; @Override @AbstractFactory( role = Role.CONCRETE_METHOD, id = 3) public Carnivore createCarnivore() { lionCount++; return new Lion(); }

2) Checking the correct application of design pattern – as a consequence of the first problem, parts of system which represent the pattern are allowed to be modified during system evolution without any notification that the pattern is actually being broken. This may result in loss of intentions introduced to the system by application of design pattern.

public int getLionPopulation() { return lionCount; } }

Fig. 2 – Annotated class representing Concrete Factory.

Java annotations have also been used by Meffert [8], however for different purposes. Whilst he uses them as medium for expressing the intentions captured in code and exploit this information in process of advising the suitable pattern to programmer, we use them for imposing constraints on annotated entity. In our approach we expect the programmer to be experienced enough to know which design pattern to apply and we focus on ensuring that the pattern already added to the code is not broken due further code modifications.

Considering the stated problems, we have defined the objectives which need to be fulfilled in order to enhance the support for design patterns once they have been applied to source code: 1) explicit identification of language constructs which represent the design pattern on implementation level, 2) capability of determining whether pattern is applied correctly,

A.

3) assistance with resolving a broken pattern.

Correct Design Pattern Application

Although the pattern descriptions are based on semiformal class diagrams which allow for many implementation variations, they are sufficiently precise so that when selecting a particular implementation, the pattern could be formalized and form the basis of some kind of programming language support [4]. Choosing Java as our implementation platform, design pattern constructs can be formalized in terms of:

II. ANNOTATIONS TO THE RESCUE The Java 2 Platform Standard Edition 5.0 introduced many new features, among them the ability to annotate Java program elements and to create custom annotation types [6][7]. Annotated data (metadata) can then be read and processed by development and deployment tools. We find this feature perfectly suited to address the problem of traceability of design patterns in source code.

1) classes, interfaces and relationships between them, 2) enumerations and annotations,

As mentioned earlier, design pattern is on implementation level represented by a collection of classes. The reason why are these classes getting lost in code is that they implement both the intentions of pattern as well as intentions specific to the system itself. The amount of pattern specific entites inside the class is usually outnumbered by amount of system specific entities many times therefore it gets difficult to identify pattern fragments within class source code. This is the place where annotations come into play. Annotations are structured information which can be added to code and applied to many language constructs, such as package declarations, type declarations, constructors, methods, fields, parameters, enumerations and variables. Java

3) constructors, methods and member variables, 4) modifiers, parameter lists, return types, exception lists. We advocate that the best place for storing the information about correct structure of design pattern is directly in code which implements it. Java annotations can serve perfectly for this purpose as they are valid language constructs and can express virtually any information [8]. Constraints for each construct in pattern (in form of terms mentioned above) specifying its correct application within pattern structure can be

54

Structural constraints are expressed in specific extensible language designed and implemented especially for this domain using an approach presented in [9]. This form of constraint representation is easy to be read by programmers and is also convenient for automated processing. Annotated source code can be analyzed by annotation preprocessor at any moment but usually it is included in the phase of compilation of source code.

injected into the code through annotations either by programmer or by tool generating the source code of pattern. During the process of compilation, entities implementing the pattern are checked against the constraints defined by their annotations and if they do not comply, pattern is claimed to be broken and programmer is notified about this.

Since some patterns can be implemented in different ways, programmer must be able to adjust the annotation type definition. Considering Abstract Factory pattern as an example, it can be implemented either by using interface or abstract class considering Java limitation to single inheritance in first case and benefit of default implementation in the other. For the both pattern alternatives the annotation type can be easily adjusted by the modification of constraint to appropriate case. Fig. 3 – Processing of annotated source code. @Constraint( role = "ABSTRACT_FACTORY" condition = "interface(*)", bind = "AF")

Moreover, particular part of code which breaks the pattern can be localized and appropriate steps to resolve the problem can be recommended to the programmer.

vs. @Constraint( role = "ABSTRACT_FACTORY" condition = "class(abstract *)", bind = "AF")

III. ANNOTATING DESIGN PATTERNS

Fig. 5 – Adjusting the constraint for different alternatives of pattern implementation.

According to proposed approach, for each pattern is defined the specific annotation type named after the pattern. The constraints on participants in pattern are prescribed in annotation type definition via metaannotation TargetDesignator which takes single parameter – array of contraints which define the structure that annotated construct must conform to be evaluated as correctly applied.

All constructs in source code which participate in any of the patterns are designated with annotation of appropriate type. To distinguish the constructs of different instances of the same pattern, the id parameter is introduced. The role parameter defines the role in pattern concept which the construct represents. Various conditions can be imposed on entity type, modifiers, name, annotations, return value, parameters list and more. The binding feature allows programmer to impose conditions on relationships between them as well.

@Documented @Retention(RetentionPolicy.RUNTIME) @TargetDesignator({ @Constraint(role = "ABSTRACT_FACTORY", condition = "interface(*)", bind = "AF"), @Constraint(role = "CONCRETE_FACTORY", condition = "class(!abstract *)", bind = "CF"), @Constraint(role = "ABSTRACT_METHOD", condition = "method(* bind $CP *())", bind = "AM"), @Constraint(role = "CONCRETE_METHOD", condition = "method(!abstract * bind $CP *())", bind = "CM"), @Constraint(role = "ABSTRACT_PRODUCT", condition = "interface(*)", bind = "AP"), @Constraint(role = "CONCRETE_PRODUCT", condition = "class(!abstract *)", bind = "CP"), @Constraint( condition = "implementation($CF, $AF)"), @Constraint( condition = "parent($AM, $AF)"), @Constraint( condition = "parent($CM, $CF)"), @Constraint( condition = "implementation($CP, $AP)") }) public @interface AbstractFactory { Role role();

When annotated entity is checked for validity, firstly, its structure is matched against the condition of appropriate constraint from target definition of annotation type determined by role parameter. In the case of additional relationship constraints specified through binding feature, they are checked as well. If entity conforms conditions of all examined constraints, it is considered as valid pattern constituent. If all constituents within pattern are valid, the pattern is considered as correctly applied.

IV. RELATED WORKS Meffert presents the same approach to annotating design patterns [8], however, he is aiming towards different goals. He sees the problem with using design patterns in requirement of the developer’s extensive experience and claims that a wrongly selected design

int id() default 1; }

Fig. 4 – Definition of annotation type for Abstract Factory Pattern.

55

approach to preserving the correct pattern application can greatly contribute to improvements in code maintainability and application evolution.

pattern may cause more harm than the right pattern would do good. As a solution, an approach to aiding the developer in selecting the right pattern for a given context by adding semantic information to source code via annotations is proposed. The intents captured by particular design pattern are expressed in a corresponding way. Eventually, the intentions defined for design patterns are compared with those designated for a given source code fragment and if any match is found the suitable options are suggested to developer letting him choose which pattern to apply.

ACKNOWLEDGMENTS This work was supported by VEGA Grant No. 1/4073/07 – Aspect-oriented Evolution of Complex Software System and by APVV Grant No. SK-CZ-009507 – Cooperation in Design and Implementation of Language Systems.

The technique for formalizing design patterns using a technique based on attribute grammars is presented by Hedin in [4]. Her work aims the same goals as our – identification of the design patterns in the source code and support for automatic checking that the pattern is applied correctly, although taking a slightly different approach. Attribute extension is a technique for describing and enforcing programming conventions by declarative semantic rules [5]. To support the identification of a pattern in the source code, she annotates the source code with pattern roles, using attribute comments. The rules for applying a pattern can be expressed in terms of the pattern roles, enforcing them to be consistent with each other. To check that the collaborations between different roles occur according to the pattern, collaboration rules are formulated. The implementation of a prototype tool, DPDOC which supports documentation with design patterns based on the ideas described above is presented in [1]. The main advantage presented by our approach over this technique is the assistance to the programmer when resolving broken pattern. The use of specific language for defining structure of pattern constituents makes it possible to identify the particular line in source code which breaks the pattern and to formulate the concrete adjustments how to restore it.

REFERENCES [1] A. Cornils and G. Hedin, ″Tool Support for Design Patterns based on Reference Attribute Grammars″, in Proceedings of WAGA‘00, Ponte de Lima, Portugal, published as in INRIA research report, 2000. [2] G. Florijn, M. Meijers and P. van Winsen, ″Tool support for object-oriented patterns″, in Proceedings of the ECOOP’97, LNCS 1241, Springer Verlag, pp. 472 – 495, 1997. [3] E. Gamma, R. Helm, R. Johnson and J. Vlissides, ″Design Patterns: Elements of Reusable Object-Oriented Software″, Addison-Wesley, 1995. [4] G. Hedin, ″Language Support for Design Patterns using Attribute Extension″, in Proceedings of the ECOOP’97, LNCS 1357, Springer Verlag, pp. 137 – 140, 1997. [5] G. Hedin, ″Attribute Extension - a Technique for Enforcing Programming Conventions″, Nordic Journal of Computing, Volume 4, Issue 1, pp. 93 – 122, 1997. [6] Java Community Process, Java Specification Request 175: A Metadata Facility for the JavaTM Programming Language, 2004, on Internet: [7] Java Community Process, Java Specification Request 250: Common Annotations for the JavaTM Platform, 2006, on Internet: [8] K. Meffert, ″Supporting Design Patterns with Annotations″, in Proceedings of the 13th Annual IEEE International Symposium and Workshop on Engineering of Computer Based Systems, Los Alamitos, USA, pp. 437 – 445, 2006. [9] J. Porubän, ″Design and Implementation of Computer Languages″, Technical university of Kosice, 103 pp. 2008. [10] J. Soukup, ″Implementing patterns″, in Pattern Languages of Program Design, J.O. Coplien, D.C. Schmidt (eds.), Addison-Wesley, pp 395 – 412, 1995. [11] C. Szabó, B. Sobota, "Some Aspects of Database Refactoring for GIS″, In Proceedings of the Fourth International Conference on Intelligent Computing and Information Systems ICICIS 2009, Cairo, Egypt, Police Press, 2009, pp. 352-356, ISSN 1687-1103. [12] P. Václavík, ″Deriving Types Using Proxy″, In Analele Universitatii din Oradea, Romania, 2005, pp. 140-145, ISSN-1223-2106.

V. CONCLUSIONS In this paper we have addressed the problem of tool support for design patterns in later phases of software evolution. The utilization of current tools for design patterns was discussed and problems were formulated. We have found the problem of traceability of design pattern within source code and problem of preserving the correct application of pattern the most significant. As a solution to both of them, we have proposed an approach to preserving the design patterns using Java annotations. The source code is annotated either by programmer himself or by tool generating design pattern implementation. The checking whether annotated entities compose the correct application of pattern is performed automatically during compilation and is based on analyzing the structure of the entities. In the case of broken pattern, programmer is given particular location of breaking spot and is advised the concrete steps how to fix the pattern. We claim that our proposed

56

Suggest Documents