There are two major difficulties in code refactoring. One is "archaeology", that is, how to quickly sort out the original logic of the code, and the other is "release", how to make new code stably published online without generating malfunction. Let's talk about the story of a friend of mine and see how he made the code stable and online. In order to express more cordiality, you are my friend now.
Refactoring code is definitely a dirty and tiring job for many people. There is no method that can greatly improve efficiency, and it is difficult to precipitate an effective systematic reusable technology grasp. There is no obvious increase for the business. It consumes huge energy and time. There is no test case, and it may not be tested. It’s difficult to fully support the self-test, and it’s hard to go online after the final development. The main reason is fear! Of course it is not that we are not confident, but that we are really afraid.
1. Why don't you dare to send code?
It is too difficult to restore the complete product logic at the time through the code
Whose code is your refactoring? The ghost knows who belongs to it! The code that allows you to refactor is most likely not the code you wrote, but also the ancient code, using an outdated technology stack. Of course, under normal circumstances, the development, testing, and even products of that year have long since disappeared, and only a few words can be seen in the commented code. The words revealed helplessness, using the conscience of a programmer to remind later generations to "be careful of the dirty things in front." After reading these words, you can only take back the fragrance that is about to vomit out of your mouth, leave the work station silently, and pour some hot water.
From then on, you will find that comments can not only help you understand the code, but also have a warning effect, telling you to refactor the code, and remember to correct the bug. Your desire to sort out the original requirements through annotations has failed. Then you can only squat and pray that you don't miss the business logic.
No self-test use cases
Don't think that large companies have complete systems and complete test cases for testing. The reality will smash your forehead. Frequent iterations, the functions have been completely changed, the old use cases are not available at all, not to mention the old test cases can not be found at all. How to self-test without a use case? It all depends on personal imagination.
No test classmates follow up
One more person has more strength, and letting an experienced test participate in the functional regression will undoubtedly give you peace of mind in your refactoring career, but the real situation is that the test students do not want to participate in this kind of dirty work. . The demand in his own hands is still untestable, so how could he devote his time to a refactoring work initiated by a front-end. No increment, no grasping, pure physical strength, they are equally aware.
No stable release plan
Without the above-mentioned guarantees, if you can still go online, you will encounter bigger problems. How to go online? Is it directly replaced in full? What if something goes wrong online? Fortunately, the front-end rollback is very fast, but even if it rolls back quickly, from the completion of the release to the rollback of the problem, reminding the user to refresh the page, this process is enough to cause incalculable consequences, especially those high-frequency Use, and easily produce dirty data scenes. This is the common consequence caused by the lack of an effective release plan. This consequence may also cause your back to malfunction. The shifts you have spent this year, the nights you have passed, the hair loss, you can’t change anything. Give birth to the idea of re-behaving in a different place.
The above factors directly lead to the extreme insecurity of developers. A programmer who dares not to launch his own code is like being awakened by the cry of his one-month-old child in the middle of the night. At that moment, you just want to pretend to be fishing. What's more, your work is often not just about refactoring. Isn't it good to write about new requirements? In this way, you watched a page refactoring for two weeks, and it was too late to finish. You became less and less confident, more and more scared, afraid to face the half-refactored code, and began to fear the boss. Question: "How is the refactoring done?", you are not like a programmer.
At the end of the year, your refactoring career has not yet been completed. What's even more frightening is that this incident has also been marked as a "commitment type" OKR, so you learned from the pain and had a dream.
Time to go back to when you just received the reconstruction task at the beginning of the year.
2. Seek organizational guarantee
Your refactoring work is to rewrite 177 jQuery pages with React. You immediately think that you can't finish it all by yourself for a year. At this moment, remember not to promise, but to seek truth from facts, and even think in the worst direction, so that the boss fully realizes the arduousness of this task. Don't have too high expectations. The most important thing is to ensure the investment of manpower. More students must participate together, and effective division of labor is possible to complete this arduous task. Someone’s participation is just the basis, because they are very likely to go from enthusiastic to conscientious as described above. Therefore, we must ensure the investment of time, and if necessary, bring the boss in and do it with you. Once the boss gets involved , You will feel more physical and can appreciate the difficulty of everyone. Next, the old saying goes, "Don't forget, you are an owner!" Doing a good job in infrastructure construction, so that every student has the tools at hand, and has safety guarantees, it is very important to remove their worries. Therefore, you have to do the following things.
Three, divide the refactoring page priority
Through careful research, you find that among these pages, 77 pages are frequently used by users and are relatively complex pages. Most of the remaining 100 pages are additions, deletions, and changes for development. Users The frequency of use is not high. So you make the following division:
After the priority is divided, it is necessary to use different stable publishing strategies for pages of different priorities.
Complex high-frequency pages: press hard, carefully restore the original requirements, pull out the code, pull test students to organize test cases together, follow the test cases to self-test, and test students return to all functions. But in fact, this part of the page can also be divided into two types of pages:
- Edit page: This page is the most risky page. Once the back-end interface has not done complete data verification, dirty data will be edited, or the wrong data will be saved, causing abnormal online operation. This consequence will be It is unthinkable that even a very short time rollback will cause irreparable failures, so it must be tested in place like new requirements.
- Display page: Such a page will not affect the runtime and will not generate dirty data. It is a relatively low risk page. Based on the principle of not bothering the partner, after all, the resources are limited, and the test can help you produce a complete use case. Then you test yourself, or find a few more classmates to help you test yourself.
- High-frequency simple page: self-test, of course, it is best to kidnap a few developers who often use this feature to help you a little bit, but there will always be omissions in the self-test, so the following steps are needed to ensure.
- Low-frequency operation and maintenance pages: selective reconstruction, because many pages basically do not have iterations, and the frequency of use is low, basically does not need to be reconstructed, even if there are new requirements, they can also be rebuilt when new requirements are made. Under the structure, I thought it could not take up too much time.
After dividing the pages, you will find that the workload of refactoring has been reduced a lot, because in the principle of "no requirement, no change", many pages do not need to be refactored. And the above reconstructed pages must be published in grayscale.
Four, single test
The front-end does not like to write single tests, you probably summarized it, mainly due to the following reasons:
- The current benefits are not high.
- Compared with the single test of the back-end interface, the single test of the front-end is relatively complicated to write.
- The front end is more UI-oriented programming, but the UI changes greatly, and it is difficult to use the TDD (Test Driven Development) development model.
- There is no habit of writing single tests, probably because single tests increase the workload, and there is no awareness of writing pure functions, which is not conducive to testing.
- Single test tools are difficult to learn and difficult to use.
You find that the front-end does not like to write single tests for various reasons, but when you refactor those complex pages, especially when the jQuery technology stack is refactored into the React technology stack, the single test is really very useful.
For example, here is an editing page, which contains two parts: basic information and operation logic. When refactoring the operation logic, you must first ensure that when the reconstructed page is saved, the saved data structure must be the same as the previous interface parameters. It must be consistent, so there will be a lot of data conversion logic when refactoring this component of the running logic.
It can be seen that in order to ensure that your new component does not affect the maintenance of the original function, it is necessary to ensure that the original data ultimately retains the original structure through the operation of the new component. At this time, you can write a single test to ensure this process.
describe('utils', () => {
it('流程图:转换为提交的数据 transformForm', () => {
const result = transformForm(canvasData);
expect(result).toEqual(settingData);
});
it('流程图:转换为需要的数据 parseRuleSetData', () => {
const [result] = parseRuleSetData(settingData, rules);
expect(result).toEqual(canvasData);
});
it('流程图:反复转换 transformForm - parseRuleSetData', () => {
const [result] = parseRuleSetData(visualSettings, rulesData);
const newResult = transformForm(result);
expect(newResult).toEqual(visualSettings);
});
});
The front-end unit test is complicated to write, but it's just the UI single test. If you split the code enough, split more functions, more hooks, single test is a breeze.
Five, test cases
The team you are in has not always had sufficient test resources. Test cases seem to be something that cannot be met. Especially in the trend of agile development, product functions change rapidly, and few tests will always maintain that. The initial test cases are often written and used and never found again. But the test case is really important in the reconstruction scenario. The core problem he solves is to pull the test students into the quality assurance of the reconstruction and sort out the old logic together.
This valuable test case can be the basis for your self-test, and it can also provide you with different perspectives on the same function. If you see the logic of the implementation details through the code, then the test sees the entire link Flow chart. Many middle and back-end systems are divided into management mode and running mode. Management mode and front-end are very familiar, but running mode and testing are often more familiar.
Six, self-test
Once you get the test case, you can test yourself, but there is a pitfall here, that is, if you completely rely on the test case given to you by the test classmates. As long as the test cases are verified to pass, this idea will cause big problems, because the test of this function may be a novice, and may not have been in charge of the test of this function. Their test cases may only be superficial. So you need to expose the logic that is not in the test case discovered through code archeology to the test students and add it to the test case. And if you find some logic you don’t understand, you should understand it. Those blind spots that you don’t understand often have big problems after going online. Don’t be lucky.
Self-test is very important, but often you will feel that the development is complete, even if you finish this thing, and then go to other things, and there is no good self-test, I think there is a test, waiting for them to ask questions, I Change it again. This is a very common psychology of programmers, but it is difficult to avoid, after all, there are many things. At this time, you can ask the development students in the same group to help you a little bit, and solve the obvious problems first. It can be regarded as a serious and responsible programmer. Don't let the test students give you too many low-level bugs.
Seven, regression testing
It is really something that can be met but not desired to have test classmates to help you do functional regression tests. You must cherish it and take a lot of your time to cooperate. The most important of these is to communicate more. Test students may not know all the logic. When doing regression testing, it is necessary to develop and test repeatedly to check every dead corner of the logic and figure it out before daring to go online.
Of course, the functions that can be tested to help you return are extremely fault-prone functions. Here is a trick that is how to pull tests to participate in your refactoring. For important functions like this, if the test knows the logic inside, you can ask the other person with the mentality of asking for advice. If the other person does not understand, then you can tell him. A responsible test should all want to know yourself very much. Responsible for the ins and outs of the important modules of the system.
8. Grayscale release
Even if you do more tests, there may be missing points that are not considered. At this time, grayscale is very important, and grayscale must have a grayscale tool. Refactoring is generally carried out according to people with the page or block as the granularity. So your grayscale tool must include these functions:
- Configure users or user groups
- Configure the old route and the new route
- Configure gray status prompt
- Automatic management of new and old pages
In the gray configuration page, the new and old dynamic routing parameters need to be consistent, so that the parameters can be passed on.
Show gray prompts, and provide a quick "return to the old version" button, in order to solve the problem more quickly, you can give the developer's contact information.
When the user visits the old route, verify whether the current user is in the grayscale according to the grayscale configuration, if in the grayscale, immediately jump to the new route, and display the grayscale prompt. If the reconstruction is a block in the page, a gray-scale hit method can be provided, and the judgment can be made in the part of the page calling the block.
The gray scale strategy can be carried out according to the following user level distribution:
- L1: All project development, testing, designers, internal operations staff
- L2: Core users, establish DingTalk groups, observe user feedback, and solve user problems in a timely manner.
- L3: Appropriately add more users, and delete the gray-scale policy configuration after the full amount is reached.
After the release, pay attention to the RBI data:
, you must follow the dynamic routing and divide it into gray-scale hits. Click to use the old version and view the data in three dimensions that are not in gray-scale. At the same time, adjusts the gray-scale users every day, so as to ensure The page is used by someone. If many users use the function of returning to the old version, then you have to find these users to understand the situation, whether there is a bug or the interaction is uncomfortable, solve user problems one-to-one, and optimize your page repeatedly. Slowly expand the user gray range until the old route access data PV is 0.
Nine, fully online
Going online in full is not for everyone in Grayscale, but really taking down the old pages and deleting the old code. Only at this point can the reconstruction be completed.
10. Summary
After all the difficulties and dangers, you finally put the refactored page online. After going through this process, I have a lot of emotions. I just hope that I won't do refactoring again in the future. Isn't it good to do well? Looking at the whole process later, if you want to restructure the page to go online, you not only need to work hard, but also to overcome some of the weaknesses of human nature, to do these points:
- Double Check: Involve other people, one more person will help you find more problems. Before reconstruction, don't believe in yourself, trust in partners.
- Logic has no dead ends: Don’t have unintelligible code, unclear logic, according to the programmer’s sixth sense, uncertainties will cause big problems.
- Concentrate: Refactoring cannot be done in fragments. You must concentrate a large amount of time on it and do it to the end. Otherwise, after a few days, your own code will not be recognized.
- Follow it to the end: The completion of development is not the key point, the whole is online, and the old page is dropped is the end.
Pay tribute to every warrior on the road of reconstruction.
Author: ES2049 / Blackstone
The article can be reprinted at will, but please keep this link to the original text.
You are very welcome to join ES2049 Studio if you are passionate. Please send your resume to caijun.hcj@alibaba-inc.com.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。