Common Newbie Mistakes and Bad Practices in Rust: Bad Habits

When you are coming to Rust from another language you bring all your previous experiences with you.

Often this is awesome because it means you aren’t learning programming from scratch! However, you can also bring along bad habits which can lead you down the wrong rabbit hole or make you write bad code.

I decided to write up some of the things mentioned in Common newbie mistakes or bad practices, adding my own take and throwing in some examples to help spot these anti-patterns in the wild.

I'd love to hear if you have other suggestions or disagree with any of the bad habits I've mentioned!

12 Likes

Thanks, I always enjoy your blog posts.

That sentence could use a little work (and I'm not sure enough about the intention to make a concrete suggestion).

1 Like

I've bookmarked it so I can link it later!

I noticed that the hyphenator turned rune::wasmer::Runtime::load() into rune::was-mer::Runtime::load(), though it seems to have worked when I copied.

Thanks for pointing that out. I ended up doing some more proofreading after publishing the article to help fix rambly bits like that.

1 Like

Very nice article!

One personal slight disagreement is regarding the Hungarian notation, especially when combined with code which uses methods available on many types, such as .as_ref(): while it is true that either through cargo check, or through some "inlay hints" from some IDE, the types of the variables are known, I think that code review on "bare environments" / platforms such as Github ought to be taken into account: in those instances, having some usage of hungarian notation around functions with complex signatures can improve the readability a bit :slightly_smiling_face:

Funnily enough, that was probably the most intensely argued topic in the entire article. From what I saw, there was about a 50/50 split, with the people saying "shadowing is bad" being very vocal about it.

I probably didn't articulate it well in my article, but I think it's fine to shadow variables as long as the shadowing is close together (preferably on adjacent lines). If you have more than half a page between shadowed variables you are probably going to confuse readers unless it's extremely obvious from context. However, if the lines are right next to each other and you are just transitioning a piece of data between intermediate states then shadowing lets you avoid unnecessary temporary names... Like any language feature, if it's used in the right place and it can provide you with great clarity, but use it incorrectly and you can end up with an unmaintainable mess.

1 Like

Heh, I wasn't necessarily talking about shadowing, although I can see how it may be related.

That is, I agree that:

let mb_thing = …;
if let Some(thing) = &mb_thing {

is not really that much better over:

let thing = …;
if let Some(thing) = &thing {

I actually agree with you regarding shadowing: the latter is strictly better since it conveys that the Option itself is not to be accessed in that scope (that's an instance of definitely useful shadowing).


I was rather thinking of:

let thing = foo(…);
…
bar(…, thing);

vs.

let opt_thing = foo(…);
…
bar(…, opt_thing);

In this example, calling the variable opt_thing, or adding an explicit : Option<_> annotation (since code > documentation), are things which help realizing that there is an Option going around, without having to know the exact signature of foo or bar (e.g., maybe in that instance foo() is expected to yield Some(…), and thus feeding Some(opt_thing.unwrap()) (or adding an assert!(opt_thing.is_some());) would be a nice way to insert an assertion there).

1 Like