53
Refactoring

Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

  • Upload
    others

  • View
    6

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Refactoring

Page 2: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

An interesting comment

• "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Fowler)

Page 3: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Another quote• “Refactoring is like continuing repair of a living

system. The goal is to stay within reasonable operating limits with limited continual damage. By staying within these limits you keep costs low, because costs relate nonlinearly to the amount of repair necessary. It is like maintaining your house. You are best off (financially) if you continuously maintain rather than do large lump repairs.” (Dirk Riehle (quoted in Jim Highsmith’s Agile Software Development Ecosystems, page 155))

Page 4: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

What is refactoring?• Refactoring is changing a software system by improving

its internal structure without changing its external behavior, i.e. it is a technique to restructure the code in a disciplined way to improve its internal structure.

• The process could be informally referred to as "cleaning up" or "taking out the garbage." Refactoring neither fixes bugs nor adds new functionality, though it might precede either activity. Rather, it improves the understandability of the code, changes its internal structure and design, and removes dead code. (Wiki)

Page 5: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Definition from http://www.refactoring.com/

• “Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior. Its heart is a series of small behavior preserving transformations.Each transformation (called a 'refactoring') does little, but a sequence of transformations can produce a significant restructuring. Since each refactoring is small, it is less likely to go wrong. The system is also kept fully working after each small refactoring, reducing the chances that a system can get seriously broken during the restructuring.”

Page 6: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

What is refactoring

• “A change to the system that leaves itsbehavior unchanged, but enhances somenonfunctional quality – simplicity,flexibility, understandability, performance”(Kent Beck, Extreme Programming

Explained)

Page 7: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Defining Refactoring

• (Noun) – A change made to internal structure of software to make it easier to understand and modify without changing its observable behavior.

• (Verb) – to structure software by applying a series of refactorings without changing its observable behavior

Page 8: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Why refactor? Argument 1

• The changes in refactoring are intended to make the code easier to comprehend, more maintainable, and more amenable to change.

• Refactoring is usually motivated by the difficulty of adding new functionality to a program or fixing a bug in it.

Page 9: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Why should refactoring be done? Argument 2

• Refactoring Improves the Design of Software. - Without refactoring, the design of the program will decay. As people change code - changes to realize short-term goals or changes made without a full comprehension of the design of the code -the code loses its structure.

Page 10: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Why should refactoring be done? Argument 3

• Refactoring makes software easier to understand.

• There are users of your code:– The computer, – the writer, and – the updater.

• The most important is the updater. • Who cares if the compiler takes a few more

cycles to compile your code. • If it takes someone 3 weeks to update your code

that is a problem.

Page 11: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Why refactoring? Argument 4

• Refactoring helps you find bugs. • Part of refactoring code is understanding

the code and putting that understanding back into the code.

• In that process a clarification takes place. • In that clarification bugs will be found.

Page 12: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Why refactor? Argument 5

• Refactoring Helps you Program Faster. • Without a good design, you can progress

quickly for a while, but soon poor design start to slow you down.

• You spend time finding and fixing bugs and understanding the system instead of adding new function.

• New features need more coding as you patch over a patches.

Page 13: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Refactoring and Design?

• Refactoring compliments design. • By doing some of the design along the

way, programmers avoid the problems of over designing for reuse, flexibility, or extendibility that is never needed.

Page 14: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Refactoring and Performance.

• In the short refactoring may make the code slower.

• Manage the optimization for performance in a different way to alleviate the above problem.

Page 15: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Manage Optimization

• The intent in refactoring is of better design and more understandable code.

• Often, but not always, this makes the code slower.

• The recommendation is for a system to be completely built, then analyzed for performance and optimized for the 10% of the system that is the slowest.

• That optimization may work better in the end and the refactoring will meet its intent.

Page 16: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Why people hesitate to refactor• Conventional wisdom would discourage

modifying a design– You might break something in the code,– You have to update the documentation.

• Expensive• But, there are longer term concerns.• Sticking with an inappropriate design

– Makes the code harder to change– Makes the code harder to understand and maintain– Very expensive in the long run

Page 17: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Motivation for refactoring• Contrary to idealized development strategy: analysis and design code test• At first, code is pretty good but as requirements

change or new features are added, the code structure tends to atrophy. Refactoring is the process of fixing a bad or chaotic design.

• Amounts to moving methods around, creating new methods, adding or deleting classes.

Page 18: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

From Crispin & House, Testing Extreme Programming

• Duplication & needless complexity areremoved from the code during each codingsession, even when this requires modifyingcomponents that are already “complete.”• Automated unit tests are used to verifyevery change.

Page 19: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

When to Refractor ?

• When you add a functionHelps you to understand the code you are modifying.Sometimes the existing design does not allow you to easily add the feature.

• When you need to fix a bugIf you get a bug report its a sign the code needs refactoring because the code was not clear enough for you to see the bug in the first place.

Page 20: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

When to Refactor ? Continued

• When you do a Code Review- Code reviews help spread knowledge through the development team.- Works best with small review groups.

Page 21: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Benefits of Refactoring

Refactoring is useful to any program that has at least one of the following shortcomings:

• Programs that are hard to read are hard to modify.

• Programs that have duplicate logic are hard to modify.

Page 22: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Benefits of Refactoring(Continued)

• Programs that require additional behavior which requires you to change running code are hard to modify.

• Programs with complex conditional logic are hard to modify.

Page 23: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Refactoring Risks

• Introducing a failure with refactoring can have serious consequences.

• When done on a system that is already in production, the consequences of introducing bugs without catching them are very severe.

Page 24: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Costs of Refactoring

Language / Environment :Depends on how well the operations on the source code are supported. But in general the cost of applying the basic text modifications should be bearable.

Testing :Relies heavily on testing after each small step and having a solid test suite of unit tests for the whole system substantially reduces the costs which would be implied by testing manually

Page 25: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Costs of Refactoring (Continued)

Documentation :

Costs of updating documentation of the project should not be underestimated as applying refactorings involves changes in interfaces, names, parameter lists and so on.

All the documentation concerning these issues must be updated to the current state of development.

Page 26: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Costs of Refactoring (Continued)

System :

The tests covering the system need an update as well as the interfaces and responsibilities change. These necessary changes can contribute to higher costs as tests are mostly very dependent on the implementation.

Page 27: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

When to put Off Refactoring ?• Concerned code is neither able to compile

or to run in a stable manner, it might be better to throw it away and rewrite the software from scratch.

• When a deadline is very close. Then it would take more time to do the refactoring than the deadline allows.

Page 28: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Properties of Refactoring

• Preserve Correctness

• One step at a time

• Frequent Testing

Page 29: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Design Attributes

• Abstraction (information hiding)

• Flexibility

• Clarity

• Irredundancy

Page 30: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Steps to Refactoring

• Identify heavily used or time consuming code.

• Refactoring begins by designing a solid set of tests for the section of code under analysis.

• Identify problems in code by review using bad smells of code.

• Introduce a refactoring and test.

Page 31: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Steps to Refactoring (Continued)

• The steps taken when applying the refactoring should be:

- Small enough to oversee the consequences they have.

- Reproduceable to allow others to understand them.

- Generalized in a way, that they are more a rule that can be applied to any structure.

- Written down to allow sharing these steps and to keep a reference, with step by step instructions how to apply them.

Page 32: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

The first steps in refactoring is testing.

• The first step in refactoring is to build a solid set of tests for that section of code.

• In refactoring functionality does not change.

• Tests are the only insurance that changes to the coded design will not change the functionality.

Page 33: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Basic idea

Make sure your tests passFind some code that “smells”Determine how to simplify this codeMake the simplificationsRun tests to ensure things still work

correctlyRepeat the simplify/test cycle until the

smell is gone

Page 34: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

What is “code smell”?• In computer programming, code smell is any symptom

in the source code of a program that possibly indicates 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 further 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. (From Wiki)

Page 35: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Common “smells”• Duplicate code: identical or very similar code exists in

more than one location. • Long method: a method, function, or procedure that has

grown too large. • Large class: a class that has grown too large.• Long Parameter List: too many parameters in a method.• Feature envy: a class that uses methods of another

class excessively. • Divergent Change: a class that does distinctly different

things.• Shotgun Surgery: a change in one class repeatedly

requires little changes in a bunch of other classes.

Page 36: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Common “smells”• Inappropriate intimacy: a class that has dependencies on

implementation details of another class. • Data Clumps Data that's always hanging with each other

(e.g. name street zip).• Switch (case) statements: Long and complicated switch

case.• Refused bequest: a class that overrides a method of a base

class in such a way that the contract of the base class is not honored by derived class. This will be clear when we go to Liskov substitution principle.

• Lazy class: a class that does too little. • Duplicated method: a method, function, or procedure that is

very similar to another. • Contrived Complexity: forced usage of overly complicated

design patterns where simpler design would suffice.

Page 37: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniques

• Extract Method :• When we have a code fragment that can be grouped together.• Turn the fragment into a method whose name explains the purpose

of the method.

void printOwing() {

printBanner(); //print details

System.out.println ("name:" + _name);

System.out.println("amount" + getOutstanding());

}

void printOwing() {

printBanner();

printDetails(getOutstanding());}void printDetails (double outstanding) {System.out.println ("name:" +

_name);System.out.println ("amount:" +

outstanding);}

Page 38: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniquesDuplicated Code

--extract out the common bits into their own method (extract method), if code is in same class.

--if two classes duplicate code, consider extract class to create a new class to hold the shared functionality.

Long Methods

use extract method to break it up into smaller, more understandable pieces.

Page 39: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniquesLong Parameter List

--replace parameter with method (dont' pass data the receiver can get on its own accord -- receiver explicitly asks for data itself via sender getter method)

OR: if the parameters are a natural, self-contained grouping, introduce parameter object.Example: day month, year, hour minute second parameters ==> date parameter

Large Class:Class trying to do too much - often shows up as too many

instance variables. Break into smaller cohesive classes.

Page 40: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniques

Divergent ChangeIf you have a fixed class that does distinctly different things consider separating out the varying code into varying classes (extract class)that either subclass or are contained by the non-varying class. This is closely related to the Single Responsibility Principle.

Do you look at a class and say:a) These three methods deals with data baseb) These four methods deal with financial policy.

Divergent change is needed when you have a class that has to be involved in many different “kinds” of changes.

Then you probably need at least two classes not one.Any change to handle a variation should change a distinct class

Page 41: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniques

Shotgun SurgeryThis situation occurs when every time you make a kind of change, you have to make a lot of little changes to a lot of different classes. This is the opposite to divergent change.Shotgun surgery is needed when you have many classes that have to be involved in one “kind” of change.

--perform MOVE METHOD/FIELD to bring a whole bunch of behavior together since they are obviously highly interdependent.

If no suitable target class exists – create one.

Page 42: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniquesFeature EnvyIt is a method that seems more interested in a class other

in the one that it is in.Example: a method that invokes numerous getter methods

on another object to get some information and then perform the operation.

Solution -- perform MOVE METHOD or EXTRACT METHOD on the jealous bit and get it home.

However, a method may use features of several classes. Heuristic – determine which class has most of the data and

move the method with that data.

Idea to remember – put together things that change together.

Page 43: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniquesData Clumps

Data that's always hanging with each other (e.g. name street zip).--Extract out a class (extract class) for the data. Will help trim argument lists too, since name street zip now passed as one address object. Related to long parameter list above.

One good test – delete of the data values. Do others by themselves make sense?

Idea – don’t be shy about making “small” objects for “small tasks.

Example – money class that have a currency and amount.

Page 44: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniquesSwitch (case) statements

switch statements are often duplicated – the same switch statement appears in multiple places in the code.

Consider a method that deals with customers from Canada, the US, the UK, Germany and Italy. You are likely to find multiple places where different actions are taken depending on the country the customer is from.Now suppose you wish to add China to that list.

Conclusion:If you add or remove a clause in one switch, you often have to find and repair the others too.

Refactoring Actions-- Use EXTRACT METHOD to extract the switch statement and then

MOVE METHOD to get it into the class where the polymorphism is needed.

-- Then use replace type code with subclass or replace type code with state/strategy (to be discussed later)

Page 45: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniquesLazy Class

Class doesn't seem to be doing anything. -- Get rid of it!

collapse hierarchy if subclasses are nearly vacuous. inline class (stick the class' methods and fields in the

class that was using it and get rid of original class).

Page 46: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniquesHide Delegate :

When a client is calling a delegate class of an object.Idea : a class should not access features of other classes unless it is

absolutely needed. If the delegate class changes the client also has to change. So we should remove the dependency by putting a delegating method to avoid calling capabilities of the delegate class.

Example:Suppose the client deals with object myObject1 of class X which includes

an object myObject2 of class Y that includes method m().

The client can say myObject1.m() to access method m().This is bad practice since the definition of class Y, including method m() ,

may7 change with time.

It is better to design class X() including a delegating method say m1() which calls myObject2.m(). This way the client is shielded from changes.

of an object.

Page 47: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniques

Message chainsSay you want to send a message to object D in class A but you have to go through B to get C and C to get D. --use hide delegate to hide C and D in B, and add a method to B that does what A wanted to do with D.

Inappropriate IntimacyDirectly getting in and messing about with the internals of another class. --To fix this, move methodsto consolidate the intimate bits.

Page 48: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniques

CommentsComments in the middle of methods are “deodorant”. You should really refactor so each comment block is its own method. Do extract method.

Page 49: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

Consolidate conditionals :

double disabilityAmount(){

if (_seniority < 2) return 0;

if (_monthsDisabled > 12)

return 0;

if (_isPartTime) return 0;

// compute the disability amount

double disabilityAmount(){

if (isNotEligableForDisability())

return 0;

// compute the disability amount

A quick tour of basic refactoring techniques

Page 50: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniquesDecompose Conditionals :

When we have a complicated conditional (if-then-else) statement.

if (date.before (SUMMER_START) || date.after(SUMMER_END))

charge = quantity * _winterRate + _winterServiceCharge;else charge = quantity * _summerRate;if (notSummer(date))

charge = winterCharge(quantity);else charge = summerCharge (quantity);

Idea: Extract condition into its own method. Extract the then part and else part into two methods.

Page 51: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniques• Encapsulate Downcast :

When a method returns an object that needs to be downcasted by its callers.

Object lastReading() {return readings.lastElement();}

Reading lastReading() {return (Reading) readings.lastElement();}

If we know that the object returned by a method must be downcasted, do so inside the method.Idea: downcast the client should be downcasting as little as possible.(The availability of Generic classes in Java makes this refactoring less important than before)

Page 52: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

A quick tour of basic refactoring techniques

• Extract Class :When we have one class doing the work that should be done by two.

Page 53: Refactoring - University of Windsorsubir.myweb.cs.uwindsor.ca/.../RefactoringI.pdf · • Refactoring makes software easier to understand. • There are users of your code: – The

• Inline Class :When a class isn't doing very much. (The opposite what

we just said!!)

A quick tour of basic refactoring techniques