5 deadly Rust anti-patterns to avoid

  Рет қаралды 30,711

Let's Get Rusty

Let's Get Rusty

Күн бұрын

Пікірлер: 149
@letsgetrusty
@letsgetrusty 8 күн бұрын
Get your *FREE Rust training* : letsgetrusty.com/training
@darkarchon2841
@darkarchon2841 3 күн бұрын
Not free though. It's literally just "free stuff won't get you anywhere, you need a project and mentor, I'll be your mentor for some $$$".
@realcundo
@realcundo 8 күн бұрын
Nitpick: `panic!()` doesn't terminate the program, it terminates the current thread only. Another thread can then observe the panic.
@linkernick5379
@linkernick5379 8 күн бұрын
Nice catch 👍
@jackthereaper9379
@jackthereaper9379 8 күн бұрын
can you tell me atleast briefly how any other thread can observe the panic? I wanna know, it might be useful for a project of mine.
@realcundo
@realcundo 8 күн бұрын
​@@jackthereaper9379 The simplest is to look at docs for std::thread::Result, there's an example. In short, when you spawn a thread, you get a handle and when you join that handle, it'll return Err if the spawned thread has panicked. It'll return Ok if the thread finished without panicking.
@iceginlychee
@iceginlychee 8 күн бұрын
I would be interested to know as well
@realcundo
@realcundo 8 күн бұрын
Weird, I'm pretty sure I replied, maybe it'll appear twice. The simplest is to look at docs for std thread Result, there's an example. After spawning a child thread, you wait for its completion by calling join. Join will return that Result and if it's an Err, the child thread has panicked. Edit: it the result is Ok, it's the value that the function executed in the child thread returned.
@ahmetyazc7969
@ahmetyazc7969 8 күн бұрын
I think proper use of panics still has its place in applications, specifically if the error is unrecoverable and expected to never happen. Leaving the app running while the state of the application reached to a point where it should never reach is more problematic, and halting the whole program is the best option.
@rustisbae
@rustisbae 8 күн бұрын
I would also say its application dependent. For example, you wouldnt want a server just crashing out of nowhere, however a client app could deal with a crash. I just dont like to use panics personally lol 😅
@u-k
@u-k 8 күн бұрын
@@rustisbae But you WOULD want to use it if say, an API key gets unauthorized or a wrongly formatted environment variable is detected.
@rustisbae
@rustisbae 8 күн бұрын
@@u-k Right, that would be a reasonable to panic. But that's something that happens at startup, not while the server is up and running :p
@letsgetrusty
@letsgetrusty 8 күн бұрын
Yes! There are certainly use cases for panic but they are typically infrequent. The problem is developer use panic outside of the specific circumstances you've mentioned.
@jonathan2847
@jonathan2847 8 күн бұрын
You should propagate these type of errors back to main and return them from main. Panic has no place.
@RoamingAdhocrat
@RoamingAdhocrat 8 күн бұрын
Just want to say how very very nice it is to see the five patterns in the title immediately listed when the video starts. Really helps me orient myself and understand what you're communicating!
@havefuntrading6263
@havefuntrading6263 8 күн бұрын
Sometimes (like 1 out of 10 situations), it's more ergonomic to use panic! rather than introduce bespoke error type. Also, quite a few crates will use panic! internally, so there is not much you can do about it (apart from catch_unwind), even though your crate handles all errors in a clean way.
@letsgetrusty
@letsgetrusty 8 күн бұрын
Yes I agree with that when it comes to your own codebase. In terms of libraries, panicking should not be done unless there's a VERY good reason. I'm curious which crates you are referring to.
@omg33ky
@omg33ky 8 күн бұрын
One crate that panics in a certain case where it is not really good is yup-oauth which is used for authentication with some other Google API crates for example. This has actively impacted me, since there is little I could do about it, but it's a crate where I have done some PRs so when I get time I might implement proper handling. That said. In libs I see very few cases where it actually makes sense to panic instead of returning actual errors and libs should keep that in mind before publishing a 1.0 version imo
@awdsqe123
@awdsqe123 8 күн бұрын
5:26 Think you need to put `&self.settings` even when self is a reference.
@letsgetrusty
@letsgetrusty 8 күн бұрын
Yes! Good catch!
@flwi
@flwi 4 күн бұрын
Nice, didn't know that errors convert automatically. 3:45
@Shawnecy
@Shawnecy 8 күн бұрын
If you have only one reader and one writer on different threads, you may want to use Arc instead of Arc. Further for that case of a single reader and writer, if your type is integral or boolean, then you don't even need the Mutex (data that is 64 bits or less can already be read and written atomically via the Arc).
@Imaginary_One
@Imaginary_One 6 күн бұрын
If your type is integral or boolean, you really shouldn’t even be using Mutex - you should be using the atomic integral types (but I wouldn’t hold anyone to that!)
@cunningham.s_law
@cunningham.s_law 8 күн бұрын
if the data is small cloning is faster than arc most of the time
@follantic
@follantic 8 күн бұрын
And clone uses less RAM than Java or JS. RAM is expensive while CPU is often not the bottleneck. And lifetimes can get annoying at times. YMMV
@eli1882
@eli1882 8 күн бұрын
Performant but more memory usage.
@letsgetrusty
@letsgetrusty 8 күн бұрын
Yes good point but then you run into the issue of having multiple sources of truth
@IceQub3
@IceQub3 8 күн бұрын
​@letsgetrusty the data is immutable
@paulneal9908
@paulneal9908 7 күн бұрын
If the data is small it will be so fast you don't care
@newplayer7743
@newplayer7743 8 күн бұрын
New pattern matching syntax that I didn't know about.
@ErikBongers
@ErikBongers 7 күн бұрын
What I like about Rust in this context: a move is typically implicit while a copy often has to be explicit. This helps a lot in avoiding unnecessary copies. In C++ it's the other way round, and you often have no idea if copy or move is being used. What I don't like about Rust is the match syntax: match(variable) { Some(new_variable_name) if => ... You get used to it after a while, but the introduction of this new_variable_name and the extra_condition read unnaturally.
@evols7028
@evols7028 8 күн бұрын
Be careful when sharing writable data between threads. It can lead to false sharing, which is a degradation of performance when two threads constantly write to data contained in the same cache lane at the same time. In this case, making copies then reconciling them after the fact is better
@penguin_brian
@penguin_brian 8 күн бұрын
Need to ensure error handling provides enough context so that the user can determine source of error. In the example given at 3:40 if the file is not found then ErrorKind::NotFound will be returned, and if this is the only information displayed then the user will have no idea where the error was or what file was not found. On the other hand, panic!() makes it easy to include the filename in the string, and as a bonus you get the line number where the error occurred too.
@jonathan2847
@jonathan2847 8 күн бұрын
Error types should ideally be per function and variants per source. So returning an error should give you the exact details where it occurred. A lot of people in favor of panic are just writing bad error propagation.
@spacetowastee
@spacetowastee 7 күн бұрын
Great video! I appreciate the “questions you should ask yourself before you clone()”
@Techonsapevole
@Techonsapevole 3 күн бұрын
Great video, it should be in the official doc
@Mempler
@Mempler 8 күн бұрын
You can put if statements in matches?!?
@AndrewBrownK
@AndrewBrownK 8 күн бұрын
It’s the beeessssst
@Caldaron
@Caldaron 8 күн бұрын
the perfect question for claude/chatgpt
@pmmeurcatpics
@pmmeurcatpics 8 күн бұрын
Yup, they're called guard cases!
@follantic
@follantic 8 күн бұрын
I was genuinely confused by that. 7:55 for reference. Looks awesome.
@BenjaminBrienen
@BenjaminBrienen 7 күн бұрын
Guard clauses
@HagbardCelineOnRust
@HagbardCelineOnRust 4 күн бұрын
ty for the steady content
@hakanakdag9491
@hakanakdag9491 8 күн бұрын
I am building a secure peer to peer file copy command line tool with rust. Learning it on the way. I found handling errors and result pattern very difficult and concerning. I need to improve these areas.
@evtimpapushev7137
@evtimpapushev7137 Күн бұрын
At around 7:00 I would strongly disagree with the statement about Arc. Rc uses simple increment instruction. Arc requires an atomic operation to be performed by the CPU and those are slow as they need to sync between all CPU cores and even different CPUs in multi-CPU systems.
@basilefff
@basilefff 6 күн бұрын
That missing enum variant seems like a very serious issue to me, I would not expect a code to break in such a way!
@s1v7
@s1v7 8 күн бұрын
explain please how to create custom error types and what are the best practices there
@Nesdac-k1l
@Nesdac-k1l 8 күн бұрын
check out `thiserror` crate for a simple/easy solution.
@TheNoirKamui
@TheNoirKamui 8 күн бұрын
Also using Box without any good reason. Most of the time it is better to use impl Trait in function properties for static dispatch. Or even better fn() pointers for your own code.
@clot27
@clot27 8 күн бұрын
I will keep cloning
@sutsuj6437
@sutsuj6437 8 күн бұрын
Oh you don't want to clone and instead use a reference? Just re-architect the entire codebase... Nah I'm gonna keep cloning. 'Life is too short for lifetimes
@affanyunas7693
@affanyunas7693 8 күн бұрын
@@sutsuj6437 i love rust untill i meet lifetimes
@letsgetrusty
@letsgetrusty 8 күн бұрын
Just a chill guy who prefers to clone
@theevilcottonball
@theevilcottonball 6 күн бұрын
If you clone, you might as well use a language like Swift. You don't care about performance, so there is no reason to use Rust then
@sutsuj6437
@sutsuj6437 6 күн бұрын
@@theevilcottonball Ok, but if I use Rust I can feel superior over others.
@mihaigalos279
@mihaigalos279 6 күн бұрын
hi Bogdan, would you consider compiling a book with these antipatterns? Would love to see some examples of patterns as well.
@iceginlychee
@iceginlychee 8 күн бұрын
Very informative stuff, thank you as always
@qwerwasd1724
@qwerwasd1724 8 күн бұрын
Is panic! okay to use if there's no recovery possible?
@Nesdac-k1l
@Nesdac-k1l 8 күн бұрын
yes, it is usually recommended if unrecoverable.
@jonathan2847
@jonathan2847 8 күн бұрын
No, you should propagate errors up to main and return them.
@Nesdac-k1l
@Nesdac-k1l 8 күн бұрын
@@jonathan2847 i hope youre joking
@user-pq5nt1lt7i
@user-pq5nt1lt7i 4 күн бұрын
thanks for the guide ❤‍🔥🚀
@duck-e2d
@duck-e2d 5 күн бұрын
8:54 this code does not compile fn main() { let list = vec![1, 2, 3]; if let [first, ..] = list{ } } error[E0529]: expected an array or slice, found `Vec`
@JersenMan
@JersenMan Күн бұрын
Just in case you want to know how to fix it, turn the vec into a slice: fn main() { let list = vec![1, 2, 3]; if let [first, ..] = list[..]{ } }
@SamuelTravnicek
@SamuelTravnicek 7 күн бұрын
In case we are absolutely sure, the function returning Option will succeed, it's perfectly fine to call expect fn. As the name suggests, we expect some value.
@meka4996
@meka4996 8 күн бұрын
Amazing! Thank you
@christopherpetersen342
@christopherpetersen342 7 күн бұрын
Feeling good, since I understood what you said and why... O:-) How do you feel about using a suffix like _result or _option on variable names and then the bare (but meaningful!) name inside the Some()/Ok() parts?
@soberhippie
@soberhippie 8 күн бұрын
The biggest rust sin is not using Rust
@circuitbreaker7860
@circuitbreaker7860 8 күн бұрын
Do you have recommendations for how to handle a result in a function that can't return a result? (E.g. closures or implementing trait methods of library crates, that you do not own, which have a overly simply return type like String) Having to discard the entire error stack up to that point always feels so wrong.
@scheimong
@scheimong 8 күн бұрын
5:28 I think you need `&self.settings` instead.
@letsgetrusty
@letsgetrusty 8 күн бұрын
Yes! Good catch!
@oliverfoxi
@oliverfoxi 8 күн бұрын
I thought in Lazy-man error handling you will talk about mindless usage of `?` with anyhow lib
@MechMK1
@MechMK1 2 күн бұрын
What would be the correct way to handle an unrecoverable error? E.g. a program expecting to read data from a file, but the file doesn't exist, can't be accessed, etc... Outside of telling the user why the file can't be read and quitting, I can't think of anything else meaningful to do.
@JersenMan
@JersenMan Күн бұрын
That is the correct thing to do. Telling the user what went wrong and exiting the program gracefully. If possible you could retry the operation that failed (e.g. network calls to wonky server). Make sure to not retry indefinitely tho. Doing anything is a lot better than just crashing and showing the user a stack trace which they don't understand
@alexkazimir3835
@alexkazimir3835 7 күн бұрын
Cool, thanks 🎉
@MasterHigure
@MasterHigure 8 күн бұрын
Just so it's clear, points 1 and 3 are entirely allowed in Leetcode, Project Euler, Advent of Code, and similar settings. Unwrap and clone everything. Just make it run and get your answer.
@gamekiller0123
@gamekiller0123 8 күн бұрын
Using unwrap/expect in production code is not an antipattern. Sometimes you know statically that something cannot be None/Err, but getting the type system to help is impractical or impossible. There are also functions with preconditions, and panicking when these aren't upheld to provide a nicer API is fair.
@orterves
@orterves 8 күн бұрын
Unwrap and expect should be avoided except as a last resort and it's better if the function preconditions can be expressed in the input types so that the function can't even be called with invalid inputs.
@Nesdac-k1l
@Nesdac-k1l 8 күн бұрын
yes, but avoid `unwrap` especially since it cannot be given a message. and prefer `assert` where possible.
@Nesdac-k1l
@Nesdac-k1l 8 күн бұрын
​@@ortervesoften it cannot be expressed in the parameter types. eg. a parameter for an index in a slice. it could also js be incredibly unnecessary to create a custom type just to ensure some invariant. eg. a non empty vec
@pmmeurcatpics
@pmmeurcatpics 8 күн бұрын
​@@Nesdac-k1lfunnily enough `NonEmptyVec` is actually a thing. I was in a situation where I actually needed that, and found out that there's a crate for that™
@pmmeurcatpics
@pmmeurcatpics 8 күн бұрын
"the variable cannot have this value" is better expressed with `unreachable!`
@01joja
@01joja 8 күн бұрын
At 9:07 you switched place on number 2, 3 and 4.
@letsgetrusty
@letsgetrusty 8 күн бұрын
Good catch, editing mistake :)
@anon_y_mousse
@anon_y_mousse 7 күн бұрын
I would consider that broken behavior. If the point of using match with an enum is to handle every case, then extra cases should definitely be an error. I'd honestly like to know why anyone working on the design of that particular feature would think its acceptable to define a new variable especially when you're not using the keyword intended to do so.
@RustIsWinning
@RustIsWinning 5 күн бұрын
Tbf that last part is very far-fetched. I want to see a real life case where this ever caused an issue.
@anon_y_mousse
@anon_y_mousse 5 күн бұрын
@@RustIsWinning Far-fetched or not, I would still consider that broken behavior. Hopefully the next major version number they fix it.
@anlumo1
@anlumo1 8 күн бұрын
I miss the mentioning of the `Arc` anti-pattern, but maybe that's too complex for this kind of video and needs its own instead to explain why it's problematic.
@serbestianmilo1477
@serbestianmilo1477 5 күн бұрын
that's not an anti-pattern
@sighupcmd
@sighupcmd 8 күн бұрын
This missing enum variant problem can be huge problem
@aheendwhz1
@aheendwhz1 8 күн бұрын
Sadly, KZbin shit-translates your chapters when using KZbin in another language than English. I wish they stopped shit-translating things without asking and making KZbin a mess to use in the non-English versions.
@LostRunner0213
@LostRunner0213 8 күн бұрын
very interesting even for a beginner like me. but youtube enabled the audio translation. what a pain in the a** !
@rezabani9904
@rezabani9904 5 күн бұрын
Number 6: Shadowing
@RustIsWinning
@RustIsWinning 5 күн бұрын
This one is interesting because there was a kernel bug recently caused by shadowing. I think this is only an issue if you shadow a variable of the same type.
@henning.langhorst
@henning.langhorst 8 күн бұрын
The German translation is really awful.
@alerya100
@alerya100 6 күн бұрын
Luxury video!!!
@DataPastor
@DataPastor 8 күн бұрын
How is it possible? I thought, if it compiles, then it is good. /s
@OlavurNonE
@OlavurNonE 6 күн бұрын
On the 5. chapter, you switched the title of the 2., 3. and 4. chapter😂 4:32 and 9:08
@v-sig2389
@v-sig2389 8 күн бұрын
Please don't use auto-translate for your titles, the translation is unbearable.
@follantic
@follantic 8 күн бұрын
Didn't see an auto translated title, but I definitely still agree.
@letsgetrusty
@letsgetrusty 8 күн бұрын
Fixed! YT started doing this automatically -_-
@dagoberttrump9290
@dagoberttrump9290 5 күн бұрын
you forgot self referential structs
@tomkimsour
@tomkimsour 8 күн бұрын
la voix française est insupportable et on peut pas la changer sur browser de téléphone. Mais sinon good content
@farfa2937
@farfa2937 4 күн бұрын
You don't handle errors because you're lazy. I don't handle errors because I have nothing to do with an error. We're not the same.
@naive_algorithm
@naive_algorithm 8 күн бұрын
I am `unwrap_or` user 😂😂😂
@pierreollivier1
@pierreollivier1 8 күн бұрын
Man I love how Rust is just becoming C++. You have a problem ? don't worry we have syntax to solve it. Kidding love rust :) (still plz don't become C++)
@RustIsWinning
@RustIsWinning 5 күн бұрын
Nice try Zig glazer 😂
@VivekYadav-ds8oz
@VivekYadav-ds8oz 7 күн бұрын
This channel has existed for a couple years and is still making the same basic/trivial content. To grow, you need to keep up with the skill level of your audience.
@brianobot2543
@brianobot2543 6 күн бұрын
New people are coming in every day, we need this trivial content since most docs are quite technical so to say
@JurekOK
@JurekOK 7 күн бұрын
soo . . . rust is mature enough that it has anti-patterns. Uhh. We need a new language that doesn't allow these problems.
@RustIsWinning
@RustIsWinning 5 күн бұрын
So basically a language that doesn't allow any kind of pattern...
@spaghettiking653
@spaghettiking653 8 күн бұрын
Rust propagandist try not to say "powerful" challenge (impossible)
@RustIsWinning
@RustIsWinning 5 күн бұрын
YourMama is powerful (kek)
@mintx1720
@mintx1720 7 күн бұрын
I though lazy man error handling means using `?` everywhere and you get an error up a 100 function call stack and you scratch your head wondering what happened
@chonkusdonkus
@chonkusdonkus 8 күн бұрын
I really dislike the black background in this video
@CodeVault
@CodeVault 6 күн бұрын
Please stop with using the term "anti-pattern", it just creates a dogma to not use these concepts even though they have and always will have their uses. Using these "anti-patterns" doesn't make your code more buggy, inefficient or harder to maintain (at least not by themselves. The context REALLY matters) and they certainly aren't "mistakes" as you call them. The first point is the most egregious of them all... Sometimes you want to ignore the return value (the operation simply doesn't matter if it succeeded or not). Sometimes you want an .unwrap() because you already know what the value is. And I don't understand why using panic! is a problem. The second point is fair enough... although, I don't think simply using those traits makes your code any better. Implement them if you need to. That's why Rust gives you so much control. The third point also makes no sense. Sure, you don't .clone() but you instead make another object (an Arc) and also .clone() that as well. How is that any more efficient? Sure, if what you are trying to clone is some huge structure, I understand, but it's just a settings struct. If you need modifying it though, an Arc makes sense. On the fourth point... Most of the time I agree, Rust's pattern-matching is incredibly useful but there are certainly many times a simple if/else chain make things more legible. Context matters. Here I liked the use of matches! btw, I didn't know about it. But still, I am not sure if it is more legible than a simple if statement. Again, context matters, simply replacing a chain of if/else statements with a match statement doesn't make your code automatically better (depends where and how). On the fifth point, again, glob imports are a tool made available to the programmer. It's silly to call such things "mistakes" even though the context clearly matters. Overall, there are things to learn from these videos and I have always found them informative and I thank you for that! You and a handful of others motivated me to start learning and working in Rust. But please, stop making such videos that demonize tools that are useful based on context. This is how we get to creating so-called "best practices" that just make our life more difficult only for the sake of respecting such practices without an objective increase in performance / maintainability / development.
@ol_suh
@ol_suh 7 күн бұрын
13 And no man hath ascended up to heaven, but he that came down from heaven, even the Son of man which is in heaven. 14 And as Moses lifted up the serpent in the wilderness, even so must the Son of man be lifted up: 15 That whosoever believeth in him should not perish, but have eternal life. 16 For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life. 17 For God sent not his Son into the world to condemn the world; but that the world through him might be saved. 18 He that believeth on him is not condemned: but he that believeth not is condemned already, because he hath not believed in the name of the only begotten Son of God. 19 And this is the condemnation, that light is come into the world, and men loved darkness rather than light, because their deeds were evil. 20 For every one that doeth evil hateth the light, neither cometh to the light, lest his deeds should be reproved. 21 But he that doeth truth cometh to the light, that his deeds may be made manifest, that they are wrought in God. (Jn.3:13-21)
All Rust features explained
21:30
Let's Get Rusty
Рет қаралды 326 М.
The Return of Procedural Programming - Richard Feldman
52:53
ChariotSolutions
Рет қаралды 32 М.
УДИВИЛ ВСЕХ СВОИМ УХОДОМ!😳 #shorts
00:49
Quilt Challenge, No Skills, Just Luck#Funnyfamily #Partygames #Funny
00:32
Family Games Media
Рет қаралды 53 МЛН
AI is not Designed for You
8:29
No Boilerplate
Рет қаралды 162 М.
Where is Rust being used?
11:46
Let's Get Rusty
Рет қаралды 133 М.
Rust's second most complicated feature explained
7:48
Let's Get Rusty
Рет қаралды 37 М.
The Fascinating History of Rust
8:03
Awesome
Рет қаралды 22 М.
Rust Collections Explained
11:51
Code to the Moon
Рет қаралды 14 М.
LAVROV's interview with Tucker CARLSON 😁 [Parody]
8:34
Юрий ВЕЛИКИЙ
Рет қаралды 390 М.
Why I’m Learning Rust in 2024 (and new dev environment)
16:53
ForrestKnight
Рет қаралды 50 М.
You Should Really Know These Traits in Rust
18:36
Oliver Jumpertz
Рет қаралды 17 М.
This Video is AI Generated! SORA Review
16:41
Marques Brownlee
Рет қаралды 2,9 МЛН
УДИВИЛ ВСЕХ СВОИМ УХОДОМ!😳 #shorts
00:49