Sunday, February 13, 2022

Don't Ignore Compiler Warnings. Unless...


One of the advantages of using a modern compiler is that it can generate hints and warnings that suggest improvements or highlight potential bugs in your code. Well worth paying attention to.

This post was inspired by a "programming best practices" discussion in a Delphi Facebook group. I was surprised to read that some developers didn't think compiler hints and warnings were very important or even ignored them altogether. Of course, it's Facebook, so maybe someone was pulling our collective leg, but I've inherited more than one project that was littered with them, so it does happen "in the wild".

I consider it to be a matter of code hygiene.

If your code produces a tonne of hints and warnings (you know who you are), there's a pretty good chance that there are avoidable bugs in that code. Or, put another way, resolving these is an easy way to fix potentially obscure and difficult to troubleshoot bugs.

Even if you think some of these are benign, they add a lot of noise and obscure more serious problems.

If you wanted to, you can turn off all hints and warnings, but that's even worse than just ignoring them. It's like covering up the check engine light. The problem doesn't go away. In fact, it will probably get worse.

Some people go the other way and report any warnings as errors. I don't do this, but you have to respect their commitment.



I strongly recommend eliminating all hints and warnings.


Unless...

There are very few absolute rules, but there are a lot of hard learned "unless you have a really good reason to do otherwise" rules and conventions that developers should follow.

Except WITH. Don't use WITH.

So there are some cases where you might not need to pay close attention to hints and warnings.


Throw-away code

If I'm creating a proof of concept or just tinkering around to figure out how to make something work, I don't worry too much about making that code "production ready".

If any of that code makes it into a real application, then it gets cleaned up.


Someone else's code

If I'm using a third party library or unit that generates hints and warnings and I don't want to change their code, I'll do a full build, copy the appropriate DCUs to their own folder and update either the global library path or the project's search path to point to that DCU folder. Now when I do a build, these messages aren't cluttering up my build log.


Specific Warnings

It the case where you're sure that a warning won't apply to you, you can selectively ignore it in project options.

The only time I really do this is when I'm certain that an application is only ever going to support a single platform, like Windows. I explicitly turn off Platform Symbol and Platform Unit warnings




As a last resort...

I hesitate to even bring it up, but if, for some reason, you can't or won't change a tricky piece of code to remove a hint or warning, instead of turning them off for the entire project, you can use $HINTS or $WARNINGS compiler directives around a specific block of code to suppress them. Or, better yet, suppress a specific warning using the $WARN compiler directive.

If you have to do this, and that's a big if, then consider using these directives on as small a block of code as possible and maybe include a comment to explain why warnings are being suppressed. Or a TODO comment to remind your future self to clean up the code properly.


Going further With Static Code Analysis

Compiler messages are fairly conservative and limited to technical issues in the code itself.

Static code analysis tools do some of this, too, but they also take a broader look at a project as a whole and make suggestions based on well known and potentially problematic software development patterns. They might be described as being "opinionated". This includes things like overly long or complex methods that could be refactored, duplicate code, unsafe code, potential memory leaks, etc. One of my favourite Delphi-specific metrics is unused units in uses clauses, which is great for cleaning up legacy projects.

The first (as far as I know) static analysis tool was Lint, created at Bell Labs in 1978 for the C programming language. Today, implementations exist for almost any language, including Delphi.

Some ship with Delphi:

And there are some commercial options:


If you have some other suggestions, please post them in the comments.


Conclusion

Fixing compiler hints and warnings at the earliest opportunity improves the quality of your code and keeps you from accumulating technical debt.

You still need to be careful. Any code change has the potential of introducing new bugs, so use good software maintenance practices. Make sure you understand a change before making it and try to only change code that you're sure is going to be tested.

2 comments:

Roland Bengtsson said...

https://github.com/JAM-Software/SonarDelphi
Analyzer for Sonarqube

dummzeuch said...

I have inherited lots of code that was littered with hints and warnings and also had memory leaks. Some people apparently think they are so good at programming that they don't need to heed those who advice them differently because they know how to do things. Of course they usually turn out to be wrong and some formerly untraceable bugs all of a sudden go away when fixing the causes for the hints and warnings. Most of the memory leaks also vanish then. Must be magic,somehow.