> However, I've never seen a convincing and objective description of clear code.
I take "clever code" to mean "code that looks pretty on surface the but requires the reader to dig in in order to understand the intent".
The problem with clever code is that it is misleading. It lacks empathy. You assume the next programmer will understand it at first glance just because it looks cool or pretty, but they'll struggle to parse it.
---
> Sometimes people mean that clear code is verbose code.
I also consider some verbose code to be "clever code" too. Most of the time it is just people using hammers where screwdrivers would be more appropriate:
- Unnecessary structures - eg: classes that could be functions taking 2x or 3x more space
- Unnecessary usage of polymorphism - eg: inheritance chain that could be a simple if
- Excessive indirection - eg: layered code where most of the time the layers don't do anything
- Plain wrong abstractions - eg: using query builders to build queries that would be smaller and more readable in SQL
- Fear of making classes too big - eg: instead of adding a method to a class, making a second class that knows too much about the innards of the first one
- Procedural code disguised as OOP - eg: breaking up a method into multiple private ones, but ending up having a lot of instance variables that were local variables before. When everything could be a single function.
---
> The best we have is cyclomatic complexity, but there's some reason to believe that line count may be a better indicator (which can't be good). And cyclomatic complexity completely misses the effect of mutable or immutable state, the presence of bad APIs, poor variable naming, etc.
Great observations. I agree 100%.
Since you mentioned it, I find cyclomatic complexity a bit too easy to game. I always wanted to have a metric that prevented people doing that, and took multiple methods into account.
When you break a method in three or four without adding REAL abstractions (a.k.a. "things you don't have to follow with the debugger to understand"), you're not making it easier to read, in fact you're making it harder because the reader has to jump around your code.
Of course, it's harder for machines to know the difference between good and bad abstractions. But I think we should take that into account in code reviews and such.