1. Summary I have written a lot of code recently, reviewed a lot of code, and done a lot of refactoring. In short, I have been working on bad code for a few weeks. In order to express the emotions that have reached the edge of collapse several times in the past few weeks, I decided to write an article to talk about bad code. This is the first article, which talks about the causes and phenomena of bad code. 2. It’s easy to write bad code When I first started working as a programmer, I often heard a point of view: you should focus on ABCD (requirements document/functional design/architecture design/understanding principles). Writing code is just translating ideas into programming language, which is not a very technical task. When I heard this view at the time, I felt a kind of disdain that was almost arrogant: You are just a bunch of idiots who don’t understand the importance of code quality at all. If you continue like this, you will fall into a trap sooner or later, bah. But after a few months, they didn't seem to make any mistakes. As programming technology continues to develop, more people who I used to think were stupid have joined the programmer industry. Languages are becoming more and more advanced, and encapsulation is becoming more and more complete. Various technologies are helping programmers improve the efficiency of code production. Relying on layers of encapsulation, programmers really do not need to understand any technical details. They just need to translate the content in the requirements line by line. Many programmers don’t know how to organize code, how to improve operating efficiency, or what underlying principles the code is based on. In my mind, the code they write is like a pile of shit. But that piece of shitty code actually works fucking fine. Even if I think the code they wrote is shit, but from the perspective of someone who has no contact with the code (like your boss), the code has been compiled, tested, and has been running online for a month without any problems. What else do you want? So, even if we are reluctant, we must admit that writing code itself is not that difficult nowadays. 3. Bad code is bad code But there are a few times when the person who wrote the bad code leaves and things seem to be different again. When I wanted to modify the function, I found that the program was full of all kinds of incomprehensible logic. After the modification, inexplicable bugs occurred one after another. The person who took over the project began to work overtime aimlessly, and a person who was originally very optimistic and cheerful gradually began to like greeting other people's ancestors. I have summarized several types of bad code that are often criticized: 3.1. Unclear meaning Poor programmers tend to write code that makes no sense; they don't know what they are doing. Like this:
For this type of programmer, I generally recommend that they change careers. 3.2. Don’t speak human language The most common problem among novices is that they fail to speak human language. The most direct manifestation of this is that they write a very simple code but others cannot understand it. For example, the following paragraph:
Many programmers like simple things: simple function names, simple variable names, and using only a few words in the code; abbreviating when possible, omitting when possible, and merging when possible. The code written by such people is full of abbreviations such as g/s/gos/of/mss that no one in the world understands, or a long series of continuous calls that have no idea what they are doing. There are also many programmers who like complexity, and write all kinds of macro definitions, bit operations, etc. in a fancy way, for fear that if others can understand the code at once, it will appear that their level is not good enough. Simply put, their code is written for machines, not for humans. 3.3. Inappropriate organization Inappropriate organization is a more advanced form of bad code. After writing some code, programmers have a basic coding style, but they lack the ability to control larger projects and do not know how the code should be decoupled, layered, and organized. The phenomenon of this anti-pattern is that you often see a piece of code copied back and forth in the project; a large pile of code is placed in a certain file; a function has hundreds or thousands of lines; or a simple function calls dozens of functions in a circuitous way, silently calling some key logic in some hard-to-find corner. Most of these codes are highly complex and difficult to modify, and often break when modified. On the other hand, the people who created these codes tend to modify the codes and are afraid of creating them. They would rather make the originally complex codes more complex step by step than reorganize the codes. When you face a class with thousands of lines and ask why you don’t extract a certain logic, they will say: "But that would add another class." 3.4. Assumptions and lack of abstraction Compared to the previous example, suppose this anti-pattern occurs more frequently and in more ways, and it is more difficult for the initiator to realize the problem himself. For example:
When the file path changes, the code will be changed to this:
When more content needs to be loaded, it will become like this:
Then it might become like this:
This type of programmer is often the most efficient developer in the project team, but the large amount of business development work prevents them from doing any extra thinking. Their mantra is: "I have to meet XX requirements every day" or "Finish the requirements first and then consider other things." The consequence of this anti-pattern is often that the code is difficult to reuse. When facing deadlines, programmers are eager to implement requirements into code, which often becomes a cycle: there is no time to consider reuse when writing code, and the difficulty of reusing code leads to the need to continue writing a lot of code for subsequent requirements. The large amount of code that accumulated little by little brought about problems such as organization and style consistency, and finally formed a legacy system where new functions were basically copied. 3.5. Anything else? There are many types of bad code. If you follow the route of functionality-performance-readability-testability-extensibility, you can see many incredible examples. So what is bad code? In my opinion, bad code includes several levels: If the code is maintained by only one person, it is sufficient to meet the functional and performance requirements. If you work in a team, it must be easy to understand and test, giving others the ability to modify their own code. At the same time, the lower the level of the system code is, the more important scalability is. Therefore, when the underlying code in a team is difficult to read, is coupled with the upper-level logic and thus difficult to test, or makes too many assumptions about the usage scenarios and thus difficult to reuse, although the functionality is completed, it is still a pile of shitty code. 3.6. Enough code On the other hand, if the code of a project is difficult to read, can we say that it is bad code? It is difficult to define. It may not be good, but can we say it is bad? If there is only one person who maintains the project from beginning to end, and that person also maintains it well, then it seems to be "sufficient code". Many projects may just be small projects that one person is responsible for at the beginning, and everyone is concerned only about whether the code can smoothly realize its functions and be completed on time. After a while, when other people participated in the project, they found that the code was written with problems. They couldn't understand it and dared not to change it. The demand side began to urge the launch of the product again. What should I do? I had to be careful to only change the logic without changing the structure, and then write in the comments that this implementation is ugly and I will refactor it later when I understand the internal logic. After a while, there was a similar requirement and I wanted to reuse the logic. I realized that the code had dedicated logic for various specific scenarios and it was very troublesome to reuse it. In order to catch up with the progress, I had to copy the code and modify it. The problem was solved, but the problem was also doubled. Almost all bad code evolves from "sufficient code". The code has not changed, but the scenario in which the code is used has changed. The originally sufficient code does not fit the new scenario, so it becomes bad code. 4. Refactoring is not a panacea One of the lies programmers like to tell other programmers is: the schedule is tight now, wait X months until the project schedule is looser before doing the refactoring. It cannot be denied that refactoring is one of the means to solve problems in certain (extremely limited) scenarios, but after writing a lot of code, I found that refactoring is often the most complicated work in the program development process. It takes a month to write bad code, and it takes longer and more risk to refactor it. We have experienced several large-scale refactorings that were intolerable. Before each refactoring, we would gather all the experts in the team, hold countless analysis meetings, and suspend all the needs within the group before we dared to start work. During the refactoring process, there were often wailings everywhere, and many unexpected problems would arise almost every day, and there would almost inevitably be a few problems when going online. Technically, when refactoring complex code, three things need to be done: understand the old code, decompose the old code, and build new code. However, the old code to be refactored is often difficult to understand; excessive coupling between modules leads to a ripple effect on the entire system, making it difficult to control the scope of impact; and the old code is difficult to test, making it impossible to guarantee the correctness of the new code. There is another core problem here. The complexity of refactoring is not linearly related to the complexity of the code. For example, if it takes one hour to refactor 1,000 lines of bad code, then it may take two or three days to refactor 5,000 lines of bad code. Refactoring a project that is out of control is often not as efficient as rewriting it. Putting aside the specific refactoring methods, refactoring is also a very troublesome thing in terms of benefits: it is difficult to bring direct benefits, and it is also difficult to quantify. Here is a very interesting phenomenon. Basically, all books about refactoring will have a separate chapter on "How to explain the necessity of refactoring to the boss". How much efficiency can be improved after refactoring? How much risk can be reduced? It is difficult to answer this question. Bad code itself is not something that can be simply standardized. For example, if the code readability of a project is very poor, how much will it affect development efficiency? You can say: It took 3 days to modify a module before, but it only takes 1 day after refactoring. But how to deal with questions like "Why does it take 3 days to do a database operation?" The factors that make bad code "bad" are uncertain, and development efficiency varies from person to person. If you want to prove that this thing "does" increase development time by two days, it often becomes a proposition that only a lunatic would prove, such as "It took me 3 days to understand what this function does" or "It took me 3 days to make such a simple modification". On the other hand, many technical leaders have also realized the necessity of code quality and refactoring, "Then refactor", or "If you see a problem, refactor." The previous problem has been solved, but in fact, the cost and benefits of refactoring are still a mess. Without more resources allocated to you, no clear goals, and no specific methods, it is hard to imagine that anyone other than code cleanliness freaks would perform such a strange task. This often results in a situation like this: People who don't write code think that refactoring should be done. Refactoring is very simple, and both newcomers and veterans have the responsibility to do refactoring. Experienced code writers believe that refactoring should be done sooner or later, but refactoring is difficult, so just make do with it for now and don't let this happen to me. New code writers think that they should be thankful if there are no bugs. I don’t know how to refactor either. 5. Writing good code is hard Unlike writing bad code, writing good code has many prerequisites: Understand the functional requirements to be developed. Understand how the program works. Make reasonable abstractions. Organize complex logic. Correctly estimate your own development efficiency. Keep practicing. There are many methodologies for writing good code, but I think the core of writing good code is the low-sounding "continuous practice". I won't go into details here, and will leave it for the next article. Many programmers have not made any progress after writing code for a few years, and their code is still so bad that it is unbearable to look at it. There are two main reasons: Environment is one of the most important factors. It is difficult to understand what good code is when you are influenced by bad code, and most people who know will choose to go with the flow. There are also unclear subjective factors such as personal character. Programmers who write bad code are actually easy to get along with. They often love the company, unite colleagues, are approachable, and work hard - it's just that the code is bad. It is difficult to convince people who have worked for a few years to improve the quality of their code. You will only hear repeatedly: "What's the use?" or "That's how it was done before?" So how about starting from the source and raising the requirements for code quality when recruiting? A while ago, whiteboard programming was added to the interview, and recently computer programming was added. I found a phenomenon: a person who has worked for several years, done many projects, led a team, and published some articles does not necessarily mean that he is good at writing code; on the contrary, if a person writes code well, his other abilities are generally not too bad. For example, recently I like to use "write a code line counting tool" as a programming question in interviews. After seeing the question, many people's first reaction is that this question is too simple, it's just writing some code. Judging from the actual results, the recognition rate of this question is quite good. First of all, the questions are simple enough that even those who have not read books like "Interview Guide" will not be at a disadvantage. The questions are also very extensible. Even if you know the questions in advance, you can turn them into different questions with different conditions. For example, you can count the number of lines by file type, or improve the statistical efficiency, or output the number of times certain words appear while counting, etc. From the perspective of assessment, the first is the basic tree traversal algorithm; secondly, there must be a certain amount of code, which can show the programmer's ability to organize code and abstract problems; computer coding can easily show whether the applicant has not written programs for a long time; it also includes an understanding of the program's usability and performance. The most important thing is that the final result is a complete program. I can evaluate the programmer's ability according to the standards of daily work, rather than imagining how this person will perform in daily work based on a function of a dozen lines. But even so, it is difficult to say with confidence that the quality of the code written by this person is good. After all, the interview only represents his ability to write good code, not that he will write good code in the future. 6. Pessimistic Conclusion Having said so much, there are actually only two conclusions, as a programmer: Don't expect others to write high-quality code Don't assume that you write high-quality code |
<<: Careful analysis of mmap: what it is, why it is used, and how to use it
>>: The worst code collection ever
The course is suitable for people Fresh graduates...
To unlock the secrets, one must explore the past....
Recently, the "clay filter" has been ve...
Different periods of Internet development have di...
1. Industry 1. Industry data In October, the sale...
Introduction: When uploading new products to the ...
Amazon quietly entered Tmall, seemingly not wanti...
gossip Melatonin is a "magic drug" for ...
Toutiao video information flow advertising market...
Let me first tell you about my results so that yo...
Growth Effect Store size: At the end of 2018, the...
This is destined to be a turbulent year for the o...
According to Autocar, DS will launch its second S...
On the morning of July 24, 2020, the Heilongjiang...
[[134722]] Eliminating friction and bringing conv...