CS计算机代考程序代写 chain algorithm Refactoring.pdf

Refactoring.pdf

COMP2511

Refactoring

Prepared by

Ashesh Mahidadia

Refactoring: Motivation
v Code refactoring is the process of restructuring existing computer code without

changing its external behavior.

v Originally Martin Fowler and Kent Beck defined refactoring as,

“A change made to the internal structure of software to make it easier to understand
and cheaper to modify without changing its observable behavior… It is a disciplined
way to clean up code that minimizes the chances of introducing bugs.”

v Advantages: improved code readability, reduced complexity; improved maintenance
and extensibility

v If done well, helps to identify hidden or dormant bugs or vulnerabilities, by simplifying
code logic.

v If done poorly, may change external behavior, and/or introduce new bugs!

v Refactoring is different to adding features and debugging.

COMP2511: Refactoring 2

Refactoring: Motivation
v Refactoring is usually motivated by noticing a code smell (possible bad design/coding

practices).

v Code Smell is a hint that something might be wrong, not a certainty.

v Identifying a Code Smell allows us to re-check the implementation details and consider
possible better alternatives.

v Automatic unit tests should be set up before refactoring to ensure routines still behave
as expected.

v Refactoring is an iterative cycle of making a small program transformation, testing it to
ensure correctness, and making another small transformation.

COMP2511: Refactoring 3

Software Maintenance

v Software Systems evolve over time to meet new requirements and features.

v Software maintenance involve:

• Fix bugs
• Improve performance
• Improve design
• Add features

v Majority of software maintenance is for the last three points!

v Harder to maintain code than write from scratch!

v Most of the development time is spent in maintenance!

v Good design, coding and planning can reduce maintenance pain and time!

v Avoid code smells to reduce maintenance pain and time!

COMP2511: Refactoring 4

Code Smells: Possible Indicators

v Duplicated code

v Poor abstraction (change one place → must change others)

v Large loop, method, class, parameter list; deeply nested loop

v Class has too little cohesion

v Modules have too much coupling

v Class has poor encapsulation

v A subclass doesn’t use majority of inherited functionalities

v A “data class” has little functionality

v Dead code

v Design is unnecessarily general

v Design is too specific

COMP2511: Refactoring 5

Low-level refactoring
v Names:

v Renaming (methods, variables)
v Naming (extracting) “magic” constants

v Procedures:
v Extracting code into a method
v Extracting common functionality (including duplicate code) into a class/method/etc.
v Changing method signatures

v Reordering:
v Splitting one method into several to improve cohesion and readability

(by reducing its size)
v Putting statements that semantically belong together near each other

v For more, see http://www.refactoring.com/catalog/

COMP2511: Refactoring 6

IDEs support low-level refactoring

v Renaming:

• Variable, method, class.
v Extraction:

• Method, constant
• Repetitive code snippets
• Interface from a type

v Inlining: method, etc.

v Change method signature.

v Warnings about inconsistent code.

COMP2511: Refactoring 7

Higher-level refactoring

v Refactoring to design patterns.

v Changing language idioms (safety, brevity).

v Performance optimization.

v Generally high-level refactoring is much more important,
but unfortunately not well-supported by tools.

COMP2511: Refactoring 8

Code Smells

2

© Aarthi Natarajan, 2018

Smells : Design aspects that violate fundamental design
principles and impact software quality
Smells occur at different levels of granularity

– Code Smells: Structures in implementation of code such
as large methods, classes with multiple responsibilities,
complex conditional statements that lead to poor code

– Design Smells: Design aspects at a higher level of
abstraction (class level abstractions) such as classes with
multiple responsibilities, refused bequest

Regardless of the granularity, smells in general indicate
violation of software design principles, and eventually lead
to code that is rigid, fragile and require “refactoring”

Code and Design Smells

© Aarthi Natarajan, 2018

Bloaters: Code, Methods and classes that have grown in size, that
they are hard to work with

– Long Method, Large Class, Long Parameter List, Data Clumps
OO Abusers: Result from incorrect or incomplete application of OO
principles

– Switch statements, Refused Bequest
Change Preventers: Code changes are difficult (rigid code)

– Divergent change, Shot Gun Surgery
Dispensables: Code that is pointless and unnecessary

– Comments, Data Class, Lazy Class, Duplicate code
Couplers: Excessive coupling between classes

– Feature Envy, Inappropriate intimacy, Message Chains

Smells

© Aarthi Natarajan, 2018

Fix smell, long method
• Reduce length of a method body via Extract Method

– More readable, Less code duplication
– Isolates independent parts of code, – errors are less likely

• If local variables and parameters interfere with extracting a method, use
– Replace Temp With Query
– Introduce Parameter Object
– Preserve Whole Object

• If the above doesn’t work, try moving the entire method to a separate
object via Replace Method with Method Object

• Replace Method with Method Object
• Conditional operators and loops are a good clue that code can be moved

to a separate method.

Smell: Long Method

© Aarthi Natarajan, 2018

– More readable code (
The new method
name should describe
the method’s purpose
)

– Less code duplication,
more reusability

– Isolates independent
parts of code,
meaning that errors
are less likely

– A very common
refactoring technique
for code smells

Refactoring Techniques – Extract Method

© Aarthi Natarajan, 2018

– Methods contain a repeating group of parameters, causing
code duplication

– Consolidate these parameters into a separate class
• Also helps to move the methods for handling this data
• Beware, if only data is moved to a new class and

associated behaviours are not moved, this begins to
smell of a Data Class

– Eliminates smell such as Long Parameter List, Data Clumps,

Primitive Obsession, Long Method

Refactoring Techniques: Introduce Parameter Object

© Aarthi Natarajan, 2018

Often, we place the result of an expression in a local variable for later
use in the code
With Replace Temp With Query we:
• Move the entire expression to a separate method and return

the result from it.
• Query the method instead of using a variable
• Reuse the new method in other methods

• Eliminates smell such as Long Method, Duplicate Code

Refactoring Technique: Replace Temp With Query

double calculateTotal() {
double basePrice = quantity * itemPrice;
if (basePrice > 1000) {
return basePrice * 0.95;
}
else {
return basePrice * 0.98;
}
}

double calculateTotal() {
if (basePrice() > 1000) {
return basePrice() * 0.95; }
else {
return basePrice() * 0.98; } }
double basePrice() {
return quantity * itemPrice;
}
}

© Aarthi Natarajan, 2018

• Having all the phone details in class Customer is not a
good OO design and also breaks SRP

• Refactor into two separate classes, each with its
appropriate responsibility

Refactoring Technique: Extract Class

© Aarthi Natarajan, 2018

• Problem:
• Similar to Long Method
• Usually violates Single Responsibility Principle
• May have

– A large number of instance variables
– Several methods

• Typically lacks cohesion and potential for duplicate code smell
Solution:
• Bundle group of variables via Extract Class or Extract Sub-Class

Smell: Large Class

© Aarthi Natarajan, 2018

Problem: Calling a query method and passing its results as the
parameters of another method, while that method could call the
query directly
• Too many parameters to remember
• Bad for readability, usability and maintenance

Solution:
• try placing a query call inside the method body via replace

parameter with method and remove parameters with change
method signature

• Eliminates smell such as Long Method, Duplicate Code

Code Smell: Long Parameter List

© Aarthi Natarajan, 2018

Problem:
• Different parts of the code contain identical groups of variables

e.g., fields in many classes, parameters in many method
signatures

• Can lead to code smell Long Parameter List

Solution: Move the behaviour to the data class via Move Method
• If repeating data comprises the fields of a class, use Extract

Class to move the fields to their own class.
• If the same data clumps are passed in the parameters of

methods, use Introduce Parameter Object to set them off
as a class.

• If some of the data is passed to other methods, think about
passing the entire data object to the method instead of just
individual fields Preserve Whole Object will help with this.

Code Smell: Data Clumps

© Aarthi Natarajan, 2018

Problem:
• A subclass uses only some of the methods and properties

inherited from its parents
• The unneeded methods may simply go unused or be redefined

and give off exceptions
• Often caused by creating inheritance between classes only by

the desire to reuse the code in a super-class

Code Smell: Refused Bequest

© Aarthi Natarajan, 2018

Solution:
• If inheritance makes no sense and the subclass really does have

nothing in common with the superclass, eliminate inheritance in
favour of Replace Inheritance with Delegation

• If inheritance is appropriate, but super class contains fields and
methods not applicable to all classes, then consider the following
options
– Create a new subclass
– Apply Push Down Field to move field relevant only to subclass

from superclass
– Apply Push Down Method to move behaviour from super class to

sub class, as behaviour makes sense only to sub class
– Often, you may apply an Extract Sub-Class Class to combine the

above steps

Code Smell: Refused Bequest

© Aarthi Natarajan, 2018

class Camel does not use field model. It
should be pushed down to class Car

public abstract class Transport {
// Push Down Field
private String model;
// Push Down Method
public String getModel() throws Exception
{
return model;
}

}
public class Car extends Transport { … }
public class Camel extends Transport {

public String getModel() {
throw new NotSupportedException();
}
}
public abstract class Transport {

}

Refused Bequest Example

// Use Push Down Field to move field and
// Push Down Method to move behaviour
// only relevant to sub class
// from super class to sub class

public abstract class Transport {

}
public class Car extends Transport
{
private String model;
public String getModel()
{
return model;
}

}
public class Camel extends Transport
{

}

© Aarthi Natarajan, 2018

Code Fragments look similar
• If the same code is found in two or more methods in the same class:

use Extract Method and place calls for the new method in both places
• If the same code is found in two subclasses of the same level:

– Use Extract Method for both classes, followed by Pull Up Field for
the fields used in the method that you are pulling up.

– If the duplicate code is inside a constructor, use Pull Up Constructor
Body

– If the duplicate code is similar but not completely identical, use Form
Template Method

– If two methods do the same thing but use different algorithms, select
the best algorithm and apply Substitute Algorithm

• If duplicate code is found in two different classes:
– If the classes are not part of a hierarchy, use Extract SuperClass in

order to create a single superclass for these classes that maintains all
the previous functionality

Code Smell: Duplicate Code

© Aarthi Natarajan, 2018

Problem: A method that is more interested in a class other than the
one it actually is
• Invokes several methods on another object to calculate some value
• Creates unnecessary coupling between the classes

Solution: A goal of OO design is to put the methods with its
associated data
– So the method must moved to the relevant class via Move Method
• If only part of a method accesses the data of another object,

use Extract Method followed by Move Method to move the part in
question

• If a method uses functions from several other classes, first
determine which class contains most of the data used. Then place
the method in this class along with the other data.

Code Smell: Feature Envy

© Aarthi Natarajan, 2018

Divergent Change: One class is changed in different ways for
different reasons
• Solution: Any change to handle a variation should change a single

class, and all the typing in the new class should express the
variation.

• To clean this up you identify everything that changes for a
particular cause and use Extract Class to put them all together

Shot Gun Surgery: A small change in the code forces lots of little
changes to different classes
• Solution:

– Use Move Method or Move Field to put all the changes into a
single class

– Often you can use Inline Class to bring a whole bunch of
behaviour together.

• Divergent change is one class that suffers many kinds of changes,
and shotgun surgery is one change that alters many classes.

Code Smell: Divergent Change, Shot Gun Surgery

© Aarthi Natarajan, 2018

Problem: Classes that just have attributes with setters and getters
and no behaviour
One of the goals of OO design is to put behaviour where the data is

Solution: Move the behaviour to the data class via Move Method

Code Smell: Data Classes

© Aarthi Natarajan, 2018

Problem: Classes that aren’t doing much to justify their existence
(maintenance overhead)

Subclasses without any overridden methods or additional fields can be lazy
classes as well

Solution:
• Move the data (postcode) from lazy class PostCode to the class

Address
• Delete the lazy class

Code Smell: Lazy classes

© Aarthi Natarajan, 2018

Problem: Switch statements are bad from an OO design point of view

Solution: Replace switch statements with a polymorphic solution
based on Strategy Pattern applying a series of refactoring techniques
( Extract Method, Move Method, Extract Interface etc., Refer lecture
demo for complete solution )

Code Smell: Switch Statements

© Aarthi Natarajan, 2018

Move Field/Method
Extract Class/Inline Class
Extract Method
Inline Method/Temporary Variable
Replace Temp with Query
Replace Method with Method Object
Rename Method
Substitute Algorithm
Introduce Parameter Object
Preserve Whole Object
Extract Sub Class/Super Class/Interface
Extract Method
Pull Up Field/Method/Constructor Body
Form Template Method
Replace Inheritance with Delegation
Replace Conditional with Polymorphism

List of Refactoring Techniques to be familiar

© Aarthi Natarajan, 2018

https://refactoring.guru/refactoring/smells
https://www.refactoring.com/catalog/

Useful Links