Hacker News new | ask | show | jobs
by ainar-g 878 days ago
I think one of the reasons might have something to do with the fact that with more experience—and thus, often, a higher position—comes the responsibility of reading more code. Often, you come to a point where you are reading more code than you are writing, i.e. when conducting code reviews or investigating an issue. And while the code in more complex languages can still obviously be readable, simple languages force the code to be at least somewhat readable even at its worst.
4 comments

Insufficiently expressive languages make the code long and repetitive. It becomes longer to read and harder to understand the intention. Hence more bugs go unnoticed, not less.

I'm speaking as someone who reads more code than writes for many years.

I nevertheless agree that writing clever code is a bad idea. Code should not be a riddle. But writing smart code is helpful in many ways. Dumbing down a language in order to prevent people from writing clever code looks like an obvious idea, but even such spartan language as C has numerous examples of contrived code, like the Duff's device. A more expressive language won't need these contrivances.

Genuine question, as someone who is approaching the 10 year anniversary of working in the industry: how do you deal with the inherent verbosity and bare-ness that come with that level of simplicity? To this day, loops that aren't of the standard "go through array in order" kind still take me longer to parse mentally than some map/filter/reduce calls ever did, and repetitive/uniform code (like error handling in go) makes it very difficult for me to catch the details. And that's the code I've read (and had to write) for most of my professional career (most of it was procedural legacy software), so I don't think experience is the problem (unless I need more, in which case fair enough). But I think I haven't been able to make the mental switch to be able to separate the important details from the noise, and I don't really know how to
Funny you mention Go, because it's my main language these days. And I have to be honest, I don't have the issues you're mentioning. 99 % of loops in the code I review is the plain for-range type, and whenever it's something more complex, I usually am/recommending splitting away the body. Also helps with complexity metrics (and having at least a maximum cyclomatic complexity checker for your code is a must, imo). And if your error handling is repetitive, there is a high chance you're not adding the important context to errors and/or not checking if the context is added in the reviewed code.

A thing I've discovered that helps me a lot that don't see mentioned at all is to always review code by checking it out on your machine and using your editor to inspect it. Maybe it's just me, but there is something about seeing the code in your own environment as well as having all of your tools to e.g. see where a method is used helps massively.

Re: the splitting the body part, that's usually what I do. When I have to review code that doesn't fit in my brain I just end up checking out the code locally and aggressively splitting it into different functions (sometimes even going down to each function having 1 to 2 lines of code at most) just to lower the cognitive burden enough to understand it. It works reasonably well, but takes a while. As for the repetitive error handling: for me it's more about the shape of the code than the actual code itself. I haven't worked much with go, but the few times I did it was as if my brain turned off the moment I saw the word err, I don't quite know how else to explain it (I have similar problems with try catch, but those are somewhat less common in the codebases I worked with, so the problem is less prevalent)
Re. the shape of the code, it's probably a matter of habit, as I have the complete opposite experience reading code in languages with exceptions. That is, I find that there is too much happening within a few lines, wondering which line can explode and in which ways, heh.
at least for the code i see, the error strings used in wrapping errors actually helps in giving context to the preceding operation. this of course requires the discipline that programmers don't just write if err != nil { return err }
That’s a good point! I find the lower cognitive load and thus the ability of “understand” instead of trusting on multiple layers of abstractions intellectually stimulating!

Sure, I’m still trusting on a compile and an OS and a handful of libraries, but that is certainly a lot less than the standard, say, node.js app out there with a couple thousand npm dependencies.

> And while the code in more complex languages can still obviously be readable, simple languages force the code to be at least somewhat readable even at its worst.

Derived implementations of things like `equals`. An advanced language feature I guess. Easy to read in the complex language, longer to read in the simpler language, and something you have to keep in mind to update manually or regenerate when you update your data structures.