Refactor or not refactor?

    I like refactoring. No not like this. I love refactoring. No, not even that. I love damn refactoring.
    I can't stand bad code and bad architecture. It jars me when I write a new feature, and in the next class a complete mess is going on. I just can't look at the sadly named variables. Sometimes, before going to bed, I close my eyes and imagine what could be improved in the project. Sometimes I wake up at three in the morning and go to my laptop to fix something. I want the code to be not just a code at any stage of development, but a work of art that is pleasant to look at, which is pleasant to work with.

    If you share my feelings even a little, then we have something to talk about. The fact is that over time, something inside me began to suggest that refactoring everything in a row, everywhere and all the time is not the best idea. Understand me correctly, the code should be good (and it would be better for it to be perfect), but in the face of harsh reality it is not always wise to constantly improve the code. I came up with a few rules about the timeliness of refactoring. If my hands begin to scratch something to improve, then I look back at these rules and start thinking: "Is it really that moment when you need to refactor?" Let's talk about in which cases refactoring is appropriate, and in which it is not.


    Disclaimer.Most likely, after reading a post, many people will want to immediately say: “Yes, it has already been discussed 600 times!” or "This is so obvious, why write about it?" Perhaps you are right, but just this moment: chaos is still happening in the world around us. Everything seems to be clear to everyone, but in reality it turns out that it is not so clear. Therefore, I think that it will not be too harmful to take another look at this topic. But if specifically you have no problems with refactoring, then you can simply skip this post, you are already fine.

    Refactoring Too Early


    Can you recall the last time you had a permanent TK that did not change for months? I can’t really remember this. We live in the real world, the requirements are changing all the time. Moreover, these are not necessarily external requirements - these may be your own requirements for the project. Let’s explain the idea with an example: suppose you took a medium-sized problem for one or two days. The first few classes have already been written, but there is nothing to start yet - the process of writing a harsh architectural part is ongoing. And here you notice that one of the parts of the project is not written very universally: "But if in six months you need to make X, then everyone will suffer." It is quite reasonable that you do not want to send shitty code to the repository, so that other developers will later recall you with a bad word. And you start to refactornot yet ready feature . This is sometimes justified, but a “DANGER” sign should be placed on a similar path. Here you correct one thing, then another, then a third. A week has passed, the feature still does not start, and you say: “Somehow everything was done wrong. But now I understand for surehow to do it. Now I’ll quickly rewrite everything from scratch. ” The main problem is that the feedback on the feature has not yet been received, and you have already started working on improving the code base. Such an approach rarely leads to success. I don’t know how it is with you, but it often happens that after implementing a feature I begin to understand that everything should work a little differently. And this is not due to the fact that I am so stupid, I could not think through normally beforehand. Just some functionality you need to “touch” to understand how everything should be in the release. Sometimes you need a small prototype (even with govnokodom and bugs) to discuss the feature with colleagues. Sometimes you need to show something to the customer so that he can say: "No, well, I didn’t want it that way, everything should be the other way around." Sometimes users do not like innovations, they want everything as it was. The problem with the new features is it’s hard to predict their fate. It often happens that all the best practices are sent to the trash, because after discussing the first version, the team decided to do things differently. The general conclusion: you should not refactor the code too early, especially if you are not sure that this code will remain 100% in the project.

    Inappropriate refactoring


    Most likely, you have a development plan for the near future. It is likely that you have a deadline (even if you set them yourself). Releases need to be done on time, it is not worth delaying development. You need to control yourself, you need to do those things that are part of your immediate goals. Suppose you have a piece of code that looks complete ... Well, in general, it looks bad. But, we continue our assumption, you are not working with him right now. This bad piece of code works stably, successfully copes with its tasks and has nothing to do with your current task. Well, do not touch it! Yes, you can be extremely saddened by the fact that at the other end of the project everything is very bad. But note that right now this does not bother you. You have current tasks, do them. Of course, there are tasks to improve the code base, but infrequently - it is often more important to add new functionality or fix bugs. Concentrate on current tasks and do not drop them due to the fact that somewhere something is somehow wrong.

    Refactoring for refactoring


    Ok, you came to the conclusion that you need to refactor part of the project. Ok, let's refactor. It seems that the planned improvements have been completed, but here the thought arises: “What can I still improve? Yeah, that thing over there. ” And after that thing, this thing will appear, and then another one, and then another, etc. You need to understand that there is a bad code, there is a good code, there is an ideal code. You will never have the last in a large project. This does not mean that you do not need to strive for it, but you need to understand its unattainability. Usually the task is to write good code, not perfect. Suppose, after refactoring, you get quite readable code that works in a more or less obvious way, in which there are no crutches and which is not so difficult to use. Ask yourself the question: “Maybe it's time to stop?”. Yes, the code can be improved. Moreover, in a fairly large project, it can be improved indefinitely. But right now he is coping with his functions, it’s convenient to use, he practically does not cause you discomfort. It is very important to determine for yourselfacceptable quality of the code, after which you will stop improving it (until the eligibility property is lost). Remember that there are so many different cool stuff that you can add. No need to refactor for the sake of refactoring, for the sake of a perfect code. You need to refactor when you have good reasons for this: the code is difficult to read, the code is difficult to maintain, the code is difficult to develop, the code is difficult to use, etc. If not a single one is “difficult”, then you have good reason to spend time refactoring not.

    Refactoring the day before release


    It happens that the release of the day after tomorrow / tomorrow / today / should have been yesterday (underline as necessary). This is an important moment in the life of the project. We need to pay special attention to testing, fixes for critical bugs, and final fixes. Believe me, this is a really bad idea - to process the code base (and even worse - to process it qualitatively) at the moment when you need to give the project to production. Experienced practice suggests that you need to be released, and then calmly improve the code with a clear conscience. Some will ask: “Why?”. If such a question arose, then, probably, you have not yet had to do complex refactoring. Let me tell you: when rewriting, the code does not always improve - sometimes it can break. Why is there complex refactoring - it happens that you correct one method for five lines, you don’t keep track of any dependency, and at the other end of the project a bug will creep out, which your favorite users will immediately meet. It seems that you are not doing anything wrong, and then suddenly the beast “It was not obvious” attacks you and drowns you in a pond of a false initial assessment. Although, maybe it's just that I'm such a bad programmer - I like to break something. It is possible that you always refactor everything absolutely correctly and with complete control of the entire project. In this case, I can congratulate you, but I still will not refuse advice on the ban of pre-release refactoring. Believe me, in a few days, refactoring will not run away, and the whole team will have a little sleep, but calmer. and then suddenly the beast “It was not obvious” attacks you and drowns you in a pond of a false initial assessment. Although, maybe it's just that I'm such a bad programmer - I like to break something. It is possible that you always refactor everything absolutely correctly and with complete control of the entire project. In this case, I can congratulate you, but I still will not refuse advice on the ban of pre-release refactoring. Believe me, in a few days, refactoring will not run away, and the whole team will have a little sleep, but calmer. and then suddenly the beast “It was not obvious” attacks you and drowns you in a pond of a false initial assessment. Although, maybe it's just that I'm such a bad programmer - I like to break something. It is possible that you always refactor everything absolutely correctly and with complete control of the entire project. In this case, I can congratulate you, but I still will not refuse advice on the ban of pre-release refactoring. Believe me, in a few days, refactoring will not run away, and the whole team will have a little sleep, but calmer.

    Refactoring very old code


    The question is difficult, very difficult. Situation: there are a huge number of terrible lines of code that you got from old developers (perhaps you were these old developers several years ago, before you even learned how to write everything right and right). The code has to be supported. Here and there crutches and duplications arise, entropy grows. Every day more and more I want to throw everything and rewrite from scratch. At such a moment you need very wellthink about the risks. Yes, it is likely that in the future such an activity will be useful. But in what exactly perspective and how useful? Most likely, during a large refactoring or rewriting of individual parts, you will replace the old working govnokod with new, ideally written code, but with bugs. And it’s not at all due to the fact that you are a poor programmer and write poorly. You just may not know this code sufficiently.. You may not know why the author wrote everything that way, but there could be reasons. Sometimes you have to write very strange and crooked code. I can come up with a lot of examples: suppressing tricky processor optimizations, adjusting to bugs of a third-party library, suppressing some multi-threaded jambs, etc. I am not saying that all these problems cannot be solved normally. Just sometimes when rewriting a seemingly absurd code to normal, bugs appear. Yes, it was possible to do everything normally, but you may simply not realize the greatness of a crutch hut instead of sticks if you don’t know from the author of the code why he wrote this way (and this opportunity is not always provided). Be careful when rewriting old code that you don’t understand completely (and especially if you think there’s nothing to understand).

    And when do you refactor?


    I apologize if you got the impression from this article that refactoring is the only problem. I still insist that the code should be readable and beautiful, it should be convenient to use, it should be easy to develop. A positive approach is better than a negative one, so treat refactoring not as a source of problems, but as your very good friend who will help you out in difficult times. Moreover, this friend can make less difficult minutes in your bright future. In conclusion, I would like to outline a few points when refactoring is really appropriate.
    • Nothing to do. There are calm downtime, when all important tasks are closed, and new ones have not yet been set. Well, not that there is absolutely nothing to do, but there is a certain amount of free time. Spend it improving your code. Give entities meaningful names, get rid of duplication, rewrite an unsuccessful piece of architecture. Although new functionality is not added, you are contributing to the peace of mind of the developers who will continue the project. Believe me, this is important.
    • Everyday suffering.And it happens that there is a piece of the project that makes you sigh heavily every day. And from the neighboring tables you hear heavy sighs of your colleagues. Of course, although the release is not tomorrow, there are enough important tasks. Nevertheless, a week goes by, and looking at this piece of the project is getting sadder. Say to yourself: “Enough to endure it!”. If the business plan is the boss, then explain to him that this code just needs to be rewritten. If you work for the customer, then convince him that the week spent on refactoring will save a lot of time for development in the future. If you work for users, then decide that it would be better for these users this time to wait for a week more release, but then enjoy stable software and regular updates. Yes, negotiating with everyone and with yourself is not always easy,
    • The problem of belated refactoring. Do not absolutize the rule about refactoring too early. Some people think so: "I’m improving something now, but it will not be useful - it will be insulting." You need to understand that in the core of the program there may well be important parts that would be better to be written well. Remember that the later you refactor, the higher its price, because you will spend more time and effort rewriting. Critical basic things (which are used throughout the project) should be in the best possible shape all the time. It will be just fine if the thesis “Refactoring is not late. He comes strictly when he sees fit .
    • Meeting with the monster. You start sawing new functionality that should use an old piece of the project that looks like a real monster: you become scared only when you look at the external interface. If time permits, then first correct the basic part of the code, so that later you can focus on the new functionality and not be distracted by driving five crutches for the sake of reusing the code.
    • Reasonable perfectionism. Noticed a bad piece of code? Want to fix it? Would you really like to fix it? Well, if you really want to, I can. But pay attention to the word "reasonable." Relate the time spent refactoring to the benefits of improving the code. Do not disrupt the deadlines and dig into endless improvements. However, if timely and moderately involved in refactoring, the project from this will only get better.

    Instead of a conclusion


    All of the above is a purely subjective synthesis of experience working on a number of projects. Of course, I did not cover all life situations. Each team has its own code requirements, its own business plan and its own rules. I am sure that many will have five stories from the series “But I had a case where all these tips do not work.” This is absolutely normal, as it should be. There is no universal silver bullet for determining the amount of effort to improve the code (“We will refactor every day for 47 minutes 23 seconds and everything will be fine with us”). Based on your own experience in your specific project, you need to try to find a middle ground between writing new code and improving the old one in your specific team. I campaign only for a rational attitude towards everything without fanaticism (“Why improve the code, new functionality will not appear from this ”/“ We urgently need to make the whole code perfect so that later we can work normally with it ”). Take a reasonable approach to allocating time to work on existing code - and everything will be fine with you.

    Any additional thoughts on when to or not to refactor are welcome. One of the most valuable things in this area is the experience of real developers on real projects.

    Also popular now: