methods of the god class to refer to instances of the new data containers.

2. Identify all classes used as data containers by the god class (including those created in step 1) and apply Move Behavior Close to Data to promote the data containers into service providers. The original methods of the god class will simply delegate behavior to the moved methods.

3. After iteratively applying steps 1 and 2, there will be nothing left of the god class except a facade with a big initialization method. Shift the responsibility for initialization to a separate class, so only a pure facade is left. Iteratively redirect clients to the objects for which the former god class is now a facade, and either deprecate the facade (see Deprecate Obsolete Interfaces [p. 215]), or simply remove it.

# Tradeoffs

## Pros

* Application control is no longer centralized in a single monolithic entity but distributed amongst entities that each assume a well-defined set of responsibilities. The design evolves from a procedural design towards an object-oriented design based on autonomous interacting objects.

* Parts of the original god class are easier to understand and to maintain.

* Parts of the original god class are more stable because they deal with less issues.

* Overall compilation time may be reduced due to the simplification of system dependencies.

## Cons

* Splitting up a god class is a long, slow and tedious process.

* Maintainers will no longer be able to go to a single god class to locate behavior to fix.

* The number of classes will increase.
## Difficulties

* God class methods may themselves be large, procedural abstractions with too many responsibilities. Such methods may need to be de-composed before cohesive sets of instance variables and methods can be teased out as classes.

## When the legacy solution is the solution

What is riskier? To Split Up God Class or to leave it alone? A real god class is a large, unwieldy beast. Splitting it up into more robust abstractions may introduce considerable cost.

The key issue is whether the god class needs to be *maintained*. If the god class consists of stable, legacy code that rarely needs to be extended or modified, then refactoring it is a questionable investment of effort.

Suppose, on the other hand, that it is the *clients* of the god class that are unstable, and need to be frequently adapted to changing requirements. Then the clients should be shielded from the god class since it is not presenting a clean interface. Consider instead applying Present the Right Interface [p. 207], which will introduce a layer of clean, object-oriented abstractions between the clients and the god class, and may make it easier to evolve the clients.

## Rationale

*Do not create god classes/objects in your system.*

— Arthur Riel, Heuristic 3.2 [Rie96]

God classes impede evolution because they achieve only a low level of procedural abstraction, so changes may affect many parts of the god class, its data containers and its clients. By splitting a god class up into object-oriented abstractions, changes will tend to be more localized, therefore easier to implement.

## Related Patterns

Foote and Yoder in "Big Ball of Mud" [FY00] note that god classes (and worse) arise naturally in software development.

*"People build BIG BALLS OF MUD because they work. In many domains, they are the only things that have been shown to work. In-*
deed, they work where loftier approaches have yet to demonstrate that
they can compete.

It is not our purpose to condemn BIG BALLS OF MUD. Casual
architecture is natural during the early stages of a system's evolution.
The reader must surely suspect, however, that our hope is that we can
aspire to do better. By recognizing the forces and pressures that lead
to architectural malaise, and how and when they might be confronted,
we hope to set the stage for the emergence of truly durable artifacts
that can put architects in dominant positions for years to come. The
key is to ensure that the system, its programmers, and, indeed the
entire organization, learn about the domain, and the architectural
opportunities looming within it, as the system grows and matures."

— Foote & Yoder [FY00]

Present the Right Interface [p. 207] is a competing pattern that should
be applied when the god class itself rarely needs to be modified or ex-
tended.
# Chapter 10

## Transform Conditionals to Polymorphism

After duplicated code, data containers and god classes, one of the most striking signs of misplaced responsibilities in object-oriented software is the occurrence of large methods consisting almost entirely of case statements that test the type of some argument.

Although case statements are not inherently bad, in object-oriented code they are frequently a sign that the object doing the testing is assuming responsibilities that would better be distributed to the objects being tested. Big conditionals arise naturally over time, just as duplicated code does. As the software is adapted to handle new cases, these cases pop up as conditionals in the code. The problem with these big conditionals is that they can make the code much more fragile in the long term.

### Forces

The following forces are at play:

* As requirements change over time, classes in a software system will have to be adapted to handle new, special cases.

* Adding new classes or subclasses to a system clutters the namespace.

* The quickest way to adapt a working piece of software to handle a new requirement, is often to add a conditional test for the special case at some point in the code.
* Over time, a simple design tends to get cluttered with many conditional tests for special cases.

* Case statements group all the variants into a single place instead of spreading the different cases across different classes. However, they lead to design that is less flexible if the case statement appears in more than one place.

* In some programming languages, case statements are a more conventional idiom to implement varying behavior than polymorphism.

Large conditionals are often a sign that behavior implemented by clients should probably be shifted to the provider classes. Typically a new method will be introduced to the provider hierarchy, and the individual cases of the conditional statement will each move to one of the provider classes.

Although the symptom is readily recognizable, the technical details and the preferred solution may differ considerably. In particular, when the provider hierarchy already exists, and the conditions explicitly check the class of the provider instance, the refactoring is relatively straightforward. But often the provider hierarchy does not exist, and the conditions test attributes that only implicitly model type information. Furthermore, the conditionals may occur not only in external clients, but even in the provider hierarchy itself.

## Overview

Transform Conditionals to Polymorphism is a pattern language that describes how to redistribute responsibilities to eliminate these large conditionals, thereby reducing coupling between classes, and improving flexibility in the face of future changes.

This pattern language consists of six patterns which address the most common problems that occur when conditionals are used to simulate polymorphism. Transform Self Type Checks and Transform Client Type Checks address the most typical cases that arise when explicit type checks are performed. Transform Conditionals into Registration occurs less frequently. We also include Factor out State, Factor out Strategy and Introduce Null Object, not in order to copy three established design patterns (State [p. 321], Strategy [p. 321] and Null Object [p. 320]) but rather to show how these design patterns may apply in a reengineering context to eliminate type-checking conditionals.

Figure 10.1 summarizes the relationships and the differences between the patterns.
<figure><img src="image_48.png" /><figcaption>Figure 10.1: Relationships between the patterns constituting Transform Conditionals to Polymorphism.</figcaption></figure>

* Transform Self Type Checks eliminates conditionals over type information in a provider class by *introducing subclasses* for each type case. The conditional code is replaced by a single polymorphic method call to an instance of one of the new subclasses.

* Transform Client Type Checks transforms conditionals over type information in a client class by *introducing a new method* to each of the provider classes. The conditional is replaced by a single polymorphic call to the new method.

* Factor out State handles a special case of Transform Self Type Checks in which the type information that is being tested may change dynamically. A *State* [*p. 321*] *object* is *introduced* in the provider class to model the changing state, and the conditional is replaced by a call to a method of the new State object.

* Factor out Strategy is another special case of Transform Self Type Checks in which the algorithms to handle the various provider cases is factored out by *introducing a new Strategy* [*p. 321*] *object*. The key difference with Factor out State is that the algorithm rather than the state may vary dynamically.

* Introduce Null Object addresses the special case of Transform Client Type Checks in which the test performed checks whether or not the provider is defined. The conditional is eliminated by *introducing a Null Object* [*p. 320*] which implements the appropriate default behavior.

* Transform Conditionals into Registration addresses the situation in
which the conditional is responsible for starting up an external tool
based on some attribute of an object to be handled. The solution is to
*introduce a lookup service* where tools are registered as plug-ins. The
conditional is then replaced by a simple lookup for the registered
plug-in. The solution is then fully dynamic because new plug-ins
can be added or removed without any changes to the tool users.
# 10.1 Transform Self Type Checks

**Intent** Improve the extensibility of a class by replacing a complex conditional statement with a call to a hook method implemented by subclasses.

## Problem

A class is hard to modify or extend because it bundles multiple possible behaviors in complex conditional statements that test some attribute representing the current "type" of the object.

*This problem is difficult because:*

* Conceptually simple extensions require many changes to the conditional code.

* Subclassing is next to impossible without duplicating and adapting the methods containing the conditional code.

* Adding a new behavior always results in changes to the same set of methods and always results in adding a new case to the conditional code.

*Yet, solving this problem is feasible because:*

* Self type checks simulate polymorphism. The conditional code tells you what subclasses you should have instead.

## Solution

Identify the methods with complex conditional branches. In each case, replace the conditional code with a call to a new hook method. Identify or introduce subclasses corresponding to the cases of the conditional. In each of these subclasses, implement the hook method with the code corresponding to that case in the original case statement.

## Detection

Most of the time, the type discrimination will jump in your face while you are working on the code, so this means that you will not really need to detect where the checks are made. However, it can be interesting to have simple techniques to quickly assess if unknown parts of a system suffer from similar practices. This can be a valuable source of information to evaluate the state of a system.
* Look for long methods with complex decision structures on some immutable attribute of the object that models type information. In particular look for attributes that are set in the constructor and never changed.

* Attributes that are used to model type information typically take on values from some enumerated type, or from some finite set of constant values. Look for constant definitions whose names represent entities or concepts that one would usually expect to be associated to classes (like *RetiredEmployee* or *PendingOrder*). The conditionals will normally just compare the value of a fixed attribute to one of these constant values.

* Especially look for classes where *multiple* methods switch on the same attribute. This is another common sign that the attribute is being used to simulate a type.

* Since methods containing case statements tend to be long, it may help to use a tool that sorts methods by lines of code or visualizes classes and methods according to their size. Alternatively, search for classes or methods with a large number of conditional statements.

* For languages like C++ or Java where it is common to store the implementation of a class in a separate file, it is straightforward to search for and count the incidence of conditional keywords (if, else, case, etc.). On a UNIX system, for example,
```
grep 'switch' `find . -name "*.cxx" -print'
```

enumerates all the files in a directory tree with extension .cxx that contain a *switch*. Other text processing tools like `agrep` offer possibilities to pose finer granularity queries. Text processing languages like `Perl` may be better suited for evaluating some kinds of queries, especially those that span multiple lines.

* C/C++: Legacy C code may simulate classes by means of union types. Typically the union type will have one data member that encodes the actual type. Look for conditional statements that switch on such data members to decide which type to cast a union to and which behavior to employ.

In C++ it is fairly common to find classes with data members that are declared as *void* pointers. Look for conditional statements that cast such pointers to a given type based on the value of some other data member. The type information may be encoded as an *enum* or (more commonly) as a *constant integer value*.

* Ada: Because Ada 83 did not support polymorphism (or subprogram access types), discriminated record types are often used to simulate
<figure><img src="image_49.png" /><figcaption>Figure 10.2: Transformation of explicit type check into self polymorphic method calls.</figcaption></figure>

polymorphism. Typically an enumeration type provides the set of variants and the conversion to polymorphism is straightforward in Ada95.

* *Smalltalk*: Smalltalk provides only a few ways to manipulate types. Look for applications of the methods `isMemberOf:` and `isKindOf:`, which signal explicit type-checking. Type checks might also be made with tests like `self class = anotherClass`, or with property tests throughout the hierarchy using methods like `isSymbol`, `isString`, `isSequenceable`, `isInteger`.

Steps

1. Identify the class to transform and the different conceptual classes that it implements. An enumeration type or set of constants will probably document this well.

2. Introduce a new subclass for each behavior that is implemented (see Figure 10.2). Modify clients to instantiate the new subclasses rather than the original class. Run the tests.

3. Identify all methods of the original class that implement varying behavior by means of conditional statements. If the conditionals are surrounded by other statements, move them to separate, protected hook methods. When each conditional occupies a method of its own, run the tests.
4. Iteratively move the cases of the conditionals down to the corresponding subclasses, periodically running the tests.

5. The methods that contain conditional code should now all be empty. Replace these by abstract methods and run the tests.

6. Alternatively, if there are suitable default behaviors, implement these at the root of the new hierarchy.

7. If the logic required to decide which subclass to instantiate is non-trivial, consider encapsulating this logic as a factory method of the new hierarchy root. Update clients to use the new factory method and run the tests.

## Tradeoffs

### Pros

* New behaviors can now be added in an incremental manner, without having to change a set of methods of a single class containing all the behavior. A specific behavior can now be understood independently from the other variations.

* A new behavior represents its data independently from the others, thereby minimizing the possible interference and increasing the understandability of the separated behaviors.

* All behaviors now share a common interface, thereby improving their readability.

### Cons

* All the behaviors are now dispersed into multiple but related abstractions, so getting an overview of the behavior may be more difficult. However, the concepts are related and share the interface represented by the abstract class reducing then the problem.

* The larger number of classes makes the design more complex, and potentially harder to understand. If the original conditional statements are simple, it may not be worthwhile to perform this transformation.

* Explicit type checks are not always a problem and we can sometimes tolerate them. Creating new classes increases the number of abstractions in the applications and can clutter namespaces. Hence, explicit type checks may be an alternative to the creation of new classes when:
<figure><img src="image_50.png" /><figcaption>Figure 10.3: Combining simple delegation and Transform Self Type Checks when the class cannot be subclassed.</figcaption></figure>

- the set over which the method selection is fixed and will not evolve in the future, and

- the type check is only made in a few places.

## Difficulties

* Since the requisite subclasses do not yet exist, it can be hard to tell when conditionals are being used to simulate multiple types.

* Wherever instances of the transformed class were originally created, now instances of different subclasses must be created. If the instantiation occurred in client code, that code must now be adapted to instantiating the right class. Factory objects or methods may be needed to hide this complexity from clients.

* If you do not have access to the source code of the clients, it may be difficult or impossible to apply this pattern since you will not be able to change the calls to the constructors.

* If the case statements test more than one attribute, it may be necessary to support a more complex hierarchy, possibly requiring multiple inheritance. Consider splitting the class into parts, each with its own hierarchy.

* When the class containing the original conditionals cannot be subclassed, Transform Self Type Checks can be composed with dele-
gation. The idea is to exploit polymorphism on another hierarchy
by moving part of the state and behavior of the original class into a
separate class to which the method will delegate, as shown in Fig-
ure 10.3.

When the legacy solution is the solution

There are some situations in which explicit type-checks may nevertheless
be the right solution:

* The conditional code may be generated from a special tool. Lexical analysers and parsers, for example, may be automatically generated to contain the kind of conditional code we are trying to avoid. In these cases, however, the generated classes should never be manually extended, but simply regenerated from the modified specifications.

Example

We worked on a complex system that controls large, physical machines
by sending them messages. These messages are represented by the class
Message and can be of different types.

<figure><img src="image_51.png" /></figure>

class Message {
  public:
    Message();
    set_value(char* text);
    set_value(int action);
    void send(Channel c);
    void receive(Channel c);
    ...
  private:
    void* data_;
    int type_;
    static const int TEXT = 1;
    static const int ACTION = 2;
    ...
}

Message::send(Channel c) {
  switch (type_) {
    case TEXT:
      ...
    case ACTION:
      ...
  }
}

void Client1::doit() {
  Message * myMessage =
    new Message();
  myMessage->set_Value("...");
  ...
}

<caption>Figure 10.4: Initial design and source code.</caption>
Before.

A message class wraps two different kinds of messages (TEXT and ACTION) that must be serialized to be sent across a network connection as shown in the code and the figure. We would like to be able to send a new kind of message (say VOICE), but this will require changes to several methods of Message as shown in Figure 10.4.

<figure><img src="image_52.png" /><figcaption>Figure 10.5: Resulting hierarchy and source code.</figcaption></figure>

After.

Since Message conceptually implements two different classes, Text_Message and Action_Message, we introduce these as subclasses of Message, as shown in Figure 10.5. We introduce constructors for the new classes, we modify the clients to construct instances of Text_Message and Action_Message rather than Message, and we remove the set_value() methods. Our regression tests should run at this point.
Now we find methods that switch on the *type* variable. In each case, we move the entire case statement to a separate, protected hook method, unless the switch already occupies the entire method. In the case of `send()`, this is already the case, so we do not have to introduce a hook method. Again, all our tests should still run.

Now we iteratively move cases of the case statements from `Message` to its subclasses. The `TEXT` case of `Message::send()` moves to `Text_Message::send()` and the `ACTION` case moves to `Action_Message::send()`. Every time we move such a case, our tests should still run.

Finally, since the original `send()` method is now empty, it can be redeclared to be abstract (i.e., virtual void `send(Channel) = 0`). Again, our tests should run.

## Rationale

Classes that masquerade as multiple data types make a design harder to understand and extend. The use of explicit type checks leads to long methods that mix several different behaviors. Introducing new behavior then requires changes to be made to all such methods instead of simply specifying one new class representing the new behavior.

By transforming such classes to hierarchies that explicitly represent the multiple data types, you improve cohesion by bringing together all the code concerning a single data type, you eliminate a certain amount of duplicated code (i.e., the conditional tests), and you make your design more transparent, and consequently easier to maintain.

## Related Patterns

In Transform Self Type Checks the condition to be transformed tests type information that is represented as an attribute of the class itself.

If the conditional tests *mutable* state of the host object, consider instead applying Factor out State [p. 291], or possibly Factor out Strategy [p. 295].

If the conditional occurs in a *client* rather than in the provider class itself, consider applying Transform Client Type Checks [p. 281].

If the conditional code tests some type attribute of a second object in order to *select some third handler object*, consider instead applying Transform Conditionals into Registration [p. 303].
## 10.2 Transform Client Type Checks

**Intent** Reduce client/provider coupling by transforming conditional code that tests the type of the provider into a polymorphic call to a new provider method.

### Problem

How do you reduce the coupling between clients and providers of services, where the clients explicitly check the type of providers and have the responsibility to compose providers code?

*This problem is difficult because:*

* Adding a new subclass to the provider hierarchy requires making changes to many clients, especially where the tests occur.

* Clients and providers will tend to be strongly coupled, since clients are performing actions that should be the responsibility of the providers.

*Yet, solving this problem is feasible because:*

* The conditionals tell you to which classes you should transfer behavior.

### Solution

Introduce a new method to the provider hierarchy. Implement the new method in each subclass of the provider hierarchy by moving the corresponding case of the clients conditional to that class. Replace the entire conditional in the client by a simple call to the new method.

### Detection

Apply essentially the same techniques described in Transform Self Type Checks to detect case statements, but look for conditions that test the type of a separate service provider which *already* implements a hierarchy. You should also look for case statements occurring in different clients of the same provider hierarchy.

* C++: Legacy C++ code is not likely to make use of run-time type information (RTTI). Instead, type information will likely be encoded
in a data member that takes its value from some enumerated type
representing the current class. Look for client code switching on such
data members.

*   **Ada:** Detecting type tests falls into two cases. If the hierarchy is implemented as a single discriminated record then you will find case statements over the discriminant. If the hierarchy is implemented with tagged types then you cannot write a case statement over the types (they are not discrete); instead an if-then-else structure will be used.

*   *Smalltalk:* As in Transform Self Type Checks, look for applications of `isMemberOf:` and `isKindOf:`, and tests like `self class = anotherClass`.

*   **Java:** Look for applications of the operator **instanceof**, which tests membership of an object in a specific, known class. Although classes in Java are not objects as in Smalltalk, each class that is loaded into the virtual machine is represented by a single instance of `java.lang.Class`. It is therefore possible to determine if two objects, x and y belong to the same class by performing the test:

`x.getClass() == y.getClass()`

Alternatively, class membership may be tested by comparing class
names:

`x.getClass().name().equals(y.getClass().name())`

Steps

1. Identify the clients performing explicit type checks.

2. Add a new, empty method to the root of the provider hierarchy representing the action performed in the conditional code (see Figure 10.6).

3. Iteratively move a case of the conditional to some provider class, replacing it with a call to that method. After each move, the regression tests should run.

4. When all methods have been moved, each case of the conditional consists of a call to the new method, so replace the entire conditional by a single call to the new method.

5. Consider making the method abstract in the provider's root. Alternatively implement suitable default behavior here.
<figure><img src="image_53.png" /><figcaption>Figure 10.6: Transformation of explicit type check used to determine which methods of a client should be invoked into polymorphic method calls.</figcaption></figure>

## Other Steps to Consider

* It may well be that multiple clients are performing exactly the same test and taking the same actions. In this case, the duplicated code can be replaced by a single method call after one of the clients has been transformed. If clients are performing different tests or taking different actions, then the pattern must be applied once for each conditional.

* If the case statement does not cover all the concrete classes of the provider hierarchy, a new abstract class may need to be introduced as a common superclass of the concerned classes. The new method will then be introduced only for the relevant subtree. Alternatively, if it is not possible to introduce such an abstract class given the existing inheritance hierarchy, consider implementing the method at the root with either an empty default implementation, or one that raises an
exception if it is called for an inappropriate class.

* If the conditionals are nested, the pattern may need to be applied recursively.

## Tradeoffs

### Pros

* The provider hierarchy offers a new, polymorphic service available to other clients as well.

* The code of the clients is now better organized and does not have to deal anymore with concerns that are now under the responsibility of the provider.

* All the code concerning the behavior of a single provider is now together in a single location.

* The fact that the provider hierarchy offers a uniform interface allows providers to be modified without impacting clients.

### Cons

* Sometimes it is convenient to see the code handling different cases in a single location. Transform Client Type Checks redistributes the logic to the individual provider classes, with the result that the overview is lost.

## Difficulties

* Normally instances of the provider classes should be already have been created so we do not have to look for the creation of the instances, however refactoring the interface will affect all clients of the provider classes and must not be undertaken without considering the full consequences of such an action.

## When the legacy solution is the solution

Client type checks may nevertheless be the right solution when the provider instance does not yet exist or when its class cannot be extended:

* An Abstract Factory [p. 319] object may need to test a type variable in order to know which class to instantiate. For example, a factory
may stream objects in from a text file representation, and test some
variable that tells it which class the streamed object should belong
to.

* Software that interfaces to a non-object-oriented library, such as a legacy GUI library, may force the developer to simulate the dispatch manually. It is questionable whether, in such cases, it is cost-effective to develop an object-oriented facade to the procedural library.

* If the provider hierarchy is frozen (e.g., because the source code is not available), then it will not be possible to transfer behavior to the provider classes. In this case, wrapper classes may be defined to extend the behavior of the provider classes, but the added complexity of defining the wrappers may overwhelm any benefits.

## Example

### Before

The following C++ code illustrates misplaced responsibilities since the client must explicitly type check instances of `Telephone` to determine what action to perform. The code in bold highlights the difficulties with this approach.

```cpp
class Telephone {
public:
    enum PhoneType {
        POTSPHONE, ISDNPHONE, OPERATORPHONE
    };
    Telephone() {}
    PhoneType phoneType() { return myType; }

private:
    PhoneType myType;
protected:
    void setPhoneType(PhoneType newType) { myType = newType; }
};

class POTSPhone : public Telephone {
public:
    POTSPhone() { setPhoneType(POTSPPHONE); }
    void tourneManivelle();
    void call();
};
```
class ISDNPhone: public Telephone {
  public:
    ISDNPhone() { setPhoneType(ISDNPHONE); }
    void initializeLine();
    void connect();
  };
  ...

class OperatorPhone: public Telephone {
  public:
    OperatorPhone() { setPhoneType(OPERATORPHONE); }
    void operatorMode(bool onOffToggle);
    void call();
  };

void initiateCalls(Telephone ** phoneArray, int numOfCalls) {
  for(int i = 0; i{ // numOfCalls; i++ }
    Telephone * p = phoneArray[i];

    switch(p->phoneType()) {
      case Telephone::POTSPPHONE: {
        POTSPhone *potsp = (POTSPhone *) p;
        potsp->tourneManivelle();
        potsp->call();
        break;
      }
      case Telephone::ISDNPHONE: {
        ISDNPhone *isdnp = (ISDNPhone *) p;
        isdnp->initializeLine();
        isdnp->connect();
        break;
      }
      case Telephone::OPERATORPHONE: {
        OperatorPhone *opp = (OperatorPhone *) p;
        opp->operatorMode(true);
        opp->call();
        break;
      }
      default: cerr << "Unrecognized Phonetype" << endl;
    };
  }
}
<figure><img src="image_54.png" /><figcaption>Figure 10.7: Transforming explicit type checks to polymorphic method invocations.</figcaption></figure>

## After

After applying the pattern the client code will look like the following. (See also Figure 10.7.)

```java
class Telephone {
    public:
        Telephone() {}
        virtual void makeCall() = 0;
};

class POTSPhone : public Telephone {
    void tourneManivelle();
    void call();
    public:
        POTSPhone() {}
        void makeCall();
};

void POTSPhone::makeCall() {
    this->tourneManivelle();
    this->call();
}

class ISDNPhone: public Telephone {
```
```java
void initializeLine();
void connect();

public:
    ISDNPhone() {}
    void makeCall();
};

void ISDNPhone::makeCall() {
    this->initializeLine();
    this->connect();
}

class OperatorPhone: public Telephone {
    void operatorMode(bool onOffToggle);
    void call();
public:
    OperatorPhone() {}
    void makeCall();
};

void OperatorPhone::makeCall() {
    this->operatorMode(true);
    this->call();
}

void initiateCalls(Telephone **phoneArray, int numOfCalls) {
    for(int i = 0; i{ // numOfCalls; i++ }
        phoneArray[i]->makeCall();
    }
}
```

## Rationale

Riel states, "Explicit case analysis on the type of an object is usually an error. The designer should use polymorphism in most of these cases" [Rie96]. Indeed, explicit type checks in clients are a sign of misplaced responsibilities since they increase coupling between clients and providers. Shifting these responsibilities to the provider will have the following consequences:

* The client and the provider will be more weakly coupled since the client will only need to explicitly know the root of the provider hierarchy instead of all of its concrete subclasses.

* The provider hierarchy may evolve more gracefully, with less chance of breaking client code.
* The size and complexity of client code is reduced. The collaborations between clients and providers become more abstract.

* Abstractions implicit in the old design (i.e., the actions of the conditional cases) will be made explicit as methods, and will be available to other clients.

* Code duplication may be reduced (if the same conditionals occur multiply).

## Related Patterns

In Transform Client Type Checks the conditional is made on the type information of a provider class. The same situation occurs in Introduce Null Object where the conditional tests over null value before invoking the methods. From this point of view, Introduce Null Object is a specialization of Transform Client Type Checks.

Transform Conditionals into Registration handles the special case in which the client's conditional is used to select a third object (typically an external application or tool) to handle the argument.

Replace Conditional with Polymorphism [p. 318] is the core refactoring of this reengineering pattern, so the reader may refer to the steps described in [FBB+99].
## 10.3 Factor out State

**Intent** Eliminate complex conditional code over an object's state by applying the State design pattern.

### Problem

How do you make a class whose behavior depends on a complex evaluation of its current state more extensible?

*This problem is difficult because:*

* There are several complex conditional statements spread out over the methods of the object. Adding new behavior may affect these conditionals in subtle ways.

* Whenever new possible states are introduced, all the methods that test state have to be modified.

*Yet, solving this problem is feasible because:*

* The object's instance variables are typically used to model different abstract states, each of which has its own behavior. If you can identify these abstract states, you can factor the state and the behavior out into a set of simpler, related classes.

### Solution

Apply the State [p. 321] pattern, i.e., encapsulate the state-dependent behavior into separate objects, delegate calls to these objects and keep the state of the object consistent by referring to the right instance of these state objects (see figure 47).

As in Transform Self Type Checks, transform complex conditional code that tests over quantified states into delegated calls to state classes. Apply the State [p. 321] pattern, delegating each conditional case to a separate State object. We invite the reader to read State and State Patterns [p. 321] for a deep description of the problem and discussion [GHJV95] [ABW98] [DA97]. Here we only focus on the reengineering aspects of the pattern.

### Steps

1. Identify the interface of a state and the number of states.
<figure><img src="image_55.png" /><figcaption>Figure 10.8: Transformation to go from a state pattern simulated using explicit state conditional to a situation where the state pattern has been applied.</figcaption></figure>

If you are lucky, each conditional will partition the state space in the same way, and the number of states will equal the number of cases in each conditional. In case the conditionals overlap, a finer partitioning will be required.

The interface of a state depends on how the state information is accessed and updated, and may need to be refined in the subsequent steps.

2. Create a new abstract class, **State**, representing the interface of the state.

3. Create a new class subclass of **State** for each state.

4. Define methods of the interface identified in Step 1 in each of the state classes by copying the corresponding code of the conditional to the new method. Do not forget to change the state of the instance variable in the **Context** to refer to the right instance of **State** class. The **State** methods have the responsibility to change the **Context** so that it always refers to the next state instance.

5. Add a new instance variable in the **Context** class.
6. You may have to have a reference from the **State** to the **Context** class to invoke the state transitions from the **State** classes.

7. Initialize the newly created instance to refer to a default state class instance.

8. Change the methods of the **Context** class containing the tests to delegate the call to the instance variable.

Step 4 can be performed using the Extract Method operation of the Refactoring Browser. Note that after each step, the regression tests should still run. The critical step is the last one, in which behavior is delegated to the new state objects.

# Tradeoffs

## Pros

* *Limited Impact.* The public interface of the original class does not have to change. Since the state instances are accessed by delegation from the original object, the clients are unaffected. In the straightforward case the application of this pattern has a limited impact on the clients.

## Cons

* The systematic application of this pattern may lead to an explosion in the number of classes.

* This pattern should not be applied when:

- there are too many possible states, or the number of states is not fixed

- it is hard to determine from the code how and when state transitions occur.

## When the legacy solution is the solution

This pattern should not be applied lightly.

* When the states are clearly identified and it is known that they will not be changed, the legacy solution has the advantage of grouping all the state behavior by functionality instead of spreading it over different subclasses.
* In certain domains, such as parsers, table-driven behavior, encoded as conditionals over state, are well-understood, and factoring out the state objects may just make the code harder to understand, and hence to maintain.

## Known Uses

The *Design Patterns Smalltalk Companion* [ABW98] presents a step-by-step code transformation.
## 10.4 Factor out Strategy

**Intent** Eliminate conditional code that selects a suitable algorithm by applying the Strategy design pattern.

### Problem

How do you make a class whose behavior depends on testing the value of some variable more extensible?

This problem is difficult because:

* New functionality cannot be added without modifying all the methods containing the conditional code.

* The conditional code may be spread over several classes which make similar decisions about which algorithm to apply.

Yet, solving this problem is feasible because:

* The alternative behaviors are essentially interchangeable.

### Solution

Apply the Strategy pattern, i.e., encapsulate the algorithmic dependent behavior into separate objects with polymorphic interfaces and delegate calls to these objects (see Figure 10.9).

#### Steps

1. Identify the interface of the strategy class.

2. Create a new abstract class, **Strategy**, representing the interface of the strategies.

3. Create a new class subclass of **Strategy** for each identified algorithms.

4. Define methods of the interface identified in Step 1 in each of the strategy classes by copying the corresponding code of the test to the method.

5. Add a new instance variable in the **Context** class to refer to the current strategy.
<figure><img src="image_56.png" /><figcaption>Figure 10.9: Transformation to go from a state pattern simulated using explicit state conditional to a situation where the state pattern has been applied.</figcaption></figure>

6. You may have to have a reference from the **Strategy** to the **Context** class to provide access to the information maintained by the **Context** (See difficulties).

7. Initialize the newly created instance to refer to a default strategy instance.

8. Change the methods of the **Context** class containing the tests by eliminating the tests and delegating the call to the instance variable.

Step 4 can be performed using the Extract Method operation of the Refactoring Browser. Note that after each step, the regression tests should still run. The critical step is the last one, in which behavior is delegated to the new **Strategy** objects.

## Tradeoffs

### Pros

* *Limited Impact.* The public interface of the original class does not have to change. Since the **Strategy** instances are accessed by delegation from the original object, the clients are unaffected. In a straightforward case the application of this pattern has a limited impact on the clients. However, the **Context** interface will be reduced because
all the previously implemented algorithms are now moved to Strategy classes. So you have to check the invocations of these methods and decide on a per case base.

* After applying this pattern, you will be able to plug new strategies without impacting modifying the interface of the Context. Adding a new strategy does not require to recompile the Context class and its clients.

* After applying this pattern, the interface of the Context class and the Strategy classes will be clearer.

## Cons

* The systematic application of this pattern may lead to a class explosion. If you have 20 different algorithms you may not want to have 20 new classes each with only one method.

* Object explosion. Strategies increase the number of instances in an application.

## Difficulties

* There are several ways to share information between the Context and the Strategy objects, and the tradeoffs can be subtle. The information can be passed as argument when the Strategy method is invoked, the Context object itself can be passed as argument, or the Strategy objects can hold a reference to their context. If the relationship between the Context and the Strategy is highly dynamic, then it may be preferable to pass this information as a method argument. More detailed discussions of this issue exist in the literature on the Strategy [p. 321] pattern [GHJV95] [ABW98].

## Example

The *Design Patterns Smalltalk Companion* [ABW98] presents a step-by-step code transformation.

## Related Patterns

The symptoms and structure of Factor out Strategy bear comparison with Factor out State. The main difference consists in the fact that the Factor out State identifies behavior with different possible states of objects whereas
Factor out Strategy is concerned with interchangeable algorithms that are
independent of object state. Factor out Strategy allows one to add new
strategies without impacting the existing strategy objects.
# 10.5 Introduce Null Object

**Intent** *Eliminate conditional code that tests for null values by applying the Null Object design pattern.*

## Problem

How can you ease modification and extension of a class in presence of
repeated tests for null values?

*This problem is difficult because:*

* Client methods are always testing that certain values are not null before actually invoking their methods.

* Adding a new subclass to the client hierarchy requires testing null values before invoking some of the provider methods.

*Yet, solving this problem is feasible because:*

* The client does not need to know that the provider represents a null value.

## Solution

Apply the Null Object [p. 320] pattern, i.e., encapsulate the null behavior as a separate provider class so that the client class does not have to perform a null test.

## Detection

Look for idiomatic null tests.

Null tests may take different forms, depending on the programming language and the kind of entity being tested. In Java, for example, a null object reference has the value null, whereas in C++ a null object pointer has the value 0.

## Steps

Fowler discusses in detail the necessary refactoring steps [FBB+99].
<figure><img src="image_57.png" /><figcaption>Figure 10.10: Transformation from a situation based on explicit test of null value to a situation where a Null Object is introduced.</figcaption></figure>

1. Identify the interface required for the null behavior. (This will normally be identical to that of the non-null object.)

2. Create a new abstract superclass as a superclass of the **RealObject** class.

3. Create a new subclass of the abstract superclass with a name starting with **No** or **Null**.

4. Define default methods into the **Null Object** class.

5. Initialize the instance variable or structure that was checked to now hold at least an instance of the **Null Object** class.

6. Remove the conditional tests from the client.

If you still want to be able to test for null values in a clean way, you may introduce a query method called `isNull` in **RealObject** and **Null Object** classes, as described by Fowler [FBB+99].

# Tradeoffs

## Pros

* The client code is much simpler after applying the pattern.
* The pattern is relatively simple to apply since the interface of the provider does not have to be modified.

### Cons

* The provider hierarchy becomes more complex.

### Difficulties

* Multiple clients may not agree on the reasonable default behavior of the Null Object. In this case, multiple Null Object classes may need to be defined.

### When the legacy solution is the solution

* If clients do not agree on a common interface.

* When very little code uses the variable directly or when the code that uses the variable is well-encapsulated in a single place.

## Example

The following Smalltalk code is taken from Woolf [Woo98]. Initially the code contains explicit null tests::

VisualPart>>objectWantedControl
...
↑ctrl isNil
ifFalse:
    [ctrl isControlWanted
        ifTrue:[self]
        ifFalse:[nil]]

It is then transformed into :

VisualPart>>objectWantedControl
...
↑ctrl isControlWanted
    ifTrue:[self]
    ifFalse:[nil]
Controller>>isControlWanted
↑self viewHasCursor
NoController>>isControlWanted
↑false
## 10.6 Transform Conditionals into Registration

**Intent** Improve the modularity of a system by replacing conditionals in clients by a registration mechanism.

### Problem

How can you reduce the coupling between *tools* providing services and *clients* so that the addition or removal of tools does not lead to changing the code of the clients?

*This problem is difficult because:*

* Having one single place to look for all the kinds of tools makes it easy to understand the system and easy to add new tools.

* However, every time you remove a *tool*, you have to remove one case in some conditional statement, else certain parts (*tool clients*) would still reflect the presence of the removed tools, leading to fragile systems. Then every time you add a new tool, you have to add a new conditional in all the tool clients.

*Yet, solving this problem is feasible because:*

* Long conditionals make it easy to identify the different type of tools used.

### Solution

Introduce a *registration mechanism* to which each tool is responsible for registering itself, and transform the *tool clients* to query the registration repository instead of performing conditionals.

#### Steps

1. Define a class describing *plug-in objects*, i.e., an object encapsulating the information necessary for registering a tool. Although the internal structure of this class depends on the purpose of the registration, a plug-in should provide the necessary information so the tool manager can *identify* it, *create* an instance of the represented tool and *invoke* methods. To invoke a tool method, a method or a similar mechanism like a block closure or inner class should be stored in the plug-in object.
<figure><img src="image_58.png" /><figcaption>Figure 10.11: Transforming conditionals in tool users by introducing a registration mechanism.</figcaption></figure>

2. Define a class representing the *plug-in manager*, i.e., that manages the plug-in objects and that will be queried by the tool clients to check the presence of the tools. This class will certainly be a singleton since the plug-ins representing the tools available should not be lost if a new instance of the plug-in manager is created.

3. For each case of the conditional, define a plug-in *object* associated with the given tool. This plug-in object should be created and registered automatically when the tool it represents is loaded, and it should be unregistered if and when the tool becomes unavailable. Sometimes information from the tool client should be passed to the tool. The current tool client can be passed as argument when the tool is invoked.

4. Transform the entire conditional expression into a query to the tool manager object. This query should return a tool associated to the query and invoke it to access the wished functionality.

5. Remove any tool client actions that directly activate tools. This behavior is now the responsibility of the plug-in manager.
The client or the plug-in object may have the responsibility to invoke a tool. It is better to let the plug-in object having this responsibility because it already holds the responsibility of representing how to represent the tools and let the clients just says that they need a tool action.

## Example

In Squeak [IKM+97], the FileList is a tool that allows the loading of different kinds of files, such as Smalltalk code, JPEG images, MIDI files, HTML, and so on. Depending on the suffix of the selected file, the FileList proposes different actions to the user. We show in the example the loading of the different file depending on their format.

### Before

The FileList implementation creates different menu items representing the different possible actions depending on the suffix of the files. The dynamic part of the menu is defined in the method menusForFileEnding: which takes a file suffix as its argument and returns a menu item containing the label of the menu item and the name of the corresponding method that should be invoked on the FileList object.

FileList>>menusForFileEnding: suffix

(suffix = 'jpg') ifTrue:
    [↑MenuItem label:'open image in a window'.
        selector: #openImageInWindow].

(suffix = 'morph') ifTrue:
    [↑MenuItem label: 'load as morph'.
        selector: #openMorphFromFile].

(suffix = 'mid') ifTrue:
    [↑MenuItem label: 'play midi file'.
        selector: #playMidiFile].

(suffix = 'st') ifTrue:
    [↑MenuItem label: 'fileIn'.
        selector: #fileInSelection].

(suffix = 'swf') ifTrue:
    [↑MenuItem label: 'open as Flash'.
        selector: #openAsFlash].

(suffix = '3ds') ifTrue:
    [↑MenuItem label: 'Open 3DS file'.
        selector: #open3DSFile].

(suffix = 'wrl') ifTrue:
    [↑MenuItem label: 'open in Wonderland'.
        selector: #openVRMLFile].
(suffix = 'html') ifTrue:
    [↑MenuItem label: 'open in html browser'.
     selector: #openInBrowser].

(suffix = '*') ifTrue:
    [↑MenuItem label: 'generate HTML'.
     selector:#renderFile].

The methods whose selectors are associated in the menu are imple-
mented in the FileList class. We give two examples here. First the method
checks if the tool it needs is available, if not it generates a beep, otherwise
the corresponding tool is created and then used to handle the selected file.

FileList>>openInBrowser
Smalltalk at: #Scamper ifAbsent: [↑ self beep].
Scamper openOnUrl: (directory url, fileName encodeForHTTP)

FileList>>openVRMLFile
| scene |
Smalltalk at: #Wonderland ifAbsent: [↑ self beep].
scene := Wonderland new.
scene makeActorFromVRML: self fullName.

After

The solution is to give each tool the responsibility to register itself and let
the FileList query the registry of available tools to find which tool can be
invoked.

*Step 1.* The solution is to first create the class ToolPlugin representing the registration of a given tool. Here we store the suffix files, the menu label and the action to be performed when the tools will be invoked.

Object subclass: #ToolPlugin
instanceVariableNames: 'fileSuffix menuLabelName blockToOpen '

*Step 2.* Then the class PluginManager is defined. It defines a structure to hold the registered tools and defines behavior to add, remove and find registered tool.

Object subclass: #PluginManager
instanceVariableNames: 'plugins '

PluginManager>>initialize
plugins := OrderedCollection new.

PluginManager>>addPlugin : aPlugin
plugins add: aRegistree

PluginManager>>removePlugin: aBlock

(plugins select: aBlock) copy
do: [:each| plugins remove: each]

PluginManager>>findToolFor: aSuffix
"return a registree of a tool being able to treat file of format
aSuffix"

↑ plugins
detect: [:each| each suffix = aSuffix]
ifNone: [nil]

Note that the findToolFor: method could take a block to select which of the plug-in objects satisfying it and that it could return a list of plug-in representing all the tools currently able to treat a given file format.

Step 3. Then the tools should register themselves when they are loaded in memory. Here we present two registrations, showing that a plug-in object is created for each tool. As the tools need some information from the FileList object such as the filename or the directory, the action that has to be performed takes as a parameter the instance of the FileList object that invokes it ([:fileList | ...] in the code below).

In Squeak, when a class specifies a class (static) initialize method, this method is invoked once the class is loaded in memory. We then specialize the class methods initialize of the classes Camper and Wonderland to invoke their class methods toolRegistration defined below:

Camper class>>toolRegistration

PluginManager uniqueInstance
addPlugin:
(ToolPlugin
  forFileSuffix: 'html'
  openingBlock:
    [:fileList |
      self openOnUrl:
        (fileList directory url,
         fileList file_name encodeForHTTP])
    menuLabelName: 'open in html browser')

Wonderland class>>toolRegistration

PluginManager uniqueInstance
addPlugin:
(ToolPlugin
    forFileSuffix: 'wrl'
    openingBlock:
        [:fileList |
        | scene |
        scene := self new.
        scene makeActorFromVRML: fileList fullName]
    menuLabelName: 'open in Wonderland')

In Squeak, when a class is removed from the system, it receives the message `removeFromSystem`. Here we then specialize this method for every tool so that it can unregister itself.

### Scamper class>>removeFromSystem

super removeFromSystem.
PluginManager uniqueInstance
    removePlugin: [:plugin| plugin forFileSuffix = 'html']

### Wonderland class>>removeFromSystem

super removeFromSystem.
PluginManager uniqueInstance
    removePlugin: [:plugin| plugin forFileSuffix = 'wrl']

*Step 4.* The `FileList` object now has to use the `ToolsManager` to identify the right plug-in object depending on the suffix of the selected file. Then if a tool is available for the given suffix, it creates a menu item specifying that the `FileList` has to be passed as argument of the action block associated with the tool. In the case where there is no tool a special menu is created whose action is to do nothing.

### FileList>>itemsForFileEnding: suffix

| plugin |
plugin := PluginManager uniqueInstance
    findToolFor: suffix ifAbsent: [nil].
↑ plugins isNil
    ifFalse: [Menu label: (plugin menuLabelName)
        actionBlock: (plugin openingBlock)
        withParameter: self]
    ifTrue: [ErrorMenu new
        label: 'no tool available for the suffix ', suffix]
# Tradeoffs

## Pros

* By applying Transform Conditionals into Registration you obtain a system which is both dynamic and flexible. New tools can be added without impacting tool clients.

* Tool clients no longer have to check whether a given tool is available. The registration mechanism ensures you that the action can be performed.

* The interaction protocol between tools and tool clients is now normalized.

## Cons

* You have to define two new classes, one for the object representing tool representation (plugin) and one for the object managing the registered tools (plugin manager).

## Difficulties

* While transforming a branch of the conditional into a plug-in object, you will have to define an action associated with the tools via the plug-in object. To ensure a clear separation and full dynamic registration, this action should be defined on the tool and not anymore on the tool client. However, as the tool may need some information from the tool client, the tool client should be passed to the tool as a parameter when the action is invoked. This changes the protocol between the tool and the tool client from a single invocation on the tool client to a method invocation to the tool with an extra parameter. This also implies that in some cases the tool client class have to define new public or friend methods to allow the tools to access the tool client right information.

* If each single conditional branch is associated only with a single tool, only one plug-in object is needed. However, if the same tool can be called in different ways we will have to create multiple plug-in objects.

## When the legacy solution is the solution

* If there is only a single tool client class, if all the tools are always available, and if you will never add or remove a tool at run-time, a
conditional is simpler.

## Related Patterns

Both Transform Conditionals into Registration and Transform Client Type Checks eliminate conditional expressions that decide which method should be invoked on which object. The key difference between the two patterns is that Transform Client Type Checks moves behavior from the client to the service provider, whereas Transform Conditionals into Registration deals with behavior that cannot be moved because it is implemented by an external tool.

## Script: Identifying simulated switches in C++

This Perl script searches the methods in C++ files and lists the occurrences of statements used to simulate case statement with `if` then `else` i.e., matching the following expression: `elseXif` where X can be replaced by `//...` or some white space including carriage return.

```perl
#!/opt/local/bin/perl
$/ = '::';
# new record delimited.
$elifPattern = 'else[\s\n]*{?[\s\n]*if';
$linecount = 1;
while (<>) {
    s/(//.*)//g; # remove C++ style comments
    $lc = (split \n/) - 1; # count lines

    if($elifPattern) {
        # count # of lines until first
        # occurrence of "else if"
        $temp = join("", $`, $&);
        $l = $linecount + split(\n/, $temp) - 1;
        # count the occurrences of else-if pairs,
        # flag the positions for an eventual printout
        $swc = s/(else)([\s\n]*{?[\s\n]*if)
                       /$1\n
                       * HERE *$2/g;
        printf "\n%s: Statement with
                %2d else-if's, first at: %d",
               $ARGV, $swc, $l;
    }
    $linecount += $lc;
    if eof) {
        close ARGV;
        $linecount = 0;
```
```perl
print "\n";
}
}
```
# Part IV

## Appendices
<figure><img src="image_59.png" /></figure>
# Appendix A

## Thumbnail patterns

There are many patterns that are not specifically concerned with reengineering, but are still relevant to the reengineering process. In this chapter we have listed only those patterns that are specifically referred to at some point in this book. We have grouped them into the following three categories:

* *Testing patterns*. These patterns help you to focus your testing efforts. Our principle source is a pattern language by DeLano and Rising [DR98], though of course a vast literature is available on the subject. Binder, for example, devotes an entire book to the subject [Bin99].

* *Refactoring patterns*. These patterns focus on individual refactoring steps that you might applying during a reengineering project, or that you might just as well apply during any forward engineering project. Our principle sources are Fowler *et al.* [FBB+99], and the Roberts' PhD thesis [Rob99].

* *Design patterns*. Very frequently the result of a reengineering operation is to put a particular design pattern into place. Here we remind the reader of some of the most common design patterns that pop up in a reengineering context. Our main source is, of course, the *Design Patterns* book [GHJV95].
# A.1 Testing Patterns

## A.1.1 Retest Persistent Problems

**Problem:** What areas of the system should receive concentrated testing, irrespective of the features being implemented?

**Solution:** Keep a list of persistent problem areas and test cases to verify them, not just for resolving the current problems but also for use in subsequent testing. Test these areas thoroughly, even if there are no new features going into them. Retest regularly using, even one last time before the release goes out of the door.

**Source:** Patterns for system testing [DR98].

**Referenced from:** Regression Test After Every Change [p. 201].

## A.1.2 Test Fuzzy Features

**Problem:** How can possible problem areas of the system be pinpointed so that the most problems can be found in the least amount of time?

**Solution:** Study the documentation available on the system. Look for areas that seem ambiguous or ill-defined. Write test plans that cover these areas more thoroughly and concentrate testing in these areas. If designers can tell you all about a feature, it probably works. It's what they can't tell you that needs attention during testing.

**Source:** Patterns for system testing [DR98].

**Referenced from:** Grow Your Test Base Incrementally [p. 159].

## A.1.3 Test Old Bugs

**Problem:** What areas of the system should be targeted for testing so that the most problems can be found in the least amount of time?
**Solution:** Examine problem reports from previous releases to help select test cases. Since it would be inefficient to test for all old problems, look at problems reported after the last valid snapshot of the system. Categorize problem reports to see if a trend is determined that could be used for additional testing.

**Source:** Patterns for system testing [DR98].

**Referenced from:** Grow Your Test Base Incrementally [p. 159].

## A.2 Refactorings

### A.2.1 Encapsulate Field

**Also Known As:** Abstract Instance Variable [Rob99].

**Intent** There is a public field. Make it private and provide accessors.

**Source:** Refactoring: Improving the Design of Existing Code [FBB+99].

**Referenced from:** Eliminate Navigation Code [p. 253].

### A.2.2 Extract Method

**Intent** You have a code fragment that can be grouped together. Turn the fragment into a method whose name explains the purpose of the method.

**Source:** Refactoring: Improving the Design of Existing Code [FBB+99].

**Referenced from:** Refactor to Understand [p. 127], Visualize Code as Dotplots [p. 233], Move Behavior Close to Data [p. 243]

### A.2.3 Move Method

**Intent** A method is, or will be, using or used by more features of another class than the class on which it is defined. Create a new method with a similar body
in the class it uses most. Either turn the old method into a simple delegation, or remove it altogether.

**Source:** Refactoring: Improving the Design of Existing Code [FBB+99].

**Referenced from:** Refactor to Understand [p. 127], Move Behavior Close to Data [p. 243]

### A.2.4 Rename Attribute

**Intent** Rename an instance variable and update all references to it.

**Source:** Practical Analysis for Refactoring [Rob99].

**Referenced from:** Refactor to Understand [p. 127].

### A.2.5 Rename Method

**Intent** The name of a method does not reveal its purpose. Change the name of the method.

**Source:** Refactoring: Improving the Design of Existing Code [FBB+99].

**Referenced from:** Refactor to Understand [p. 127]

### A.2.6 Replace Conditional with Polymorphism

**Intent** You have a conditional that chooses different behavior depending on the type of an object. Move each leg of the conditional to an overriding method in a subclass. Make the original method abstract.

**Source:** Refactoring: Improving the Design of Existing Code [FBB+99].

**Referenced from:** Transform Client Type Checks [p. 281]
# A.3 Design Patterns

## A.3.1 Abstract Factory

**Intent** Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

**Source:** *Design Patterns* [GHJV95].

**Referenced from:** Look for the Contracts [p. 137], Transform Client Type Checks [p. 281].

## A.3.2 Adapter

**Intent** Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.

**Source:** *Design Patterns* [GHJV95].

**Referenced from:** Present the Right Interface [p. 207], Move Behavior Close to Data [p. 243].

## A.3.3 Facade

**Intent** Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

**Source:** *Design Patterns* [GHJV95].

**Referenced from:** Eliminate Navigation Code [p. 253], Split Up God Class [p. 263].

## A.3.4 Factory Method

**Intent** Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
**Source:** *Design Patterns* [GHJV95].

**Referenced from:** Look for the Contracts [p. 137]

### A.3.5 Flyweight

**Intent** Use sharing to support large numbers of fine-grained objects efficiently.

**Source:** *Design Patterns* [GHJV95].

**Referenced from:** Speculate about Design [p. 97]

### A.3.6 Null Object

**Intent** A Null Object provides a surrogate for another object that shares the same interface but does nothing. Thus, the Null Object encapsulates the implementation decisions of how to do nothing and hides those details from its collaborators

**Source:** *Null Object* [Woo98].

**Referenced from:** Introduce Null Object [p. 299].

### A.3.7 Quantity

**Problem:** Representing a value such as 6 feet or $5.

**Solution:** Use a quantity type that includes both the amount and the unit. Currencies are a kind of unit.

**Source:** *Analysis Patterns: Reusable Objects Models* [Fow97].

**Referenced from:** Analyze the Persistent Data [p. 87].
### A.3.8 Singleton

**Intent** Ensure a class only has one instance, and provide a global point of access to it.

**Source:** *Design Patterns* [GHJV95].

**Referenced from:** Read all the Code in One Hour [p. 53].

### A.3.9 State

**Intent** Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

**Source:** *Design Patterns* [GHJV95].

**Referenced from:** Factor out State [p. 291].

### A.3.10 State Patterns

**Intent** The State Patterns pattern language refines and clarifies the State Pattern.

**Source:** *State Patterns* [DA97].

**Referenced from:** Factor out State [p. 291].

### A.3.11 Strategy

**Intent** Define a family of algorithms, encapsulate each one in a separate class, and define each class with the same interface so they can be interchangeable. Strategy lets the algorithm vary independently from clients that use it.

**Source:** *Design Patterns* [GHJV95].

**Referenced from:** Factor out Strategy [p. 295].
### A.3.12 Template Method

**Intent** Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

**Source:** *Design Patterns* [GHJV95].

**Referenced from:** Look for the Contracts [p. 137].

### A.3.13 Visitor

**Intent** Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

**Source:** *Design Patterns* [GHJV95].

**Referenced from:** Move Behavior Close to Data [p. 243].
Bibliography

[ABW98] Sherman R. Alpert, Kyle Brown, and Bobby Woolf. *The Design Patterns Smalltalk Companion*. Addison Wesley, 1998.

[Arn92] Robert S. Arnold. *Software Reengineering*. IEEE Computer Society Press, Los Alamitos CA, 1992.

[Bak92] Brenda S. Baker. A program for identifying duplicated code. *Computing Science and Statistics*, 24:49–57, 1992.

[BCK98] Len Bass, Paul Clements, and Rick Kazman. *Software Architecture in Practice*. Addison Wesley, 1998.

[BDS+00] Mike Beedle, Martine Devos, Yonat Sharon, Ken Schwaber, and Jeff Sutherland. Scrum: A pattern language for hyper-productive software development. In Neil Harrison, Brian Foote, and Hans Rohnert, editors, *Pattern Languages of Program Design 4*, pages 637–652. Addison Wesley, 2000.

[BE96] Timothy Ball and Stephen Eick. Software visualization in the large. *IEEE Computer*, 29(4):33–43, 1996.

[Bec97] Kent Beck. *Smalltalk Best Practice Patterns*. Prentice-Hall, 1997.

[Bec00] Kent Beck. *Extreme Programming Explained: Embrace Change*. Addison Wesley, 2000.

[BF01] Kent Beck and Martin Fowler. *Planning Extreme Programming*. Addison Wesley, 2001.

[BG98] Kent Beck and Erich Gamma. Test infected: Programmers love writing tests. *Java Report*, 3(7):51–56, 1998.

[BH95] Olin Bray and Michael M. Hess. Reengineering a configuration management system. *IEEE Software*, 12(1):55–63, January 1995.
[Big89] Ted J. Biggerstaff. Design recovery for maintenance and reuse. *IEEE Computer*, 22:36–49, October 1989.

[Bin99] Robert V. Binder. *Testing Object-Oriented Systems: Models, Patterns, and Tools*. Object Technology Series. Addison Wesley, 1999.

[BLM98] M. Blaha, D. LaPlant, and E. Marvak. Requirements for repository software. In *Proceedings of WCRE '98*, pages 164–173. IEEE Computer Society, 1998. ISBN: 0-8186-89-67-6.

[BMF99] Simon Bennett, Steve McRobb, and Ray Farmer. *Object-Oriented System Analysis and Design using UML*. McGraw Hill, 1999.

[BMMM98] William J. Brown, Raphael C. Malveau, Hays W. McCormick, III, and Thomas J. Mowbray. *AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis*. John Wiley Press, 1998.

[BMR+96] Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad, and Michael Stad. *Pattern-Oriented Software Architecture — A System of Patterns*. John Wiley Press, 1996.

[BMW93] Ted J. Biggerstaff, Bharat G. Mittbander, and Dallas Webster. The concept assignment problem in program understanding. In *Proceedings of the 15th international conference on Software Engineering (ICSE 1993)*. IEEE Computer, 1993.

[BMW94] Ted J. Biggerstaff, Bharat G. Mitbander, and Dallas E. Webster. Program understanding and the concept assignment problem. *Communications of the ACM*, 37(5):72–82, May 1994.

[Boe88] Barry W. Boehm. A spiral model of software development and enhancement. *IEEE Computer*, 21(5):61–72, 1988.

[Boo94] Grady Booch. *Object Oriented Analysis and Design with Applications*. The Benjamin Cummings Publishing Co. Inc., 2nd edition, 1994.

[BP94] Jack Barnard and Art Price. Managing code inspection information. *IEEE Software*, 11(2):59–69, March 1994.

[Bro75] Frederick P. Brooks. *The Mythical Man-Month*. Addison Wesley, Reading, Mass., 1975.

[Bro87] Frederick P. Brooks. No silver bullet. *IEEE Computer*, 20(4):10–19, April 1987.
[Bro96] Kyle Brown. Design reverse-engineering and automated design pattern detection in Smalltalk. Master's thesis, North Carolina State University, 1996.

[BS95] Michael L. Brodie and Michael Stonebraker. *Migrating Legacy Systems*. Morgan Kaufmann, 1995.

[BS97] David Bellin and Susan Suchman Simone. *The CRC Card Book*. Addison Wesley, 1997.

[BW96] Kyle Brown and Bruce G. Whitenack. Crossing chasms: A pattern language for object-rdbms integration. In John M. Vlissides, James O. Coplien, and Norman L. Kerth, editors, *Pattern Languages of Program Design 2*, pages 227-238. Addison Wesley, 1996.

[CHR01] Stephen Cook, Rachel Harrison, and Brian Ritchie. Assessing the evolution of financial management information systems. In *ECOOP 2001 Workshop Reader*, volume 2323 of LNCS. Springer-Verlag, 2001.

[CI92] Elliot J. Chikofsky and James H. Cross II. Reverse engineering and design recovery: A taxonomy. In Robert S. Arnold, editor, *Software Reengineering*, pages 54-58. IEEE Computer Society Press, 1992.

[Coc93] Alistair Cockburn. The impact of object-orientation on application development. *IBM Systems Journal*, 32(3):420-444, March 1993.

[Con68] Melvin E. Conway. How do committees invent? *Datamation*, 14(4):28-31, April 1968.

[Cop92] James O. Coplien. *Advanced C++: Programming Styles and Idioms*. Addison Wesley, 1992.

[Cop95] James O. Coplien. A development process generative pattern language. In James O. Coplien and Douglas Schmidt, editors, *Pattern Languages of Program Design*, pages 183-237. Addison Wesley, 1995.

[Cor89] Thomas A. Corbi. Program understanding: Challenge for the 1990's. *IBM Systems Journal*, 28(2):294-306, 1989.

[CRR96] Debra Cameron, Bill Rosenblatt, and Eric Raymond. *Learning GNU Emacs*. O'Reilly, 1996.
[DA97] Paul Dyson and Bruse Anderson. State patterns. In Robert Martin, Dirk Riehle, and Frank Buschmann, editors, *Pattern Languages of Program Design* 3. Addison Wesley, 1997.

[Dav95] Alan Mark Davis. *201 Principles of Software Development*. McGraw-Hill, 1995.

[DD99] Serge Demeyer and Stéphane Ducasse. Metrics, do they really help? In Jacques Malenfant, editor, *Proceedings of Languages et Modèles à Objets (LMO'99)*, pages 69–82. HERMES Science Publications, Paris, 1999.

[DDL99] Serge Demeyer, Stéphane Ducasse, and Michele Lanza. A hybrid reverse engineering platform combining metrics and program visualization. In Francoise Balmas, Mike Blaha, and Spencer Rugaber, editors, *Proceedings of 6th Working Conference on Reverse Engineering (WCRE '99)*. IEEE Computer Society, October 1999.

[DDN00] Serge Demeyer, Stéphane Ducasse, and Oscar Nierstrasz. Finding refactorings via change metrics. In *Proceedings of 15th International Conference on Object-Oriented Programming, Systems, Languages, and Applications (OOPSLA '00)*, pages 166–178, New York NY, 2000. ACM Press. Also appeared in ACM SIGPLAN Notices 35 (10).

[DG97] Serge Demeyer and Harald Gall, editors. *Proceedings of the ESEC/FSE Workshop on Object-Oriented Re-engineering*. TUV-1841-97-10. Technical University of Vienna — Information Systems Institute — Distributed Systems Group, September 1997.

[DL99] Tom DeMarco and Timothy Lister. *Peopleware, Productive Projects and Teams*. Dorset House, 2nd edition, 1999.

[DR98] David E. DeLano and Linda Rising. Patterns for system testing. In Robert Martin, Dirk Riehle, and Frank Buschmann, editors, *Pattern Languages of Program Design 3*, pages 503–527. Addison-Welsey, 1998.

[DRD99] Stéphane Ducasse, Matthias Rieger, and Serge Demeyer. A language independent approach for detecting duplicated code. In Hongji Yang and Lee White, editors, *Proceedings of 15th IEEE International Conference on Software Maintenance (ICSM'99)*, pages 109–118. IEEE Computer Society, September 1999.
[FBB+99] Martin Fowler, Kent Beck, John Brant, William Opdyke, and Don Roberts. *Refactoring: Improving the Design of Existing Code*. Addison Wesley, 1999.

[FH79] R.K. Fjeldstad and W. T. Hamlen. Application program maintenance study: report to our respondents. In *Proceedings of GUIDE 48*. The Guide Corporation, 1979.

[FMvW97] Gert Florijn, Marco Meijers, and Pieter van Winsen. Tool support for object-oriented patterns. In Mehmet Aksit and Satoshi Matsuoka, editors, *Proceedings ECOOP '97, volume 1241 of LNCS*, pages 472–495, Jyvaskyla, Finland, June 1997. Springer-Verlag.

[Fow97] Martin Fowler. *Analysis Patterns: Reusable Objects Models*. Addison Wesley, 1997.

[FP96] Norman Fenton and Shari Lawrence Pfleeger. *Software Metrics: A Rigorous and Practical Approach*. International Thomson Computer Press, London, UK, second edition, 1996.

[Fro94] Stuart Frost. Modelling for the rdbms legacy. *Object Magazine*, pages 43–51, September 1994.

[FY00] Brian Foote and Joseph W. Yoder. Big ball of mud. In N. Harrison, B. Foote, and H. Rohnert, editors, *Pattern Languages of Program Design*, volume 4, pages 654–692. Addison Wesley, 2000.

[GG93] Tom Gilb and Dorothy Graham. *Software Inspection*. Addison Wesley, 1993.

[GHJ98] Harald Gall, Karin Hajek, and Mehdi Jazayeri. Detection of logical coupling based on product release history. In *Proceedings International Conference on Software Maintenance (ICSM '98)*, pages 190–198, Los Alamitos CA, 1998. IEEE Computer Society Press.

[GHJV95] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. *Design Patterns: Elements of Reusable Object-Oriented Software*. Addison Wesley, Reading, Mass., 1995.

[Gla97] Robert L. Glass. *Building Quality Software*. Prentice-Hall, 1997.

[GR95] Adele Goldberg and Kenneth S. Rubin. *Succeeding With Objects: Decision Frameworks for Project Management*. Addison Wesley, Reading, Mass., 1995.
[GW99] Harald Gall and Johannes Weidl. Object-model driven abstraction-to-code mapping. In *Proceedings of the 2nd Workshop on Object-Oriented Reengineering (WOOR 1999)*. Technical University of Vienna — Technical Report TUV-1841-99-13, 1999.

[Har96] Neil B. Harrison. Organizational patterns for teams. In John M. Vlissides, James O. Coplien, and Norman L. Kerth, editors, *Pattern Languages of Program Design 2*, pages 345–352. Addison Wesley, 1996.

[HEH$^{+}$96] J.-L. Hainaut, V. Englebert, J. Henrard, J.-M. Hick, and D. Roland. Database reverse engineering: From requirements to CARE tools. *Automated Software Engineering*, 3(1-2), June 1996.

[Hel95] Jonathan I. Helfman. Dotplot patterns: a literal look at pattern languages. *TAPOS*, 2(1):31–41, 1995.

[IKM$^{+}$97] Dan Ingalls, Ted Kaehler, John Maloney, Scott Wallace, and Alan Kay. Back to the future: The story of Squeak, A practical Smalltalk written in itself. In *Proceedings OOPSLA '97, ACM SIGPLAN Notices*, pages 318–326. ACM Press, November 1997.

[JAH01] Ron Jeffries, Ann Anderson, and Chet Hendrickson. *Extreme Programming Installed*. Addison Wesley, 2001.

[JC00] Daniel Jackson and John Chapin. Redesigning air traffic control: An exercise in software design. *IEEE Software*, 17(3):63–70, May 2000.

[JCJO92] Ivar Jacobson, Magnus Christerson, Patrik Jonsson, and Gunnar Overgaard. *Object-Oriented Software Engineering — A Use Case Driven Approach*. Addison Wesley/ACM Press, Reading, Mass., 1992.

[JGJ97] Ivar Jacobson, Martin Griss, and Patrik Jonsson. *Software Reuse*. Addison Wesley/ACM Press, 1997.

[JGR99] Mehdi Jazayeri, Harald Gall, and Claudio Riva. Visualizing Software Release Histories: The Use of Color and Third Dimension. In *Proceedings of ICSM '99 (International Conference on Software Maintenance)*, pages 99–108. IEEE Computer Society Press, 1999.
[JS96] Dean F. Jerding and John T. Stasko. The information mural: Increasing information bandwidth in visualizations. Technical Report GIT-GVU-96-25, Georgia Institute of Technology, October 1996.

[JSZ97] Jens. H. Jahnke, Wilhelm. Schäfer, and Albert. Zündorf. Generic fuzzy reasoning nets as a basis of reverse engineering relational database applications. In *Proceedings of ES-EC/FSE '97*, number 1301 in LNCS, pages 193–210, 1997. in-proceedings.

[KC98a] Rick Kazman and S. Jeromy Carriere. View extraction and view fusion in architectural understanding. In *Proceedings of the 5th International Conference on Software Reuse*, Victoria, B.C., 1998.

[KC98b] Wolfgang Keller and Jens Coldewey. Accessing relational databases: A pattern language. In Robert Martin, Dirk Riehle, and Frank Bushmann, editors, *Pattern Languages of Program Design 3*, pages 313–343. Addison Wesley, 1998.

[KC99] Rick Kazman and S. J. Carriere. Playing detective: Reconstructing software architecture from available evidence. *Automated Software Engineering*, April 1999.

[Kel00] Wolfgang Keller. The bridge to the new town — a legacy system migration pattern. In *Proceedings of EuroPLoP 2000*, 2000.

[Knu92] Donald E. Knuth. *Literate Programming*. Stanford, California: Center for the Study of Language and Information, 1992.

[Lan99] Michele Lanza. Combining Metrics and Graphs for Object Oriented Reverse Engineering. Diploma Thesis, University of Bern, October 1999.

[LB85] Manny Lehman and Les Belady. *Program Evolution: Processes of Software Change*. London Academic Press, London, 1985.

[Lea96] Doug Lea. *Concurrent Programming in Java, Design Principles and Patterns*. The Java Series. Addison Wesley, 1996.

[LHR88] Karl J. Lieberherr, Ian M. Holland, and Arthur Riel. Object-oriented programming: An objective sense of style. In *Proceedings OOPSLA '88, ACM SIGPLAN Notices*, volume 23, pages 323–334, November 1988.
[LK94] Mark Lorenz and Jeff Kidd. *Object-Oriented Software Metrics: A Practical Guide*. Prentice-Hall, 1994.

[Lov93] Tom Love. *Object Lessons — Lessons Learned in Object-Oriented Development Projects*. SIGS Books, New York, 1993.

[LPM$^{+}$97] Bruno Laguë, Daniel Proulx, Ettore M. Merlo, Jean Mayrand, and John Hudepohl. Assessing the benefits of incorporating function clone detection in a development process. In *Proceedings of ICSM (International Conference on Software Maintenance)*. IEEE, 1997.

[Mar82] Tom De Marco. *Controlling Software Projects*. Yourdon Press, 1982.

[Mey96] Scott Meyers. *More Effective C++*. Addison Wesley, 1996.

[Mey98] Scott Meyers. *Effective C++*. Addison Wesley, second edition, 1998.

[MJS$^{+}$00] Hausi A. Müller, Jens H. Janhke, Dennis B. Smith, Margaret-Anne Storey, Scott R. Tilley, and Kenny Wong. Reverse engineering: A roadmap. In A. Finkelstein, editor, *The Future of Software Engineering 2000*. ACM Press, 2000.

[MLM96] Jean Mayrand, Claude Leblanc, and Ettore M. Merlo. Experiment on the automatic detection of function clones in a software system using metrics. In *International Conference on Software Maintenance (ICSM)*, pages 244–253, 1996.

[MN97] Gail C. Murphy and David Notkin. Reengineering with re-flexion models: A case study. *IEEE Computer*, 8:29–36, 1997.

[Nes88] Paolo Nesi. Managing OO project better. *IEEE Software*, July 1988.

[Nie99] Jakob Nielsen. *Usability Engineering*. Morgan Kaufmann, 1999.

[O'C00] Alan O'Callaghan. Patterns for architectural praxis. In *Proceedings of EuroPLoP 2000, 2000*.

[ODF99] Alan O'Callaghan, Ping Dai, and Ray Farmer. Patterns for change — sample patterns from the adaptor pattern language. In *Proceedings of EuroPLoP 1999, 1999*.

[PB94] William J. Premerlani and Michael R. Blaha. An approach for reverse engineering of relational databases. *Communications of the ACM*, 37(5):42–49, May 1994.
[PK82] J. Pustell and F. Kafatos. A high speed, high capacity homology matrix: Zooming through SV40 and polyoma. *Nucleid Acids Research*, 10(15):4765-4782, 1982.

[PK01] Joseph Pelrine and Alan Knight. *Mastering ENVY/Developer*. Cambridge University Press, 2001.

[Pre94] Roger S. Pressman. *Software Engineering: A Practitioner's Approach*. McGraw-Hill, 1994.

[RBCM91] D.J. Robson, K. H. Bennet, B. J. Cornelius, and M. Munro. Approaches to program comprehension. *Journal of Systems and Software*, 14:79-84, February 1991. Republished in [Arno92a].

[RBJ97] Don Roberts, John Brant, and Ralph E. Johnson. A refactoring tool for Smalltalk. *Theory and Practice of Object Systems (TAPOS)*, 3(4):253-263, 1997.

[RD99] Tamar Richner and Stéphane Ducasse. Recovering high-level views of object-oriented applications from static and dynamic information. In Hongji Yang and Lee White, editors, *Proceedings of 15th IEEE International Conference on Software Maintenance (ICSM'99)*, pages 13-22, Los Alamitos CA, September 1999. IEEE Computer Society Press.

[Ree96] Trygve Reenskaug. *Working with Objects: The OOram Software Engineering Method*. Manning Publications, 1996.

[RG98] Dirk Riehle and Thomas Gross. Role model based framework design and integration. In *Proceedings OOPSLA '98, ACM SIGPLAN Notices*, pages 117-133, October 1998.

[Rie96] Arthur Riel. *Object-Oriented Design Heuristics*. Addison Wesley, Boston MA, 1996.

[Ris00] Linda Rising. Customer interaction patterns. In Neil Harrison, Brian Foote, and Hans Rohnert, editors, *Pattern Languages of Program Design 4*, pages 585-609. Addison Wesley, 2000.

[Rob99] Donald Bradley Roberts. *Practical Analysis for Refactoring*. PhD thesis, University of Illinois, 1999.

[RS89] Trygve Reenskaug and Anna Lise Skaar. An environment for literate Smalltalk programming. In *Proceedings OOPSLA '89, ACM SIGPLAN Notices*, volume 24, pages 337-346, October 1989.
[RW98] Spencer Rugaber and Jim White. Restoring a legacy: Lessons learned. *IEEE Software*, 15(4):28–33, July 1998.

[SG96] Mary Shaw and David Garlan. *Software Architecture: Perspectives on an Emerging Discipline*. Prentice-Hall, 1996.

[Sha97] Alec Sharp. *Smalltalk by Example*. McGraw-Hill, 1997.

[SLMD96] Patrick Steyaert, Carine Lucas, Kim Mens, and Theo D'Hondt. Reuse Contracts: Managing the Evolution of Reusable Assets. In *Proceedings of OOPSLA '96 (International Conference on Object-Oriented Programming, Systems, Languages, and Applications)*, pages 268–285. ACM Press, 1996.

[Sne99] Harry M. Sneed. Risks involved in reengineering projects. In *Proceedings of the 6th Working Conference on Reverse Engineering (WCRE)*. IEEE, 1999.

[Som96] Ian Sommerville. *Software Engineering*. Addison Wesley, fifth edition, 1996.

[SP98] Perdita Stevens and Rob Pooley. System reengineering patterns. In *Proceedings of FSE-6*. ACM-SIGSOFT, 1998.

[SRMK99] Reinhard Schauer, Sébastian Robitaille, Francois Martel, and Rudolf Keller. Hot-Spot Recovery in Object-Oriented Software with Inheritance and Composition Template Methods. In *Proceedings of ICSM '99 (International Conference on Software Maintenance)*. IEEE Computer Society Press, 1999.

[SSRB00] Douglas C. Schmidt, Michael Stal, Hans Rohnert, and Frank Buschmann. *Pattern-Oriented Software Architecture Volume 2 — Networked and Concurrent Objects*. John Wiley and Sons, 2000.

[SW98] Geri Schneider and Jason P. Winters. *Applying Use Cases*. Addison Wesley, 1998.

[Tay00] Paul Taylor. Capable, productive, and satisfied: Some organizational patterns for protecting productive people. In N. Harrison, B. Foote, and H. Rohnert, editors, *Pattern Languages of Program Design*, volume 4, pages 611–636. Addison Wesley, 2000.

[Tho98] Rob Thomsett. The year 2000 bug: a forgotten lesson. *IEEE Software*, 15(4):91–93,95, July 1998.
[WBWW90] Rebecca Wirfs-Brock, Brian Wilkerson, and Lauren Wiener. *Designing Object-Oriented Software*. Prentice-Hall, 1990.

[WG98] Johannes Weidl and Harald Gall. Binding object models to source code: An approach to object-oriented rearchitecting. In *Proceedings of the 22nd Computer Software and Application Conference (COMPSAC 1998)*. IEEE Computer Society Press, 1998.

[Woo98] Bobby Woolf. Null object. In Robert Martin, Dirk Riehle, and Frank Buschmann, editors, *Pattern Languages of Program Design 3*, pages 5–18. Addison Wesley, 1998.

[WTMS95] Kenny Wong, Scott R. Tilley, Hausi A. Müller, and Margaret-Anne D. Storey. Structural redocumentation: A case study. *IEEE Software*, 12(1):46–54, January 1995.

[Wuy98] Roel Wuyts. Declarative reasoning about the structure object-oriented systems. In *Proceedings of the TOOLS USA '98 Conference*, pages 112–124. IEEE Computer Society Press, 1998.

[You97] Edward Yourdon. *Death March*. Prentice-Hall, 1997.
# Index

Abstract Factory (Pattern), 139, 284, 319

Abstract Instance Variable, 317

Ada, 40, 274, 282

Adapter (Pattern), 13, 208, 247, 319

ADAPTOR pattern language, 208, 212

Agree on Maxims (Pattern), 20, 23, 43

Alexander, Christopher, 12

Always Have a Running Version
(Pattern), 13, 152, 157, 183,
193, 199–201

Analyze the Persistent Data (Pattern),
59, 67, 85–87, 96, 320

Appoint a Navigator (Pattern), 20, 25,
164, 193

architecture, 19, 25, 29, 99

Arranging the Furniture, 130

AST Matching, 255

Beck, Kent, 6, 27, 58, 223

Belady, Les, xiii, 219

Bennett, Simon, 74

Big Ball of Mud, 197, 267

Binder, Robert, 149, 315

black box testing, 160, 174

Blaha, Michael, 95

Boehm, Barry, 8

Brant, John, 130

Bridge to the New Town, 203

Brodie, Michael, 205

Brooks, Frederick, 117, 197

bug reports, 46

Build Confidence (Pattern), 20, 31, 37,
182, 183, 185, 187, 189, 190,
192, 200, 201, 205

business model, 23

C++, 40, 58, 130, 212, 232, 247, 274, 281,
285, 299, 310

Chapin, John, 66

Chat with the Maintainers (Pattern), 42,
45, 55, 59, 67, 71, 76, 82, 144

Chicken Little, 191, 192

Chikofsky, Elliot, 8, 11

class abuse, 11

COBOL, 232

Cobol, 130

Cockburn, Alistair, 103

code reviews, 54

code smells, 6, 53

CodeCrawler, 104, 115

coding idioms, 54

Compare Code Mechanically (Pattern),
225, 227, 261

Conserve Familiarity (Pattern), 183,
186, 219, 220

Continuous Integration, 200

Conway's law, 49

Conway, Melvin, 49

Cook, Stephen, 51

Coplien, James, 187

Cross, James, 8, 11

Daimler-Benz, xiv, xvii

DALI, 105

data bridge, 203

data container, 239, 241

database, 87
schema, 87

DATRIX, 232

Davis, Alan, 157, 202, 222

De Marco, Tom, 49, 114

debugger, 133

DeLano, David, 315

Deprecate Obsolete Interfaces (Pattern),
183, 208, 212, 213, 215, 245,
266
Deprecation, 215, 217
DESEL project, 51
design drift, xiv
Design Patterns, xv, 315
DESIRE, 105
Detailed Model Capture (Pattern cluster), 14, 86, 105, 115, 117–119
Detecting Duplicated Code (Pattern cluster), 16, 224, 225
Distinguish Public from Published Interface (Pattern), 183, 209, 211, 213
Do a Mock Installation (Pattern), 47, 51, 59, 72, 77, 79, 82
Do it, then do it right, then do it fast, 222
Do the simplest thing that will work, 37 documentation, 61 insufficient, 10 obsolete, 4
dotplot, 236
Dup, 238
duplicated code, 6, 10, 227
duplicated functionality, 10
Duploc, 238

Eiffel, 124
Eliminate Navigation Code (Pattern), 242, 244, 253, 257, 259, 261, 317, 319
Encapsulate Field (Pattern), 251, 317 encapsulation violation of, 11, 253
Engage Customers, 185
Envy, 81
ESPRIT, xiv, xvii
EuroPLoP, xvii
evolutionary prototype, 195
exploratory prototype, 195
Extract Method (Pattern), 128, 130, 225, 238, 244, 293, 296, 317
Extreme Programming, 37, 157, 190, 202
 FACADE (Pattern), 13, 257, 265, 319
Factor out State (Pattern), 270, 271, 280, 291, 297, 321

Factor out Strategy (Pattern), 270, 271, 280, 295, 297, 298, 321
Factory Method (Pattern), 139, 319
FAMOOS, xiv, xv, xvii, 40, 58, 66, 67, 75, 81, 115, 130, 238
First Contact (Pattern cluster), 14, 42, 83, 84, 87, 107, 117
Fix Problems, Not Symptoms (Pattern), 20, 25, 30, 31, 33
Flyweight (Pattern), 102, 320
Foote, Brian, 197, 267
forces, see pattern, forces
foreign key, 91
forward engineering definition, 8
Fowler, Martin, 11, 27, 223, 299, 315
frameworks, xiv
FZI, xiv, xvii

God Class, 239, 241, 263
Goldberg, Adele, 23, 75
Grow Your Test Base Incrementally (Pattern), 150, 157, 159, 178, 193, 201, 316, 317

hook method, 139, 166

IEEE, 11
If It Ain't Broke, Don't Fix It (Pattern), 20, 33, 35
inheritance missing, 11 misuse of, 11
Initial Understanding (Pattern cluster), 14, 43, 86, 117, 137, 141
Interview During Demo (Pattern), 42, 47, 51, 55, 59, 63, 67, 69, 71, 76, 79, 81, 82, 97, 99, 135, 144
Introduce Null Object (Pattern), 270, 271, 289, 299, 320
Involve the Users (Pattern), 20, 31, 37, 43, 182, 183, 185, 187, 190, 220
Jackson, Daniel, 66
Java, 6, 139, 211, 215, 248, 255, 259, 274, 282, 299
Javadoc, 57
JUnit, 156, 163, 164
Keep It Simple (Pattern), 21, 37, 228

Keep the Data — Toss the Code, 203

Keller, Wolfgang, 205

Konigsberg, Allen, 57

Law of Conservation of Familiarity, 220

Law of Demeter, 240, 241, 253, 261

Law of Increasing Complexity, 5

layering

improper, 10

Learn from the Past (Pattern), 30, 120, 140, 141

legacy software, 3

legacy systems, xiv

Lehman, Manny, xiii, 219

literate programming, 124

Look for the Contracts (Pattern), 92, 96, 120, 135, 137, 140, 144, 319, 320, 322

Love, Tom, 197

maintenance, 46

maintenance costs, 23

Make a Bridge to the New Town (Pattern), 33, 183, 190, 193, 197, 203

maxims, 23

MediaGeniX, 125

meetings, 27

metrics, 107, 142

Migrate Systems Incrementally (Pattern), 31, 152, 157, 182, 183, 186, 187, 191, 205, 220

Migrating Legacy Systems, 192

Migration Strategies (Pattern cluster), 16, 152

misplaced operations, 11

modularity

lack of, 10

Most Valuable First (Pattern), 20, 23, 25, 29, 33, 181, 185, 193

Move Behavior Close to Data (Pattern), 225, 238, 241–244, 250, 251, 253, 256, 266, 317–319, 322

Move Method (Pattern), 244, 317

mural visualization, 236

navigator, 25

Nielsen, Jakob, 74

Nokia, xiv, xvii

Nortel, 50

Null Object (Pattern), 270, 271, 299, 320

O’Callaghan, Alan, 208

pattern

forces, xvi

language, xvi, 14

tradeoffs, xvi

Perl, 274, 310

Planning Game, 30, 187

Pooley, Rob, 217

Present the Right Interface (Pattern), 33, 183, 192, 193, 196, 207–209, 213, 267, 268, 319

Pressman, Roger, 65

Prototype the Target Solution (Pattern), 183, 190, 192, 195, 220

Published Interface, 211, 212

Python, 237

Quantity (Pattern), 100, 320

Read all the Code in One Hour (Pattern), 42, 47, 51, 53, 58, 59, 63, 67, 72, 76, 81, 97, 321

Record Business Rules as Tests (Pattern), 76, 120, 134, 152, 160, 161, 173, 175, 178

Redistribute Responsibilities (Pattern cluster), 16, 115

reengineering, 10

continuous, 7, 12

definition, 8

reengineering patterns, 12, 13

form, 14

Refactor to Understand (Pattern), 14, 118, 120, 125, 127–131, 140, 180, 222, 317, 318

refactoring, 128

definition, 11

Refactoring Browser, 58, 129, 255

Regression Test After Every Change (Pattern), 152, 183, 192, 193, 200–202, 265, 316

Rename Attribute (Pattern), 128, 318
Rename Method (Pattern), 128, 318

Replace Conditional with
Polymorphism (Pattern), 289,
318

restructuring
definition, 11

Retest Persistent Problems (Pattern),
152, 202, 316

reverse engineering, 9
definition, 8

Rewrite Rule Editor, 255

Riel, Arthur, 95, 251, 267

Rigi, 105

Rising, Linda, 315

Roberts, Don, 130

Roberts, Donald, 315

RT-100, 50

RTTI, 281

Rubin, Kenny, 23, 75

Rugaber, Spencer, 50

Sema, xvii

Sema Group, xiv

Semantic Wrapper, 207, 208, 263

Setting Direction (Pattern cluster), 14,
20, 181

Singleton (Pattern), 54, 320

Skim the Documentation (Pattern), 42,
47, 51, 55, 59, 61, 67, 72, 76,
97, 98

Small Releases, 190

Smalltalk, 58, 81, 144, 177, 212, 247, 255,
275, 282, 301

Sneed, Harry, 130

software maintenance, 11
definition, 11

software reuse, 7

Speak to the Round Table (Pattern), 20,
27, 84

Speculate about Design (Pattern), 67,
76, 85, 86, 90, 92, 96, 97, 104,
143, 320

spiral development lifecycle, 8

Split Up God Class (Pattern), 33, 242,
263, 267, 319

SQL, 88, 91-93

Squeak, 125, 305, 307

stakeholder, 29, 33

State (Pattern), 270, 271, 291, 321

State Patterns (Pattern language), 291,
321

Step Through the Execution (Pattern),
120, 133, 135, 140

Stevens, Perdita, 217

Stonebraker, Michael, 205

Strategy (Pattern), 270, 271, 295, 297,
321

Study the Exceptional Entities
(Pattern), 59, 85, 86, 105, 107

SUnit, 163

Sweeping it Under the Rug, 207

Template Method (Pattern), 139, 321,
322

Test Fuzzy Features (Pattern), 152, 160,
316

Test Old Bugs (Pattern), 152, 160, 316

Test the Interface, Not the
Implementation (Pattern),
120, 144, 152, 158, 160, 161,
171, 174, 193

Test-Driven development, 202
testing, 149

tests
missing, 5

Tests: Your Life Insurance
(Pattern cluster), 14, 54, 77, 96, 105,
120

The Blob, 263

The Law of Continuing Change, xiii

The Law of Increasing Complexity, xiii

Thomsett, Rob, 49

Throwaway Code, 197

throwaway prototype, 195

Tie Code and Questions (Pattern), 118,
121, 123, 125, 129, 131, 134,
180

tradeoffs, *see* pattern, tradeoffs

Transform Client Type Checks
(Pattern), 244, 270, 271, 280,
281, 284, 289, 310, 318, 319

Transform Conditionals into
Registration (Pattern), 270,
271, 280, 289, 303, 309, 310
Transform Conditionals to
Polymorphism (Pattern
cluster), 16, 115, 225, 237, 238,
270

Transform Self Type Checks (Pattern),
270, 271, 273, 277, 280–282,
291

UML
class diagram, 87, 92, 105

unit tests, 54
University of Bern, xiv, xvii
UNIX, 274
Unix, 141

Use a Testing Framework (Pattern),
150, 161, 163

Use Profiler Before Optimizing
(Pattern), 184, 221, 222

violation of encapsulation, *see*
encapsulation, violation of

Visitor (Pattern), 247, 322

Visualize Code as Dotplots (Pattern),
225, 233, 317

white box testing, 174

White, Jim, 50

Wong, Kenny, 66

Woolf, Bobby, 301

Write Tests to Enable Evolution
(Pattern), 150, 153, 157, 172,
181, 183, 193, 202

Write Tests to Understand (Pattern),
120, 128, 129, 131, 135, 152,
162, 178, 179

XP, *see* Extreme Programming

Yoder, Joseph, 197, 267

Yourdon, Edward, 186
<figure><img src="image_60.png" /></figure>
<figure><img src="image_61.png" /></figure>
<figure><img src="image_62.png" /></figure>
<figure><img src="image_63.png" /></figure>