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:
// Detect da...
For further actions, you may consider blocking this person and/or reporting abuse
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.
Lately the more Bob Martin quotes I see on dev.to the less I find myself agreeing with them :-)
He definitely has a point, even the agile coach at a client's company keeps saying that but that doesn't mean the point they make it's absolute and applies to every situation.
BTW if you need to justify refactoring to a PO and "be respectful" of Agile/XP/Kanban/whatever you can just use a bug as an excuse. Bugs purposefully don't have points in tracking systems because bugs are just bugs.
Sometimes it's a white lie, sometimes it isn't. Yesterday I refactored a piece of code another (very competent) developer wrote in one session because they needed the feature fast and his holidays were incoming.
I could have just added a breakpoint, fixed the two I found and called it a day. Instead I took a while more refactoring to add a few functional tests, better logging and a little bit of defensive programming (it's a parser for data we don't control), and also fixed the bugs of course :D
It might also be that more senior(ish) programmers can get away with it, I might not have been able to do it if I were a junior, because I would have probably been given less leeway (plus the fact that I would have been less experienced to begin with).
Also it's summer, customers here are on holiday, the backlog is lighter, it's a great time to lessen technical debt ;-)
Oh, we definitely put it as a backlog item. From this month:
In this case, we later discovered better ways to structure our Elm models, and our old models were "oversharing" a lot of things between pages. So, refactoring is a change that potentially touches a lot of places. Intermixing this kind of refactoring with other stories would cause the stories to be too big.
We added this item to a lot of different sprints, but sometimes other stories ate up the available time and it got pushed to next sprint. But here and there some time was put to it, the full refactor should be complete this sprint. And all along the way we have deployed the interim changes.
We have the good fortune to basically approve our own backlog. So nobody told us we could not do that. I act as the product owner and I approved it. :) It is a win for both devs and customers anyway. It prevents a class of bugs that crop up with shared state and is more straightforward to maintain. A good foundation going forward. So worth the time IMO.
I don't schedule time for refactorings. I just clean up a little bit the code I touch. It's just part of the implementation. No need for approval for that.
If there is something big, of course, I get an approval for that. But most of the time, small cleanups are just fine.
I typically create technical debt tickets and prioritize them in with my other tasks. If they are important enough for refactoring, I will go back.