Clean as You Code: How to win at Code Quality without even trying

The first time you analyze a legacy project - and here I mean any project older than about two months - the results are usually truly overwhelming. There might be: thousands of Code Smells, hundreds of Bugs, high duplication and - depending on the age and technology of the project - 0% Code Coverage. The usual emotional response to this is fear, sadness… even despair. And then the questions come: Where do I start? How do I pick? Which should I fix first: Bugs, Vulnerabilities, test coverage…? Or should I start with all the blockers and work my way down?

People jump to problem solving so quickly that it can be difficult to get across that none of that is really necessary.

Leave the past behind

“First rule of programming. If it works don’t touch anything.”

If you haven’t worn that t-shirt, you’ve probably at least laughed at it. And it’s funny because to some degree it’s true. Digging into old code for no other reason than fixing technical debt brings the risk of functional regression. Plus, the reality is that very few developers have the leverage to get the resources (time, budget, re-testing from the business…) to address problems in “working” code. So let’s set old code aside for a minute (I’ll come back to it) and focus on New Code. As a developer, you own new code. Every keystroke is yours, and you can make sure it meets your own high standards. As a developer you own New Code and more specifically you own quality in New Code.

Personal responsibility, not heroics

That means that instead of hunting down problems in code that hasn’t been touched in years, you should concentrate on making sure the code you touch in the normal course of business - handling feature requests and fixes of user-reported bugs - is clean. Old issues in code you’re touching anyway get fixed, no new issues get added, duplications get cleaned up, and tests get written if they didn’t already exist. That’s it. All you have to do is what you want to do anyway: make sure the code you write today is good.

And focusing on the code the business folks want you to touch, versus dredging up random old problems, lets you focus on getting things done. That means you’re more productive as an individual, and your team is too.

Consistent standards across languages, projects… the entire organization

“But I work on a legacy project in [really old language]!” you say? That’s cool. The tools are the same regardless of language. So just maintain the same standards your colleagues working in [hot new language] are held to: do a good job on the New Code you’re working on today . It doesn’t matter how old or crufty your project is. Everyone can keep their new code clean, regardless of language, project age, or existing technical debt.

Tools to get the job done

I know you’re saying “Sure, but how do I do that?” Fortunately, SonarQube gives you multiple tools. First is automatic issue assignment; no one is responsible for someone else’s code. If you do add new issues, they’ll be automatically assigned to you , and the same for your colleagues, so no one is asked to clean up after someone else. Of course, that applies to any old issues SonarQube finds just as much as it does to new ones, so if you look at the “My Issues” filter on the Issues page you’ll see both old and new issues by default. That’s why there are plenty of other tools in the box.

The most important tool is a New Code Period-focused Quality Gate. The built-in Quality gate uses only conditions “on New Code”. That means the built-in Releasibility indicator only looks at the quality of your recent changes. There’s also the project homepage, which emphasizes those New Code Period values. Then, if you click through on a New Code Period value or on a failing Quality Gate condition, what you land on will be automatically pre-filtered to show only problems in New Code.

And of course, there’s PR analysis (in commercial editions), and SonarLint in your IDE so you can make sure new issues never even get committed and/or merged in the first place.

Technical debt remediation: side-effect of business-as-usual

“But what about all those old Blocker Bugs?!” I hear you asking.

Earlier I said that developers own New Code and more specifically quality in New Code. What I left out at that point is that managers own quality in old code. Remember, developers don’t have the leverage to get the resources to deal with old code. Managers do. That makes sense because managers also own the business risk of having those old issues out in production and they own the business risk of proactively fixing code that no one’s complaining about, potentially breaking something else in the process. So whether problems in old code need to be addressed is a business decision, and it’s up to management to prioritize (or not) work on old code.

But even if they don’t… even without active cleanup, the code base will gradually be cleaned up anyway. It happens in the normal course of business, as you touch old code to make new changes. Areas of code that are modified frequently will be fixed quickly. That makes future maintenance of those high-traffic areas easier, cheaper, and far less painful (\o/). Less-trafficked areas of code will be cleaned up more slowly, but the fact that they’re not impacted by user requests means they’re less crucial and can afford to wait.

Get cleaning!

So that’s it. Just keep your New Code clean to make sure that the code you release into production tomorrow is at least as good as - and probably better than! - the code that’s in production today. SonarQube gives you all the tools you need to make that happen. All you have to do is get started.

12 Likes

Hello Ann,

thanks a lot for this article - I couldn’t have said it better myself :stuck_out_tongue_winking_eye:!

One small note:

Technical Debt means removing Code Smells. A code smell is not a bug: “Smells are certain structures in the code that indicate violation of fundamental design principles and negatively impact design quality”. Code smells are usually not bugs; they are not technically incorrect and do not prevent the program from functioning. Instead, they indicate weaknesses in design that may slow down development or increase the risk of bugs or failures in the future.

On the other hand bugs are bugs and must be removed – independent of their age. By the way: I think it’s great that your tool makes a clear distinction between these two categories.

Regards,
Günter

1 Like

Good article… as long as the optimism it embodies is tightly coupled (small joke there!) with following the principles: i.e. NEW CODE GETS COVERED. Always. Beware the slippery slope of “I’m just changing this one line, do I really need a test for this method, it never had one before…”. That way lies madness.

Also the author references the “1st law of programming”… but much like Asimov’s Laws of Robotics, remember that there is an implied 0th Law: “Is it working?” Broken code sometimes sits around forever, as no-one notices that it’s not really working – stack dumps in logs, work-arounds that tech support has to do for a feature that hasn’t worked in ages, etc.