Should you learn Rust?
Oftentimes, I see a variant of this question posted or asked somewhere. In general, most of the times I think the answer is „Yes“, but maybe for reasons other than you’d think at first.
First, the trivial things out of the way. If you ask me if you should learn something, most of the times I’d answer yes simply because learning anything is good for you. It broadens horizons, stimulates the brain and makes you step out of your comfort zone. Besides, you never know what knowledge or skill comes handy. And Rust definitely is something stimulating to learn and you’ll step out of your comfort zone doing so.
But if presented with the question „Should I learn Rust or this other language?“ (because everyone’s capacity to learn and time is limited), then it needs some explaining why I’d think it still is a good idea to choose Rust, especially if you already know some other language (Rust might be a bit hard as the first language).
If you consider Rust because you already know C or C++, find it annoying to work with or slow to code in, then you probably already have your answer. If you know you want the challenge of learning Rust or you find the community nice, then this as good reason as any. If you want a good, enjoyable free-time language, then go ahead.
But if you ask if Rust will help you get a better paid job, then it is a little more complex. Getting a Rust job is not easy (it’s probably easier to convert an existing job to a Rust one, but that takes a lot of social skill and a lot of time). So how could learning Rust help you to a better paid job? I think it could. And not 5 years from now (when companies start hiring Rust programmers), but now.
Let me digress here a bit. There are programs of different qualities. Some of them are mostly bug free. Someone wrote them, put them to production and forgot about them for two years, until the user base grew hundredfolds and it needed to be extended. On the other hand other programs bring attention to their existence on weekly basis, with a fresh bug every time. You can guess which ones I like more (both to have around an do be writing). You can guess which ones the companies prefer to have running on their servers (even though some of them fall pray to the illusion the other ones are cheaper to make).
What sets them apart? Is it the tool used to build them? Is it some trick, dark magic or technique, transferred under the promise of silence from master to novice? Praying to the right god before each commit?
While some techniques or tools exhibit a tendency to help or hurt the quality of the code, these are just statistical tendencies. I’m pretty sure I could find an artful masterpiece in whatever language, as well as terrible piece of crap (yes, that also includes Rust). I could find failed projects despite them following every piece of good advice out there.
However, I know people who reliably without any exception produce the masterpieces, no matter how inadequate tools you arm them with, as well as people who produce substandard quality results despite all the tools you give them. It is the first kind that chooses their employers at will.
So if it is all about people, why does the industry strive to produce the better tools? Mostly, because it is easier to produce good-quality tools than good-quality people, but for other reasons as well.
How do the bugs come into existence in the first place anyway?
A bug is a consequence of a broken, confused or completely missing mental model
of the problem and program. It is not the programs that are being confused. It
is us, their authors (yes, I know, that is a bit humbling realization,
considering all the broken software out there). To create a good program, one
has to first attain a clear and correct understanding of the problem, the
solution, to know it inside out. And there are many challenges to this. The most
obvious one is the fuzzy human brain, but unclear requirements, the sheer size
of the program, its age, the team (there are
n+1 versions of the vision in a
n people) or companies not wanting their employees to think also add
To get a good program, also some technical good practices are needed ‒ like paying attention, having the time to do it, etc. But bugs caused by this are often easier to fix than the ones coming from the broken vision.
Things that help
This is where our tools come into play. They help our limited brain power in the fight with the many-headed hydra of confusion. However, many of them need to be applied with care and moderation or they could hurt more than help.
- Splitting the problem into separate, mostly independent pieces helps, as one needs to keep only the model of the one smaller part in mind at each given time. The big problem can be split up between people or teams. If not split, one gets a spaghetti mess of code (everything is interconnected and it’s impossible to make sense of it). The other extreme is Lasagne code ‒ if partitioned into too many too small pieces, when there are just too many layers and it’s impossible to find the place where something actually happens.
- Writing (drawing, imagining, …) a design up-front, even though it isn’t followed 100% in the end. It helps to have a vision instead of cancer-grown code that works only because of luck. This helps fighting complete lack of the mental model, as well as helps solidifying it to some extent ‒ in other words, think before starting to debug an empty program.
- Reasonable amount of tests (somewhere in between of none at all and boring everyone to death with testing trivial getter methods). These don’t only help you catch a regression right after it is introduced to the old code, but it also helps you check your assumptions about the code and state how the code should be used (which is a valuable archaeological artifact with legacy code ‒ tests tend to be less out of date than documentation). As a note, I often find that it makes sense to write some tests before the actual code (as TTD states) to help me understand what result I want to achieve, and some after, when I know where the tricky parts of code lie and aim the tests at the most vulnerable places, to make sure I didn’t break these parts.
- Code reviews help to catch bugs made out of not paying attention. More
importantly, they help to unify the team mental model (it’s still
n+1different versions, but the differences are smaller) and invite challenging the mental models of each other.
So, how does this relate to Rust or languages in general? I noticed few things:
There are languages in which I produce mostly bug-free code. This is code I wrote and after trying it once or twice, fixing few trivial things, I’m reasonably confident it does what it should (and it later on turns out to be mostly true). And there are languages that often lead to code I’m just not confident about all (or I’m confident the code is broken, but don’t want to spend the time fixing it).
The first group contains Rust for me. It is not a big surprise, as it is language specifically designed to help write correct code. But I think the advertised reasons (preventing segfaults, data races…) are the less important part (they are still very valuable, as they prevent the most dangerous catastrophes, but it’s not what helps against most of the bugs, or the most frustrating ones). What might be a surprise for many is that this first group also contains Perl for me.
On the other hand, if I want a reliable code I’d never willingly choose Python (note that this may differ for you, this is nothing against Python, and even I choose it for some tasks ‒ just not the ones where reliability is the key factor).
However, I also noticed that after learning Rust, the code in all the languages I write in improved. Why?
It comes back to the mental model of the problem. Rust has a very strict and tight type system. If your mental model is confused, something will not align in it properly and it won’t compile. It doesn’t matter if it’s lifetimes, types, or just getting a very hairy interface (which you, in the end, beat into submission, but feel that it’s not supposed to be that way), you’ll get a feedback that what you wrote is wrong in some way. It’ll kindly remind you to step back and think about what you try to do. Haskell is very similar in this, but it also kind of assumes you are an expert in algebraic theories ‒ so if you like algebra and formalisms, you might get the same benefits from Haskell, and you may enjoy it more than Rust (or you may find that you need neither of these two, because your thinking is precise enough already and there’s nothing more they can teach you).
Furthermore, Rust’s community has a large concentration of the kind of programmers that produce the masterpieces. If you hang around, you’re bound to learn something from them ‒ curiosity and good thinking habits are contagious.
With Perl ‒ at least for me ‒ it’s better expressiveness of the languages. Perl
was made by a linguist and whatever mental model I have is easier to transfer to
it than to other languages (for example, while technically equivalent, there’s a
slight difference in the connotation between
if not and
unless to the human
brain). That mental model can still be wrong somehow, but at least it doesn’t
get worse by the translation to the language and I can think with less
restrictions, closer to how my brain works, not how the language works. Also,
the fact Perl programs are just terrible to debug and fix makes me pay much more
attention to the thinking upfront as well as the implementation. If Rust is
martial arts teacher, Perl is a pub brawler. If you survive either, you’re
likely to be good at defending yourself, though both can be painful at times.
Taking Python, the language tries to be comfortable. Which isn’t a bad thing in itself, but it lets one slack in the thinking. Where Rust’s type system breaks and shatters on the wrong mental model, Python’s simply bends. This is a good thing when the goal is to get something done quickly and the quality doesn’t matter that much (learning the first steps, writing tests for other software, prototypes, one-time analyses of data, something that runs on premises and under surveillance of the author), as it doesn’t force one to make the proper mental model. It just kind of works, without that much effort. Imagine a donkey in medieval time ‒ traveling on a donkey wasn’t especially elegant or fast, or fancy but it was reasonably cheap and got you from place A to place B, probably without throwing you off and breaking your neck. It just didn’t make you exceptionally good at anything, while riding a horse (especially a wild one) could.
Even if you don’t expect to write a single line of Rust code for money in the next two years (I hope companies learn by then that Rust is a good solution for some of their needs), learning Rust is very likely to help you get a better job by becoming a better programmer overall. There are easier languages to learn, but it is because learning Rust is 10% learning its syntax and rules and 90% learning how to think properly. Most of that 90% is applicable in other languages, they just don’t mandate that you do.
In other words, Rust has your back when it comes to making sure you thought about the problem and that you have solid model. In other languages you’re on your own, but at least you know what you aim for.
Therefore, you probably should learn something like Python first (if you haven’t already). It’ll let you get away with almost everything. This is good as the first step, to get familiar with programming in general, what it is about (and then keep it in your toolbox for times when it is the right tool for the job, same as every DIY person has a lot of duct tape around). Then something that is a good teacher, which could be Rust. As it is said, smooth sea never made a good sailor. But you better start your first attempt at the smooth sea.
And then, lot and lot of practice. Of course you don’t reach mastery just by learning a language or two, but by spending thousands of hours fixing errors (made by you and others) and learning from them.
However, one warning. You’ll have easier time getting paid more, but also harder time picking an employer that can give you satisfying problems to solve.