• Ei tuloksia

Chapter 1 Introduction

1.4 Thesis Contents

The contents of this thesis are as follows. Chapter 2 introduces the concept of OO patterns. The focus is on design patterns, i.e. “the building blocks of frame-works”, and metapatterns that capture the structural essence of design patterns.

Chapter 3 is devoted to OO frameworks. The chapter goes through a short history of frameworks, describes the typical structure and evolution of frameworks, dis-cusses framework specialization, compares frameworks with other reuse tech-niques, and finally, lists the benefits and problems with applying the framework technology in general.

Chapter 4 discusses tool support for frameworks and how tools can help over-coming the problems related to employing frameworks. The chapter begins with an illustration of some of the proposed modeling techniques for frameworks and continues with a description of desired functionality for different kinds of framework tools. Also, several existing framework tools are presented. Finally, the chapter identifies several challenges that we have found critical when study-ing and developstudy-ing tool support for framework specialization in particular.

In Chapter 5 we bring in a general theory that characterizes the role-based terns and describes how programming tasks are generated based on these pat-terns. The chapter also shows how role-based patterns can be developed in a hi-erarchical manner. On the whole, Chapter 5 lays a ground for our own frame-work engineering tool, JavaFrames.

In Chapter 6 we first introduce the JavaFrames tool and the general ideas behind it. Then we take a closer look at JavaFrames and how it is intended to be used in the framework specialization process. We also present the library of generic re-usable patterns and the methodology for utilizing the library for systematic speci-fication of a framework’s reuse interface.

Chapter 7 reports the case studies carried out in order to test the framework reuse interface specification methodology. The chapter presents the JavaFrames pat-terns developed for describing the reuse interfaces of the Struts and JHotDraw frameworks and shows how the patterns can be used for building applications.

The case study patterns (made by using the library of generic patterns) are com-pared with patterns made from scratch and with patterns developed by using the Pattern Extractor tool [Viljamaa J. 2004]. The case studies show that JavaFrames can offer considerable help in framework specialization and that the library of generic patterns significantly alleviates the burden of developing framework re-use interface specifications.

Finally, Chapter 8 concludes the thesis with an evaluation of the capabilities of JavaFrames and the framework reuse interface modeling methodology. The chapter also contains a comparison to related work and a discussion on the short-comings of this work as well as future plans for improving on them. Chapter 8 finishes off with a summary of the contributions of this thesis and a vision of some possible further research directions based on JavaFrames and this thesis.

9 9

Patterns of Object-Oriented Programming

Object-oriented patterns [Beck 1988; Gamma et al. 1994; Coplien-Schmidt 1995; Buschmann et al. 1996] describe general and reusable solutions to recur-ring problems in different aspects of OO software development. Patterns typi-cally stem from real-world experiences and their purpose is to condense the knowledge and expertise of experienced software developers.

More often than not, patterns describe ways of implementing flexible, maintain-able, and reusable designs. Therefore patterns are heavily utilized in OO frame-works, especially when implementing framework reuse interfaces. Consequently, it is not surprising that most of the current tools supporting frameworks are based on some form of the pattern concept.

In this chapter we first look at the origin and history of patterns and discuss the types of patterns introduced so far (Chapters 2.1 and 2.2). The patterns that have influenced this thesis the most are the implementation-oriented design patterns and metapatterns. These are typically based on the fundamental OO reuse mechanisms. The OO reuse mechanisms are discussed in Chapter 2.3. Chapters 2.4 and 2.5 concentrate on design patterns and metapatterns, respectively. While discussing design patterns, Chapters 2.4 introduces two important concepts that will be used frequently in this thesis: pattern role and pattern instance. After that, Chapter 2.6 discusses the problems related to patterns and Chapter 2.7 the relevance of patterns when developing tool support for frameworks.

The general problems of handling patterns with automated tool support are dis-cussed later in Chapters 4.2 and 4.3. These problems include, for example, pat-tern instantiation and the validation of the consistency between patpat-terns and source code.

2.1 The Origin of Patterns: The Timeless Way of Building

The idea of a pattern and a pattern language originates from the work of a well-known building architect and urban planner Christopher Alexander. His ambi-tious aim was to condense the knowledge of experienced architects, as well as common sense rules and traditions of builders in various cultures into a

struc-tured set of patterns, i.e. into “rules which establish a relationship between a context, a system of forces which arises in that context, and a configuration which allows these forces to resolve themselves in that context”. Alexander be-lieved that patterns could guide designers to achieve the combination of elegance and practicality, “the quality without a name”, that he thought was common in all great designs. According to Alexander, by following the pattern rules it should be possible even for ordinary inexperienced people to design their own houses, streets, and communities.

Alexander and his colleagues published their work in a series of three books. The Oregon Experiment [Alexander et al. 1975] described a pattern-based architec-tural design process for the campus of the University of Oregon. The patterns were tailored especially for the university environment. The second book, A Pat-tern Language — Towns, Buildings, Construction [Alexander et al. 1977], pre-sented 253 generally applicable architectural patterns tied together into a lan-guage-like framework that was supposed to guide people through the process of architectural design. Each pattern in the language first discusses and illustrates a specific design problem in a specific context and then describes a working solu-tion for the problem. Alexander hoped that his pattern language could be an in-spiration and skeleton for people around the world for their own culture-dependent pattern languages. The last book in the series, The Timeless Way of Building [Alexander 1979] explains the rationale behind patterns and pattern-based architectural design. It sums up the concept of patterns and serves as a kind of an introduction for the previous books.

Most Alexander’s patterns offer practical design guidelines. For example, Light on Two Sides of Every Room [Alexander et al. 1977] says that a room should have at least two outdoor walls with windows to enable proper lighting. Building Edge [Alexander et al. 1977] suggests that in order to make the surroundings of a building livelier, the outer edges of the building should be crenellated with places that invite people to stop, sit, lean, walk, etc.

These down-to-earth patterns were not enough, however. Instead, Alexander took his pattern language and its consistency to an extreme, as he described how the world should be broken into nations and nations into smaller regions, and how roads, parking, shopping, etc., should be arranged.

After 27 years from the publication of The Timeless Way of Building, it has be-come clear that turning the creative process of architectural design into controlled steps of applying a pattern after pattern has not succeeded in the way Alexander planned it. Alexander’s ideas appear to be too extravagant and alienating from the practice; it seems that it is not possible to systemize the artistic process of architecting to such extent.

2.2 History and Types of Object-Oriented Patterns

Despite the difficulties in introducing patterns into real building architecture, pat-terns have since become a hot topic within the OO software community. Are

there rational reasons for considering software development to be a more fertile ground for patterns? Clearly, the quality attributes for software architecture and building architecture are quite different. Software must above all be robust and extensible, and — from the perspectives of both end-users and maintainers — the structure of software should be as standard and simple as possible. Buildings on the other hand, must of course meet the functional requirements, but in addition, they should also provide a comfortable and personal environment for people.

Thus, a number of rather subjective quality attributes have to be taken into ac-count when designing buildings. It seems that the properties of software artifacts could be more objectively measurable and therefore software development might be more suitable for systemization. Of course in software development, too, some software engineers would rather consider themselves as artists. They prefer making things in their “own” unique way and stubbornly neglect standards.

An analysis and discussion of Alexander’s work and its relevance to software engineering is presented in [Lea 1994]. One of the main differences between building architecture patterns and OO software patterns stems from the fact that, unlike building architecture, OO software can contain abstract components that hold the behavior common to all concrete components.

The software pattern movement was set in motion at OOPSLA’87 when Beck and Cunningham presented their experiences in applying the concept of patterns to software development [Beck 1988]. Being influenced by the work of Alexan-der, they had developed a language of five patterns for designing graphical Smalltalk [Goldberg 1984] user interfaces.

Johnson was the first to emphasize the close relationship between design patterns and application frameworks. In [Johnson 1992] he proposed using design pat-terns for documenting frameworks and introduced a set of patpat-terns for the Hot-Draw framework as an example. HotHot-Draw is a graphics framework for object-based editor applications.

A true break-through of design patterns was seen in 1994 when the “gang of four” (Gamma, Helm, Johnson, and Vlissides) published their book Design Pat-terns — Elements of Reusable Object-Oriented Software [Gamma et al. 1994].

The book described the ideas behind design patterns and presented 23 reusable design patterns in a compact catalog format. (Design patterns will be discussed in more detail in Chapter 2.4.)

Pree soon discovered that there is a limited set of archetypal design patterns or ways to use the basic mechanisms of OO programming to compose different kinds of object structures with different properties. Pree calls such basic struc-tures metapatterns [Pree 1995]. According to Pree, metapatterns can be used to analyze and explain why certain patterns have been chosen, why they work, and which things are common or different in certain patterns. (Metapatterns will be discussed in more detail in Chapter 2.5.)

Buschmann and his colleagues distinguished three different levels of granularity for patterns [Buschmann et al. 1996]: architectural patterns1, intermediate level design patterns, and low-level idioms. The architectural patterns introduced in [Buschmann et al. 1996] are strongly related to architectural styles [Shaw-Garlan 1996]. They instruct on how to arrange the general structure of a software sys-tem. Many of the architectural patterns can also be seen as large-scale variations of design patterns. Examples of architectural patterns include Model-View-Controller and Layer. The former describes the separation of a functional or con-ceptual model from its visualization and manipulation. The latter is often used, for instance, in network protocols where more abstract upper layers request ser-vices implemented in lower concrete layers.

Idioms are small patterns dealing with implementation and coding style aspects typically tied to a particular programming language. An idiom for one language can be a built-in mechanism in another language. Idioms for C++ [Stroustrup 1986] are described in [Coplien 1992]. For instance, the Pointer Counting idiom shows how to keep track of object references. A set of idiom-like patterns for Smalltalk is available in [Beck 1997]. These patterns instruct, for example, on removing duplicates from a collection. Also, diverse examples of idioms dealing with things like memory management problems in C++ as well as efficiency and source code control in Smalltalk can be found in [Vlissides et al. 1996].

Coad’s modeling patterns [Coad 1992; Coad et al. 1995] have many characteris-tics in common with design patterns. For example, the Observer design pattern [Gamma et al. 1994] and the Publisher-Subscriber modeling pattern [Coad et al.

1995] practically address the same problem. However, modeling patterns have also broadened the scope of patterns: Coad’s patterns include, for instance, Top 10 that suggests building a list of the ten most important features of a system in order to avoid being overwhelmed by low-level details.

According to [Fayad et al. 1999], Coad’s modeling patterns are best suited for the transition from domain analysis to application design. Fowler’s analysis patterns [Fowler 1997] are more purely related to domain analysis. They are intended for modeling specific business domains, for instance, accounting, trading, measure-ment, and organizational associations. Fowler’s patterns include, for example, Measurement that describes a model for capturing measurements about a patient in a health care system.

In addition to different constructive phases of software development, there are also “administrative” patterns for the process of developing software. These in-clude organizational and process management patterns [Coplien 1995; Foote-Opdyke 1995; Kerth 1995].

Patterns do not necessarily describe useful or successful solutions. The notion of antipatterns was introduced in [Akroyd 1996] as it was considered also necessary to document recurring failures in software analysis, design, and implementation.

An antipattern describes a recurring bad design or process and suggests a better

1 Buschmann originally used the term architectural framework, but the term architectural pattern was later adopted to avoid confusing Buschmann’s concept with OO application frameworks.

solution for the problem at hand. Similar work on providing software guidance based on identifying dysfunctional behavior and refactoring a solution for it has been documented, for example, in [Brooks 1979], [Webster 1995], and [Coplien 1996]. In [Brown et al. 1998], a set of antipatterns (for example Spaghetti Code) was described using the form of representation introduced in [Gamma et al.

1994].

For the last fifteen years or so the idea of patterns has been a central topic in the field of OO research and software engineering. Since the release of Design Pat-terns [Gamma et al. 1994], many other catalogs of general patPat-terns have been published, for example [Buschmann et al. 1996] and [Coplien 1996]. Also pat-tern catalogs for more specific fields of software development have been written;

these are called domain-oriented patterns (see, for instance, [Cunningham 1995]

and [Lea 1996]).

By now, patterns have established their status in the OO community. There is a devoted conference on patterns — Pattern Languages of Program Design (PLoP) [Coplien-Schmidt 1995; Vlissides et al. 1996; Martin et al. 1998; Foote et al. 1999]. Also numerous pattern-related sites and mailing lists exist on the Inter-net: see, for example, [hillside.net/patterns]. A range of implementation varia-tions of the original design patterns [Gamma et al. 1994] have been introduced for different programming languages (for Java versions, see [Metsker 2002]; for Smalltalk, see [Alpert-Woolf 1998]). Alexander, the godfather of the pattern movement, has also continued his research. He has recently published a four-volume work, The Nature of Order [Alexander 2003], that investigates the inter-action between science and architecture.

2.3 Object-Oriented Reuse Mechanisms

As noted earlier, the patterns that are most relevant to describing the reuse inter-faces of OO frameworks, i.e. metapatterns and different forms of design patterns, mainly aim at describing flexible, maintainable, and thus reusable designs. In order to accomplish this, the patterns utilize the general mechanisms of OO pro-gramming.

Reuse in OO programming is based on abstract classes [Deutsch 1989, Gamma et al. 1994]. The main purpose of an abstract class is to define a common inter-face for the objects that are created at run-time based on the concrete subclasses of the abstract class.

By separating an object’s interface and its concrete implementations we achieve two things. Firstly, the object becomes encapsulated: a client using the object can access it only through its interface and the object’s concrete state remains safely hidden. Secondly, since the client is not dependent of the concrete implementa-tion of the object, the implementaimplementa-tion can be replaced — even at run-time — with another implementation. This is called polymorphism: a single variable or procedure parameter can take the values of several types or classes. The actual concrete implementation that carries out a request sent by the client is determined

dynamically just before its execution. This is known as dynamic binding. Encap-sulation, polymorphism, and dynamic binding allow us to develop flexible OO programs where parts of programs can be redefined or replaced without having to change other parts that use them. This is an essential benefit and it allows care-fully designed OO software to be truly reusable.

In OO languages, subclass–superclass relationships are specified using inheri-tance. Many patterns suggest using inheritance just to specify type relationships (interface inheritance), not to directly reuse code (implementation inheritance).

Instead of inheritance of data attributes and operation implementations, most pat-terns emphasize the use of object composition and delegation [Raj-Levy 1989;

Palepu 1996; Yelland 1996]. Implementation inheritance should be avoided be-cause (1) it is determined at compile-time and thus the implementations inherited from the parent classes cannot be changed at run-time and (2) since the parent classes define at least part of the behavior used in the subclass, possible changes in the parent classes usually force changes in the subclasses too [Gamma et al.

1994]. Because of the latter reason, implementation inheritance is often said to break encapsulation [Snyder 1986]: the subclass implementations become bound to the parent class implementations. On the whole, it is generally argued that us-ing object composition and delegation leads to more reusable OO designs.

2.4 Design Patterns, Roles, and Pattern Instances

It is difficult to design reusable software — especially application frameworks.

This is because in order to achieve reusability, it is not enough just to directly map the real world objects in the application domain into concrete implementa-tion objects. Instead, a reusable design always introduces addiimplementa-tional objects that are necessary, for example, when implementing indirection that flexibility typi-cally requires. Discovering these organizational objects [Wolf-Liu 1995, Zimmer 1995] can be laborious for an inexperienced developer. For instance, it is often convenient to represent the state of an entity or an algorithm as a separate object.

However, less obvious designs like these are hard to develop, since they are not directly present in the application domain. Without a strong design expertise the organizational objects are not found until the later phases of design after many trials and errors.

According to [Deutsch 1989], two aspects of OO software architecture — inter-face design and functional factoring — constitute the key intellectual content of a software design. Interface design of classes is concerned with the external prop-erties of a component as opposed to its implementation. Functional factoring is concerned with the distribution of functionality between the various components.

This distribution expresses the logical structure of software.

Design patterns assist in discovering organizational objects and managing both interface design and functional factoring in a way that promotes reusability. Re-usability is achieved by adding layers of indirection that enable more flexible designs.

A design pattern is an informal description that systematically names, motivates, and explains a general design that addresses a recurring design problem in OO systems. It identifies a set of forces and constraints that are resolved in its solu-tion. A design pattern describes the problem, the solution, criteria for choosing the pattern, and the consequences of the solution. It also gives implementation hints and examples. The solution is a general arrangement of objects and classes that solve the problem in a particular context.

The pattern form has evolved from its origin since its adoption to software

The pattern form has evolved from its origin since its adoption to software