iTranslated by AI
What to Consider When You Feel the Urge to Refactor Right After Joining a Project
Introduction
Shortly before writing this "poem" (essay), terms like "refactoring" and "immediately after joining a project" were trending in the engineer clusters on SNS.
It was triggered by a specific article, and starting from the content discussed in that article, various opinions were shared on SNS, making it a trend to exchange views from many different perspectives.
I also read that article and decided to write this because I wanted to verbalize and share my current thoughts and exchange opinions.
If you read this article to the end, please leave a comment with your impressions or opinions. It will help everyone, including myself, update our values.
Recommended Readers
- Engineers who have just joined a project
- Engineers who have doubts about the code quality of the project they are involved in
- Engineers who are hesitant about how to propose or proceed with refactoring
- Management-level professionals who want to know the reasons why engineers propose refactoring
Why do engineers feel the urge to refactor?
I believe there are several backgrounds to the patterns in which engineers want to refactor.
- The maintainability of code that has been passed down over time is declining
- When viewed by an expert, many points for improvement exist
- It is incompatible with the code or design that they personally find comfortable
- They cannot understand the code and want to bring it down to a domain they can comprehend
I will verbalize each of these patterns in more detail.
The maintainability of code that has been passed down over time is declining
This is probably the easiest pattern to understand. It occurs when problems that were not apparent during the "0 to 1" phase start to emerge as development continues over a long period.
In a manner of speaking, the portfolio of code assets is in a bad state, and bad money is starting to drive out good. This includes both cases where "bad money was intentionally accepted to maximize profit" and cases where "no one noticed that bad money was included in the portfolio."
There is a risk in leaving manifest problems untreated. When that risk exceeds the development team's tolerance for risk-taking and becomes a source of significant stress in performing their duties, the background of "which part is causing what kind of problem and why it should be solved" becomes easy for the entire development team to digest. This makes it easy to create a movement of "Let's solve this together as a team!"
In this pattern, the impact on the business varies greatly depending on whether you can move to "do something before it's too late" or whether you are at the stage where "it's already too late, so new development must be paused to perform refactoring." The latter can be a major blow depending on the business phase, as it requires stopping the growth of the product.
When viewed by an expert, many points for improvement exist
Engineers (to a greater or lesser extent) are often involved in the "0 to 1" phase of creation, and their proficiency (implementation and design skills) at that stage is, honestly, all over the place. Sometimes, engineers with high technical skills and experience build things out aggressively; other times, they write code that is nearly identical to an example while testing out a new technology.
And in the latter case, to a technical expert who has understood and used that technology to some extent, it "appears" as if:
- It is not optimized
- Language features are not being utilized well
- The design (quality, maintainability, scalability, etc.) is inherently poor
I believe this is inevitable as long as a gradient in technical proficiency exists.
It is also in an engineer's nature to feel an itch regarding these points. Since their role is to touch, create, and ship new things, the supreme missions of their job are "how to efficiently develop and ship" and "how to implement high-quality products without bugs," and these teachings and instincts are passed down continuously.
No engineer wants to be involved in an environment "overflowing with glass-like code that triggers a bug at the slightest touch" or where "excessive redundancy prevents smooth development." This is because the fear that their own commits might have a negative impact on the product is always present, making it stressful.
Engineers are a profession with a very strong awareness of performing refactoring to resolve these issues and improve the situation even slightly.
In this pattern, you may sometimes be given a role with the request to fully demonstrate your high technical skills and experience to make continuous improvements. In such cases, clearly communicate the areas for improvement, set a direction, and drive improvements aggressively. After all, that is the commitment expected of you.
Incompatibility with the code or design that you personally find comfortable
This pattern is also a classic. I used to fall into this often myself. And it's a pattern that tends to generate more negative opinions than others.
Through various past projects, personal development, and study, engineers establish their own "best practices" and "anti-patterns."
Then, you are assigned to a new project, and looking at the code... what do you know, the design and concept are far from your own best practices! Seeing code built on a philosophy completely different from what you find comfortable, you might become eager, thinking, "I must improve this!"
I call this the "Mom who cleans the room without permission phenomenon." I'm sure many of you have experienced this from the perspective of both the child and the mom.
This "Mom who cleans the room without permission" has the following problems:
- Mom uses only her own values as the standard for judgment.
- Mom starts cleaning without permission, without imagining "why it's messy."
- Even if it's uncomfortable for Mom, it might be comfortable for the child.
Now, let's look at these in order.
Mom uses "only her own values" as the standard for judgment
This is the episode I mentioned at the beginning of this section. Under the conviction that "(My) best practices are not being followed! It's definitely better to do it this way!", one ends up trying to perform refactoring.
To be sure, from that person's experience, it is a best practice, and they have likely been saved by that method many times. Moreover, that was probably undertaken after obtaining the team's agreement. Whether it was through agreement when addressing the issue of "declining maintainability of code passed down over time" or being accepted through daily code reviews, it varies.
However, what if it isn't a natural flow like that, but starts suddenly based only on the feeling that "it should be done this way!"? What would other engineers think as they watch the cleaning proceed steadily, even though they haven't been able to fully digest the merits (and demerits) of that practice?
Mom starts cleaning "without permission" without imagining "why it's messy"
The environment you are in now is different from the one you were in before. Project scale, people involved, and roles. Why the project was launched. How they solved the difficulties they encountered. There are almost no parts that are the same as where you previously belonged.
If you try to start cleaning at a stage where you haven't been able to catch up on that background, you might make the team feel (somewhat negative) emotions like "Why are they trying to clean the room..."
Also, the child might have actually "been planning to clean." They might have been in the middle of agonizing over "What should I use to clean?", "Where should I start cleaning?", and "How should I clean?"
Exactly at that moment, Mom comes in and starts cleaning. This spoils the fun for the child who was planning to clean. "It's better to put this here!", "This clothes is already too small for you, so I'll throw it away!", "This is an important memory, so keep it without throwing it away!"—she even starts decluttering and organizing.
That act might disregard and (to use strong words) even negate the child's thoughts like "It would have been more convenient if it were closer to the bed...", "It might be small, but it was my favorite outfit...", or "I've kept it as photos and albums, and since I was having trouble with where to put it, I was thinking of storing it in the closet..."
Even if it's uncomfortable for Mom, "it might be comfortable for the child"
This part is difficult to talk about because it involves psychological workings, but humans have a bias where "immediate gains are considered more important than far-future gains" (this is called present bias).
Every human has a psychological tendency to "want to feel satisfaction from current things rather than the future." Even if one vaguely thinks "I might have a hard time someday," they find strong value in "now" rather than that "someday." And everyone gets used to that situation.
Members who have been involved in the project for a long time might be in this psychological state and might even feel that the current environment is "comfortable."
Unable to understand the code and wanting to bring it down to a level I can comprehend
Strictly speaking, this falls outside the definition of "refactoring," but...
I do this myself as well. There are times when I read code for the first time and the complexity is so high that I can't fully digest it. In such cases, I sometimes take the approach of making changes until the code takes a form I can understand, and then deepening my understanding during or after that process. It's following the process of "Understand, Deconstruct, Reconstruct."
There are a few points in this pattern that often spark debate:
- The pros and cons of altering code solely to deepen one's understanding.
- The pros and cons of the opinion that "if you don't understand it, you should just ask someone who does."
First, regarding "the pros and cons of altering code solely to deepen one's understanding," I think there are both good and bad sides.
The good sides are:
- The code becomes easier for newly joined members to understand (and as a side effect, the code becomes more scalable relative to the number of people).
- By organizing the code, new points for improvement may be discovered.
The bad sides are:
- For existing members, there is almost no point in refactoring.
- Code that was (thought to be) optimized might end up in a non-optimized form.
Whether these are seen as good or bad depends heavily on how the team perceives these points.
Next, regarding "the pros and cons of the opinion that 'if you don't understand it, you should just ask someone who does,'" I think this varies greatly depending on the maturity of the entire team and the existing members.
If all existing members "are thoroughly familiar with all specifications and implementations" and "can clearly communicate them to new members," then it will likely function without issue. However, if even a part of this is not mature, it can lead to feelings like "I couldn't understand it even after asking, so I have to figure it out myself." This leads to such alterations being made, or in the worst case, a situation where they have to modify the code without understanding it. This results in shortening the lifespan of the code that everyone has worked so hard to make durable.
Engineers live by understanding the code they touch. It is vital to prevent that from being significantly hindered, and we often deconstruct code in order to understand it thoroughly.
Is Refactoring Immediately After Joining Bad?
So, let's summarize the thoughts on the pros and cons of refactoring immediately after joining.
I believe that among the patterns mentioned above, it is highly likely to become an anti-pattern in cases other than the "many points for improvement exist when viewed by an expert" pattern.
The pattern where "the maintainability of code that has been passed down over time is declining"
First, when "the maintainability of code that has been passed down over time is declining," it is no longer just an issue for the development team, but a full-fledged business issue. Since it is a business issue, it becomes a problem that not only the development team but also the product owner and people in layers above them must be aware of.
So, when making a proposal, you must take responsibility for "raising an alert to people in all levels involved." Would a member who has just joined the project be given the authority or judgment to do such a thing?
Unfortunately (in my career experience), such things are rarely entrusted to you. This is because it creates highly political problems. Impact on business, methods to compensate for decreased profits, accountability to customers, and various other things will come rushing in all at once. Unless you have a very strong voice, proposals that have a strong impact on business plans will not pass.
Also, there are cases where "the product owner is making a business decision to accept current debt." In that case, they will choose "developing product features from code that is continuing to generate profit, knowing it might be somewhat messy," over "time to create clean code that doesn't directly generate business profit." In that situation, you must provide an explanation strong enough to significantly overturn the present bias. This is an act that requires a great deal of effort and stress. However, unless you overcome this, the business judgment will not be overturned.
Therefore, if you are trying to make a proposal for this pattern immediately after joining, you must face it with the corresponding determination. You must stand up to a large organization with the smallest voice. And very few people can successfully achieve this.
In this case, let's start with understanding "why the codebase is like this." Is it the result of piling up to ship features quickly in a short development period, was it unachievable at the time because the team's proficiency was lacking, or did they arrive at it after trial and error? Understanding history is understanding the background, and thus understanding the present and the future.
By learning from the past, current issues become more refined than before. You might find that the improvements you thought were necessary are actually low priority, or new issues might come to light. Next, break down the solutions to those issues into small tasks and try submitting them during the gaps in daily work or spare time. Present the future little by little, saying, "If we complete all these small tasks, such good things will happen."
The most important thing is to gradually increase the number of people involved in the improvement. From "just you, who just joined" to "members who know the code's background and current issues well," then to "the development team that reviews daily improvement tasks and understands the ultimate goal." And finally to "stakeholders who understand the benefits of improvement and willingly accept daily improvements," gradually increase your allies. Practice bottom-up through collaboration, not conflict.
The pattern where "when viewed by an expert, many points for improvement exist"
Regarding this pattern, I believe it is perfectly fine to make improvement proposals aggressively.
Those who agreed to your joining the project strongly expect this kind of movement as part of your role. Fulfill your role of improving the quality of the code and the product by making solid proposals.
However, even in this case, understanding the background of "why it was implemented this way" is essential. While it's fine to propose fixes for universally recommended areas, things get a bit different when it comes to best practices based on experience.
There is always a reason why the codebase became that way. Pushing through solely based on your own experience without knowing that reason amounts to disregarding the best practices of existing members.
The pattern where "it is incompatible with the code or design that they personally find comfortable"
In this pattern, the issue of the "Mom who cleans the child's room without permission" mentioned earlier emerges. It is a bad move until you understand the background of why such an implementation exists.
The pattern where "they cannot understand the code and want to bring it down to a domain they can comprehend"
In this pattern, you want to avoid suddenly saying, "I didn't really understand it, so I tried refactoring it!" This is because the diffs created by refactoring do not necessarily have a positive impact on existing development.
When you are about to fall into this pattern, I first recommend asking the existing members as many questions as possible. The existing members who actually wrote the code are the most knowledgeable about "what the logic is" and "why it was built this way."
If the answers to your questions are unclear, or if they don't answer your questions at all, the team's level of proficiency might be low. In that case, it is acceptable to submit the results of deconstruction and reconstruction, even if only to verify the understanding of existing members. At this stage, considering refactoring as a means to achieve understanding of the code is, in my opinion, acceptable.
The submission method could be "summarizing in a document" or "submitting the actual refactoring results as a Pull Request to see how it goes." In the case of a Pull Request, if it's unnecessary for existing members, they will likely just close it without merging, and if it's a document, it will certainly help future members understand the project.
How to Make Refactoring Proposals Easier to Pass?
To put my thoughts into one sentence: "Instead of being the 'Mom who cleans without permission,' first aim to be the 'Professional cleaner who is hired to clean.'"
A "cleaning professional" does not discard the client's personal belongings without permission, nor do they significantly move the placement of objects. They only clean the areas that "anyone can judge as dirty."
As you repeat such cleaning frequently, the client starts to feel, "Come to think of it, I don't really need this," or "Since it's become clean and the room feels wider, I want to make effective use of the space." That is your chance. Try making a proposal that you believe is best based on your experience. Try decluttering together or suggesting ways to utilize the space. While empathizing with the customer's pain, let's achieve the best improvement together.
Summary
In this article, I verbalized the "background of why we want to refactor," "is refactoring bad?", and "how to make refactoring easier to pass."
I would be happy if this "poem" helps you brush up your values or serves as a seed for discussion.
If you liked this article, please "Like" and "Follow"!
Discussion