clang-format considered harmful
I don't know of a good C++ code formatter, but clang-format is not one. It is a thing I don't like about C++.
1. Myths
First, I must dispel 4 oft-cited myths used to argue for uncritically slapping on a random coding standard.
Myth 1: Any coding standard is as good as another.
There is such a thing as practicality in coding standards. Before even contemplating controversial topics – aesthetics, it's not hard to think of aspects of code formatting that contribute to write amplification – how big a change becomes in the resulting diff – that should be uncontroversial. Let's get the basics right:
-
Ease of adding or removing an element at the end. This thing:
XXX XXX = XXX::XXXXXXXXXXXXXX { X, Y } -
Reflow ripple effects: This thing, after inserting "something":
XXX XXX = XXX::XXXXXXXXXXXXXX { "something", X, Y } -
Dependent indentation: This thing, after you renamed it (and forgot to reformat):
XXX XXX = XXX::XXXX { X, Y } -
Indentation dependence: When changing the scope of a section of code causes the formatter to change strategy:
{ XXX XXX = XXX:: XXXXX { X, Y } } -
Human predictability: Does the formatter follow rules that a human with infinite experience can predict, or does it play chess with sums of weighted costs? In practical terms, must you run a formatter locally in order to write anything that CI will accept?
There exists a formatting that has none of these problems. I'm of course talking about the self-evident pythonic/rustic formatting (which probably has many more names):
XXX XXX = XXX::XXXXXXXXXXXXXX {
X,
Y,
}
Myth 2: The most important thing is to have a coding standard and enforce it.
I remember a time before clang-format: I would say that professional developers did at least as good of a job as clang-format to begin with. In fact, in some ways better than any autoformatter could ever come up with, because the human knows best, such as which arguments are associated. Freedom of expression! This openness to creativity made the conventions fluid, so that better ideas had a foothold.
In contrast, with clang-format, I see good developers being passive and indifferent to details like trailing comma that are not at all insignificant to what clang-format will do.
If the purpose of automatic formatting is to avoid style disputes in code review, it doesn't work, because too few people know the importance it gives to trailing comma – I have to nag people about it.
Myth 3: It is possible to configure clang-format to a pythonic/rustic style.
I have tried every config option. There is AlignAfterOpenBracket, but you have to do the rest yourself in terms of remembering trailing comma (which is only applicable in curly braces and not enforceable), forcing line breaks with line comments and liberal use of // clang-format off.
Myth 4: It is always convenient for everyone to run the formatter.
If you haven't noticed the trend, everything is wrapped in impenetrable all-encompassing dockerized CI-scripts that can't just check a small change quickly.</sarcasm>
It doesn't actually matter how convenient it is, because I don't necessarily approve of what it does to my code – I can't run the formatter before I have committed my changes anyway. Then, I rewrite my code to comply if needed be. If revising one's commit stack isn't hard enough as it is, doing it with style changes into the mix is the worst.
2. Properties of a good formatter
- Sensible by default, or a sensible configuration (after the criteria above) must exist in its configuration space.
- Slack: The human knows certain things better than the formatter, such as which arguments are associated, and may therefore have a preference for where to break the line if necessary. The formatter's job is not to take this freedom of expression away. Its job is to satisfy a disjoint set of requirements. Therefore, it must allow more than one way to lay out the same code. Python formatters do a good job in this department.
- Humanly predictable.
3. So what's wrong with clang-format in particular?
All the above. If clang-format behaved like a python formatter or like rustfmt, you wouldn't be reading this. Though I'm no fan of automatic formatting in general, other languages have it better.