18 comments

[ 3.7 ms ] story [ 42.9 ms ] thread
I really enjoy seeing devs do what this author has done, being open to re-reevaluating previously held opinions. It gives me some measure of hope that others are still capable of giving a language, project, genre, etc a fair chance after an unfavorable first impression. Maybe the second attempt does not change the initial determination for a given user, but the mere openness to give it a shot is what I’m looking for as general practice.

I don’t mean to impose some duty on people to just at random intervals re-evaluate something, but as in the article, if something prompts the possibility for a second chance I would want the default position of devs to be to go for it.

> I now value simplicity more than I did before and I find myself scowling at some of the advanced modern programming features, grumbling that they exist to solve uncommon problems or, worse, to provide an exciting toy to otherwise bored programmers

I wonder if this is “maturing” as a software engineer or becoming more “specialized” (a nice way to say, not wanting to touch/learn new technology)

I also find myself placing a premium in simplicity, but what if “simple” for me simply means what I’m familiar with?

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.
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.

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 }
> 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.

I really can't justify using a language with manual memory management anymore, despite how fantastic a language may otherwise be. I believe progress being made towards simpler automated static memory management is more important, the likes of V autofree and Vale.
This speaks more about the kind of systems that you personally use programming languages to build than the importance of any particular memory management strategy. Pretty much any automatic memory management will need to be disabled or worked around when developing embedded systems or operating systems.

The industry needs a C replacement, and there are many contenders including Hare. You can't replace C without being able to build all the same kinds of software that it can.

There’s this elephant in the room. But it name shan’t be mentioned. Explicitly.
Nim’s automatic memory management is explicitly designed to work efficiently on embedded systems.
> Pretty much any automatic memory management will need to be disabled or worked around when developing embedded systems or operating systems.

I have done a fair amount of hobbyist development with Rust on embedded devices. The naysayers make this sound difficult; it isn't at all.

Great post, love reading these.

I noticed the author mentions implicit context argument passing in Odin. I looked into it, and as I understand it is for language related use only - memory management, etc.

I'm looking for inspiration in this regard as I'm working on a language. I'm familiar with Go-s context passing and aware of Java's thread locals. Can you recommend other any languages with different approaches that I should look into?

Some words on how relatively older he is. No words on the technical side aside from “simple good” and some unfounded or not jabs about complexity being “for fun” or something.

Yeah you’re not gonna get any old age wisdom points from me when the technical argumentation is so thin. But I guess intuition is also a form of wisdom.