This evening, I sat down to read on some of Uncle Bob's tweets and they are quite interesting, but one of them stood out for me:
And I can totally understand what he means, but I recently started working on a project that is so tangled that it was actually slowing us down. No matter your seniority, you would find yourself increasing the "WTF per minute" counter constantly while working on what seemed like a basic task.
In case you may wonder what the "WTF per minute" reference is about, the following image should help you out:
Which led us to speak to our manager and try to convince them that if we kept going that road we would make our lives worse with each step we take.
So, that resulted in a bunch of tasks that had to be estimated, divided into multiple devs in order to reduce the overall time it would take (as long as they could be worked in parallel) and blah blah blah.
This meant that we would have to spend at least 1-2 months putting everything on hold until we could refactor our code to be easier to manage, for both experienced and unexperienced developers.
Personally, I find that Uncle Bob's opinion should be the way everyone should think, but it should not be written in stone. Depending on how critical or big the refactor may be needed, you may need those refactoring tasks to be tracked.
Other opinions found in this tweet thread:
Which was replied with:
And then Uncle Bob added:
Top comments (14)
I get what Bob is saying, but "never" definitely doesn't jive with me. I definitely settle in for good refactoring sessions. It's always time for refactoring, but some times refactoring is the only goal, and that can be a ton of healthy fun.
In my opinion there are no absolutes when it comes to stuff like this, every project will require different levels of refactoring depending on a myriad of different variables, some of them out of your control (third party API changes etc.). Some projects may be more 'set it and forget it' in that they may perform without ever requiring refactoring.
As for my opinion on scheduling refactoring, I feel like at the start of a project if you spend more time with technical planning (mapping out database tables, deciding on an approach as well as language and framework etc.) and some pair programming this can really help nail a solid code base which won't be littered with
// TODO
s. In theory this project will require less refactoring than a project that has been planned and developed by a single developer whilst rushing and skipping code reviews etc.If you are inheriting a project then I would certainly budget some time in for refactoring. If a project needs significant refactoring I may suggest a refactoring sprint or something similar where we focus on refactoring the required code and stop any new features temporarily. If a codebase doesn't need that level of refactoring but could benefit from a refresh then I would just budget that in with each issues estimate, for example if I estimate 3 hours to solve a task I would say 4 hours to give me an opportunity to refactor some of the portions of code this issue also touches or relies on.
Obviously all of the above is in an ideal world where clients are happy to pay for refactoring time and understand that it should benefit their business in the long term. Unfortunately this isn't always the case and sometimes as developers we do just have to work with what we have and push through and ensure our code is as robust as possible despite the sub-par code we may be encountering.
In my understanding, it depends on the team dynamics (technology, skillset & timeline of the project, etc., ).
We have applied both approaches in our project. One instance, We were able to buy in the Product Manager's approval to do Code Refactoring as a separate task to increase the productivity (reduced time to fix bugs, test & release was the main driving point). But it took a while to do that, especially when people doesn't wanna make change to working product however ugly the code is. We had to explain the benefits that we would get out of the refactoring and we are glad that we did that. This was the image that we showed to PM.
Also as we did the Code refactoring as a separate task, We realized that we could have avoided this separate undertaking if we were little proactive earlier. So as a team we have agreed to do careful refactoring frequently as we work. We do commit the refactoring as a separate commit and submit PR. But We agreed to keep it minimal.
So far We have good success with the approach. As we started doing, the number of PRs for refactoring has declined steadily(fingers crossed).
P.S: To give perspective, We are a small team of 5 people(2 junior & 3 senior developers) working on android apps.
In my own projects, I follow this mentality of refactoring before adding any new features, I own these projects and I define my values, and by my nature as a developer, I give a higher priority for technical values than for business values.
But when working on someone else's projects values vary, they may think that having new features are more valuable than having a high-quality software, some of them would understand the long-term price they would pay by rushing new features and they will listen to developer's advice, but many will not.
Sometimes you will HAVE to write terrible code, you will HAVE to skip tests, then weeks or months later you will finally find a chance to fix your shit, it will become necessary to schedule your refactoring and add it to your backlog.
In Complete Developer Podcast episode 138, Understanding Technical Debt two hosts (Will & BJ) discusses 3 types of technical debts
Technical debt do occur and unfortuntely causes a long term debt.
A famous example of paying off the
Long Term
debt was React Fiber (v 16).React team worked on it for quite a long time to refactor their code inside and out and it was trackable on Is Fiber Ready Yet?.
And now they are adding new features left and right
In an ideal world, you'd refactor constantly following the boy scout rule,
leaving your code better than you found it
.But in practice, how many times have you had one of those,
high priority
tasks/issues and evenhigher
priority issues on top of that?For last two weeks, 👆 is what happened to me. I wrote terrible code and quite ashamed of it. But when you are given 2 days for a week long project, sometimes debt should be accrued to put out the fire 🔥 IMHO.
And yes, I will pay off the debt accumulated last 2 weeks starting tomorrow
I disagree a bit with a few things from the tweets. A patient might not tell the doctor the diagnosis or treatment but they CAN approve or not approve it. For the most part a doctor can't just walk up to a patient and say "hey, we are doing this surgery on you. Done." They have to say "We suggest and recommend this surgery based off my professional opinion" and give it to them in terms that they understand on WHY it would benefit them.
That is how these types of refactors honestly need to be approached sometimes.
This subject interests me a lot and I'd have a lot to say, but can't type it all out on my phone right now
If the project had been kept clean and refactored up until now, there would be no need for you to refactor now. That is the point Robert Martin is trying to make.
Also, it depends on what you consider refactoring.
I tell this story a lot. I like telling it, so I’ll tell it here.
The single proudest day I’ve ever had at work went something like this.
I’m sitting at my desk, working on getting some really gnarly legacy code under test and I wasn’t having a good go of it. I’d already had to roll back a few attempts at doing so. That’s when I overhear this conversation.
Jr. Dev 1: Hey man... this thing could really use some refactoring. What should I do? Who do I need to ask for approval?
Jr. Dev 2: Do it man. It’s just part of the work. Just wrap it in some tests before you change it much.
That was the precise moment I knew I had succeeded as a Sr. Dev at the company.
In my own experience, there are times that code gets to a point where major work is needed to improve performance, readability, and maintainability.
Think of it as remodeling your kitchen:
Removing a broken box fan from your house is easy, removing a wall from your house isn't. Obviously if your adding onto your kitchen, its not a bad idea to look into removing that wall between the kitchen and living room, because the kitchen is already going to be torn apart. Just as obvious, you would repaint your kitchen after the new walls and addition are plastered, not before.
Code's the same way. if you are planning some large new sections of code and dropping others, Obviously you don't want to rewrite something that's getting the boot. As well, knowing what those new sections need in older ones first, prevents you from refactoring code twice, or even 3 or 4 times.
With SBTCVM, a base 3 virtual machine project i run, I and the other project devs decided it was best to start a new codebase, as we wanted to redesign the architecture anyways. With that, it didn't make much sense to refactor the old codebase for python3, when we were working on its successor.
my point is, it depends on what you are planning right now. if you are going to write a new codebase, or massively overhaul your current one, planning your refactoring accordingly isn't a bad idea.
Since there are projects and 'projects' my current rule for new features is to allocate 10-20% of the new feature time for code cleanup of the new feature dependency.
Also, there is the need for refactoring sessions, since you can have a system that's grown too complex, but it touches so many places in the codebase it's hard to track in a small session.