By Peter Wayner
Contributing writer, InfoWorld |
It seems a new programming language is invented every day—certainly more languages than most software developers will ever need. A programmer gets a flash of genius and sets out to create something fresh and wonderful. Many end up being niche languages, best used to scratch an itch or fix a particular issue. It’s rare for a new programming language to break out into the big leagues and be widely used.
Rust is one of the few newer languages to find a home in the field, where developers write code that runs in production for real enterprises. Rust certainly fills a niche. It’s aimed at helping systems programmers and others who want to create code that juggles dozens, thousands, or even millions of events simultaneously. Building these systems is challenging enough, and squeezing the bugs out of them is even harder. Rust turns all the deep theoretical thinking about the best ways to create systems into a living, breathing, useful language.
Rust’s core team runs a developer survey each year. In 2021, for the first time, more than half of all Rust programmers were using the language on the job. They weren’t just playing with Rust on the side anymore; they were using it to produce professional code for other people to run.
Here’s a look at what developers tend to love, or hate, about programming with Rust.
Software has grown more complex as developers tackle problems of scale and concurrency—namely, the requirement to juggle simultaneous inputs from a multitude of different sources. Many consider Rust the best language for building tools suited for today’s architectures.
The web browser is a good example of an application that requires massive scalability, so it’s no surprise that Rust was created by Mozilla, the not-for-profit corporation that developed Firefox. Mozilla’s developers studied the problems they were having with their code and sought a better solution. In the end, they came up with Rust.
While multithreaded systems are growing more popular, many developers don’t really need them. Scientific programmers tend to write single-threaded functions that chew through endless streams of data. Web developers can write PHP code, which offers a simple, declarative approach to creating websites. Serverless programmers write one function and leave the hard work to someone else.
Developers who need to create more sophisticated web applications can turn to Node.js, which offers another strategy for tackling multithreaded applications. Node’s event-driven model married with promise-based code can produce results that are simple and elegant.
All of this means that Rust’s multithreaded programming model offers more sophistication than many programmers require. You can ignore the extra features and still enjoy the language, but some programmers would rather not deal with the complexity at all. They just don’t need it.
Much of programming language design today focuses on creating functional languages that guide the coder into writing software that’s easier to analyze. Rust is part of this trend. Many developers love Rust’s logical, functional syntax that encourages structuring their code as a sequence of nested function calls.
At the same time, Rust’s creators wanted to build something that could handle the bit-banging, low-level programming required to keep IoT (Internet of Things) functioning. Rust offers the right combination for programmers looking to tackle these very real challenges with modern style.
If you want to leverage Rust’s benefits, you have to be willing to relinquish some familiar features that can lead to bugs. Rust’s language syntax is also complex—some would say too much so. It’s not just curly brackets and parentheses, anymore; square brackets, vertical lines, and the greater-than symbol all make an appearance. Sometimes, there are even double colons—because one colon isn’t enough, apparently.
Rust developers who are building complex, multithreaded tools may see Rust’s syntactic complexity as a worthwhile tradeoff. True fans who grok the functional flow may even enjoy it. Others will just be frustrated. Learning all of Rust’s semantic rules is not for the casual user.
Some developers see all the extra details and boilerplate required by Rust as an advantage. It lets them inject hints that make it easier for the compiler to figure out what is going on and catch any potential bugs. The ornate code is a better chance for the developer to fully specify what is supposed to happen, which helps with avoiding compiler errors. Rust invites developers to write better, faster code by injecting hints about how their code should work.
Some developers just want a language they can use to bang out loops that run without crashing. They want a language that handles the background work so they don’t have to worry about it. If the compiler sometimes produces code that’s a bit slower, or maybe a bit buggier, that’s okay. Many jobs aren’t that complex and it’s not too hard to debug them. Provisioning more hardware is cheaper than slogging through all the extra details the Rust compiler needs.
Rust’s development team is committed to ensuring that code continues to run even as the language evolves. The team works to ensure that older code continues to compile and run with newer versions of the language, which is something that other languages sometimes ignore. Rust enthusiasts often note that they’re able to maintain their codebase without endless rewriting. That’s because Rust is a language that respects its own history.
Rust does not adhere to object-oriented programming principles, which is an issue for some programmers. You can mimic some aspects of object-oriented programming in Rust—true fans know all the best ways to imitate OOP with Rust constructs—but anyone who wants to build elaborate type hierarchies will be frustrated by Rust.
Rust’s asynchronous programming model lets developers create separate functions that run independently and then join the results. Many developers say that this structure helps them build faster code while experiencing fewer bugs.
Nothing Rust does can save us from having to think carefully about our code. Rust can’t protect the code from deadlocks or delays; it can only offer better advice and a less buggy structure. Developers are still responsible for good application design and writing clean code. It would be nice if Rust were a magic wand, but it isn’t. Rust just minimizes problems and reduces some of the more obvious dangers.
Rust was built to support system-level programmers who write low-level, byte-tweaking code. It offers access to the raw bits and expects programmers to use it. The language is designed to cohabitate with much of the old C or assembly language code that’s part of the lower levels of operating systems and network stacks. Real programmers want that access to build the best, most responsive stack. Rust delivers.
Many languages have evolved to avoid byte-level access for a good reason: it’s an easy way for programmers to get into trouble. Hiding the access avoids the risks. Some programmers are better off letting the hidden back end of the language handle the details of allocating memory and representing data.
Many popular languages handle internal memory allocation and garbage collection for you, which is a nice service until the garbage collector stalls everything. It’s bad enough when garbage collection stalls the movie playing on your computer on Friday night. It’s potentially deadly if it strikes a medical device.
The Rust language has its own approach to memory management that’s not as comprehensive as traditional GC but can be more powerful. A good developer can deliver great performance using Rust’s memory model, but they’ve got to master the type system and atomic reference counting.
For die-hard Rust fans, hands-on memory management is a feature they love. Even if the job means juggling numerous threads and ensuring the code is responsive, they’d rather do it themselves. For better or worse, Rust puts the power in your hands.
Many popular programming languages (like Java) have implemented internal memory management because it prevents memory leaks and other bugs. Most programs don’t need to worry about an occasional hiccup caused by garbage collection. As a programmer, you might prefer not to worry about memory.
We can debate whether Rust offers the best model for asynchronous coding, whether getting rid of garbage collection really helps the developer, and so on, but in the end Rust is still a very new language. Developers are actively learning its details and discovering the best practices for working with Rust. The right way to create Rust programs is open to debate, and developers are constantly learning and experimenting in this area.
Rust may or may not be the best language for you or your project. It may or may not be the best solution for creating software, generally. But it’s an exciting option with plenty of opportunities for exploration. As a language, Rust is novel, and learning it stretches the brain. As programmers, it gives us a reason to rethink our challenges, reframe our goals, and set out to find the best way to write modern software. What could be better than that?
Copyright © 2022 IDG Communications, Inc.
Copyright © 2022 IDG Communications, Inc.
7 reasons to love the Rust language—and 7 reasons not to – InfoWorld
By Peter Wayner