| Lesson 2 || Refactoring |
| Objective ||Define the goal and process of refactoring |
Refactoring, in the realm of software development, is the systematic process of restructuring an existing body of code, altering its internal structure without changing its external behavior or functionality. The principal objective of refactoring is to improve the design, readability, and maintainability of the codebase, thereby making it more efficient, clean, and understandable without introducing new functionality.
Goal of Refactoring:
The overarching goal of refactoring is to enhance the 'non-functional' attributes of a software system. It aims to:
- Improve Code Readability: Refactoring enhances the readability and comprehension of the software, making it easier for any developer to understand, update, and maintain the codebase.
- Reduce Complexity: It aims to simplify complex code structures, breaking down large code chunks into smaller, more manageable pieces. This makes the code more understandable and less error-prone.
- Enhance Maintainability and Extensibility: By improving the structure and design of the software, refactoring aids in easier maintenance, allows for more effective debugging, and better accommodates future changes or extensions.
- Improve Performance: Though not its primary aim, refactoring can occasionally lead to better performance by optimizing the way the code is executed.
Process of Refactoring:
Refactoring is not a haphazard process, but a well-planned and disciplined activity. It typically involves the following steps:
- Code Analysis: The first step involves identifying areas of the code that require refactoring. This could be sections of code that are overly complex, hard to understand, or frequently result in bugs.
- Identify Refactoring Techniques: Various refactoring techniques exist, such as 'Extract Method', 'Inline Method', 'Rename Method', 'Move Method', 'Replace Conditional with Polymorphism', etc. The appropriate technique is selected based on the identified code smells.
- Unit Tests: Before refactoring, it's crucial to have a set of unit tests covering the areas of the code to be refactored. These tests serve as a safety net, ensuring that the functionality remains consistent after refactoring.
- Incremental Refactoring: Refactoring is performed incrementally, a small change is made, and the codebase is retested to ensure that the functionality has not been inadvertently altered. This process is repeated until the refactoring is complete.
- Code Review and Verification: The refactored code is reviewed and verified against the unit tests to ensure that no functionality has been lost or modified unintentionally. If the tests pass successfully, the refactored code is considered valid.
Refactoring should be a regular practice during the software development process, and not considered as a one-time activity. Continuous refactoring aids in keeping the code clean and manageable, thereby reducing technical debt and facilitating easier software evolution.
Fundamental Approach to Software Development
Almost without thinking, we slip into standard ways of thinking. Giving people a new tool does not guarantee that they will change the way they think. Statistics describe an industry that more often than not tries to apply new technologies without making a corresponding change in the fundamental approach to software development. We are kind of like carpenters, who have for years used hammers to pound nails. Someone hands us a nail gun while singing the praises of this powerful new tool.
We listen to the song and dance and look at the tool. We think, I know how to use this. I've been hammering nails for year. We then proceed to use the nail gun like a hammer, pounding away with the flat side of the nail gun. Of course it doesn't work.
The tool must be defective.
Four Fundamental Principles of Software Development:
- The best predictor of success is how dedicated the team is to the software methodology. A recommended methodology imposed from above will consistently fail if the underlying team does not believe in it, and that same team may be successful when they create their own methodology.
- The second best predictor of any methodology is how well it eliminates waste. In this case I mean the topic of waste from the "Lean School" of Dr. Deming. The central purpose of all methodologies is the elimination of waste and having an insufficient process is waste.
Having too much process is waste, while using an incorrect process is waste.
- Any methodology that includes continous improvement can eventually be a great methodology.
If implemented correctly, your development methodology is constantly evolving and improving.
Of course continuous improvement is challenging, requiring 1) good goals, 2) metrics to measure progress toward those goals, 3) the ability to modify the process as needed with little friction, and 4) the drive to do so (see rule number one).
- The software development methodology must be designed, built, managed, evolved, and evaluated by the software team and not by management. This very bottom-up approach goes against everything that many executives learned in MBA school, unless of course they happened to study lean manufacturing. Executive management has a role to play such as 1) assembling the right staff and other resources, 2) empowering the team, 3) communicating goals and objectives, 4) providing feedback, guidance, and mentoring.
Generally the role of top management in the lean world is to act when asked, not to command.
What is Refactoring?
Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure. It is a disciplined way to clean up code that minimizes the chances of introducing bugs. In essence when you refactor you are improving the design of the code after it has been written. "Improving the design after it has been written." That's an odd turn of phrase. In our current understanding of software development we believe that we design and then we code.
A good design comes first, and the coding comes second. Over time the code will be modified, and the integrity of the system, its structure according to that design, gradually fades. The code slowly sinks from engineering to hacking. Refactoring is the opposite of this practice. With refactoring you can take a bad design, chaos even, and rework it into well-designed code. Each step is simple, even simplistic.
You move a field from one class to another, pull some code out of a method to make into its own method, and push some code up or down a hierarchy. Yet the cumulative effect of these small changes can radically improve the design. It is the exact reverse of the normal notion of software decay.
With refactoring you find the balance of work changes. You find that design, rather than occurring all up front, occurs continuously during development. You learn from building the system how to improve the design. The resulting interaction leads to a program with a design that stays good as development continues.
Refactoring and patterns
The term refactoring describes a process for (1) evaluating a model or process in terms of the problems that it causes, and (2) applying common solutions to mitigate those problems. The solutions are revisions to the models or processes themselves.
Most of the problems that we encounter in software development have been experienced throughout the industry for many years.
Consequently, the refactored solutions are typically available within the development community as a
type of pattern
that is, a recurring solution that includes common elements even though the specific implementation may vary.
Refactoring really just means rethinking the problem and the solution. The need for refactoring comes from the observed problems created by the current solutions.
However, refactoring has to have a clearly defined goal to arrive at a better solution than the original. The goals that we have used in this course to direct us toward the best solutions include:
|Consistent and meaningful communication|
In the following lessons, I will reemphasize the purpose and value of each goal as it applies to the iterative process of improving your model.
Domain Driven Design