Boring Languages Are Underrated (2015)
danluu.com
danluu.com
Most of my day job is spent reading C++ (I write some, too) and it is more terrifying than boring. Understanding when certain errors can (and do) occur and when to optimize for performance over readability is really, really hard.
I believe that Rust, Go and TypeScript have gained a lot of popularity because they are boring to read. Even OCaml has gained a ton of popularity because it is boring to read.
C, C++, python and JavaScript: not boring to read, you constantly need to be on your toes.
Python and Go are good for the reader. These aren't exhaustive lists, just what I'm familiar with. Admittedly, Python is tricky because it looks simple(boring) at first glance, but lets one use a lot of magic.
My daughter is learning cursive and it just reminded me how much I blasted hate it. I can write it fine, reading it is a tossup. It's solely a shortcut for the writer, at the expense of reading. But anything of importance is read thousands or millions more times than it's written.
In programming especially, the easier to read the better, no matter how verbose and boring the language. I think we'll get there, when we all quit pretending we're too clever to write that way.
IMO, Yes! If you put a mental onus on folks to understand x before you understand y, there's no telling how deep the rabbit hole goes. Why not use asm? Why can't you understand pointer arithmetic? The more you increase the mental requirements of the reader, the worse.
I used to be the opposite. I used to write smart C code and feel good about it. Because it was fun and challenging to write, which is what we all desire. With age(mostly) and experience, I realize how much of a mistake that was, if not for others, then older me.
To play off your example, list comprehensions are a nice one liner. In Python, you can do in one line what Go takes 10x more lines for. I still prefer Go, despite it feeling like shackles at time to write.
There's a careful balance required to make a language simple yet expressive so that concepts are obvious. On one side is a Turing machine or Brainfuck, where the concepts in a piece of code don't pop out to the reader because the language is too simple to express them concisely. On the other is Haskell or Rust, where the language expresses so many concepts and has so many rules that the reader will necessarily be unfamiliar with some parts of what they read.
I'm not talking about any difference in "mental requirements". I'm saying suppose, for an equally skilled reader at an equivalent starting point, codebase A (200 lines) takes a week to read, and codebase B (20,000 lines) also takes a week to read. And my point is that many people would blindly say that this means A is harder to read than B, but actually, what matters is whether A is doing more or less than B (i.e. is A solving a harder problem than B or vice versa) - the number of lines is irrelevant!
I wonder if there's a measurable difference in possibility space where 200 lines of dense code is less likely to contain bugs than 20,000 lines of readable code. might be a case of "some infinities are larger than others"
Why would you prefer 10k lines of readable code over 1K lines of readable code?
IDE's make languages like Python really easy to read. Plus these days you also have type hints in Python as well.
-- Reg Braithwaite
Advanced tooling should be a nice-to-have, not a requirement.
On the other hand, there are other contexts such as research or prototyping where it's much more important to get things out quickly; turn your ideas into code so you can see how they work.
I guess my wish is that the language du jour was one that made things harder for the writer and easy to read.
The only reason people seek shortcuts is because they exist.
Software projects are more than just code. Getting MVP out in 2 Months instead of 3 or 4 that it would take to do it properly, could doom the project.
And I am not just talking about startups. I am talking about project at big slow moving enterprises.
Getting somethin that the client can see, is one of the most important milestones.
Sometimes that means that you will need to do a lot of cleanup, after first mvp, and sometimes yes it stays in sad state.
But the alternative often is not better project, but project that got canceled/failed before first release.
There are times that you want to go fast, and times that you want to take your time and do it properly.
This has been the trend for a few years with static typing being added to every language.
Otherwise, it's rather useless as anything but an art form; modern pens don't benefit from it at all and if you're not writing a lot by hand for whatever reason, why bother?
Coincidentally, also the languages actually used to make real-world software. (As opposed to self-congratulatory blog posts.)
If Rust or Ocaml ever get to the point when they're the tool for actually keeping the software ecosystems alive, they'll be terrifying too.
(It's not a problem with the languages; software is terrifying, that's a core property of software engineering and no amount of language abstraction will ever make the terror go away.)
P.S. I've been mentoring software developers for decades, and in my opinion the psychological ability to deal with the terror is the #1 predictor for success in the software industry.
(Probably also what makes it fun and addictive when you ride that tiger.)
For me a boring language is a language that has a single paradigm, and there's one way to implement most stuff. With C and Java, there is little room for making "fun" code, you just write lines and make it work. Java forces you into the OOP paradigm and every problem is just a few design patterns away. With C++ you can have a lot of fun with OOP, templates, compile-time magic, old C APIs, new C++ APIs, even if you solve the same problem, two codebases in C++ will look completely different.
A specific quality described there would be languages that have fewer unknown unknowns, a lack of surprises. C, C++, Java (the three he picks) have relatively few surprises. Either by virtue of design (here I'd say both C and Java) or total industry experience with the language (C++, C, Java). Ubiquity might be another consideration. A lot of other languages could probably be added to the list on that criteria.
Another would be how common it is, especially for a particular domain. In my field (embedded, safety critical, real-time) it would seem like Rust would be a great choice, but it's not common and there are both technical and logistical hurdles preventing its use (for fielding, at least, for proofs of concept it's viable and that could lead to its use in fielded systems later). I'm constrained to C, C++, and maybe Ada. Fortran has been phased out, but would've been one of the boring languages for this domain up to about 20 years ago (for a new project).
I don't think I ever saw more surprising behaviour from a language than c++, although most of the horrible surprises were cfront related and I hope they are gone now.
It seems to me that "boring" is an reverse-pejorative for "C/C++/Java" - which I think is ridiculous, because even in 2015 Ruby and Python should've assumed "boring" status by all means, and the author even sort of acknowledges this! I understand the word as used in "Use Boring Tech" has a certain instinctive resonance to most people, but in all usages I think we should replace it with familiar. What's familiar varies from person to person, team to team, and also doesn't serve as a pejorative to anything else. Pick what you're used to if the goal isn't to experiment.
[1]: Follow-up thought experiment: how many people should have been fired for choosing IBM?
For Rust, it's another kind of boring. The language may be new, but lots of libraries are there. If you want to do something, you can usually pull a few libaries, read the (usually great) documentation, write some glue code and your problem is solved. In that way the experience is usually close to Go.
OCaml is another kind of boring. It's less "crazy" than something like Haskell or Scala. It's really stable, code from 20+ years ago can compile just fine. You can write most of your code as plain functions and data structures but you still have the object and module systems if you need them. Even when they bring big changes to the language such as removing the GIL and adding multicore, they work hard to make sure that existing code won't break and single core performance won't suffer too much.
My point with all of that is that boring means different things to different people. People identities are stongly tied to the language they use (I talk a bit more about that here https://news.ycombinator.com/item?id=28256211). People talking about "boring" languages is probably a reaction to people talking about "exciting" languages and trying their identities to them. Someone says he learned Haskell, I feel inferior because he knows Haskell and JS and I only know JS, but I can counter that by saying that I "focus on the product" and "solve real problems" with "boring languages".
I like the irony that on the same website, there is an article about "Keeping your identity small" (http://www.paulgraham.com/identity.html) and how people that don't use Lisp can't even understand why Lisp is better (http://www.paulgraham.com/avg.html).
Programming languages are a kind of pyramid scheme. If you get more people into the community, you have more chances of using it at your day job, more libraries will be developed, more people will work on the language itself, more people will promote it and do cool stuff with it. Popularity brings even more popularity. And popularity is usually the most important feature of a programming language.
Edit: as mentionned by ashtonkem, the proper term would be "network effect" and not "pyramid scheme".
But you are remunarated in a way. If your pet language become really popular, you don't have to choose between using it for less pay or not using it for more pay. That's either more pay or more happiness compared to the previous choice. There will also be more libraries, better tooling, better everything in general that will make you gain a lot of time.
Also, people that follow you will also be "trapped" in the language as they will have invested in it. If they want to make their investment better, one of the thing you can do it again, bring other people to the language.
Another thing is that if you're someone very important in a small language, and that language gets big, you become someone very important, period. Again, an incentive to bring people into it.
With the above hypothetical, you benefit from more programmers in your language regardless of how they got there, even if someone else “recruits” them, or they were there before you got there.
"Shut up and give me another 500 lines of PHP, we have (made up) deadlines to meet!"
I agree. Ecosystem shapes how good a given language is right now but the language itself is what provides the long-term ceiling. One very real example is JavaScript. You can write all the JavaScript libraries you want and people certainly have ... but ultimately the language is what it is and many of its users still clamor for something better even after immense investment in the ecosystem.
For example, I was writing some vimscript earlier today. Vimscript supports var-args in functions: bad idea. Dynamic type systems: generally a bad idea. Mixing declarative and imperative code: bad. Fancy comments/docstring systems (javadoc, python test): bad. Complicated type system features (e.g. dependent types): not necessarily bad but often unnecessary. Type casting: sometimes necessary but bad. Optional function arguments/arguments with default values: convenient but bad…
Basically any semantic element that increases the cognitive demand placed on the reader should be avoided. Circling back to varargs, they might be convenient when I’m writing a function initially, but they give readers no information, and it’s not uncommon at all that I have to go back and examine the precise details of how exactly I was using this or that vararg again.
Essentially, the more I program the more I think it’s best to use the simplest features possible and avoid anything fancy unless absolutely necessary, even when the fancy stuff is terser. This is part of what makes c, go, standard ml, scheme (even though I just knocked dynamic types) some of the best languages imo. Sure they are missing a lot of great writer-oriented features that programmers tend to drool over, but their absence is actually what makes these languages better.
For instance, natural languages develop all sorts of intricacies that are inconvenient for the learners, but expressive for the native residents.
If the frequency of language usage is high, features of previously medium-level complexity become simpler and more “chunked”, due to how many times you have seen them (e.g. decorators in Python). So to Python residents, decorators are simple.
I wonder if TFA is thinking about some of the harsh words Spolsky had for Java (e.g., [0]). That's not a criticism of boring languages in general, but is pretty negative on one boring language.
[0] https://www.joelonsoftware.com/2005/12/29/the-perils-of-java...
"for Serious Business Stuff you really must recognize that there just isn’t a lot of experience in the world building big mission critical web systems in Ruby on Rails" - in 2006 was true
"I’m really not sure that you won’t hit scaling problems" - Twitter's issues scaling Rails are well known
"that’s not a safe choice for at least another year or six" - For many that was true. For example, prior to Bundler (released in 2010), managing dependencies was hairy.
"you’ll be buying 5 times as many boxes as the .NET guy down the hall" - Easy to throw resources at a problem now, but pre-cloud, that required some serious capex, so it wasn't a problem you take lightly. DHH himself has acknowledged Rails needs more resources, as they aren't optimizing for that problem: "Don’t get me wrong, though. I love speed. I especially love free and cheap speed. It’s just that I’m not willing to trade things that are of real, enduring value to get more of a nice-to-have once we’ve long since reached Good Enough. Things like programmer happiness, the eloquence of Ruby, and the productivity of Rails." (https://m.signalvnoise.com/ruby-has-been-fast-enough-for-13-...)
(FWIW, I'm 100% Team Rails these days, but I do think Spolsky's assessment at the time was valid)
Much like Facebook did with PHP at scale (Hack).
I liked Hack, never used it but it drove a huge amount of change in the PHP ecosystem, 7 was a huge step forward and so was 8 in part because of Facebook.
You can't cite Twitter as a counter-counter example, because it's definitely not a "boring" problem domain (or, wasn't, in 2006).
If you're going to give a wrong prediction like that a pass, then what the heck is the point of the scientific method?
And no, theories do not need measurable data. Qualitative results can be used to support theories (much of my hard science grad school work was basically a binary "can this happen"? That is not really a measurement in a meaningful sense unless you consider all observations measurements -- I do not).
Some things I can think of: databases, architecture, unix tools.
What else do people recommend doing to become a better programmer? I'll admit I've fallen for the "learn esoteric languages" trap for a large part of my journey as a programmer.
- Gdb
- SpaceX real-time flight control
- All fintech (besides FPGAs)
- Fuschia OS
Gdb and Gcc are interesting as wholly successful drama-free transitions from C.[1] https://mobile.twitter.com/danluu/status/934880279772258304
Outside of HFT and matching engines at big exchanges exactly what do you think is in C++? Because I don't think what you said is remotely true. C++, if used at all, would be reserved for the smallest, fastest spinning cog, everything else (95%+) in a more human-scalable tech stack.
Not all. Source: personal experience.
They call it evangelist.
Related: What makes C++ a boring language?
Nah
Rust, replacing C/C++, or Java in some cases (not Android apps), and Kotlin, replacing Java, seem like winners. They are pretty boring in the end, and prevent programmers from making the mistakes that programmers consistently make. Swift also qualifies, if you happen to be writing an iOS app.
In terms of checks for null vs checks against an option type for data, there's some ergonomic improvements for languages with good option support, but it's mostly the same. The real benefit is that not everything is null, and if it is nullable then its explicitly called out.
It's mainly to do with languages that couldn't signify that some value could be null so you'd be forever doing defensive nullity checks. Developers get lazy or forgetful and miss out those checks when they need to be there; without language support, the compiler has no reason to assume that's a problem and lets code go ahead with unexpected behaviour.
The ergonomics of a language that can tell you this value may be null, check for that" or one that provides syntactic shorthand — and that the compiler complains when you aren't treating those nullable values safely — is where the magic happens.
Turning nulls into optionals is all in the name of helping the reader AND the writer.
(And I know I basically repeated what kentm said :-) but it's a message worth repeating!)