Taking Rust for a Test Drive
At Ferrous, we often help folks who are in the "getting started" phase of using Rust. Sometimes their engineering teams have started using the language unofficially and they'd like some help making it official, and other times we are approached by CTOs or Engineering leads who are interested to see if Rust can help their development team.
We don't generally advise folks to dive in head first, or to rewrite everything from scratch in Rust. Instead, we suggest finding a good first project to take Rust for a test drive, so you can try before you buy.
The right "first project" aims to solve a problem in Rust that's isolated and compact, but still poses a realistic test case to assess whether Rust fits a team's needs.
Picking the right first project can be hard! Since we have experience helping teams with this process, especially in selecting projects that are specific to them, we wanted to share some of our common guidance. This is directed both at managers as well as engineers starting this process on their own.
On the search for a first Rust project, we aim to answer these three questions:
- How can we minimize cost or risk to projects and timelines?
- How can we maximize rewards (reliability, efficiency, developer happiness)
- How can we maximize the learnings from the first trial?
Let's break these down in more details, and remember: If you ever need a hand with this, just get in touch, we're happy to help!
Qualities of a good first challenge
Choosing a good first project with Rust is all about finding something big enough to give you real data, while being small or isolated enough to limit the total amount of time and effort invested, in case it doesn't pay off on your first try.
Pick a problem domain you already know
Implement (or re-implement) a problem you are already familiar with. It's important (from a learning perspective) to focus on learning one thing at a time, and if you're already learning Rust, you don't want to be struggling to know whether there is a problem with the language, or with your understanding of the project.
This makes it easier to assess whether it was Rust that made the problem-solving difficult, or the problem and its unknown unknowns itself. By only changing one variable at a time, you'll get better measurements from your experiment, and avoid unexpected schedule delays.
For example, if you have a REST based webservice, try porting that (or part of that) to Rust, rather than using Rust to switch over to GraphQL. Or if you are working in embedded, (re)implement functionality for chips you already are familiar with, rather than trying to port existing code to a new and different architecture.
Avoid the "critical path"
We generally don't suggest folks try Rust out on projects that have tight deadlines. This also applies if other components rely on your project being done ASAP. Learning a new tool is always a little unpredictable: managers tend to get nervous when they see the schedule slipping with unexpected delays, and rightly so!
Instead, look for the kind of tasks that would typically be assigned to a new hire or intern: Projects that are great if they work, but if they don't, it's not going to ruin anyone's day. In fact, you might even ask if any new hires or interns in your company are familiar with Rust, as it could be a great chance for them to share something they are interested and knowledgeable about, and give your team a chance to exchange domain knowledge.
Pick components that are well documented and well isolated
Although it is tempting to re-implement parts of your code that have grown hard to maintain or hard to modify, these parts often survive because everybody needs that part, and/or because nobody understands it! Both of these factors can make a rewrite be put under extreme scrutiny.
Suitable components are:
- Well documented/have good requirements
- Note: If you don't have requirements, but it's easy to write tests, this might be a good time to do it!
- Well isolated, architecturally
- These are components that can be easily extracted or replaced
- They should not be super tightly coupled
Solve a problem you have
All different languages are good at different things, and there are a couple common "pains" we've experienced at different companies.
Maybe you have experienced pain in deploying or packaging python scripts between different developer environments. Maybe you've had challenges with slow-to-start CLI tools written in Node.js. Maybe you've struggled with making tools that are portable between Windows, Mac, and Linux. If you need help picking something that Rust is good at, check out our Favorite Things section below!
We find that it's easiest to communicate the need for something like Rust when you can point to something concrete that can be fixed.
Tooling: Our Favorite "First Challenge"
Our favorite first challenge is to implement support tooling for your development process. These are often great because:
- Developers always appreciate cleaning up little "paper cuts" that slow down the development process
- Your team is already working without these tools, so if the effort fails, there is little risk
- These tools are not typically part of your "main product" or "main project", which means they tend to have more relaxed organizational rules around which languages or techniques can be used.
- These tools are often relatively small, and have a specific purpose or scope.
For example, you might need a tool for collecting, searching, and sorting logs during testing or deployment, or maybe you have one, but it isn't super reliable or quick at the moment. This could be a great chance for an experiment to try out Rust! If it works: you have faster and more reliable tools, and have had a great first experience in Rust. If it doesn't: you are no worse off than when you started, and you have limited potential impact to your project.
Strengths of Rust to lean on
Now that you know which kind of projects are suitable for a first trial of Rust, how do you pick the one that will benefit the most from the qualities Rust has to offer?
Although Rust is great at a lot of things, sometimes those benefits require a decent knowledge of the language, or benefits that come from having multiple parts of your project in Rust.
A few of our favorite things
But don't fear! We have a couple "favorite features" where we find Rust really shines, and can be benefitted from fairly quickly, even for new users of the language. Here's a lightning tour of a few of our favorites:
- Portability/cross compiling
- Rust compiles and runs natively on Windows, Mac, Linux, and a number of other platforms.
- CLI tools
- Libraries like clap make it a breeze to design well documented command line tools that are quick to launch, and run reliably.
- Since Rust supports multiple platforms natively, you'll find that shipping statically-linked CLI tools makes deployment a breeze.
- Libraries like serde make it easy to serialize and deserialize data, whether you use JSON, TOML, YAML, CBOR, or many other sorts of data formats.
- Serde works all the way down to embedded systems as well, and is a great way to avoid messy memory management or byte-packing for custom formats as well.
- Data parsing/number crunching
- As a compiled language, data parsing and number crunching are generally very quick!
- If you are parsing or processing data in languages like Node.js or Python, you might be pleasantly surprised at the performance, even without complex optimizations.
- If you are coming from other compiled languages, you might also be pleasantly surprised at features like Rust's expressive type system, which can be useful for catching data processing errors at compile time, without additional testing.
- Multithreaded code
- The Rust compiler understands multithreaded code natively, and allows for what we call "Fearless Concurrency": You'll never have to worry you're sharing data incorrectly between threads, because that's caught at compile time!
- In some languages, working with multiple threads can be a hassle. With libraries like Rayon, it can be easy to turn single-threaded code into multithreaded code in a snap.
Reminder, Rust isn't magic!
At the end of the day: Rust is just another tool that can be used for solving problems. We find that the features of Rust help us to ship correct and performant code - faster than we can in other languages. Despite that, we find it's always healthy to take a step back when considering Rust, and make sure that it helps to address problems that you are actually experiencing.
If you're perfectly happy with the tools you're already using: There's no need to switch to Rust!
But if you are experiencing papercuts with your current way of doing things, it's always worth the effort to consider if there is a better way to keep your whole team working effectively.
This was a first taste of the kinds of topics we discuss with our customers when they are thinking about using or scaling up their use in Rust. In the next weeks, we plan to expand on this post, focusing in on more details from both an engineering and a management perspective.
If your company could use a hand to make sure your first experience with Rust is a success, get in touch for help with consulting, training, or development! There has never been a better time to add Rust to your team's toolbox.