When debugging, testing, and troubleshooting, code is often rewritten to change how it works, a process that is also known as refactoring. The benefit of having test cases available means that changes to the code can be checked to see whether functionality has been compromised, such as interactions between functions or methods or if end-user complications have developed.
In large testing projects, continuous integration test suites are utilized to check code as the developers upload it to the server. These tests not only check each developer's code, but also check it against other code that was submitted to ensure that the entire project continues to function properly.
Refactoring can take many different forms, such as the following:
- Adding comments to help clarify key bits of code or why a certain piece of logic was used.
- Improving readability by separating code into logical blocks.
- Abstracting code into more general types. For example, if we had started the fuel scenario by writing the code for a globe valve, we could refactor it by abstracting the valve parameters to make a generic valve class.
- Encapsulation fields, which force code to use getter/setter methods rather than direct access.
- Replacing conditional behavior with class polymorphism. In other words, instead of testing for different conditions that dictate different logic paths, we create a class with a method that can account for the different conditions.
- Separating functions/methods that perform several jobs into multiple ones, where each one does only one job.
- Moving methods to more appropriate classes or even modules.
- Renaming objects to make them readily understandable.
- Converting a class into a superclass (pull up) and converting other classes into subclasses (push down).
When using an IDE, a number of refactoring tools may be available with just a click of a mouse. For example, the PyCharm IDE provides the following refactoring tools:
- Rename: This renames anything, from a variable or function to modules and projects.
- Change signature: This can be used to rename functions, add/remove parameters, assign default values, or reorder parameters.
- Move: This moves an object to another location within the code directory.
- Copy: This copies an object to another location within the code directory.
- Safe delete: Before deletion, PyCharm will check for locations where the file is being called. If found, the user will be allowed to make changes to the code prior to deletion.
- Extract: This addresses expressions that are hard to understand or are duplicated in the code by placing the expression result into a separate variable that is less complex and, therefore, easier to understand.
- Parameter: This adds a new parameter to a function declaration and automatically updates function calls.
- Superclass: This creates a superclass from the existing class or renames the existing class to become an implementation for a new superclass.
- Constant: This allows the conversion of multiple occurrences of an expression into one constant.
- Field: This allows the declaration of a new field and its initialization with a selected expression.
- Method: This takes a code fragment that can be grouped together and creates a separate method with it.
- Variable: This allows conversion of a duplicated expression, or one that is hard to understand, into a separate variable that is less complex.
- Inline: The following items are the opposite implementation of their respective "extract" tools:
- Variable
- Constant
- Field
- Parameter
- Method
- Superclass
- Invert Boolean: This changes any Boolean value to its opposite. This also changes its respective usage.
- Pull members up: This moves class members to a superclass.
- Push members down: This moves class members to a subclass.
- Convert in Python package: This automatically converts a directory or subdirectory into a Python package with the required __init__.py file.
- Convert in Python module: This consolidate all modules from a package into a single module.