Refactoring - PowerPoint PPT Presentation

1 / 62
About This Presentation
Title:

Refactoring

Description:

Start with an existing code base and make it better. Change the internal structure (in-the-small ... Refactoring done to clean up hacks. Done after reflection. ... – PowerPoint PPT presentation

Number of Views:291
Avg rating:3.0/5.0
Slides: 63
Provided by: MikeGo4
Category:

less

Transcript and Presenter's Notes

Title: Refactoring


1
Refactoring
  • Overview
  • What is refactoring?
  • A catalogue of bad smells

2
Refactoring
  • Basic metaphor
  • Start with an existing code base and make it
    better.
  • Change the internal structure (in-the-small to
    in-the-medium) while preserving the overall
    semantics
  • i.e., rearrange the factors but end up with the
    same final product
  • The idea is that you should improve the code in
    some significant way. For example
  • Reducing near-duplicate code
  • Improved cohesion, lessened coupling
  • Improved parameterization, understandability,
    maintainability, flexibility, abstraction,
    efficiency, etc

3
What Is Refactoring?
  • Definition
  • The process of changing software in a way that
    the external behavior is not alteredbut the
    internal structure is improved.
  • Or, an instance of such a change.(E.g. I
    carried out a refactoring.)
  • Cleaning up code. Improving design.But after
    the code works.
  • Fights against software entropy

4
Why Refactor?
  • Continuous improvement of design
  • Tidying up. Avoids decay.
  • Needed if make it work is first priority
  • Best design choices may not evident at first
  • Makes software easier to understand
  • Refactoring done to clean up hacks
  • Done after reflection.
  • May be done to remove ambiguity, misleading code,
    a hack, etc.
  • If you can change it successfully, you understand
    it

5
Why Refactor? (2)
  • Helps you find bugs
  • A change to improve structure may reveal a flaw
    in old implementation
  • Helps you developing working code more quickly
  • Counter-intuitive!
  • Short cycles of add-functionality then
    improve-design. (Kent Becks two hats idea).

6
But Hold On
  • Possible objections.
  • Touching the design is asking for trouble!
  • Once its working, why bother?
  • After I think its working, dont I have to
    re-verify the design changes again?
  • What we need to make refactoring successful is
  • Unit tests

7
Refactoring
  • Reference
  • Refactoring Improving the Design of Existing
    Code,
  • by Martin Fowler (et al.),1999, Addison-Wesley
  • Fowler, Beck, et al. are big wheels in the OOAD
    crowds
  • Smalltalk experience
  • OO design patterns
  • XP (extreme programming)

8
Refactoring
  • Book is very good
  • Ideas have been around for a long time tho.
  • Experienced OO programmers will have a pretty
    good handle on most of the ideas
  • Mostly its a catalogue of transformations that
    you can perform on your code, with motivation,
    explanation, variations, and examples
  • e.g., Extract interface, Move method, Pull up
    constructor body
  • Refactorings often come as duals
  • e.g., Replace inheritance with delegation and
  • Replace delegation with inheritance

9
Refactoring
  • Book has a catalogue of
  • 22 bad smells
  • i.e., things to look out for, anti-patterns
  • This font and colour indicates the name of a bad
    smell.
  • 72 refactorings
  • i.e., what to do when you find them
  • This font and colour indicates the name of a
    refactoring.
  • As with GoF book on OODPs, there is overlap
    between the catalogue items, and the ideas start
    to blur.
  • We will look at some of the bad smells and what
    to do about them.

10
Some advice from Fowler
  • When should I refactor? How often?
  • How much time should I dedicate to it?
  • Its not something you should dedicate two weeks
    for every six months
  • rather, you should do it as you develop!
  • Refactor when you recognize a warning sign (a
    bad smell) and know what to do
  • when you add a function
  • Likely its not an island unto itself
  • when you fix a bug
  • Is the bug symptomatic of a design flaw?
  • when you do a code review
  • A good excuse to re-evaluate your designs, share
    opinions.

11
When Should Refactor?
  • Remember afterwards! (After what?)
  • The Rule of Three
  • First, just do it. Second time, do it badly but
    tolerate it. Third time, do it well refactor.
  • Some guidelines
  • When you need to add a function. Existing
    design makes this hard. Improve it.
  • When you need to fix a bug.
  • As part of a code review.

12
The rule of three (XP)
  • The first time you code a task, just do it.
  • The second time you code the same idea, wince and
    code it up again.
  • The third time you code the same idea, its time
    to refactor!
  • Any programming construct can be made more
    abstract but thats not necessarily a good
    thing.
  • Generality (flexibility) costs too
  • Dont spin you wheels designing and coding the
    most abstract system you can imagine.
  • Practise Just-in-Time abstraction.
  • Expect that you will be re-arranging your code
    constantly. Dont worry about it. Embrace it.

13
Refactoring and Design Smells
  • Fowler, design smells, and catalog of
    refactorings
  • The book
  • http//www.refactoring.com/
  • List of smells on the webhttp//wiki.java.net/bi
    n/view/People/SmellsToRefactorings

14
Bad smells in code
  • Duplicated code
  • The 1 bad smell
  • Same expression in two methods in the same class?
  • Make it a private ancillary routine and
    parameterize it
  • (Extract method)
  • Same code in two related classes?
  • Push commonalities into closest mutual ancestor
    and parameterize
  • Use template method DP for variation in subtasks
  • (Form template method)

15
Bad smells in code
  • Duplicated code
  • Same code in two unrelated classes?
  • Ought they be related?
  • Introduce abstract parent (Extract class, Pull up
    method)
  • Does the code really belongs to just one class?
  • Make the other class into a client (Extract
    method)
  • Can you separate out the commonalities into a
    subpart or a functor or other function object?
  • Make the method into a subobject of both classes.
  • Strategy DP allows for polymorphic variation of
    methods-as-objects
  • (Replace method with method object)

16
Bad smells in code
  • Long method
  • Often a sign of
  • Trying to do too many things
  • Poorly thought out abstractions and boundaries
  • Micromanagement anti-pattern
  • Best to think carefully about the major tasks and
    how they inter-relate. Be aggressive!
  • Break up into smaller private methods within the
    class
  • (Extract method)
  • Delegate subtasks to subobjects that know best
    (i.e., template method DP)
  • (Extract class/method, Replace data value with
    object)

17
Bad smells in code
  • Long method
  • Fowlers heuristic
  • When you see a comment, make a method.
  • Often, a comment indicates
  • The next major step
  • Something non-obvious whose details detract from
    the clarity of the routine as a whole.
  • In either case, this is a good spot to break it
    up.

18
Bad smells in code
  • Large class
  • i.e., too many different subparts and methods
  • Two step solution
  • Gather up the little pieces into aggregate
    subparts.
  • (Extract class, replace data value with object)
  • Delegate methods to the new subparts.
  • (Extract method)
  • Likely, youll notice some unnecessary subparts
    that have been hiding in the forest!
  • Resist the urge to micromanage the subparts!

19
Bad smells in code
  • Large class
  • Counter example
  • Library classes often have large, fat interfaces
    (many methods, many parameters, lots of
    overloading)
  • If the many methods exist for the purpose of
    flexibility, thats OK in a library class.

20
Bad smells in code
  • Long parameter list
  • Long parameter lists make methods difficult for
    clients to understand
  • This is often a symptom of
  • Trying to do too much
  • too far from home
  • with too many disparate subparts

21
Bad smells in code
  • Long parameter list
  • In the old days, structured programming taught
    the use of parameterization as a cure for global
    variables.
  • With modules/OOP, objects have mini-islands of
    state that can be reasonably treated as global
    to the methods (yet are still hidden from the
    rest of the program).
  • i.e., You dont need to pass a subpart of
    yourself as a parameter to one of your own
    methods.

22
Bad smells in code
  • Long parameter list
  • Solution
  • Trying to do too much?
  • Break up into sub-tasks
  • (Extract method)
  • too far from home?
  • Localize passing of parameters dont blithely
    pass down several layers of calls
  • (Preserve whole object, introduce parameter
    object)
  • with too many disparate subparts?
  • Gather up parameters into aggregate subparts
  • Your method interfaces will be much easier to
    understand!
  • (Preserve whole object, introduce parameter
    object)

23
Bad smells in code
  • Divergent change
  • Occurs when one class is commonly changed in
    different ways for different reasons
  • Likely, this class is trying to do too much and
    contains too many unrelated subparts
  • Over time, some classes develop a God complex
  • They acquires details/ownership of subparts that
    rightly belong elsewhere
  • This is a sign of poor cohesion
  • Unrelated elements in the same container
  • Solution
  • Break it up, reshuffle, reconsider relationships
    and responsibilities (Extract class)

24
Bad smells in code
  • Shotgun surgery
  • the opposite of divergent change
  • Each time you want to make a single, seemingly
    coherent change, you have to change lots of
    classes in little ways
  • Also a classic sign of poor cohesion
  • Related elements are not in the same container!
  • Solution
  • Look to do some gathering, either in a new or
    existing class.
  • (Move method/field)

25
Bad smells in code
  • Feature envy
  • A method seems more interested in another class
    than the one its defined in
  • e.g., a method Am() calls lots of get/set
    methods of class B
  • Solution
  • Move m() (or part of it) into B!
  • (Move method/field, extract method)
  • Exceptions
  • Visitor/iterator/strategy DP where the whole
    point is to decouple the data from the algorithm
  • Feature envy is more of an issue when both A and
    B have interesting data

26
Bad smells in code
  • Data clumps
  • You see a set of variables that seem to hang
    out together
  • e.g., passed as parameters, changed/accessed at
    the same time
  • Usually, this means that theres a coherent
    subobject just waiting to be recognized and
    encapsulated

void ScenesetTitle (string titleText, int
titleX, int titleY, Colour titleColour) void
ScenegetTitle (string titleText, int
titleX, int titleY, Colour titleColour)
27
Bad smells in code
  • Data clumps
  • In the example, a Title class is dying to be born
  • If a client knows how to change a titles x, y,
    text, and colour, then it knows enough to be able
    to roll its own Title objects.
  • However, this does mean that the client now has
    to talk to another class.
  • This will greatly shorten and simplify your
    parameter lists (which aids understanding) and
    makes your class conceptually simpler too.
  • Moving the data may create feature envy initially
  • May have to iterate on the design until it feels
    right.
  • (Preserve whole object, extract class, introduce
    parameter object)

28
Bad smells in code
  • Primitive obsession
  • All subparts of an object are instances of
    primitive types
  • (int, string, bool, double, etc.)
  • e.g., dates, currency, SIN, tel., ISBN, special
    string values
  • Often, these small objects have interesting and
    non-trivial constraints that can be modelled
  • e.g., fixed number of digits/chars, check digits,
    special values
  • Solution
  • Create some small classes that can validate and
    enforce the constraints.
  • This makes your system mode strongly typed.
  • (Replace data value with object, extract class,
    introduce parameter object)

29
Bad smells in code
  • Switch statements
  • We saw this before heres Fowlers example

Double getSpeed () switch (_type) case
EUROPEAN return getBaseSpeed() case
AFRICAN return getBaseSpeed()
getLoadFactor() _numCoconuts case
NORWEGIAN_BLUE return (_isNailed) ? 0
getBaseSpeed(_voltage)
30
Bad smells in code
  • Switch statements
  • This is an example of a lack of understanding
    polymorphism and a lack of encapsulation.
  • Solution
  • Redesign as a polymorphic method of PythonBird
  • (Replace conditional with polymorphism, replace
    type code with subclasses)

31
Bad smells in code
  • Lazy class
  • Classes that doesnt do much thats different
    from other classes.
  • If there are several sibling classes that dont
    exhibit polymorphic behavioural differences , the
    consider just collapsing them back into the
    parent and add some parameters
  • Often, lazy classes are legacies of ambitious
    design or a refactoring that gutted the class of
    interesting behaviour
  • (Collapse hierarchy, inline class)

32
Bad smells in code
  • Speculative generality
  • We might need this one day
  • Fair enough, but did you really need it after
    all?
  • Extra classes and features add to complexity.
  • XP philosophy
  • As simple as possible but no simpler.
  • Rule of three.
  • Keep in mind that refactoring is an ongoing
    process.
  • If you really do need it later, you can add it
    back in.
  • (Collapse hierarchy, inline class, remove
    parameter)

33
Bad smells in code
  • Message chains
  • Client asks an object which asks a subobject,
    which asks a subobject,
  • Multi-layer drill down may result in
    sub-sub-sub-objects being passed back to
    requesting client.
  • Sounds like the client already has an
    understanding of the structure of the object,even
    if it is going through appropriate
    intermediaries.
  • Probably need to rethink abstraction
  • Why is a deeply nested subpart surfacing?
  • Why is the subpart so simple that its useful far
    from home?
  • (Hide delegate)

34
Bad smells in code
  • Middle man
  • All hard problems in software engineering can be
    solved by an extra level of indirection.
  • OODPs pretty well all boil down to this, albeit
    in quite clever and elegant ways.
  • If you notice that many of a classs methods just
    turn around and beg services of delegate
    subobjects, the basic abstraction is probably
    poorly thought out.
  • An object should be more than the some of its
    parts in terms of behaviours!
  • (Remove middle man, replace delegation with
    inheritance)

35
Bad smells in code
  • Inappropriate intimacy
  • Sharing of secrets between classes, esp. outside
    of the holy bounds of inheritance
  • e.g., public variables, indiscriminate
    definitions of get/set methods, C friendship,
    protected data in classes
  • Leads to data coupling, intimate knowledge of
    internal structures and implementation decisions.
  • Makes clients brittle, hard to evolve, easy to
    break.
  • Solution
  • Appropriate use of get/set methods
  • Rethink basic abstraction.
  • Merge classes if you discover true love
  • (Move/extract method/field, change bidirectional
    association to unidirectional, hide delegate)

36
Bad smells in code
  • Alternative classes with different interfaces
  • Classes/methods seem to implement the same or
    similar abstraction yet are otherwise unrelated.
  • This is not a knock against overloading, just
    haphazard design.
  • Solution
  • Move the classes closer together.
  • Find a common interface, perhaps an ABC.
  • Find a common subpart and remove it.
  • (Extract superclass, move method/field, rename
    method)

37
Bad smells in code
  • Data class
  • Class consists of (simple) data fields and simple
    accessor/mutator methods only.
  • Often, youll find that clients of this class are
    using get/set methods just like the micromanager
    anti-pattern (albeit via a level of indirection).
  • Solution
  • Have a look at usage patterns in the clients
  • Try to abstract some commonalities of usage into
    methods of the data class and move some
    functionality over
  • My own view is that data classes are quite
    reasonable, if used judiciously.
  • In C, often use structs to model data classes.
  • Data classes are like children. They are OK as
    a starting point, but to participate as a grownup
    object, they need to take on some
    responsibility.
  • (Extract/move method)

38
Bad smells in code
  • Refused bequest
  • Subclass inherits methods/variables but doesnt
    seem to use some of them.
  • In a sense, this might be a good sign
  • The parent manages the commonalities and the
    child manages the differences.
  • Might want to look at typical client use to see
    if clients think child is-a parent
  • Do clients use parents methods? use parent as
    static type?
  • Did the subclass inherit as a cheap pickup of
    functionality?
  • Fowler/Beck claim this isnt as bad a smell as
    the others
  • Might be better to use delegation
  • (Replace inheritance with delegation)

39
Bad smells in code
  • Refused bequest
  • Another perspective
  • Parent has features that are used by only some of
    its children.
  • Typical solution is to create some more
    intermediate abstract classes in the hierarchy.
  • Move the peculiar methods down a level.
  • (Push down field/method)

40
Bad smells in code
  • Comments
  • XP philosophy discourages comments, in general
  • Instead, make methods short and use long
    identifiers
  • Fowler is not so critical, tho.
  • In the context of refactoring, Fowler claims that
    long comments are often a sign of opaque,
    complicated, inscrutable code.
  • They arent against comments so much as in favour
    of self-evident coding practices.
  • Rather than explaining opaque code, restructure
    it!
  • (Extract method/class, many others applicable
    )
  • Comments are best used to document rationale
  • i.e., explain why you picked one approach over
    another.

41
Unit Testing in TDD
  • Motto Clean code that works. (Ron Jeffries)
  • Unit testing has broader goals that just
    insuring quality
  • Improve developers lives (coping, confidence)
  • Support design flexibility and change
  • Allow iterative development with working code
    early

42
Unit Testing Benefits
  • Developers can work in a predictable way of
    developing code
  • Programmers write their own unit tests
  • Get rapid response for testing small changes
  • Build many highly-cohesive loosely-coupled
    modules to make unit testing easier

43
Red/Green/Refactor
  • The TDD mantra of how to code
  • Red write a little test that doesnt work,
    perhaps even doesnt compile
  • Green Write code to make the test work quickly
    (perhaps not the best code)
  • Refactor Eliminate duplication and other
    problems that you did to just make the test work

44
Summary
  • Fowler et al.s Refactoring is a well-written
    book that summarizes a lot of best practices of
    OOD/OOP with nice examples.
  • Many books on OOD heuristics are vague and lack
    concrete advice.
  • Most of the advice in this book is aimed at
    low-level OO programming.
  • i.e., loops, variables, method calls, and class
    definitions.
  • Next obvious step up in abstraction/scale is to
    OODPs.
  • i.e., collaborating classes
  • This is an excellent book for the
    intermediate-level OO programmer.
  • Experienced OO programmers will have discovered a
    lot of the techniques already on their own.

45
Tool Support for Refactoring
  • Refactorings standard re-structurings to solve
    common problems
  • Can do them by hand
  • Put might be tricky
  • IDEs and separate tools support this
  • IntelliJ, ReSharper, JRefactory, C Refactory
  • Eclipse, JBuilder, next release of Visual Studio

46
Why tools? Ponder these
  • In Java, you decide to change a classs name.
    What needs to changed?
  • In Java, you want to change the name of a method.
    What needs to be changed?

47
Java Refactorings in Eclipse
  • See help info in Eclipse. And Gallardo article.
  • Renaming resources
  • classes, methods, fields
  • moving to another package
  • inner and anonymous classes
  • Class hierarchy modifications
  • includes make an interface from a class
  • Code level mods
  • make a code segment a function

48
Refactoring Processes
  • Strategic
  • general design
  • Tactical
  • detailed design
  • Transformations
  • mechanical steps

49
Strategic and Tactical Refactoring Examples
  • Strategic
  • Convert Procedural Design to Objects
  • Separate Domain From Presentation
  • Tactical
  • Tease Apart Inheritance
  • Extract Hierarchy

50
Strategic Refactoring Convert Procedural Design
to Objects
  • Functional/Procedural Design
  • data is passed from one function to the next,
    which operates on it and returns data
  • Approach
  • convert data entities into objects
  • decompose behavior from functions
  • move behavior to objects

51
Introduce Architecture
  • Identify general design metaphor (e.g. 3
    tier/layer)
  • identify possible layers from procedural model
  • Create interfaces
  • Distribute objects/classes
  • Edit and revise as necessary

52
Strategic Refactoring Separate Domain From
Presentation
  • Need to separate domain logic from presentation
    logic (e.g. going from 2 to 3 tier system)
  • Starting point
  • create domain objects for each GUI window
  • move or duplicate domain oriented data in/to new
    domain objects
  • move domain oriented logic to new domain objects

53
Domain Presentation Separation and System
Architecture
  • GUI will make calls to logic moved to domain
    object
  • Domain interface needs to be determined
  • calls may be made to facade for whole domain or
    subset of domain objects that support domain
    interfaces

54
Tactical Refactoring Tease Apart Inheritance
  • 2 or more inheritance hierarchies involved
  • merged hierarchies have 2 different purposes
  • approach
  • identify major hierarchy
  • extract subordinate hierarchy
  • create instance variable in common superclass
  • point to subordinate hierarchy

55
Tactical Refactoring Extract Hierarchy
  • Class grows in size and complexity as new
    responsibilities are added
  • Starts to look like a representative of the Swiss
    Army Knife Anti-Pattern
  • Cohesion is bad
  • Usage create an instance and call one of its
    methods

56
Extract Hierarchy Steps
  • Create subclasses of the super class for each of
    the different kinds of behavior
  • Create a factory method for the superclass that
    returns an instance of the appropriate subclass
  • Change calls to the superclass constructor to the
    superclass factory method

57
Extract Hierarchy and Factory Methods
  • Standard use of factory methods
  • factory method in a superclass is defined to
    return an object defined by an interface
  • when superclass is subtyped, the factory method
    is overriden to return a concrete class instance,
    which implements the interface
  • Emphasis in this kind of use is on subclass
    selection/definition at code writing time or
    system start up (via properties object)

58
Factory Methods and Extract Hierarchy Re-factoring
  • Emphasis is on selection of subclass behavior at
    run time
  • Techniques
  • subtype argument code and switch statement used
    to create appropriate subclass instance
  • subtype argument is name of class. Use
  • (type) Class.forName(name).newInstance()
  • to return instance of selected subtype

59
Refactoring Steps - Categories
  • Composing Methods
  • Moving Features Between Objects
  • Organizing Data
  • Simplifying Conditional Expressions
  • Making Method Calls Simpler
  • Dealing with Generalization

60
Composing Methods - Examples
  • Method creation
  • extract code and make a method from it
  • issues local variables, parameter references
  • if there are many local variables, turn the
    method into an object whose class has a compute
    method
  • class variables for each local variables
  • now it will be easier to extract a new method
  • Inlining code
  • taking a small piece of code and removing its
    method envelope
  • inlining an expression in place of the variable
    whose value was derived from it

61
Moving Features Between Objects - Examples
  • Move Method
  • Move Attribute
  • Extract Class
  • InLine Class
  • Hide Class Delegate
  • Remove Middleman
  • Introduce Foreign Method
  • Introduce Local Extension

62
Refactoring Tools
  • Simple edit-like tools
  • e.g. changing method names
  • find all possible references
  • change names
  • E.g. IntelliJ IDE
Write a Comment
User Comments (0)
About PowerShow.com