6 ms·
It's hard to overestimate how extremely Rust is optimized towards making refactors as easy as possible. This often means a greater cost for initially writing so
by est31 4y ago
It's hard to overestimate how extremely Rust is optimized towards making refactors as easy as possible. This often means a greater cost for initially writing some code, but once that code exists, it's way easier to search around in that code and also way easier to refactor it. Often times, being written is only the start of some piece of code's journey through the years and decades until it is finally deleted.
- sfpotter 4y agoWhy? Give some examples. As someone with little Rust experience, it appears similar to C++, which I have a lot of experience with. C++ is a chore to refactor.
- iudqnolq 4y agoIn one sense it's impressive Rust has mediocre refactoring support despite orders of magnitude less investment in tooling. But that isn't worth all that much. It's no worse than any other typed language I've tried. Rust in theory has a lot of potential here because it's designed to minimize action at a distance.
- syntheweave 4y agoIt's the type system. When people say a language is easier to refactor it's usually because the types are designed more like ML, with a little more formal rigor, so the compiler errors can actually help you along as you make changes. Rust's model of mutability adds context to what you're doing - which is also what makes it hard at first(since it adds ceremony and constricts your initial design). In a large system where data can move through a lengthy code path with a lot of indirection, more nuance in types becomes a major advantage to your confidence in making changes. C++ can never quite get there despite all the innovations made because of its descent from C style types, which are much more simplistic.
- dgunay 4y agoIt's not that it isn't tedious, but the workflow is a lot more reliable. Refactor, `cargo check`, fix the errors, repeat. When there are no more errors, it is very likely the code will still work. I would say C++ is mostly the same experience, with the exception of anything involving memory safety & lifetimes. It can't guarantee you didn't accidentally introduce a use-after-free/move or anything else of that nature.
- taberiand 4y agoThat's a huge benefit though - I'm more than happy to slowly and methodically refactor a system if at the end of it I can be nearly 100% certain that I haven't inadvertently broken something in the process. The time spent upfront is multiplied time saved in fixing bugs in production. In a tortoise and hare race, sprinting off quickly doesn't count if you can't reliably reach the finish line.
- Diggsey 4y agoIt's hard to give concrete examples because the problem is inherent to large, "real" codebases - toy examples can't really do it justice. That said, there are some general themes: - The lack of implicit magic in the language. Destructors (specifically the fact that they are called automatically) is implicit. That's it. - The context-free nature of the language. This exists at several levels: 1. At a function level. There is no cross-function inference and all the information about a function is in its signature, so you don't need to look anywhere else to understand what it does. 2. At a module level. Everything you use from elsewhere is explicitly imported in the module. There's nothing that can change what a piece of code does across a crate (eg. the way you can just redefine `true` to something else in C/C++.). 3. At a file level. The module hierarchy is explicit, it is not inferred based on the layout of files on disk. Together, these things means you can look at a piece of Rust code and understand it in isolation, without even needing to be familiar with the codebase as a whole. You can move a piece of code from one location to another and (aside from fixing imports) can expect it to continue to function exactly as it did before. - The amount of information that is available to the compiler. The rich type system and lifetimes means that it's harder to mess up a refactor without the compiler detecting it. - The fact that it can be used as a safe language. This is not unique to Rust, but Rust is unique in being suited to the lowest-level tasks whilst still being safe. Safety limits the damage a bad refactoring can do (at worst, you break the code being refactored, but at least you won't give the whole program UB or cause a segfault). - The fact that macros operate on the AST rather than text. This eliminates a class of bugs with C-like macros, where implementation details of the macro have a tendency to leak through the macro definition. Refactorings can often trigger these kinds of bugs because you cannot easily think at that level while doing a large refactor. - The tooling. Whether it's quickly knowing the type of a variable, swapping out a dependency, or applying broad fixes to a codebase, the tooling works extremely well together. - Consistency of the language. Everything is an expression. "void" is just a normal type, etc. This level of consistency means that large refactorings require fewer actual changes than they might do in other languages. For example, when I used a bit of C# again after using Rust, it was very noticeable the amount of "pointless" transformations I had to do when refactoring because making an expression conditional may require introducing a new variable because `if` statements cannot be used in an expression. (Yeah there's the ternary operator, but it can't be used in every case, and that's just another example of inconsistency).
- cogman10 4y agoFor a C++ -> Rust comparison, I think the best examples would be changing return types. Imagine in C++ if you wanted to change a `Foo*` to a `unique_ptr<Foo>`. All the rules about when you can safely use/share this thing and who needs to deallocate this thing becomes a pain to figure out throughout the code base. With rust, because ownership is baked into the type system, those classes of problems just don't exist. Change it from a `Foo&` to a `Box<Foo>`, no problem. The compiler will blow up and tell you exactly where (and how) to fix those things. This applies to more than just memory allocations. Imagine calling a method from 2 threads that manipulates shared memory. Rust won't allow you to do that without protecting that memory with something like a `Mutex`.
- gary_0 4y agoIn addition to what others have said, C and C++ rely on a textual macro preprocessor and text-based #include, which can lead to a lot of annoying code-breakage when refactoring. Automated tools can't parse C/C++ unless they're effectively built on top of a full compiler; even building a complete C preprocessor is an extremely non-trivial task. (Many newer C++ code-bases discourage relying on the preprocessor, but that only goes so far.)
- jandrewrogers 4y agoIt comes down to the type system. In C++ maximal use of the type system is optional. If your C++ code base is C with classes, refactoring will be a mess. If your code base uses modern C++ with maximum type safety, refactoring is straightforward in the same way it is for Rust. The experience in C++ depends on the code base. Use of maximal type safety in modern C++ is astonishingly robust and expressive. If it compiles it generally works. The majority of developers are a bit lazy about type safety in my experience, which works against you. It depends on the org.
- Gigachad 4y agoEditors like VS code just become super powered when using Rust too. Switching back to Ruby feels like crossing a road with my eyes closed in comparison.
- airstrike 4y ago+1. Started a new project targeting WASM and decided to learn Rust coming from a Python (hobbyist) background. The VS code experience is like I stepped into a time machine and landed in the future. Oh my god, it is so much better. I don't think I'm going back to Python unless I have to
- culi 4y agoHave you tried any other typed language? I think going from hobbyist Python to any typed language might have that effect
- airstrike 4y agoTried F#, beautiful language. Read some tutorials and was amazed. Hated getting setup and VS Code felt clunky in comparison. Tried TypeScript but that felt.. like a dirty afterthought. Maybe just because I generally dislike JavaScript? I am still using both for this project (since WASM+React) but can't say I love it Rust was just like seeing God. The Rust book is awesome. Well written, fun, comprehensive. Reminded me of my experience with the Django Book way back when... Namespaced module imports? Yes, please. Then cargo "Just Works"! Especially compared to what I had in Python (particularly if you compare to my first days using the language!) or the messiness of Javascript... When I learned I could use cargo to open docs for a crate or build my own documentation in section I nearly fell off my chair laughing with joy