Introduction
What is refactoring? Why would a developer need to do a refactor? How do I refactor? I'll strive to answer these questions.
What is Refactoring
Refactoring is developers rewriting code to improve its structure. Developers make small incremental changes and verify functionality has not changed. Unit tests are the single most important enabler of refactoring. They provide automatic verification. They allow the developer to refactor and improve the underlying code with impunity.
Motivation
Developers refactor in order to make code testable, easier to understand, and easier to update. This code restructuring does NOT change its external behavior.
Refactoring Step by Step
PreRefactor Class
The following is a wxPython dialog in pre-refactoring mode. A cursory look at the code outline shows a curious mix of code functionality. It is violating the basic Single Responsibility Principle. Look at the code highlighted in the following figure:
Single Responsibility Principle
Classes should honor the single responsibility principle. This principle says that a class should do a single thing and only a single thing and do it well.
More formally it states, that every class in a computer program should have responsibility over a single part of that program's functionality and it should encapsulate it.
I assert that being a dialog this class should only do or handle user interface functionality. Specifically, functionality required by a wxPython dialog. All other things should be deferred to another “chunk of code” or better yet another class.
I assert that the following methods are basic functionality that manipulate which tip text to display and do not directly belong in a user interface class.
• ._getCurrentTipText()
• ._incrementTipNumber()
• ._normalizeTip()
Post Refactor Class
Extract Functionality
Thus, the first step is to extract the tip manipulating functionality into a separate class. This makes it necessary to create a class named TipHandler
.
In literate programming this name is self-explanatory. Literate programming is a way to write computer code that is understandable by a human. In the past, programmers wrote programs and code that was optimized for a computer. With today’s advances in computer speed and optimization it is perfectly possible with no penalty to write a verbose program that reads like prose.
Notice that in the following figure the TipHandler
has the following non-UI functionality:
• Knows the current tip number
• Knows the current tip text
• Can properly increment the current tip number
Pure UI Class
Once we extract the above functionality from the UI class we wind up with a pure UI class as illustrated below.
At first glance the following class methods do not appear to be UI only functionality.
• ._getTipText()
• ._normalizeTip()
UI Constructor
Let us first look at the class constructor in the following image.
The UI class has effectively encapsulated the TipHandler
functionality, so that it can delegate to it. This allows the UI class to be oblivious to the TipHandler
inner workings.
TipHandler
Unit Tests
The following figure depicts the unit tests necessary to functionally test the newly extracted class. These tests verify:
• How the tip count is computed
• Retrieving the correct current tip number
• Retrieving the correct current tip text
• How to properly increment the tip number and account for wrap-around
Conclusion
Thus, what we have accomplished is:
• A simple refactor that turns one class into two
• Demonstrated the single responsibility principle
• Demonstrated literate programming
• Provided an example of unit tests for the extracted functionality
Top comments (0)