Introduction
Martin Fowler's "Refactoring: improving the design of existing codes" has been in existence for more than more than 10 years since 2003, and refactoring has been an obsolete technology, according to the rapidly changing speed of the computer field. But the old does not mean unimportant, just as the evolutionary design is more and more widely used, the reconstruction technology has been considered as a necessary basic skill in modern software development! So today in any software development team, you will hear or see and refactor related code activities from time to times. However, for such a technology that is supposed to be the same as "air and water in software development," in reality, it is seen in the false understanding and application of refactoring. The first is not know the correct use of refactoring, always wait until the code has been corrupted to Humpty to remember the refactoring, and then face a bunch of code bad taste no choice standard, do not start; the next step in the process of modifying the code does not understand the security, small steps of refactoring, always bold to put the code in a dangerous situation, It's hard to take it back, and finally either build, fail to recover after the test fails, or the end result just modifies the code from one bad flavor to another!
Part of the reason for this is that there is no correct understanding of refactoring, no knowledge of the starting and target of refactoring, no standard for measuring and comparing the objects and goals of reconstruction, and secondly, because of the lack of formal reconstruction techniques and procedures, the process of reconstruction is often just followed by the feeling; Without first straightening out your own development, build and test environment, resulting in a high cost of refactoring! For the development, build and test of the environment, the C/C++
field is particularly serious, in addition to Java
the field as well as the use of automated refactoring tools, many developers even a good IDE can not find, not to mention the general awareness of the slow construction, the lack of automated testing and so on!
On the basis of the author's study and Practice reconstruction, this article is to comb the reconstruction technology and lead us to re-understand the goal and the starting point of reconstruction, the principle behind the reconstruction technique and the practice way. Finally, we introduce the C/C++
experiences, techniques and tools of implementing refactoring efficiently in practice.
What is refactoring? Definition of refactoring
Martin Fowler the two definitions of refactoring in the book "Refactoring: Improving the design of existing code."
The first one is the noun form:
Refactoring: An adjustment to the internal structure of software, in order to improve its understanding and reduce its modification cost without changing the observable behavior of software.
The second one is the verb form:
Refactor: It uses a series of refactoring techniques to adjust its structure without changing the observable behavior of the software.
The goal of refactoring
What is the goal of refactoring? The goal of refactoring is never to change the code from someone else's taste to your own taste, or to change the code from one bad taste to another!
Matin Fowler uses the above two definitions to indicate the objectives of the refactoring:
Does not change software observable behavior
Improved software understanding
Reduce software modification costs
And for the above goal, we go into a bit of analysis, found that in fact there is a more classical definition. That's Kent Beck's simple design. Four principles:
Pass all test: through all tests;
No duplication: no repetition (DRY)
Reveals Intent: program expression Intent, easy to understand
Has no superfluous parts: no redundancy, or Yagni principle
The importance of the above four is reduced in turn.
So far, the simple design four principle is the best definition of "what is good software design"!
Simple design four principles the first defined software should pass all tests, that is, to meet all functional requirements correctly. The most basic of the refactoring goal is to "not change the observable behavior of the software", that is to say:
1) The reconstructed software cannot destroy all the original tests!
The other two objectives of the refactoring defined by Matin correspond to the 2nd and 3rd of the Simple Design principles:
2) refactoring should eliminate duplication: Reduce the cost of software modification;
3) refactoring should allow the program to display the expression intent: to improve the understanding of software;
Finally, we add the final piece of the simple design four principle to the goal of refactoring:
4) refactoring should eliminate redundancy: reduce the complexity of software unnecessarily.
So later, when we discuss the goal of refactoring, or judge whether there is any benefit to refactoring, use simple design four principles to measure it.
where to start?
When we agree on the goal of refactoring, we go back to the beginning: what kind of software needs refactoring? And when to refactor?
For the first question, since the goal of our refactoring is to make the software meet the simple design four principle, any code that violates the simple design four principle should be the goal of our refactoring. 1) The code is prone to bugs, causing the test to fail! or 2) The code exists knowledge duplication makes it difficult to modify! or 3) code write obscure very difficult to understand! or 4) The code is over-designed, and redundancy leads to complexity!
There may be a lot of code problems in the real world waiting for us to solve, and time, cost, manpower is limited, so we need to start refactoring from the most valuable, least controversial part. Since the importance of the simple design four principle is reduced in turn, the determination of the four principles from the top down is also gradually subjective, so we choose to refactor the priority order of the code is in accordance with their destruction of the simple four principle of the order of descending! If there is a lot of duplication of code, and another piece of code is difficult to understand, then we prefer to solve the problem of duplicate code, because the simple four principle of eliminating duplication is more important and more easily evaluated objectively.
In the book "Refactoring," Martin summed up the 22 bad flavors of the code in order to avoid a vague argument about the so-called programming aesthetics. In practice we tend to refactor from the bad taste of a code, but we follow the principles described above for priority refactoring of which bad taste.
For the timing of refactoring, Matin gives:
In fact, during my work, refactoring is done anywhere, anytime. Especially for the use of evolutionary design methodology, refactoring and code development is tightly integrated hard to split, and even many times only rely on refactoring to complete the development of code.
The method of reconstruction
Understand the starting point and the goal, the most important thing is to master the means to complete the process! The refactoring approach is the tool that leads us to the right target.
Many people think that learning refactoring is enough to master the thought behind it. Its detailed and cumbersome operation is not important. As a matter of fact, we see a lot of people in the actual operation of the process of refactoring all no, once the start of a half-day stop, code many times in the non-compile or test can not pass the state, and sometimes changed the error is difficult to make the code back to the original state, can only be pushed In fact, refactoring is a very practical technique, and it is the core standard to evaluate the reconfiguration ability to use the refactoring operation correctly and reasonably, and to complete the code modification safely, quickly and efficiently.
So what is the right refactoring technique?
Martin mentions the second definition of refactoring 使用一系列的重构手法
, but there is no generalization of this series of refactoring techniques.
and William Opdyke in his thesis "Refactoring objected-oriented Frameworks" in the face of refactoring gives the following definition:
Refactoring: Program reconstruction and program transformation of behavior-preserving (Behavior preservation).
In this paper, the refactoring technique is defined as the operation of some program reconstruction or program transformation, which satisfies the requirements of the behavior keeping (Behavior preservation). The definition of behavioral retention in this paper is as follows:
Behavior Preservation:for the same set of input values,the resulting set of output values should be the same before and After the refactoring.
This means that there is a series of code transformations, and after applying these operations, the output of the software will not change under the same input conditions. We call code-equivalent transformation operations that meet the requirements described above. In William Opdyke's paper, 26 low-level code equivalence transformations are proposed for C + + (for example: renaming variables, adding a parameter to the function, deleting a class that is not referenced ...). In order to combine the above-mentioned low-level code equivalence transformation operations in a certain designed sequence, we can complete a secure code refactoring to ensure the behavior of code reconfiguration before and after the refactoring.
Here the code is equivalent to the transformation process. Similar to the polynomial transformations in elementary mathematics. For example, the following formula changes:
At each step, we use the polynomial equivalent transformation formula, one step at a time to simplify the polynomial, each transformation before and after the polynomial to maintain the equivalence relationship.
In this example of polynomial simplification, the equation that carries the simplification process is a polynomial equivalent transformation that has been mathematically proven. In the same way, the reconstructed method of the code equivalent transformation operation is proved.
In addition, the order of use of these techniques is crucial because it takes a series of refactoring techniques to complete a refactoring!
We learn to refactor by learning how to use small steps in each scenario and how to use them, and keep practicing! The ability to use a series of refactoring techniques flexibly and smoothly to accomplish a refactoring is a very important indicator to measure the capability of refactoring.
One of the key points behind this paper is to refine the common reconstruction techniques and use order to reduce the difficulty of learning.
Finally, since refactoring uses a code-equivalent transformation approach to secure small steps, why do we need to test? The first is because we are human, we always make mistakes! In addition, because of the complexity of programming languages, so-called equivalence transformations are context-constrained, such as renaming a member method in C + + for a class that has an inheritance relationship, it is possible to cause the new method name to be the same as a virtual method with a default implementation in one of its parent classes, even if the compiler cannot find the error.
Efficient refactoring
Although we know how/when to start, goals, and how to refactor, it makes us safer and more efficient if we are assisted by these factors.
Good and efficient automated testing coverage
The right IDE, it's best to provide a basic automated refactoring menu
Good engineering Setup
An efficient build environment
Good coding habits
For these, different languages are facing different status, for the C + + language We will be a special summary later.
What is not refactoring?
For the above discussion, we stand on a strict refactoring definition to see the following anti-patterns:
"I've refactored the bug!"
"Debug, there's something wrong with the refactoring just now."
"The bugs that I reconstructed last night haven't been found yet."
"Refactor the code first, then see what the test is."
"I have distributed the software architecture by a centralized weight-structure."
Think about the above scene where there is a problem?
In the actual development process, we also often face another scenario, that is, a software module has been developed to complete the reconstruction. In this process, although there are frequent use of refactoring techniques to modify the original module code, but more is to do a lot of architectural and design changes. To differentiate ourselves from the refactoring we're discussing, we call this a reengineering (software rebuild).
Software reconstruction is generally based on the previous development, testing, along with the software to solve the problem and the solution itself has a deeper understanding, by modifying the software to reflect these learning results into the structure of the software, so that the software can be better and more refined solution to business problems. Standing in the perspective of DDD (Domain driven design), software reconstruction is generally a further refinement of the domain model, making the software more fit for the nature of the business! Although successful software reconstruction can often bring greater benefits to the organization, because software reconstruction is generally expensive, and software development is a business activity, it is necessary to carefully assess the cost-benefit ratio and process risk of software reconstruction before deciding whether to start. The refactoring technology in this paper is a safe and efficient code modification technique frequently used in daily coding, which is widely regarded as one of the essential skills in modern software development technology, and it is a necessary means to achieve the goal of evolutionary software design or software reconstruction.
about this article
We conclude that refactoring has three main points, see:
You have to have a sensitive nose that can sniff out bad smells in the code; In general, if you find code that does not conform to the simple design four principle, it is the target object that we need to refactor. And Martin's summary of the 22 code bad taste gives us a good starting point for practice.
You know the goal of refactoring is to get the code moving closer to the simple four principle.
It is necessary to master the small security refactoring techniques and the reasonable order of use in different scenarios in order to carry out the reconstruction target safely and efficiently.
Since refactoring techniques and order of implementation are key to learning refactoring, this topic is highlighted later in this article. In addition, how to reconstruct efficiently and safely in practice, and the relationship between the programming language and its development, construction and testing environment is very close. This article concludes with a summary of the issues related to the C + + language.
Efficient refactoring of C + + code