Remix.run Logo
npalli 16 hours ago

I wonder how much of this love of Rust stems from the fact that he actually didn't have a full time job programming in Rust. When one starts off doing hobby projects in Rust the experience can be very pleasant thanks to cargo (btw, it is a bit puzzling that vcpkg is not adopted more broadly in C++ land since the gap from cargo is not that bad).

However, once you get a job writing programs and find out you need to quickly prototype, refactor the code or make changes under a strict deadline, not good, it quite literally is the worst language to make large scale updates beating even C++. This is not counting the other memory safe languages (golang, C#, Java, Kotlin, etc..) which is where you should first target.

lvkv 16 hours ago | parent | next [-]

> it quite literally is the worst language to make large scale updates beating even C++

Having worked in both C++ and Rust codebases professionally, my experience has been the complete opposite. I have to be extremely cautious when making changes to C++ codebases, (especially async ones) and it’s always a huge time sink trying to just get the damn thing and its tests compiled. Rust’s compiler and tooling, on the other hand, allow me to make high-pressure changes much more confidently. It’s not perfect, but I’ll take it over the average C++ project every time

echelon 15 hours ago | parent [-]

Rust is the easiest language I've ever made refactors in. This article is nonsense.

I've got a massive multi-binary monorepo and it's so easy to make sweeping refactors to core libraries that impact all build targets.

I can't fathom doing this in C++, or worse, a dynamic language.

saghm 15 hours ago | parent | prev | next [-]

I'm not sure what's happened on the Rust projects you've worked on professionally, but having used Rust for over nine years now personally and about five years professionally, every experience I've had trying to refactor large projects in Go, C++, Python, and Ruby at work has been strictly worse than even my worst experience having to do so in Rust. Following the compiler errors makes it super easy to follow a chain of cascading changes from needing to change something that gets used elsewhere, which combined with the usual strategy of using the test suite to detect regressions makes it as easy as I could ever imagine. I've often had the experience where I've done large refactors that touch dozens of files and thousands of lines of changes where the tests pass immediately after finishing the changes to get it to compile, and in the refactors at least that size (including ones larger than that where it isn't as cinnamon to where that doesn't happen as often), the remaining work to fix things beyond stuff the compiler can catch is still much smaller than I've had to deal with in other languages.

Obviously, some amount of this is due to my own level of comfort in Rust and not specific to the language, but even if I accepted your premise that Rust is horrendous for large changes, that still would mean that being comfortable with a language can easily make up for any inherent issues with refactoring due to the language itself. If you strongly dislike working on large Rust codebases, I agree that it's probably better to avoid trying to use it professionally, but my experience is so radically different from what you describe that I have trouble believing that this is due to Rust being objectively unfit for large refactors to the extent that you describe.

bryanlarsen 16 hours ago | parent | prev | next [-]

The disadvantage of doing a big refactor in Rust is that you can't do a partial refactor -- it won't compile until you've fixed everything.

The advantage of doing a big refactor in Rust is that you can't do a partial refactor -- it won't compile until you've fixed everything.

echelon 15 hours ago | parent [-]

Why would you want a refactor into a broken state?

You always need to figure out how much you're going to bite off with each refactor. It's usually possible to do things incrementally.

zsyllepsis 15 hours ago | parent | next [-]

I don’t think that’s what the parent was saying.

There are cases when refactoring Rust code where it’s possible to hit limits in the compiler related to e.g. lifetime inference. When these limits are hit, simple straightforward refactorings that are perfectly safe become more complicated - suddenly you’re forced to manually annotate lifetimes, and to thread those lifetimes through function calls, and…

And your small, incremental refactor suddenly isn’t. It doesn’t happen all that often, and they’re working to reduce how often users run into these challenges, but a number of cases like this still exist. And when you run into them it can be a frustrating experience.

estebank 9 hours ago | parent [-]

Personally I'm convinced that the solution to that is not for the language to be more implicit but rather to make tooling for refactoring more front and center. A task for "add a lifetime to this struct everywhere it's mentioned" is already catered to by modifying the original type and then applying rustfix, but more advanced but relatively common changes should also be mechanized away. The annotations are there not only for the benefit of the compiler but also the developers.

jayd16 13 hours ago | parent | prev [-]

You might want to test some optimization or refactor without crossing all the Ts. Lost of reasons you'd want to quickly iterate without doing the maximum amount of work needed upfront.

efficax 14 hours ago | parent | prev | next [-]

You hear this about refactoring a lot and I don't get it. I've done several multi-thousand line refactors of a 500k line rust codebase in the past few years, and it's absolutely fantastic for this task. The type system guides you along, and once the thing compiles, it almost always works exactly as you intended it to. the "quick prototyping" languages like say python are a nightmare to do large refactors in, in my experience. at least if you don't want type system timebombs lurking in infrequently executed corner cases.

Tuna-Fish 16 hours ago | parent | prev | next [-]

My experience is the exact opposite. Rust is slow for the initial programming, but great for making changes in, because the type system holds your hand and makes sure your changes are sound.

Maxatar 15 hours ago | parent | prev | next [-]

Refactoring C++ is an absolute nightmare due to templates and overloading. If you rename a function for example, tools can't propagate that change through a template because there's no way to know if that template is only ever used to call that particular function, and not some other function that happens to share the same name (some overload).

Another way to think of it is that in C++, templates are dynamically typed, and so templates suffer from all of the same refactoring problems that dynamically typed languages do.

In Rust that problem doesn't exist, there is no function overloading and generics are "statically-typed" via traits, so you can factor code that resides within generics just as you would refactor any other code and it all just works.

tcfhgj 14 hours ago | parent [-]

You probably are looking for duck typing

brson 16 hours ago | parent | prev | next [-]

Rust was specifically designed to be refactorable and in my experience it is. It was part of the dogfooding process of building Rust in Rust - lots of changes to the language, lots of changes to the compiler, lots of churn. Rust's strong type system means you can refactor and be confident that programs continue to work.

Buttons840 15 hours ago | parent | prev | next [-]

> you need to quickly prototype, refactor the code or make changes under a strict deadline, not good

How many projects like this shouldn't be written in C++ in the first place? C++ isn't automatically faster than Java, and with the level of care you're describing ("strict deadlines, just get it done") you're unlikely to realize the advantage of C++.

zozbot234 3 hours ago | parent [-]

Rust is a lot better at quick prototyping than C++. There is a specific idiom to writing prototype "throwaway" code in Rust though, where you .clone() and use RefCell<> and Rc<> a lot more than you normally would (not to mention really niche features like Any). The advantage is that this boilerplate guides you when refactoring the code for better reliability and performance later on.

ribadeo 8 hours ago | parent | prev | next [-]

Rust is one of the easiest languages for code refactoring, in my experience: the compiler amd clippy tell me everything i forgot to do. Just literally doing what clippy suggests often gets it compiled.

pkulak 16 hours ago | parent | prev [-]

I use Kotlin all day at work and still think it’s a wonderful language.

I never use Rust at work and also think it’s a wonderful language. Rust is really just a fun language to write apps in. Is it okay for us to admit that yet?

lmm 15 hours ago | parent [-]

Funnily enough I read the article and thought of Scala, which I love but can no longer find a job doing - and can't help thinking it's in large part due to FUD spread by the Kotlin people.

vips7L 4 hours ago | parent [-]

I’ve casually used Scala at work and home over the past 5 years. I mostly think this is because of the community and also the tooling and libraries.

WRT the community the functional zealots have pushed out everyone that doesn’t align to their ideology. Everyone that just wanted a better Java has moved on to Kotlin or back to modern Java.

WRT the tooling: scalac and sbt are so slow it’s painful and even IntelliJ can’t figure out what’s going on in Scala sometimes.

WRT libraries: every single time I have to upgrade play or the scala version there is a breaking change that either forces me to refactor or is undocumented and screws me at runtime.

So mostly at least for me, I’ve been burned by the language too many times to start a new project in it, especially at work where it will be long lived and I’ll eventually have to upgrade things.