Hacker News new | ask | show | jobs
by j1elo 1073 days ago
I'd categorize not being able to convert "unused thing" errors into warnings during development iterations as one of "The Bad".

Just today I had a couple blocks of code which were causing erratic issues. Wanted to see if it was the second one, so I quickly commented it out. This is just an exploratory development session, no need to comply with code quality guidelines. Still, the code failed to compile because now I had to worry about 8 lines with stuff that had become unused. The stubbornness about not adding an escape hatch for, again, exploratory intermediate development iterations is unnerving.

"But code should not leave unused stuff around". I agree. That's why after a hundred iterations, in the final compilation phase for production, this kind of errors-are-warnings flag would be disabled.

4 comments

Honestly, I'm incredibly frustrated with this issue; it's just pure idiocy. Commenting out a part of the code and observing the effects is such a simple and useful debugging technique, yet this "feature" of Go prevents you from doing so effectively.

What's even more frustrating is that when you search for solutions, you come across two kinds of (pardon my language) completely brain-dead responses:

First, there are those who argue that unused variables/imports lead to bugs and worse performance in production, so they should always be fixed. But that's completely beside the point; I've never seen anyone argue that allowing unused variables is good for production. It's always been about facilitating the development process and debugging. Yes, I am aware now there are unused variables, but please just let me see what does removing this part of the code do.

Secondly, people suggest using a dummy function like UNUSED or a blank variable _ to solve the problem. But again, these suggestions miss the mark entirely. Changing variable names or adding UNUSED calls to "disable" the rule is even worse than what we've been doing to temporarily "circumvent" the rule, which is simply commenting out the declarations, test, and undo afterwards. Not only it involves more effort, but more crucially, you might actually forgot to revert those changes and leave in unused variables.

Frankly, I believe this is just a bad design decision, and it seems like the Go team is stubbornly doubling down on this mistake due to ego.

(Sorry, I just have a very strong opinion on this topic, and I am deeply frustrated when the tools I am using think they know better than I do and are adamantly wrong.)

> I've never seen anyone argue that allowing unused variables is good for production. It's always been about facilitating the development process and debugging. Yes, I am aware now there are unused variables, but please just let me see what does removing this part of the code do.

Yes, but once you allow that, you'll inevitably end up with unused variables in production code (warnings are useless). That's the core of the issue and why the Go team made the decision.

In my opinion, the real solution is to have two build modes: --devel and --release. This would allow for not bothering devs with anal checks during development while preventing substandard code in production.

Though the real advantage would come from the reduced pressure on compilation speed in --release mode which would make room for more optimization passes, resulting in faster production runtime speed and lower binary size.

Fully agree on both of these messages. This is the only thing I don't agree:

> warnings are useless

Warnings are useful, to (no surprise here) warn me about possibly problematic stuff. That's why my C++ builds are usually full of warnings during development, but the final build for production won't contain any, because it is performed with -Werror (i.e. "treat all warnings as if they were compilation errors"), thus any unsolved warning would break the build.

A common reply to this argument, which just in case I'd like to reply in advance, is: "but the end result will be that in order to save time, and to avoid having to fix all those pesky warnings, lazy devs will end up doing production/release builds without the -Werror flag (or equivalent for whatever compiler)". To which my response is: That's a social/political/behavioral problem, a poor project management, or any combination of them, and you cannot even start to pretend that those can be solved with technology.

I will literally not touch any language that does that. Not too sad about missing out on Go, but Zig unfortunately also shares this braindead thing.

The solution is all so easy also — just add a debug and a production profile. Enable your strong linter in prod, for all I care, but this is a must-have development tool.

I completely agree. The wonderful speed of the compiler allows for quick small-change, test, small-change, test development. In theory. They then sabotage it by making "unused" warnings into errors, which forces you to waste the time the fast compiler could have saved, making temporary changes (ex: commenting out/in) that aren't needed for the test and won't be needed for production.
I use a technique I call "runtime comments":

  if false {
    ... stuff I don't want to run right now but the compiler still has to deal with it ...
  }
Well, for that specific case (it was a well defined block that could be all selected and commented out in order to disable it), your technique would have worked fine, true :)

But of course it can get tiring and not be very practical if the logic to disable is a little bit more spread out (I'd say having to "if false" anything more than 2 paragraphs or blocks of code would already start to feel annoying)

This is just an intractable problem: if there is any way for people to leave unused code, they will. If you want the code to be clean, you cannot have (for example) a debug mode that allows unused code, because the code will just be left in 'debug' format. Eventually the community shared code will have so much debug-but-it-works code that you'll never get a system of clean code.

And think of what the current strict rule has done: go is the only(?!) language that has a consistently clean ecosystem. When's the last time you looked at go code that huge chunks commented out?

That said... it is annoying. More annoying the less import the script, and the faster you want to test something.

Make debug mode have runtime costs automatically (like race checks, less optimizations for faster compile). That way people are left alone while developing (plus getting cool tools for that as well), while are incentivized to build final prod builds for sane performance, for which they have to clean up after themselves.

Though personally, I dislike this paternalistic approach to handling devs.