2.2 First Example

 

At this point it is customary to count all the benefits(see section 6.2) of refactorings. Instead, we would like to continue with an example which will show the practical use of refactorings. This example is a part of  the DPT-tool and can be performed by users.

For the description of a transformation in examples, the following scheme will be used:

- Name and short information about transformation

- Start- and end- state (UML-diagram)

- Actual parameters of transformation

Note: For a complete definition and preconditions of each transformation see chapter 4

 

2.2.1 Program description

 

The welcome-program is a simple car-lifecycle simulation program written in Java. It creates a BMW3 car with BMW3 tires and a BMW3 engine, and lets this car drive until the car is a wreck. During the drive, the tires are rotated and changed and the engine is replaced. This program works only for a BMW3 car.

 

- Program-files(see appendix C):

AppMain.java    - Contains main function, creates and runs a new application frame.

AppFrame.java  - Class contains GUI-Components. Creates and drives a BMW-3 car.

Car.java              - Class Car(BMW3) contains tires and engine and calls to their methods

HelpBox.java     - Dialog that displays help-information.

BMW3_Tire.java - Contains concrete class tire for a BMW3 car

BMW3_Engine.java - Contains concrete class engine for a BMW3 car

 

- New requirements for car-simulator:

a) Next the BMW3 will be built with a new type of engine/tire (Program extension)

b) A manager decides to use this program to simulate other cars.(Reuse of the program)

 

2.2.2 Step by step transformations

 

First we will make the program more flexible and easily extendible (e.g. for adding new types of tires/engine), and finally reuse this program(for a new type of car).

 

Step1: Generalize class

The transformation creates a super-class for a given class.

Motivation:

Generalization of concrete Car-parts. New generalized parts have the same interface as concrete parts to the class ”Car”. This is important to make the program more flexible (e.g. application could use other concrete parts as implementation of generalized parts).

Concrete classes “BMW3_Engine” and “BMW3_Tire” will be generalized. New generalized class “CarEngine” / ”CarTire” will be created and “BMW3_Engine” / ”BMW3_Tire” extends those classes.

(Figure 2.1 Example: class-generalization)

Name: Generalization

Description: The transformation creates super class(generalization) of  an existing class

Parameters:

- New class(Super) ="CarEngine"; modifier="public"; option=create constructor  

- Class for generalization(Subclass)  ="BMW3_Engine";

- Methods and variables to move to new super-class

 

The same transformation needs to be done with class „BMW3_Tire“

 

Step2:  Substitute members of a class

The transformation changes the type of variable/method(method-parameters) from class  to super class

Motivation:

The class “Car” will use generalized parts instead concrete BMW3 parts. This makes the program more flexible because the class “Car” is no longer dependent on concrete parts and it can operate with any Car tire and Car engine. (Note: The application still builds cars with concrete BMW3-Tire and BMW3-Engine.) 

This is a two step refactoring:

- Substitute class-variable:  Type of car-variables engine/tires changes to the super-class.

- Substitute constructor : car-constructor will use generalized engine and tires as parameters

(Figure 2.2 Example: substitute members )

a)  Substitute variable

Name:              Substitute type of the variable.

Description:      Transformation changes the type(=class) of variable to its super class.

Parameters:      Car variables for „Engine“ and  „Tire“

 

b)  Substitute method-parameters 

Name:              Substitute parameters of the method.

Description:      Transformation changes the type(=class) of parameters to its super class.

Parameters:      Constructor-method of class „Car“

 

The transformation creates new factory-class(or adds factory method to existing class)

 

Motivation :

The application still builds cars with concrete parts. Next a factory will be created to build engine and tires. This step makes the program easily extendible(e.g. by change of only one factory method we can build a car with, for example, a new type of engine).

This is also a two step refactoring:

- Create/add concrete factory for BMW3 cars: factory creates BMW3- engine and tires

- Substitute type of create-methods: factory will build generalized engine and tires

 

(Figure 2.3 Example: create factory)

a)  Create/Add factory

Name:              Create factory / Add factory method

Description:      Transformation creates/uses a factory and creates a factory-method.

Parameters:      Name of the factory=“BMW3_Factory“; option =“create constructor“

Create-method name =“Make_engine“

 

 

Class to be created=“BMW3_Engine“; constructor to be used =“default“

The same transformation needs to be done with class „BMW_Tire“, but this time for the existing factory(Transformation=“Add factory method“).

 

b)  Substitute type of the method

Name:              Substitute type of the method

Description:      Transformation changes the type(=class) of the method to its super class

Parameters:      „BMW3_Factory“ methods „MakeEngine“ and  „MakeTire“

 

Step 4:  Create interface for a class

The transformation creates an interface for an existing class.

Motivation:

The BMW3 factory creates parts for the BMW3 car. Now we can generalize this factory to interface „Car_Factory“, that can be used in the future to build a new car-type. Any implementation of  this interface will build a car that is suitable for this application. This step makes the program more extendable.

(Figure 2.4 Example: create interface)

Name:              Create interface.

Description:      Transformation creates an interface for the existing class.

Parameters:      New interface name „Car_Factory“; modifier="public"

Implementor name „BMW3_Factory“; Implementor methods for interface.

 

Step 5: Create instance variable for a class

The transformation creates an instance variable of an existing class.

Motivation:

Application gets the factory-variable that will build a car. This makes the program more flexible because the application is no longer responsible for the creation of the car-parts.    

This is a two step refactoring:

 - Create new member (new variable with type = „BMW3_Factory“)

 - Substitute type(=class) of variable to its super class(e.g. interface „Car_Factory“)

(Figure 2.5 Example: create instance)

a)  Create instance variable

Name:              Create new variable.

Description:      Transformation creates a variable with default initialization

Parameters:      Class name =“AppFrame“ New variable  name =„oFactory“;

Type of new variable=“BMW3_Factory“

 

b) Substitute variable

Name: Substitute the type of the variable.

Description: Transformation changes the type(=class) of variable to its super class

Parameters: variable „oFactory“ for class „AppFrame”

 

 

Step 6:  Reassociate (App will use Car_Factory to build a Car)

Transformation replaces the creation of a class with create-method of its factory class.

Motivation:

So far the application calls car-constructor and passes concrete BMW3-parts in order to create a car. Now application will use factory to create those parts. This step finalizes the modifications completed by step 4 and step 5 .

 

 

Description:      Transformation replaces the current method-parameters with a call to a factory-method.

Parameters:      Application-class =“AppFrame“, Factory-member =“oCarFactory“.

 

2.2.3 Benefits

 

The source code modifications completed by step1 to step 6 didn’t change the functionality of the program. The program will build and drive the BMW3 cars as good as before. But the program is now more flexible and the extension of this program can be done “on the fly”:

- Other tires or engines can be added.

(e.g. Transformation: "Specialize" can create new subclasses of generalized tire /engine)

(Figure 2.7 Example: extend classes)

-         Switching the tires and engines for a car can be done by modification of only one factory-method

(Figure 2.8 Example: switch class)

- Other factories can be added to create other cars (e.g. Transformation: "Implements" can create new implementations of interface "Car_Factory")

 

- Application can be reused by the use of other car-factory

(Figure 2.9 Example: reuse of application)