Download Refactoring: Improving Code Design through Semantics-Preserving Transformations and more Slides Computer Science in PDF only on Docsity!
Refactoring
Refactoring
- Refactoring is:
- restructuring (rearranging) code...
- ...in a series of small, semantics-preserving transformations (i.e. the code keeps working)...
- ...in order to make the code easier to maintain and modify
- Refactoring is not just any old restructuring
- You need to keep the code working
- You need small steps that preserve semantics
- You need to have unit tests to prove the code works
- There are numerous well-known refactoring techniques
- You should be at least somewhat familiar with these before inventing your own
Design vs. coding
- “Design” is the process of determining, in
detail, what the finished product will be and
how it will be put together
- “Coding” is following the plan
- In traditional engineering (building bridges),
design is perhaps 15% of the total effort
- In software engineering, design is 85-90% of
the total effort
- By comparison, coding is cheap
The refactoring environment
- Traditional software engineering is modeled after traditional engineering practices (= design first, then code)
- Assumptions:
- The desired end product can be determined in advance
- Workers of a given type (plumbers, electricians, etc.) are interchangeable
- “Agile” software engineering is based on different assumptions:
- Requirements (and therefore design) change as users become acquainted with the software
- Programmers are professionals with varying skills and knowledge
- Programmers are in the best position for making design decisions
- Refactoring is fundamental to agile programming
- Refactoring is sometimes necessary in a traditional process, when the design is found to be flawed
Back to refactoring
- When should you refactor?
- Any time you find that you can improve the design of existing code
- You detect a “bad smell” (an indication that something is wrong) in the code
- When can you refactor?
- You should be in a supportive environment (agile programming team, or doing your own work)
- You should have an adequate set of unit tests
Example 1: switch statements
- switch statements are very rare in properly
designed object-oriented code
- Therefore, a switch statement is a simple and easily detected “bad smell”
- Of course, not all uses of switch are bad
- A switch statement should not be used to distinguish between various kinds of object
- There are several well-defined refactorings for
this case
- The simplest is the creation of subclasses
Example 1, improved
- class Animal { String getSkin() { return "integument"; } } class Mammal extends Animal { String getSkin() { return "hair"; } } class Bird extends Animal { String getSkin() { return "feathers"; } } class Reptile extends Animal { String getSkin() { return "scales"; } }
How is this an improvement?
- Adding a new animal type, such as Amphibian, does
not require revising and recompiling existing code
- Mammals, birds, and reptiles are likely to differ in
other ways, and we’ve already separated them out (so we won’t need more switch statements)
- We’ve gotten rid of the flags we needed to tell one
kind of animal from another
- Basically, we’re now using Objects the way they were
meant to be used
Bad Smell Examples
- We should refactor any time we detect a “bad smell” in the code
- Examples of bad smells include:
- Duplicate Code
- Long Methods
- Large Classes
- Long Parameter Lists
- Multi location code changes
- Feature Envy
- Data Clumps
- Primitive Obsession
The End