The siren song of Rust, with its promises of safety and performance, has lured many developers. But as the complexity of our software grows, are we paying too steep a price for this perceived perfection? I recently read an article, "I spent 18 months rebuilding my algorithmic trading platform in Rust. I’m filled with regret.," and it resonated deeply with my own experiences.
The Cost of Complexity
Having been in this industry for decades, I've witnessed firsthand the insidious creep of complexity. It's easy to underestimate its cost when you're young and laser-focused, but as you gain experience, you realize that maintainability and understanding become paramount. I've returned to Go code after years away and found it remarkably easy to pick up. This is because Go's creators prioritized simplicity, both in the language and its tooling.
The Feature Creep Trap
Rust, along with languages like Swift, often prioritizes safety and "perfection" at the expense of simplicity. This approach can be a trap. It reminds me of a pattern I've seen repeatedly in software development: the feature creep dilemma. Experienced users often clamor for new features, and developers, eager to please, add them. Each new feature might seem small on its own, but the cumulative effect over time can be devastating. The software becomes so complex that new users are completely overwhelmed. It becomes a product only experts can use.
The Bloat Problem
This isn't just a theoretical problem. I've seen it firsthand in companies I've worked for. We added feature after feature to satisfy our existing user base, but in doing so, we made our software unusable for newcomers. We painted ourselves into a corner. Rust, Swift, C++, and Python are all falling into this same trap. They cater to the needs of existing users, adding features that increase the barrier to entry for everyone else.
Lessons from Apple and Microsoft
Apple, to their credit, seems to understand this. They're willing to completely rewrite their software when it becomes too complex, even if it means short-term pain. Microsoft, on the other hand, often lets their software bloat, adding feature upon feature until it becomes a tangled mess. Think of Excel, a powerful tool, but one that can be incredibly difficult to navigate for the average user.
The Rise and Fall of Languages
New languages often emerge because older ones become bloated and unmaintainable. Perl, once dominant, lost ground to Python because Python offered a simpler, more manageable experience. Now, Python is facing a similar challenge. Complexity is unavoidable to some degree, but it should never be the primary focus. Rust, in its pursuit of correctness and performance, has seemingly disregarded the importance of simplicity. It's a mistake that Scala also made, leading to its displacement by the simpler Kotlin.
The Engineer's Blind Spot
Why does this happen? Many engineers and tech leads aren't UI designers. They're drawn to "cool" technology, and Rust certainly fits that bill. They often don't understand the value of good design, which is often invisible. Good design creates a positive user experience, which leads to adoption and loyalty. Similarly, simple languages offer a better developer experience, but this isn't always apparent at first glance. You have to use them for a while to appreciate the benefits.
The Zig Example
Andrew Kelley, the creator of Zig, understands this. He was inspired by Rust, but he also recognized the danger of a language becoming so complex that debugging becomes an exercise in deciphering the language itself. Clear, simple code makes it easier to identify and fix problems. Ultra-safe languages often miss this point. They assume that if the compiler catches more errors, it's automatically a win. But this increased complexity can make compiler errors themselves harder to understand and resolve.
Simplicity and Dynamic Typing
My own experience with Julia has reinforced this belief. While it's dynamically typed, I've found that I can often resolve runtime errors in Julia faster than compile errors in a statically typed language like Haskell. This is because the simplicity of Julia's type system makes it easier to reason about the code.
Go's Balanced Approach
Go's approach to structural typing is another example of how static typing can be achieved without excessive complexity. It's a testament to the fact that safety and simplicity aren't mutually exclusive.
The Rust Reality
The allure of Rust is undeniable. But as projects grow in size and complexity, many developers are finding that the price of its perceived perfection is too high. A complex language combined with a complex project is a recipe for disaster. For large-scale development, simplicity is not just a virtue, it's a necessity. As the designers of Go recognized, simplicity is the key to scalability. It's a lesson that the Rust community would do well to heed.
I guess a good point to highlight is that go is a gc lang and rust isn't, then you can't use go in projects where you need full control of memory allocation.