📜 ⬆️ ⬇️

Refactor or not refactor?

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

If you share my feelings a little bit, then we have something to talk about. The fact is that over time, something inside me began to suggest that refactoring everything, everywhere and all the time, is not a good idea. Understand me correctly, the code should be good (and it would be better for it to be perfect), but in the conditions of harsh reality it is not always reasonable to constantly improve the code. I made several rules for myself about the timeliness of refactoring. If my hands begin to itch to improve, then I look back at these rules and start thinking: “Is there really a time when I need to refactor?”. Let's argue about in what cases it is appropriate to refactor, and in which - not very.


Disclaimer Most likely, after reading the post, many will immediately want to say: “Yes, this has already been discussed 600 times!” Or “It's so obvious, why write about it?”. Perhaps you are right, but this is the moment: chaos is still going on in the outside world. It seems that everyone understands everything, but in fact it turns out that it is not so clear. Therefore, I think it will not be too harmful to look at this topic once more. But if you specifically have no problems with refactoring, you can simply skip this post, you are already fine.
')

Too early refactoring


Can you recall the last time you had a permanent TK that has not changed for months? I do not really remember this. We live in the real world, the demands are changing all the time. Moreover, these are not necessarily external requirements - these can be your own requirements for the project. Let me clarify the idea with an example: let's say you took a medium-sized puzzle for one or two days. The first few classes have already been written, but for now there is nothing to start - the process of writing the harsh architectural part is in progress. And here you notice that one of the parts of the project is not particularly universal: “But if you need to make X in six months, then everyone will suffer.” It’s quite reasonable that you don’t want to send a fucking code to the repository so that other developers later remember you with a bad word. And you begin to refactor not yet ready feature . Sometimes this is justified, but on such a path should hang a sign "DANGER". Here you correct one thing, then another, then the third. The week has passed, the feature still does not start, and you say: “Somehow everything was done incorrectly. But now I understood exactly how to do it. Now I will quickly rewrite everything from scratch. ” The main problem is that the feedback on the feature has not yet been received, and you have already begun to work on improving the code base. Such an approach rarely leads to success. I do not know about you, but it often happens with me that after the implementation of the 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 out in advance normally. Just some functionality you need to "touch" to understand how everything should be in the release. Sometimes you need a small prototypist (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 of new features is that it is difficult to predict their fate. It often happens that all the developments are sent to the garbage, because after discussing the first version, the team decided to do everything differently. The general conclusion: you should not refactor the code too soon, 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, do not delay the development. You need to control yourself, you need to do those things that are included in your immediate goals. Suppose you have a piece of code that looks like a complete ... Well, in general, it looks bad. But, we will continue our assumption, you are not working with him now. This bad piece of code works stably, successfully copes with its tasks and is in no way related to your current task. Well, do not touch it! Yes, you can be extremely sad that the situation at the other end of the project is very bad . But notice that right now it doesn't bother you at all. You have current tasks, take care of them. Of course, there are tasks to improve the code base, but not often - it is often more important to add new features or fix bugs. Concentrate on your current tasks and do not drop them due to the fact that somewhere there is something wrong.

Refactoring for refactoring


Ok, you came to the conclusion that it is necessary to refactor a part of the project. Well, let's refactor. It seems that the planned improvements have been made, but then a thought arises: “What else can I improve? Yeah, that thing over there. ” And after that thing, this thing will appear, and then another one, and then another, and so on. 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 big project. This does not mean that you do not need to strive for it, but you need to understand its inaccessibility. 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 are not so difficult to use. Ask yourself the question: “Maybe it's time to stop?”. Yes, the code can be improved. Moreover, in a large enough project it can be improved to infinity. But right now he is coping with his functions, it is convenient to use them, he practically does not cause you discomfort. It is very important to determine for yourself the acceptable quality of the code, after which you will stop improving it (until the acceptability property is lost). Remember that there are still so many different cool things 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 compelling reasons for it: 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 there is no one “difficult” to occur, then there are good reasons to spend time refactoring you not.

Refactoring the day before release


It so happens that the release the day after tomorrow / tomorrow / today / should have been yesterday (underline the necessary). This is an important moment in the life of the project. It is necessary to pay special attention to testing, fixes critical bugs, final improvements. Believe me, this is a really bad idea - reworking the code base (and even worse, reworking quality) at the moment when you need to give the project to production. Experienced practice suggests that you need to unlock, 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. I'll tell you: when rewriting, the code does not always necessarily improve - sometimes it can break. Why, there is a complicated refactoring - it happens, you correct one method for five lines, you don’t follow any dependency, and at the other end of the project a bug crawls out, which your favorite users will immediately meet. That seems to be nothing bad and you are not doing anything, and then suddenly the beast is attacking you, “It was not obvious,” and drowning 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 full control of the entire project. In that case, I can congratulate you, but I will not refuse from the advice on the prohibition of pre-release refactoring. Believe me, in a few days refactoring will not run away anywhere, and the whole team’s sleep will be a little, but calmer.

Refactoring very old code


The question is hard, very hard. Situation: there are a huge number of horrible lines of code that you got from the old developers (perhaps these old developers were you a few years ago, even before you learned how to write everything correctly and immediately). The code has to be maintained. Here and there crutches and duplications arise, entropy grows. Every day more and more I want to throw everything out and rewrite it from scratch. At such a moment you need to think very well about the risks. Yes, it is likely that in the future such activities will be useful. But in what perspective and how useful? Most likely, in the process of a large refactoring or rewriting of individual parts, you replace the old working govnodode with a new, ideally written code, but with bugs. And not because you are a bad programmer and write badly. Just you may not know this code sufficiently . You may not know why the author wrote it all this way, and in fact there could be reasons. Sometimes you have to write very strange and curved code. I can come up with a lot of examples: suppressing tricky optimizations of the processor, adjusting for the bugs of a third-party library, suppressing some multi-threaded jambs, etc. I’m not saying that all these problems cannot be solved normally. Just sometimes, when rewriting a seemingly absurd code into a normal one, bugs appear. Yes, it was possible to do everything normally, but you can simply not realize the greatness of the hut of crutches instead of sticks, if you don’t find out from the author of the code why he wrote that way (and this possibility is not always provided). Be careful when rewriting old code that you don’t fully understand (and especially if you think there’s nothing to understand).

And when to refactor?


I apologize if you have the impression from this article that there are only problems with refactoring. 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 consider refactoring not as a source of problems, but as your very good friend who will help you out at a difficult moment. Moreover, this friend can make it so that in your bright future difficult minutes would be smaller. At the end, I would like to mark a few moments when refactoring is really appropriate.

Instead of conclusion


All of the above is a purely subjective generalization of the experience of working on a number of projects. Of course, I covered far from all life situations. Each team has its own requirements for the code, its business plan and its own rules. I am sure that many will have five stories from the series “But I had a case when all these tips do not work.” This is absolutely normal, it should be. There is no universal silver bullet to determine the amount of effort to improve the code ("We will refactor every day 47 minutes 23 seconds - and everything will be fine"). You need, based on your own experience in your particular project, in your specific team to try to find a middle ground between writing new code and improving the old one. I am agitating only to ensure that everything is a rational attitude without fanaticism (“Why improve the code, the new functionality does not appear from this” / “We urgently need to make all the code ideal so that later we can work with it normally”). Approach intelligently to allocate time to work on existing code - and everything will be fine with you.

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

Source: https://habr.com/ru/post/229051/


All Articles