There’s a point I made in the book that I’ve had to point out to people several times since then, so I wanted to emphasize it a little more.
When you clean up your code, you’re always doing it for the product. Refactoring is essentially organized Process (the definition of “organization” is not defined as “having to do with business”, but rather “having to do with organizing things”). In other words, we are organizing it so that we can do it. do something.
Refactoring gets a bad name when you start refactoring just for the sake of refactoring. People will start to think you’re wasting their time, you’ll lose credibility, and your boss or co-workers will stop you from continuing to work.
When I say “refactoring just for the sake of refactoring”, what I mean is looking at a piece of code like this: there is nothing In relation to what you’re actually working on, it’s about saying “I don’t like the way it’s designed” and moving parts of the design around without affecting the functionality of the system. This is like watering your lawn when your house is on fire. If your codebase is like most codebases I’ve seen, the “your house is on fire” analogy is probably appropriate. Still, if things aren’t that bad, the point is, you’re concentrating on things you don’t need to be concentrating on. You may feel like you’re doing a great job of reorganizing your code, and you probably are. point Watering your lawn means creating a nice lawn. in front of your house. If the refactoring has nothing to do with the system’s current product or feature goals, it really does nothing other than reorder something that no one uses, engages with, or has any interest in. It means you haven’t achieved it.
So what is it you want to do? Typically, what you want to do is choose a feature you want to implement and think about what you can refactor to make it easier to implement. Or, find areas in your code that are frequently worked on and reorganize in those areas.this will make a person appreciate Your job.It’s not just about that, it’s about the fact that they value you because you’re doing something. effective. But getting recognition for the work you’ve done, or at least some kind of polite thank you, can help encourage persistence and show that others are starting to care about your work. and hopefully help spread good development practices around the world. your company.
Do you sometimes work on a refactoring project with a blank slate? directly Does it have something to do with the work you have to do?Well, sometimes refactoring is what you have to do indirectly Along with the goals you have. Sometimes, when you start working on a particularly complex problem, it’s like picking up a stone on the beach and trying to get down to the sand at the bottom. If you try to move a rock, you will find that you have to move another rock first. Then they saw that the rock was standing on a large rock and there were rocks all around it. that Rocks that impede movement.
Therefore, you should, within reason, address the issues that prevent you from performing the refactoring. If these problems become large enough, you will need a dedicated engineer tasked with solving these problems, especially those that prevent refactoring itself. (For example, the code and its build system dependencies are so complex that no one can move the code anywhere. If it’s a big enough problem, it could take one person months.) Of course. , ideally, d never find yourself in a situation where the problem is too big to be solved by individuals with regular jobs. The way to accomplish this is to follow the principles of incremental development and design, always making it appear as if the system was designed to do the job it is currently doing.
But assuming you’re like most software projects in the world; did not do it Otherwise, you’re now in some kind of bad situation and have to dig your system out of the pile of rocks it’s buried under. I don’t feel bad about this. Because feeling bad about it doesn’t actually accomplish anything. Instead of feeling bad or confused about it, you should have some kind of system in place that will allow you to tackle the problem bit by bit and get to a better state from where you are. This is much more complex than continuing to properly design the system, but it can be done.
A key principle for cleaning up complex codebases is to constantly refactor the services of functionality.
The problem is that there is this pile of “rocks”. There’s something like a house on fire, except that the house is the size of several mountains and it’s always on fire. You need to determine which part of your “mountain” or “house” you really need right now, and take small steps to make it “usable.” This is not a perfect analogy, as fires are temporary, dangerous, and life-threatening. They also destroy things faster than they can clean them. However, your codebase may actually be in such a state. It’s getting worse faster than it’s getting better. That’s another principle.
The first goal is to get the system into a state that improves over time, rather than making it worse.
These are actually same Even if they sound completely different, the principles are the same. How could that be? The way your codebase gets better over time, instead of getting worse, is to have the code you’re adding functionality refactored right before you add it.
Let’s take a look at some of the code. Let’s say this is the code that generates a list of employee names for a company. I need to add a new functionality to sort the list by date hired. I’m reading the code, but I don’t understand what the variable names mean. So the first thing to do before adding a new feature is another, a self-contained change that improves variable names. Even if I run it, I can’t understand the code. This is because it all contains one function with 1,000 lines of code. So we split it into several functions. Perhaps this is enough for you and you find it very easy to add new sorting functionality. However, if you are using an object-oriented language, you may need to change these functions to properly designed objects before proceeding. It’s all up to you. The basic point is that you need to make things. Better And it should get better sooner than it gets worse. The deciding point is how far to go. We need to balance the fact that do Understand that you need to advance your feature goals and cannot refactor your code forever.
Generally I like to set some kind of border around my code. For example, “I’m not going to refactor anything outside of the project to achieve this functionality” or “I’m not going to wait for the programming language itself to change beforehand.” This feature is ready for release. ” But within my limits, I try to do a good job. And we try to set the boundaries as wide as possible so that we don’t end up in a situation where we can’t actually develop features. This is usually a time boundary as well as a “codebase scope” boundary (such as how much outside the codebase is). The time part is often the most important. Create a two-day feature. ” But I still balance things out on the side of spending time refactoring. Especially when you’re doing this for the first time in your codebase, it’s new and the whole thing is very confusing.
And that brings us to another point. You might think it would take more time to refactor and then develop a feature, but in my experience it usually takes less or the same amount of time overall. “Total” here includes all the time spent debugging, rolling back releases, submitting bug fixes, writing tests for complex systems, etc. It may seem faster to create functionality in a complex system without refactoring, and sometimes it is. , but most of the time you will spend less time. whole Before you start adding new features, it would be nice if you could get your system in order first. This is not just a theory. I have demonstrated this to be true many times.I’ve actually had a team complete a project Faster When we did this, the team was working on a new codebase with better tools. (That is, other teams could have outperformed us, but we continually refactored in service of the product, always released releases faster, and actually outperformed in terms of features.) (The developers of both projects are working on very similar features.)
Another point in determining when I’m “done” to refactor a particular piece of code is that others can clearly see the patterns I’ve designed and think they’ll maintain the code. with that pattern Since then. Sometimes I have to write a small document explaining the intended design of a system for people to follow, but generally my theory (which is really just a theory and there’s not enough evidence) (Not yet) If you’ve designed your code well enough, you shouldn’t need documentation to explain how it’s designed. Just read the code and you’ll probably see how it’s designed. it’s very obvious How do you add new functionality within that design that no one would do otherwise? clearly, perfectly It’s impossible to achieve that goal, but this is a general truth in software design.
There is no perfect design, there is Better design.
So this means you’re “bikeshed”, you’re overengineering, or you’re spending a lot of time thinking about how to refactor something, or make it “perfect”. That’s another way to know what you’re trying to do. It will never be “perfect” because there is no such thing as “perfect”. There is something called “doing a good job for that purpose”. So you can’t even really tell if it’s a design or not. teeth It’s okay if you don’t understand what the code is designed for. Some designs are suitable for some purposes, others for others. Yes, there are general purpose libraries, but they also have a purpose. And the best general-purpose libraries are designed through real experimentation with real codebases, allowing you to confirm that they work extremely well for your specific purpose. The idea when refactoring is to change a design that is currently not fit for purpose into a design that is fit for purpose. the current The purpose of a piece of code. This isn’t all you need to know about refactoring, but it’s a very good basic principle to get started.
In other words, refactoring is an organizational process that you perform to enable operations. If you are not targeting production when refactoring, you will run into issues such as: a lot different types of troubles. I can’t even tell you everything that can go wrong, but mistakes will happen. On the other hand, if you simply try to create a system, I never have Rearranging it would create such a mess that it would be difficult or impossible to produce. So you need to do both of these things. A product needs to be produced, and a system needs to be organized so that that product can be produced quickly, reliably, easily, and properly. If you omit the tissue, you will not get the product you need. And if you skip operations, there’s literally no reason to even refactor in the first place.
Yes, it’s okay to water your lawn, but first put out the fire.
-Max