Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic...

56
Refactoring (Some material adapted from Martin Fowlers book)

Transcript of Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic...

Page 1: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Refactoring (Some material adapted from Martin Fowler’s book)

Page 2: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Lehman & Belady: Laws of Software Evolution

(1974) n  Continuing Change - Systems must be continually

adapted else they become progressively less satisfactory.

n  Increasing Complexity - As a system evolves its complexity increases unless work is done to maintain or reduce it.

Page 3: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Library system – Existing design

Source: MITRE

What areas do you see as potential problem areas? Why did you identify each of those areas?

Page 4: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Library system – Changing the design

Page 5: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Library system – Changing the design

Page 6: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Library system – Changing the design

Page 7: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Library system – Changing the design

Page 8: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

It is usually hard to counter, “If it ain’t broke, don’t fix it.” n  Generally improves product quality

n  Pay today to ease work tomorrow

n  May actually accelerate today’s work

Page 9: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

From this…

3

Refactoring is taking software which through natural processes  has  lost  its  original  clean  structure…

Source: Mike Lutz, RIT

Page 10: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

… To this

4

…and  restoring  a  clean  structure.

Source: Mike Lutz, RIT

Page 11: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Design Entropy Vs Time

7

The design entropy of a software system tends to increase over time.

Time

Des

ign

Entro

py

Design

Design

Design

If you no longer can see the design, how can you stay consistent to it?

Time

Page 12: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

What causes Design Smells?

n  Violation of design principles q  java.util.Calender

n  Violates Single responsibility principle (overloaded with date functionality and time functionality)

q  java.util.Stackn  extends java.util.Vectorn  Do Stack and Vector share a IS-A

relationship?n  Violates principle of hierarchy (Broken

Hierarchy – substitutability is broken)

Page 13: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

What causes Design Smells?

n  Inappropriate use of patterns n  Language limitations n  Procedural thinking in OO n  Viscosity

q  Software viscosity q  Environment viscosity

n  Non-adherence to best practices and processes

Page 14: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Design Smell classification

Abstraction n  Missing Abstraction n  Imperative Abstraction n  Incomplete Abstraction n  Multifaceted

Abstraction n  Unnecessary

Abstraction n  Unutilized Abstraction n  Duplicate Abstraction

Modularization •  Broken Modularization •  Insufficient

Modularization •  Cyclically-dependent

Modularization •  Hub-like Modularization

Page 15: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Design Smell classification

Encapsulation n  Deficient Encapsulation n  Leaky Encapsulation n  Missing Encapsulation n  Unexploited

Encapsulation

Modularization •  Missing Hierarchy •  Unnecessary Hierarchy •  Unfactored Hierarchy •  Wide Hierarchy •  Speculative Hierarchy •  Deep Hierarchy •  Rebellious Hierarchy •  Broken Hierarchy •  Multipath Hierarchy •  Cyclic Hierarchy

Page 16: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Code Smells Within Classes n  Comments

q  Are the comments necessary? q  Do they explain "why" and not "what"? q  Can you refactor the code so the comments aren't required? q  Remember, you're writing comments for people, not machines.

n  Long Method q  Shorter method is easier to read, easier to understand, and easier to

troubleshoot. q  Refactor long methods into smaller methods if you can

n  Long Parameter List q  The more parameters a method has, the more complex it is. q  Limit the number of parameters you need in a given method, or use an object

to combine the parameters. n  Duplicated code

q  Stamp out duplication whenever possible. q  Don't Repeat Yourself!

Page 17: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Code Smells Within Classes n  Conditional Complexity

q  large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over time.

q  Consider alternative object-oriented approaches such as decorator, strategy, or state.

n  Combinitorial Explosion q  Lots of code that does almost the same thing.. but with tiny variations in data or

behavior. q  This can be difficult to refactor-- perhaps using generics or an interpreter?

n  Large Class q  Large classes, like long methods, are difficult to read, understand, and

troubleshoot. q  Large class can be restructured or broken into smaller

Page 18: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Code Smells Within Classes

n  Uncommunicative Name q  Does the name of the method succinctly describe what that method

does? Could you read the method's name to another developer and have them explain to you what it does?

n  Inconsistent Names q  set of standard terminology and stick to it throughout your

methods. n  Dead Code

q  Ruthlessly delete code that isn't being used n  Speculative Generality

q  Write code to solve today's problems, and worry about tomorrow's problems when they actually materialize.

q  Everyone loses in the "what if.." school of design.

Page 19: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Code Smells Between Classes n  Alternative Classes with Different Interfaces

q  If two classes are similar on the inside, but different on the outside, perhaps they can be modified to share a common interface.

n  Primitive Obsession q  If data type is sufficiently complex, write a class to represent it. 

n  Data Class q  Avoid classes that passively store data. q  Classes should contain data and methods to operate on that data,

too.

n  Data Clumps q  If you always see the same data hanging around together, maybe it

belongs together. q  Consider rolling the related data up into a larger class.

Page 20: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Code Smells Between Classes n  Refused Bequest

q  Inherit from a class but never use any of the inherited functionality n  Inappropriate Intimacy

q  Classes that spend too much time together, or classes that interface in inappropriate ways.

q  Classes should know as little as possible about each other n  Indecent Exposure

q  Classes that unnecessarily expose their internals. q  Aggressively refactor classes to minimize their public surface. q  You should have a compelling reason for every item you make public. If

you don't, hide it. n  Feature Envy

q  Methods that make extensive use of another class may belong in another class.

q  Move the method to the class it is so envious

Page 21: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Code Smells between Classes n  Lazy Class

q  Classes should pull their weight. q  If a class isn't doing enough to pay for itself, it should be collapsed or

combined into another class. n  Message Chains

q  Long sequences of method calls or temporary variables to get routine data. q  Intermediaries are dependencies in disguise. 

n  Middle Man q  If a class is delegating all its work., then cut out the middleman. q  Beware classes that are merely wrappers over other classes or existing

functionality in the framework. n  Divergent Change

q  If changes to a class that touch completely different parts of the class, it may contain too much unrelated functionality.

q  Isolate the parts that changed in another class.

Page 22: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Code Smells between Classes n  Shotgun Surgery

q  If a change in one class requires cascading changes in several related classes

n  Parallel Inheritance Hierarchies q  Every time you make a subclass of one class, you must

also make a subclass of another. q  Consider folding the hierarchy into a single class.

n  Solution Sprawl q  If it takes five classes to do anything useful, you might

have solution sprawl. q  Consider simplifying and consolidating your design.

Page 23: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Refactoring n  As a software system grows, the overall design often suffers n  In the short term, working in the existing design is cheaper

than doing a redesign n  In the long term, the redesign decreases total costs

q  Extensions q  Maintenance q  Understanding

n  Refactoring is a set of techniques that reduce the short-term pain of redesigning q  Not adding functionality q  Changing structure to make it easier to understand and extend

Page 24: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

The Scope of Refactoring

n  Small steps: q  Rename a method q  Move a field from one class to another q  Merge two similar methods in different classes into one

common method in a base class

n  Each individual step is small, and easily verified/tested

n  The composite effect can be a complete transformation of a system

Page 25: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Principles

n  Don’t refactor and extend a system at the same time q  Make a clear separation between the two activities

n  Have good tests in place before you begin refactoring q  Run the tests often q  Catch defects immediately

n  Take small steps q  Many localized changes result in a larger-scale change q  Test after each small step

Page 26: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

When Should You Refactor?

n  You’re extending a system, and realize it could be done better by changing the original structure q  Stop and refactor first

n  The code is hard to understand q  Refactor to gain understanding, and leave the code better

than it was

Page 27: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Refactoring and OOD

n  The refactoring literature is written from a coding perspective

n  Many of the operations still apply at design time n  It helps if you have an appropriate level of detail in

the design q  Too much, and you may as well code q  Too little, and you can’t tell what’s happening

Page 28: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

AntiPatterns

Material adapted from “AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis” by William J Brown et. al.

Page 29: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

AntiPatterns

n  A pattern of practice that is commonly found in use

n  A pattern which when practiced usually results in negative consequences

n  Patterns defined in several categories of software development q  Design q  Architecture q  Project Management

Page 30: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Purpose for AntiPatterns

n  Identify problems n  Develop and implement strategies to fix

n  Work incrementally n  Many alternatives to consider n  Beware of the cure being worse than the disease

Page 31: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Pattern Vs AntiPattern

n  Patterns q  Usually bottom up q  Begin with recurring solution q  Then the forces and context q  Usually leads to one solution

n  AntiPatterns q  Top down q  Begin with commonly recurring practice q  Obvious negative consequences q  Symptoms are past and present; consequences go into the future

Page 32: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Software Design AntiPatterns

n  AntiPatterns q  The Blob q  Lava Flow q  Functional Decomposition q  Poltergeists q  Golden Hammer q  Spaghetti Code q  Cut-and-Paste Programming

n  Mini-AntiPatterns q  Continuous Obsolescence q  Ambiguous Viewpoint q  Boat Anchor q  Dead End q  Input Kludge q  Walking through a Minefield q  Mushroom Management

Page 33: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

The Blob

n  AKA q  Winnebago, The God Class, Kitchen Sink Class

n  Causes q  Sloth, haste

n  Unbalanced Forces: q  Management of Functionality, Performance, Complexity

n  Anecdotal Evidence: q  “This is the class that is really the heart of our architecture.”

Page 34: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

The Blob (2)

n  Like the blob in the movie can consume entire object-oriented architectures

n  Symptoms q  Single controller class, multiple simple data classes q  No object-oriented design, i.e. all in main q  Start with a legacy design

n  Problems q  Too complex to test or reuse q  Expensive to load into system

Page 35: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Causes

n  Lack of OO architecture n  Lack of any architecture n  Lack of architecture enforcement n  Limited refactoring intervention n  Iterative development

q  Proof-of-concept to prototype to production q  Allocation of responsibilities not repartitioned

Page 36: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Solution

n  Identify or categorize related attributes and operations

n  Migrate functionality to data classes n  Remove far couplings and migrate to data classes

Page 37: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Lava Flow

n  AKA q  Dead Code

n  Causes q  Avarice, Greed, Sloth

n  Unbalanced Forces q  Management of Functionality, Performance, Complexity

Page 38: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Symptoms and Consequences

n  Unjustifiable variables and code fragments n  Undocumented complex, important-looking

functions, classes n  Large commented-out code with no explanations n  Lot’s of “to be replaced” code n  Obsolete interfaces in header files n  Proliferates as code is reused

Page 39: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Causes

n  Research code moved into production n  Uncontrolled distribution of unfinished code n  No configuration management in place n  Repetitive development cycle

Page 40: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Solution

n  Don’t get to that point n  Have stable, well-defined interfaces n  Slowly remove dead code; gain a full understanding

of any bugs introduced n  Strong architecture moving forward

Page 41: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Functional Decompostion

n  AKA q  No OO

n  Root Causes q  Avarice, Greed, Sloth

n  Unbalanced Forces q  Management of Complexity, Change

n  Anecdotal Evidence q  “This is our ‘main’ routine, here in the class called

Listener.”

Page 42: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Symptoms and Consequences

n  Non-OO programmers make each subroutine a class

n  Classes with functional names q  Calculate_Interest q  Display_Table

n  Classes with single method n  No leveraging of OO principles n  No hope of reuse

Page 43: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Causes

n  Lack of OO understanding n  Lack of architecture enforcement n  Specified disaster

Page 44: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Solution

n  Perform analysis n  Develop design model that incorporates as much of

the system as possible n  For classes outside model:

q  Single method: find home in existing class q  Combine classes

Page 45: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Poltergeists

n  AKA q  Gypsy, Proliferation of Classes

n  Root Causes q  Sloth, Ignorance

n  Unbalanced Forces q  Management of Functionality, Complexity

n  Anecdotal Evidence q  “I’m not exactly sure what this class does, but it sure is

important.”

Page 46: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Symptoms and Consequences

n  Transient associations that go “bump-in-the-night” n  Stateless classes n  Short-lived classes that begin operations n  Classes with control-like names or suffixed with

manager or controller. Only invoke methods in other classes.

Page 47: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Causes

n  Lack of OO experience n  Maybe OO is incorrect tool for the job. “There is

no right way to do the wrong thing.”

Page 48: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Solution

n  Remove Poltergeist altogether n  Move controlling actions to related classes

Page 49: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Cut-and-Paste Programming

n  AKA q  Clipboard Coding

n  Root Causes q  Sloth

n  Unbalanced Forces q  Management of Resources, Technology Transfer

n  Anecdotal Evidence q  “Hey, I thought you fixed that bug already, so why is it doing this

again?” “Man, you guys work fast. Over 400,000 lines of code in three weeks is outstanding progress!”

Page 50: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Symptoms and Consequences

n  Same software bug reoccurs n  Code can be reused with a minimum of effort n  Causes excessive maintenance costs n  Multiple unique bug fixes develop n  Inflates LOC without reducing maintenance costs

Page 51: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Causes

n  Requires effort to create reusable code; must reward for long-term investment

n  Context or intent of module not preserved n  Development speed overshadows all other factors n  “Not-invented-here” reduces reuse n  People unfamiliar with new technology or tools just

modify a working example

Page 52: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Solution

n  Code mining to find duplicate sections of code n  Refactoring to develop standard version n  Configuration management to assist in prevention

of future occurrence

Page 53: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Golden Hammer

n  AKA q  Old Yeller

n  Root Causes q  Ignorance, Pride, Narrow-Mindedness

n  Unbalanced Forces q  Management of Technology Transfer

n  Anecdotal Evidence q  “Our database is our architecture” “Maybe we

shouldn’t have used Excel macros for this job after all.”

Page 54: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Symptoms and Consequences

n  Identical tools for conceptually diverse problems. “When your only tool is a hammer everything looks like a nail.”

n  Solutions have inferior performance, scalability and other ‘ilities’ compared to other solutions in the industry.

n  Architecture is described by the tool set. n  Requirements tailored to what tool set does well.

Page 55: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Causes

n  Development team is highly proficient with one toolset.

n  Several successes with tool set. n  Large investment in tool set. n  Development team is out of touch with industry.

Page 56: Refactoring€¦ · Code Smells Within Classes ! Conditional Complexity " large conditional logic blocks, particularly blocks that tend to grow larger or change significantly over

Solution

n  Organization must commit to exploration of new technologies

n  Commitment to professional development of staff n  Defined software boundaries to ease replacement of

subsystems n  Staff hired with different backgrounds and from

different areas n  Use open systems and architectures