Hacker News new | ask | show | jobs
by ravenstine 1053 days ago
I really dislike when someone considers my code "clever" because it always means they don't approve of it or think it's too confusing. No, I wasn't trying to be clever, but to create the most appropriate solution I could imagine.

The author's problem isn't being overly clever, but that they had applied an inappropriate yet imtellectually-satisfying programming pattern that is notorious for being difficult to make exceptions for. The quote about the correct solution being a "class generator" shows that the author misdiagnosed their problem. If you continue down the path of making everything a class, you're gonna have a worse one than if you made most of your functionality into compostable functions, reserving classes for things that truly deserve it.

So many issues in programming would be diminished if programmers toned down the thinginess of their code, focusing more on procedures and data shapes.

3 comments

Making things worse, I suspect there's at least two (and probably more) definitions for 'clever' that are thrown around and the intent half the time is that one definition is masquerading as the other.

One plausible definition for clever code is that it's code that only works because of a non-obvious dependency on some other fact being true in the code base or outside of the code base. Once the fact is no longer true the code will be broken or subtly broken (or it will break or subtly break other code). "Ah ha, very clever, but we shouldn't do this."

Another plausible definition is approximately, "I don't understand the feature or pattern you're using, and I don't want to understand it or form a coherent argument against it."

The other option is "yes this works well and is very neat, but it's not going to withstand 5 years of people changing it and only reviewing the diffs."
Does anything withstand that? I don't think that's the responsibility of the original author, I think it is the responsibilities of all those devs and reviewers to make sure changes make sense and don't make the system worse.

Nothing can stop morons from ruining good code. Good devs will evolve code into something that makes more sense.

The only code that probably does withstand it is code that does its job so thoroughly from its inception that there becomes no reason for someone to frequently make changes to it. I know such code exists because I definitely have run into code in popular repos that hasn't been touched in 10+ years. This is not exactly the norm though, particularly within web development, it seems. The more developers and reviewers you introduce to a unit of code, the more chaos you introduce, and said code is liable to losing comprehension until a major rewrite is performed.
> So many issues in programming would be diminished if programmers toned down the thinginess of their code, focusing more on procedures and data shapes.

Exactly my reaction too. The code is complicated and requires boilerplate because it tries to adhere to a pattern that doesn't need to exist.

Whenever something becomes entangled and complex, decompose it into pieces first (functions and data) and then put it together again, piece by piece. The right abstractions (if needed) emerge naturally from simple code.

Agreed, when someone calls my code "complex" or "clever," it comes across as an insult
I wouldn't object so much to "complex" because there may be a much simpler way to writing my code. What I don't like about "clever" is that it's always a shit-sandwich that comes off as misrepresenting my intentions. I never write code with the intent of impressing myself or anyone else; my only interest is in writing minimal code that is maintainable and as easy to understand as possible. If my code doesn't achieve that, just tell me without patting me on the head by telling me I was trying to be clever.
It's the focus on "minimal" that sometimes gets called "clever".

Some that I've found in actual code

Using ternary operators everywhere instead of if-else just because it's a few characters less, mixing them in the middle of already complex function calls so that it takes a less clever coder hours to untangle when there's an issue.

Creating your own classes for storage, the best of which was a custom from-scratch implementation of a Vector, but it kept the 3 largest items in the first three cells. It was 100% API compatible with Vector and no part of the API gave any hint of the weird sorting mechanic.

Fluent APIs. Just don't. They look pretty when written, but are a complete horror show to debug.

> Using ternary operators everywhere instead of if-else just because it's a few characters less

This isn't a fair assumption to make. One good reason to prefer ternaries over if-elses in languages which lack if-else expressions (and only have if-else statements) is that ternaries guarantee that you'll get a value for each branch, and with static typing you'll even know what type that value will be, whereas each branch of an if-else tree might do anything, is usually forced to rely on mutation to accomplish its job, and has no statically enforced guarantee of producing the value that you want.

The fact that ternaries are terser is irrelevant. Some modern languages, like rust, have avoided copying this awkward if-else-ternary dichotomy by providing if-else expressions, which is the perfect solution to this particular situation.

I am also honestly a bit concerned over how many developers consider ternaries hard to read. They're one of the most basic constructs of most of the popular languages out there, not some advanced corner case where it might be understandable to struggle with them.

They probably consider them hard to read because people overdo it with multiple nested layers of them when they don't need to, and tools like prettier often format them in completely moronic ways that obfuscate the original dev's intention.
I agree with you and am reminded of "KISS" (keep it simple, stupid): https://en.m.wikipedia.org/wiki/KISS_principle