Form Template Method - You have two methods in ...

toaststicksrifleΛογισμικό & κατασκευή λογ/κού

15 Αυγ 2012 (πριν από 5 χρόνια και 11 μήνες)

365 εμφανίσεις

Piotr Warczak

CSS 555

Spring 2010

As a




Refactoring is the process of transforming the internal structure of existing code while keeping the
integrity of the code’s functional requirements. Refa
ctoring is proven to increase program
maintainability, flexibility, and understandability and is recognized as a best practice in the software
development community
[1, 9].


Refactoring comes from mathematics when an expression is factored into i
ts equivalence

factors are cleaner ways of expressing the same statement.

The first person to use refactoring
in print was Ralph Johnson, but it’s

that he most
learned about it
from Smalltalk programmers at Tektronix. He and
Bill Opdyke
wrote a paper
about refactoring in 1990 with emphasis on the importance of refactoring in the design of frameworks.
Then Bill Opdyke
wrote a PhD thesis on refactoring in 1992.

John Brant and Don Roberts
built the Refactoring Brow
er for Smalltalk, and Don wrote a PhD thesis on it in 1999.

Why Refactor?

Fowler’s catalogue of refactoring [
] can be considered to be the work which triggered industry
adoption of refactoring practices. In his book, Fowler suggests four purposes of re

Improve the design of software

Through accumulating code changes, code loses its structure,
thereby increasingly drifting towards a state of decay. Refactoring can be used to cure software
decay by redistributing parts of the code to the righ
t places, and by removing duplicated code.
The claim that refactoring can improve the design of software is confirmed by [
] with regard
to cohesion and by [
] with regards to coupling, as indicators for internal software quality.
Another claimed benefit

in the area of improved design is improved flexibility [

Make software easier to understand

Refactoring can help make the code more readable by
making it better communicate its purpose. A different way in which refactoring supports
program understan
ding is in reflecting hypotheses about the purpose of the code by changing
the code, and afterwards testing that understanding through rerunning the code. The
suggested process to do so is to start refactoring the little details to clarify the code, there
exposing the design. The potential to improve understandability through refactoring is
confirmed by many authors [



]. In more specific terms, [
] discusses how refactorings
can be used to improve communicating the purpose of the code.


find bugs

Through clarifying the structure of the code, the assumptions within the code
are also clarified, making it easier to find bugs.

Program faster

Through improving the design and overall understandability of the code, rapid
software developme
nt is supported. Traditionally, Opdyke [
] is referenced for publishing the
first PhD with respect to refactoring. However, in his PhD thesis, Opdyke refers to the PhD of
Griswold, acknowledging his precedence. Griswold did not use the word refactoring e
yet referred to the same concept: automatable meaning preserving restructurings [

Clearly, refactoring is something all developers do, e
ven when

code and do not realize

actually doing it. Despite its

association with Extre
me Programming (XP) and other radical
coding methods, refactoring

is a basic process.

When modifying
code to make it more rational, portable, modular, or readable,
much of the process
almost always consists
of applying refactoring methods
. These


restructure code
according to
implicit micro design rules. In the recent years

a number of
IDEs have been including
refactoring as part of the install
and/or providing as an add
on option to smoothly integrate
capabilities with the exi
sting development process
. These micro design rules force developers
to think
about their code structure and to identify

Code Smells

A code smell

also known as bad smell

is any symptom in the source code of a program that possibly
ates a deeper problem.

Often the deeper problem hinted by a code smell can be uncovered when the code is subjected to a
short feedback cycle where it is refactored in small, controlled steps, and the resulting design is
examined to see if there are any fu
rther code smells that indicate the need of more refactoring. From
the point of view of a programmer charged with performing refactoring, code smells are heuristics to
indicate when to refactor, and what specific refactoring techniques to use. Thus, a code

smell is a driver
for refactoring.

The term appears to have been coined by Kent Beck on WardsWiki in the late 1990s. Usage of the
term increased after it was featured in Refactoring. Improv
ing the Design of Existing Code.

Determining what is and is
not a code smell is often a subjective judgment, and will often vary by
language, developer and development methodology. There are tools, such as Checkstyle, PMD and
FindBugs for Java, to automatically check for certain kinds of code smells.

Since there i
s a large number of defined code smells, here is subset
the most commonly used

divided into two categories


Smells Within Classes

Duplicated Code:

The same code structure in two or more places is a good sign that the code
needs to be refact
ored: if you need to make a change in one place, you will probably need to
change the other one as well, but you might miss it

Long Method:

Long methods should be decomposed for clarity and ease of maintenance

Large Class:

Classes that trying to do too muc
h often have large numbers of instance variables.
Sometimes groups of variables can be clumped together. Sometimes they are only used
occasionally. Over
large classes can also suffer from code duplication.

Long Parameter List:

Long parameter lists are har
d to understand. You don’t need to pass in
everything a method needs so it can find all it needs.

If the comments are present in the code because the code is bad, improve the

Speculative Generality:
Often methods or classes are designed
to do things that in fact are not
required. The dead
wood should probably be removed.

Switch Statements:

Switch statements tend to cause duplication. You often find similar switch
statements scattered through the program in several places. If a new data

value is added to the
range, you have to check all the various switch statements. Maybe classes and polymorphism
would be more appropriate.

Smells Between Classes

Divergent Change:

Software should be structured for ease of change. If one class is ch
anged in
different ways for different reasons, it may be worth splitting the class in two so each one
relates to a particular kind of change

Shotgun Surgery:

If a type of problem change requires lots of little code changes in various
different classes, it
may be hard to find all the right places that do need changing. Maybe the
places that are affected should all be brought together into one class.

Feature Envy:

This is where a method on one class seems more interested in the attributes of
another class t
han in its own class. Maybe the method would be happier in the other class.

Data Clumps:

Sometimes you see the same bunch of data items together in various places:
fields in a couple of classes, parameters to methods, local data. Maybe they should be gro
together into a little class.

Primitive Obsession:

Sometimes it’s worth turning a primitive data type into a lightweight class
to make it clear what it is for and what sort of operations are allowed on it (eg creating a date
class rather than using a

couple of integers)

Parallel Inheritance Hierarchies:
In this case, whenever you make a subclass of one class, you
have to make a subclass of another one to match.

Lazy Class:
Classes that are not doing much useful work should be eliminated

Temporary Fi
It can be confusing when some of the member variables in a class are only
used occasionally

Message Chains:
A client asks one object for another object, which is then asked for another
object, which is then asked for another, etc. This ties the cod
e to a particular class structure.

Middle Man:
Delegation is often useful, but sometimes it can go too far. If a class is acting as a
delegate, but is performing no useful extra work, it may be possible to remove it from the

Inappropriate Inti
Two classes are overly intertwined.

Alternative classes with different interfaces:
Classes that do similar things, but have different
names, should be modified to share a common protocol.

Incomplete Library Class:
It’s bad form to modify the code
in a library, but sometimes they do
not do all they should do.

Data Class:
Classes that just have data fields, and access methods, but no real behavior.
public data private.

Refused Bequest:
If a subclass does not want or need all of the behavior
of its base class,
maybe the class hierarchy is wrong.

After identification

of code smell
, the according code is changed based on a catalogue of change
steps referring to the problem. These steps range from renaming of variables, extraction of methods to

the extraction of complete classes from the existing code.

Design Guidelines

The concept of refactoring is an exploitation of Parnas’s design guidelines,

stating that structural
system modifications can be postponed by assuring locality of change for l
ikely changes [
]. To assure
locality, Parnas su
ggests the following steps:
identify the

that are likely to change,
specialized components in separate
modules; and
design intermodule interfaces insensitive to the
anticipated changes [
]. The
se steps respectively correspond to three design principles:

encapsulation, and
information hiding.

These concepts are clearly distinguished by [
] based on an extensive literature survey:


As a process, abstraction denotes ex
tracting the essential details about an item or a
group of items while ignoring the inessential details. Examples of these essential details are
difficult or likely
change design decisions. As an entity, abstraction denotes a model, a view,
or some oth
er focused representation for an actual item. Among others, abstraction differs from
information hiding in that it does not specify a mechanism for handling the unimportant


As a process, encapsulation means the act of enclosin
g one or more items within
a (physical or logical) container. As an entity, encapsulation refers to a package or an enclosure
that holds (contains, encloses) one or more items. Encapsulation can be used as a strategy to

what has to be extracted, di
sregarding whether these items should be visible or hidden.

Information hiding:

The process of hiding information, especially difficult or likely
design decisions. Information hiding does not incorporate the identification of which

is to be hidden (e.g., through abstraction), nor the strategy for hiding them (e.g.,
through encapsulation).


Fowler’s catalogue [9] lists
oriented refactorings and since then many others have
been discov

To demonstrate the possibility of reasoning about refactoring in terms of their impact
on program structure,
I will illustrate examples of

Method, Encaps
ulate Field,


Extract class, and Form Template Method


ese refactorings

are quite typical for the
categories of refactoring strategies they belong to

respectively Composing Methods, Organizing

and Dealing with Generalization

which are among the most popular refactoring s
trategies in today’s

g tools

IntelliJ IDEA, Eclipse, Together
, Visual Studio etc..)
. Hence they may serve as
representatives for the complete set of primitive refactorings.

extracts part of a method and factors it out into a new method.


void printOwing
() {


//print details

System.out.println ("name:

" + _name);

System.out.println ("amount

" + getOutstanding());



void printOwing() {




void printDetails (double outstandi
ng) {

System.out.println ("name:

" + _name);

System.out.println ("amount

" + outstanding);

encapsulates public attributes by making them private and providing
accessors. In other words, for each

public attribute a method is introduced

for accessing
(getting) and updating (setting) its value, and all direct references to the

attribute are replaced
by calls to these methods.


public String _name


private String _name;

public String getName() {return _name;}

public void setN
ame(String arg) {_name = arg;}

moves identical methods from subclasses into a common superclass.

Extract Class

You have one class doing work that should be done by two.
Create a new class
and move the relevant fields and methods from the

old class into the new class.

Form Template Method


You have two methods in subclasses that perform similar steps in the
same order, yet the steps are different.

Get the steps into methods with the same signature, so
that the original methods become

the same. Then you can pull them up.

And here is a complete
list of available
refactoring methods where details of each can be found at
the following


Add Parameter

Change Bidirectional Association to Unidirectional

Change Reference to Value

Change Unidirectional Association to Bidirectional

Change Value to Reference

Collapse Hierarchy

Consolidate Conditional Expression

Duplicate Conditional Fragments

Convert Dynamic to Static Construction by Gerard M. Davison

Convert Static to Dynamic Construction by Gerard M. Davison

Decompose Conditional

Duplicate Observed Data

Eliminate Inter
Entity Bean Communication (Link Only

Encapsulate Collection

Encapsulate Downcast

Encapsulate Field

Extract Class

Extract Interface

Extract Method

Extract Package by Gerard M. Davison

Extract Subclass

Extract Superclass

Form Template Method

Hide Delegate

Hide Method

Hide present
ation tier
specific details from the business tier (Link Only)

Inline Class

Inline Method

Inline Temp

Introduce A Controller (Link Only)

Introduce Assertion

Introduce Business Delegate (Link Only)

Introduce Explaining Variable

Introduce Foreign Met

Introduce Local Extension

Introduce Null Object

Introduce Parameter Object

Introduce Synchronizer Token (Link Only)

Localize Disparate Logic (Link Only)

Merge Session Beans (Link Only)

Move Business Logic to Session (Link Only)

Move Class by
Gerard M. Davison

Move Field

Move Method

Parameterize Method

Preserve Whole Object

Pull Up Constructor Body

Pull Up Field

Pull Up Method

Push Down Field

Push Down Method

Reduce Scope of Variable by Mats Henricson

Refactor Architecture by Tiers

(Link Only)

Remove Assignments to Parameters

Remove Control Flag

Remove Double Negative by Ashley Frieze and Martin Fowler

Remove Middle Man

Remove Parameter

Remove Setting Method

Rename Method

Replace Array with Object

Replace Assignment with I
nitialization by Mats Henricson

Replace Conditional with Polymorphism

Replace Conditional with Visitor by Ivan Mitrovic

Replace Constructor with Factory Method

Replace Data Value with Object

Replace Delegation with Inheritance

Replace Error Code wit
h Exception

Replace Exception with Test

Replace Inheritance with Delegation

Replace Iteration with Recursion by Dave Whipp

Replace Magic Number with Symbolic Constant

Replace Method with Method Object

Replace Nested Conditional with Guard Clauses

Replace Parameter with Explicit Methods

Replace Parameter with Method

Replace Record with Data Class

Replace Recursion with Iteration by Ivan Mitrovic

Replace Static Variable with Parameter by Marian Vittek

Replace Subclass with Fields

Replace Temp w
ith Query

Replace Type Code with Class

Replace Type Code with State/Strategy

Replace Type Code with Subclasses

Reverse Conditional by Bill Murphy and Martin Fowler

Self Encapsulate Field

Separate Data Access Code (Link Only)

Separate Query from Mo

Split Loop by Martin Fowler

Split Temporary Variable

Substitute Algorithm

Use a Connection Pool (Link Only)

Wrap entities with session (Link Only)


As the list of object
oriented program quality metrics is virtually endless (i.e.

alone describes
more than 200 complexity metrics),
will focus on those program metrics which are most commonly
used, being Number of Methods, Cyclomatic Complexity, Number of Children, Coupling Between
Objects, Response For a Class and Lack of Cohesion
among Methods.

Definitions for these metrics are:

Number of Methods
calculates the number of methods of a class. It is an indicator of the
functional size of a class.

Cyclomatic Complexity
counts the number of possible paths through an algorithm. It is
indicator of the logical complexity

of a program, based on the number of flow graph edges and
nodes [7].

Number of Children
measures the immediate descendants of a class [5]. It is an indicator of the
generality of the class.

Coupling Between Objects

a measure for the number of collaborations for a class [18]. It is an
indicator of the complexity

of the conceptual functionality implemented in the class.

Response For a Class
is the number of both defined and inherited methods of a class, including
ods of other classes

called by these methods [5]. It is an indicator of the vulnerability to
change propagations of the class.

Lack of Cohesion among Methods
is an inverse cohesion measure (high value means low
cohesion). Of the many variants

of LCOM, we u
se LCOM1 as defined by Henderson
Sellers [10]
as the number of pairs of methods in a class having no

common attribute references. It is an
indicator of how well the methods of the class fit together.

w to achieve well formed object
oriented method

In or
der to achieve
a well formed object
oriented method
the following requirements must be met:

acceptably cohesive [10, 19],

low in complexity [12],

appropriately sized,

independently testable [3], and

well documented.

Acceptably Cohesive

One of the most imp
ortant characteristics of a well formed object oriented method is cohesion.
Method cohesion is defined as a measure of how well the elements within a module work together
to provide a specific functionality. While cohesion was first used in structured desi
gn [22, 5, 14],
method cohesion has been adapted for object
oriented software. Kang [10] defines six levels of
oriented method cohesion ranked from best to worst as shown in Figure 1. The highest level,
functional cohesion, deals

with the ability of

a module to produce one output for one module (i.e.,
to change the state of one object). As shown by Kang’s empirical evidence, strongly cohesive
methods are desired because the stronger the cohesion, the easier the method is to maintain,
understand, and
reuse [10].


Only one output exist for the


One output is dependent on the other output


Two outputs are dependent on a common input


Two outputs are iteratively dependent on the
same input


Two outputs are conditionally dependent on the
same input


Two outputs have no dependence relationship
which each other and no dependence relation on a
common input

Figure 1

Cohesion in Object
oriented Design



aving a low level of complexity is another important characteristic of a well formed object
method. Students are introduced to McCabe’s Cyclomatic Complexity [12] as the metric for
measuring complexity of their code. McCabe’s Cyclomatic Complexity
, which measures the number
of linearly

independent paths within code, is defined as the number of decision points + 1 where
decision points are conditional statements such as
. Figure 2

shows McCabe’s
complexity scale. The goal is code tha
t is not very complex and, therefore, low risk. Low level of
complexity within a method

makes methods more understandable and maintainable [18].

Number of Paths

Code Complexity



Not very complex



Moderately complex



hly complex




Very high

Figure 2

McCabe’s Complexity Scale

Appropriately Sized

The third characteristic of a well formed object
oriented method is size. One of the techniques for
determining the size of software is counting its lines
of code (LOC). The method of determining

LOC depends on how the executable lines, blank lines, comment lines, data declarations, and
multiple line statements are treated. LOC is considered inappropriate for measuring the quality of
oriented classes

[2, 15]. However, it is useful in measuring object
oriented methods since
studies have shown that large methods result in a reduction of understandability, reusability,
testability, and maintainability [9, 11, 21, 17, 18, 6]. The appropriate size of a met
hod depends on
the programming

language being used and the application being developed. Multiple line
statements such as
should be

counted as one statement with each executable line
within these multiple line statements also being counted
. A strict rule for method size is enforced to
to produce small, functionally cohesive methods.
Developers should

limit the
size of a method to 10 lines of C++ or Java

or any other

code with a possibility of up to 20 lines of
code if j
ustified by two lines of comments per extra line.

Independently Testable

The testing of software is critical in software development and, therefore, an essential concept to
Each developer should have the knowledge and understanding of functional t
esting and
This familiarity will help to
build independently testable methods which improves the
effectiveness of unit testing.

A method is considered independently testable [3] if it meets the following criteria:

The method is invokable b
y a method call with parameters to set particular values.

The method output can be inspected by validating the return values.

The method output is unique to that method.

Well Documented

Making software well documented is
very important
The best practic
e is to name your classes and
method names appropriately so that the code is self descriptive.
The effectiveness of well

named program elements and meaningful comments is widely recognized [8, 4, 16]. Comments are
typically measured by comment percentage

with approximately 30 percent being most effective
[18]. It is calculated by dividing the total number of comments by the total lines of code less the
number of blank lines. Well documented software is known to improve the understandability,
and maintainability of code. Research also shows that method documentation improved
understandability more than class documentation [13].



Many software editors and IDEs have automated refactoring support. Here is a

list of a few of these
editors, or so
called refactoring browsers.

IntelliJ IDEA (for Java)

Eclipse's Java Development Toolkit (JDT)

NetBeans (for Java)

Embarcadero Delphi

Visual Studio (for .NET)

ReSharper (An addon for Visual Studio)

l Assist (An addon for Visual Studio with refactoring support for VB, VB.NET. C# and C++)

DMS Software Reengineering Toolkit (Implements large
scale refactoring for C, C++, C#, COBOL,
Java, PHP and other languages)

Photran a Fortran plugin for the Ecli
pse IDE

SharpSort addin for Visual Studio 2008

Sigasi HDT (for VHDL)


Refactoring is

to positively affect non
functional aspects,
such as
extensibility, modularity,
reusability, complexity, maintainability, and efficiency as stated i
. However, additional negative
aspects of refactoring are reported as well. They consist of additional memory consumption, higher
power consumption, longer execution time, and lower suitability for safety critical applications.
Therefore, before re
factoring is applied to the software system the developer should analyze which
quality characteristics are the most important
to achieve for a particular, module, etc..
and only then
he/she should
take necessary steps to
continue with the rest of the proce


[1] Beck, K.
Extreme Programming Explained: Embrace Change.
Wesley, Reading, MA, 2000.

T. Mens, .A survey of software refactoring,.
IEEE Transactions on Software Engineering
, vol. 30,

no. 2, pp. 126.139, February 2004.

[3] V.
R. Basili andW. L. Melo. A validation of object
oriented design metrics as quality indicators.

IEEE Trans. Software Engineering
, 22(10):751

761, October 1996.

[4] Deursen, A. and Moonen, L. (2002). The video store revisited

thoughts on refactoring and
esting. In Marchesi, M. and Succi, G., editors,
Proceedings of the 3nd International Conference on
Extreme Programming and Flexible Processes in Software Engineering (XP2002)
, pages 71

University of Cagliari.

[5] S. R. Chidamber and C. F. Kemerer. A me
trics suite for object
oriented design.
IEEE Trans.

Software Engineering
, 20(6):476

493, June 1994.

[6] Griswold, W. (1991).
Program Restructuring as an Aid to Software Maintenance
. PhD

thesis, University of Washington.

[7] J. C. Coppick and T. J. Cheath
am. Software metrics for object
oriented systems. In
Proceedings of

the 1992 ACM annual conference on Communications
, pages 317

322. ACM Press, 1992.

[8] Wake, W. C. (2003).
Refactoring Workbook
. Addison
Wesley Longman Publishing Co., Inc., Boston,


[9] M. Fowler.
Refactoring: Improving the Design of Existing Programs
. Addison
Wesley, 1999.

[10] Kang, B., and Bieman, J.M. A quantitative framework for software restructuring.
Journal of

Software Maintenance: Research and Practice, 11
, 4 (July/Augus
t 1999), 245

[Khan et al., 1996] Khan, M. K., Rashid, M. A., and Lo, B. W. (1996). A task
oriented software

maintenance model.
Malaysian Journal of Computer

[11] Kataoka, Y., Imai, T., Andou, H., and Fukaya, T. (2002). A quantitative evaluation

maintainability enhancement by refactoring. In
Proc. Int’l Conf. Software Maintenance
, pages

585. IEEE Computer Society Press.

[12] McCabe. T. A software complexity measure.
IEEE Trans. On Softw. Eng.
4 (December 1976),


] DeMarco,
Structured Analysis and System Specification
. Yourdon Press, New York, NY, 1978.

Jones, M.
The Practical Guide to Structured Systems Design
. Yourdon Press, New York, NY,


] Simon, F., Steinbr
uckner, F., and Lewerentz, C. (2001). Metric
s based refactoring. In

Proc. European Conf. Software Maintenance and Reengineering
, pages 30

38. IEEE Computer

Society Press.

[16] W. Opdyke.
Refactoring Object
Oriented Frameworks
. PhD thesis, University of Illinois at

Champaign, 1992.

[17] W.

Opdyke and R. Johnson. Creating abstract superclasses by refactoring. In
Proc. ACM

Computer Science Conference
, pages 66

73. ACM Press, 1993.

[18] Rosenberg, L. and Hyatt, L.
Software quality metrics for object
oriented system environments

Technical Report SATC
1001, 1995.

[19] Berard, E. V. (1993).
Essays on Object
Oriented Software Engineering
. Prentice
Hall, Inc.,

Englewood Cliffs, New Jersey.

[21] Parnas, D. L. (1978). Designing software for ease of extension and contraction. In
CSE ’78:

Proceedings of the 3rd international conference on Software engineering
, pages 264

Piscataway, NJ, USA. IEEE Press.

[22]Yourdon, E. and Constantine, L.
Structured Design
. Yourdon Press, New York, NY, 1978.


T. Mens and T. Tourw´e. A surv
ey of software refactoring.
IEEE Transactions on Software

, 30(2), 2004.


H. Zuse.
Software Complexity
. Walter de Gruyter, Berlin, 1991.

, 9(2):36

B. Henderson
Oriented Metrics: Measures of Complexity

Hall, 1996.