Lets take a minute to appreciate good quality content like this ❤
@midewestmond9442
Жыл бұрын
Yes I love his content I'm going to visit his Chanel and watch all the remaining videos they are so informative with raw content no copy from docs
@alexkarav
Жыл бұрын
Oh my god, this tutorial should be in the first chapters of Rust Lang Book. So simple and clear, you just blew my mind off. Thank you so much, you just got a new subscriber!
@hughesd.mungus9819
Жыл бұрын
I could never find a video explaining a good way to begin to structure a Rust project. This seems like a great way of doing so. Thanks for such a simple and understandable video!
@vintagewander
Жыл бұрын
I thought this is just another video that shows how module in rust works, until that tryfrom method, i fell like a beginner now, thank you so much for the video!
@eignnx_1738
Жыл бұрын
Omg I love that wrapper pattern, it's like extension methods in kotlin but a little more explicit! I think I'll try naming my wrappers after the crate cause I find W a little mysterious, but I'm definitely using this
@JeremyChone
Жыл бұрын
Btw, you do not need the Wrapper pattern if the trait you want to implement on an external type belong to the crate. You can directly implement your crate trait on any type.
@wojtekkrupski8583
Жыл бұрын
So wrapper pattern is only for implementing trait on external type? Are there other uses?
@Mankepanke
Жыл бұрын
@@wojtekkrupski8583 You can implement external traits on your own types (example: implementing `From` from std or `Serialize` from `serde`), and you can extend external types with your own traits (example: `serde` implementing `Serialize` for `std` types like `String`). But if you want to use an external trait on an external type, that is not allowed. Newtypes is a pattern for doing more than this, but one case where you might want to use it is this case: You wrap an external type in your own type, such that you are now allowed to implement an external trait on an "external type" (since it's now yours).
@dr-maybe
Жыл бұрын
You earned my subscription in the first 90 seconds. Lots of useful productivity tips, love it!
@zzej
Жыл бұрын
Thanks for this! Most tutorials asume you know the basic structure. this is so helpful!
@walis85300
Жыл бұрын
This is one of the best Rust intro videos that I've ever seen. Thank you!
@learnityourself
Жыл бұрын
Really good presentation style. I would love to see more of this for different patterns i.e builder. Anyhow thanks for great content.
@JeremyChone
Жыл бұрын
Yes, the builder pattern tutorial is a good idea. I need to think of a good example and show the pros/cons between self and &mut self.
@hv1461
Жыл бұрын
Content and presentation is superb. Thank you.
@ChezSwiiz
Жыл бұрын
If you don't want to be using a wrapper, you can also simply define your own trait with the appriopriate function and implement it for the extern struct. It is cleaner that way in my opinion but i guess it's a matter of preferences
@JeremyChone
Жыл бұрын
If you can define your trait, there is no need to use the newtype/wrapper pattern. However, when we need to implement external trait on external type, the new type pattern is needed.
@dragonmax2000
Жыл бұрын
This is so awesome and very practical. Thank you!
@uovo
Жыл бұрын
this is liquid gold for me
@cryptopatrick
Жыл бұрын
OMG! I'm loving the French accent! 🥐☕😀
@codeshowbr
Жыл бұрын
Awesome, thanks for this. Which tool do you use to annotate those lines on the screen?
@JeremyChone
Жыл бұрын
Screenbrush app on Mac.
@codeshowbr
Жыл бұрын
@@JeremyChone cool, I found a Linux alternative called Gromit
@emvdl
Жыл бұрын
thanks 🤙
@irlshrek
Жыл бұрын
Yesssss thank you for this!!
@gduan
Жыл бұрын
very helpful especially that wrapper pattern
@jacekm.1789
Жыл бұрын
O! that is so useful! Thank you so much!
@jaredthanemartin
Жыл бұрын
I love your videos. you have taught me so me great little rust tricks and patterns. Keep up the great work!
@xad85
Жыл бұрын
Amazing explanations!
@basic-1337
3 ай бұрын
Crystal clear💎💎
@codingleo
10 ай бұрын
Direct to the point! Love it!
@hamzamohd.zubair1709
Жыл бұрын
i like this channel, the only problem with this channel is that there are too few videos
@JeremyChone
Жыл бұрын
I agree! Working on more, but they take time.
@ChezSwiiz
Жыл бұрын
The creation of a utils module i would say is an anti pattern, you could would be more readable and clean fitting the utils with related code. Give me your thoughts about it
@ChezSwiiz
Жыл бұрын
Still a very high quality video thanks you for the incredible content !
@JeremyChone
Жыл бұрын
This is a good topic. First, I definitely agree that utils should be per "sub-layers" when possible. For example, if we have a "data" layer, I would put the data "utils" inside that data/... folder, and it might not be named "utils." Now, the remaining question is do we still need global utils and how early we should create them. I found with Rust that it is very productive (at least for me) to implement some traits on external types early for things I commonly do in the app and lib. And more often than not, those tend to apply to multiple layers (i.e. multiple sub-modules), but when they don't, I can easily move them afterwards. So, in short, I agree with you that module's utils should be in their related modules, and this is just one way to get there while still keeping the door open for global utils. Thanks for bringing this up.
@wjd5527766
Жыл бұрын
Hey Thanks for good quality content! May I ask you one question? How to enable quick fix for creating module?
@JeremyChone
Жыл бұрын
I do not think I have done anything special for this. I use VSCode + Rust-Analyzer. Press CMD+. and I get the quick fix menu.
@mikehoughton204
10 ай бұрын
Excellent videos thanks! Do any of your other videos show examples of using the newtype wrapper pub struct W(pub T); for trait implementations? Thanks.
@JeremyChone
10 ай бұрын
It's coming in tomorrow's video. (The Cargo Workspace for Production one)
@gabrielcournelle3055
6 ай бұрын
Thank you ! I learn something in all of your videos, this is amazing. I have one question regarding your custom Error and Result. Why not change their name to be able to differenciate them from the ones of the std library (For ex MyError and MyResult)? Is this just personal preference or is there a deeper reason I am missing?
@cozyGalvinism
Жыл бұрын
This is a great quick start!
@adamduvick
11 ай бұрын
This was very informational to watch. Could this also be achieved by writing a function to operate on DirEntry & produce Result? Is there a benefit of adding the trait implementation versus just having a local function?
@JeremyChone
11 ай бұрын
Yes, you're right; in this instance, a simple function might have sufficed. Alternatively, creating a custom trait, something like `try_to_string()`, and implementing it for `DirEntry` might be a sound strategy. This could be particularly useful if additional methods are required. In this case, we could introduce a `DirEntryExt` trait and then implement the desired methods there. We might even name the methods with a prefix like `x_to_string()`... In this example, I've demonstrated using the new type pattern, but one could argue that for `TryFrom`, the value added by a new type pattern might not be significantly more than that of a custom trait. This is because the user's code would still need to know that `DirEntry` needs to be wrapped. Ultimately, there's no one-size-fits-all answer; it depends on how your code evolves. The aim should be to use the strategy that best fits, minimizing complexity while maintaining good ergonomics.
@tofixrs
Жыл бұрын
🤯
@nati7728
6 ай бұрын
Thank you!
@prawnydagrate
9 ай бұрын
I'm somewhat new to Rust, and I find it surprising that you can just simply create a universal wrapper to implement any trait you want. Is this a good practice? Or should you create separate wrappers for separate types or groups of types?
@JeremyChone
9 ай бұрын
Technically, you can have a generic wrapper type like `W` here, as long as it's within the same crate. However, there's a valid argument that better code design involves having a wrapper type specific to the type you are working with. In fact, in the rust10x rust-web-app production code, at one point, I needed a wrapper for a type `Ctx` from another crate, and I named it `CtxW`. So, my general practice is to use 'W' for the wrapper, but then I choose between a generic or a specific one. BTW, when there's no need to implement an external trait on an external type, and we can simply create our own
@porky1118
Жыл бұрын
I don't think, creating an error type before you know anything about your code is such a good idea. I'd just create custom error types depending on the possible results. And sometimes it's enough to just forward some existing error type, especially when doing IO. I also wouldn't add the prelude at the beginning. I don't really like prelude to begin with, but if I'd add one, I'd add it right before publishing. The newtype pattern should normally be avoided. This is just a hacky workaround for the orphan rules. If it's needed, I'd rather create custom newtypes. But in this case, I'd rather create a function or an extension trait. The utils module is a good idea in my opinion. I create it, if I realize, I need some helper function in multiple places. I also hope, you somewhere have a template already set up, if you start like this anyway.
@bayoneta10
Жыл бұрын
Congrats for all your videos? I have a little question. Why anyhow is used as dev-dep? Thank you a lot in advance!
@JeremyChone
Жыл бұрын
Good question. Anyhow is relatively loose and so very convenient for unit tests, examples, and benchmarks where we do not need to be that tight. For app/lib code, I prefer to be tight, and thiserror (same author btw), fits my style very well. I tend to start with crate error::Generic(String) and error::Static(&'static str) enum variants as I start my code design and eventually replace them with the appropriate error enum/variants as the code mature. This way, I avoid the panic!, unwraps, and have the proper error flow from the start, and then I fix the types later.
@bayoneta10
Жыл бұрын
@@JeremyChone good to know! Then, I need to keep learning about error handling good practices. Thank you for your quick response!
@bayoneta10
Жыл бұрын
Doing some research on the Internet I found this differentiation about when to use one or another. I even found eyre, which is a fork of anyhow. “This is why it is suggested in anyhow's docs to use anyhow for applications and thiserror for libraries.” What do you think about this sentence?
@JeremyChone
Жыл бұрын
Ok, here is my take. I agree that "anyhow" should not be used for libraries, especially public library errors. Now, for Application, it is not that important, but I still like the stricter typing thiserror/enum model provides. But again, this is no absolute truth. It's good to experiment and see what works well for you. It's great to ask other people's take, though. The goal is to have a tight but pragmatic code. What is telling of a good design is how fast you can jump back into it six months or a year later.
@bayoneta10
Жыл бұрын
@@JeremyChone totally agree!
@Boronesss
7 ай бұрын
awesome as always
@warlordlama
Жыл бұрын
Great content, thanks!
@MiaLovesRod
7 ай бұрын
Nice video!
@NeilPate
Жыл бұрын
Nice video, thanks. What theme are you using for VSCode?
@JeremyChone
Жыл бұрын
Google material theme, and then made couple of custom icons.
@JeremyChone
9 ай бұрын
Btw, I finally took some time to create the Rust10x VSCode Extension and a webpage with information about my VSCode setup. Everything can be found here: rust10x.com/vscode
@catrybou123
Ай бұрын
Where do you suggest that types and their implementations are put? Should they be put in prelude or utils?
@JeremyChone
Ай бұрын
I’ve refined the best practice a bit. See this series: kzitem.info/news/bejne/uXmowKCbmnuGgmk So, - Prelude is now more of an exception. - When "utils" is for the crate only, I name it "support." - Typically, your types should be organized by "domain," meaning within the submodule they belong to. - Also, for core types, I like to re-export key library types at the root of the library when applicable.
@smoq_4210
Жыл бұрын
Hi, I just discovered your channel and I think it’s great ! I’m a PHP developer, and trying to learn rust is quite hard for me. Could you, by any chance, make a video about understanding rust documentation better (I find it quite hard to read) ? You could list ways to easily find the method you are looking for. Also, I feel like in rust there is a lot of ways to do essentially the same thing (say string manipulation), could you explain us maybe the best one to use in a specific case or something like that ? Thanks for your content ! Ps: t’est français non ? 😅
@JeremyChone
Жыл бұрын
Interesting requests. I can see why the documentation is hard to navigate. Let me think about what I can do in this area. (yes, french, 20+ years in San Francisco but still have airport accent!)
@therealgamer8150
Жыл бұрын
Forgive me for being dumb but as a c# developer i don't understand the motivation behind what i just watched. Anyone care to explain what the W wrapper thing is for??
@BlackM3sh
Жыл бұрын
In Rust you have a concept called "traits" which is a way to define shared features between multiple different types. You can only define traits for types where the trait *or* type is defined. So if you have an external trait *and* external type then it's not possible to define the trait for that type. The W wrapper is a way to get around this limitation since type W is not external we can define any trait for it, even if it wraps an external type. Personally I don't find the example in the video to be a very good use of this pattern, but alas.
@JeremyChone
Жыл бұрын
Just curious, why do you think it is a bad example of the new type pattern?
@BlackM3sh
Жыл бұрын
@@JeremyChone Since you are asking, a few reasons. Firstly you didn't really need the `TryFrom` trait here, all you did was call the trait method which you could have gotten by just implementing a method directly on `W`. Or better yet, you could just avoid the wrapper by just writing a function like `fn direntry_to_string(val: &DirEntry) -> Result`. Secondly the new type `W` is poorly named and doesn't seem to mean anything. The new type should have a meaningful name and purpose, adding to and/or restricting the type being wrapped. Like how `String` is a newtype wrapper for `Vec`, but with added restriction that the bytes are always valid UTF-8. Or in the case you actually need a trait, like you need to serialise using `serde`, but external type doesn't implement `Serialize`, you can create a newtype like `DirEntrySerializer` that does. Another example would be an external type `SearchResult` that doesn't implement any iterator traits you can then create a wrapper `SearchResultIterator` that does. Basically `W` in your example doesn't seem to add any value.
@JeremyChone
Жыл бұрын
@BlackM3sh I am not sure I follow many of the points above. However, I appreciate you sharing your perspective. Here are some of the best practices we tend to adhere to. Of course, some of these are personal or team preferences, and I understand that approaches and preferences can differ. As long as things remain consistent, everything is fine. == From/TryFrom - Generally, when we need a simple conversion from S (source type) to T (target type), we lean towards implementing the standard library From / TryFrom traits. - It provides a uniform and standard method for the conversion, which can be utilized by both internal and external code (e.g., libraries or other crates). - We then can employ `Into` and `TryInto` in function arguments, and it also greatly simplifies the use of both declarative and procedural macros down the line. - So, our thumb rule starts with `From/TryFrom` for straightforward cases, and then we deviate if the requirements demand it. - In this example, the conversion to String is fallible, hence the choice to use TryFrom. If it had not been fallible, we would likely have implemented Display. == To Serde or not to Serde - We tend to only use Serde when the domain truly calls for it, but we don't use it as a substitute for From/TryFrom. - We aim to make our code very intent-driven. Therefore, if Serde is not required, we do not implement its trait. - And the From/TryFrom implementations simplify any future Serde implementation if necessary. == Generic Wrapper vs Specific Wrapper - I’m unsure I understand using String/Vec as an example of a generic new type pattern. The fact that String stores its content in a Vec seems like an implementation detail rather than an instance of a new type pattern. - The new type pattern I refer to in this video is when we want to implement external traits for an external type. You could make a DirEntryWrapper(DirWrapper), but this could get quite noisy when we implement other external traits. - With the new type pattern, we place the target type as generic and now have a single type that the crate owns and can implement those external traits for external types. And it's always the same type. == W naming - Assuming that the developer/team agrees that there is value in having a generic new type pattern, I definitely understand how `W` could be seen as a poor naming choice, given that Rust rightly encourages full names. - However, we decided to make an exception for this very specific case as it is a very generic type. Once its meaning is understood, the conciseness comes very close to the actual meaning. - But of course, if a developer or team prefers to spell it out as `Wrapper`, that makes total sense. == Thank you Again, I definitely understand and value different perspectives. Thank you for sharing them. Happy coding!
@csmrfx
Жыл бұрын
snake_case for some of the name and concatcase for some of it, using non-word concatcase for the rest of the name? (direntry_froms) Also, it is difficult to reason as to where does this type come from with this naming scheme. A maze of idiosynchronicities... Consider your code as your message to the rest of the World. The Other People. Or something, Rust is what it is, and it ends up not making this easy, and the base level of contemporary programs complexity simply isn't easy, either.
@logincollector
9 ай бұрын
What application is this?
@JeremyChone
9 ай бұрын
What do you mean, the IDE? It’s vscode but then I edit the parts with DaVinci Resolve.
@logincollector
9 ай бұрын
@@JeremyChone Oh it's vscode!?! wow, yours looks so neat and uncluttered. Thank you for replying. Wish we had such a neat looking version of vscode in windows. Sorry for asking dumb questions. I'm a total noob and we have a language barrier xD
@JeremyChone
9 ай бұрын
Here are one extension I made (mostly for snippets) and below the extensions I use. rust10x.com/vscode
@nm6x
Жыл бұрын
Sorry but the accent is causing me some issues, what is the "xnl" trait in "xnl" type? Can someone clarify this?
@JeremyChone
Жыл бұрын
external trait. Traits that do not belong to the crate. (Let me do a quick pass at the caption, I can fix that one) Edit: I did a quick pass at the CC caption. Hopefully, this will help others. Thanks for the feedback. 20+ years, and still have my airport accent!
@nm6x
Жыл бұрын
@@JeremyChone thank you so much for the clarification will try to keep up with the good content!
@JeremyChone
Жыл бұрын
Yes, always ask if something is not clear. It gives me an opportunity to check the CC and see what words I need to work on (can’t fix much, so, need to prioritize)
@chaqua1559
Жыл бұрын
I'd love a guide on clap
@JeremyChone
Жыл бұрын
This is a good suggestion. I did once a long time ago, but now that we have Clap 4.x, it would be a good time to refresh with some of those best practices.
@RolandHaller
3 ай бұрын
Can i have a video to explain the video?
@dot32
Жыл бұрын
am i the only person who has no idea what any of this is doing
@marcingil7425
Жыл бұрын
unfortunately I don't understand most of the things in this tutorial. I think you have to have good understanding of many Rust ideas. Still I'm impressed by this tutorial. I will analyze it step by step because I have a feeling that it will help me much in learning Rust.
@porky1118
Жыл бұрын
Code lens is confusing, especially in tutorials, and I hate it in general.
@JeremyChone
Жыл бұрын
I tend to love them when I can toggle them. Most of the time they are off.
@porky1118
Жыл бұрын
@@JeremyChone I like the highlights, which are not always there. They are in distinct boxes and don't move the code around.
@JeremyChone
Жыл бұрын
@@porky1118 yes, I can see why the code moving is distracting. This why I do not write with inlays, but I like to toggle them on to see where I am once in a while (especially when chaining)
@thefrenchdude1
5 ай бұрын
Rust file system is just so bad. Absolute joke to organise your code with folders/files
@JeremyChone
5 ай бұрын
I actually differ on this one. I really like the module and file system of Rust, especially as the code grows. I would need to make a video to explain why, but here are some points: 1) Modules/files can have multiple constructors (structs, functions, etc.) 2) The whole `my_module/mod.rs` or `my_module.rs` and `my_module/...` offers nice flexibility for different styles. 3) Child modules can see all parent module constructs, which is a good model. It's relatively simple, intuitive, and not too restrictive. 4) The re-export capability `pub use my_sub_module::*` allows a module to manage its internal file organization based on coding practice versus what hierarchy is exposed to external modules/crates. I use that a lot. 5) The advanced fact that we can redirect a module to a totally different path is very useful for unit tests that would add too much code weight to the original module. I use that rarely, but it's very useful. 6) And the whole workspace with features model takes all of that to a whole new level. There are many others, but the module and file model is one of the reasons why I find myself so productive in Rust and feel so limited when I return to my old languages (which luckily does not happen often these days).
@thefrenchdude1
5 ай бұрын
@@JeremyChone thanks for taking the time to reply, I struggled with folders and files not being recognised. rly appreciate the content of the channel. ATM building a Tauri app with angular, front end working but stuck on the back end as I wanted to use MySQL. If you have any suggestions. Thx again
@esphix
3 ай бұрын
You should never have to use a utils module.
@JeremyChone
3 ай бұрын
I actually differ with this one. Here are some points: - First, if not having utils in your app/lib/sub-crates works for a specific code design, then this is definitely a reasonable approach. - However, we have to realize there are no absolute truths in best practices. - There are many bad practices, but there could also be different ones. - In our case, using lib/app or sub-crates utils that normalize some behavior for the system (app or lib) can be a good scaling point. - For example, one pattern that scales very well for our programming style is the XTrait patterns, used in the kzitem.info/news/bejne/k4Nmtoefo36fnKg video. It allows having app/lib traits without worrying too much about making them too generic but can normalize code very well. Now, there is one thing I am going to change in an updated video about our best practices. It's the prelude. I adopted new Error Best Practices (kzitem.info/news/bejne/y2OMt3ePiWmorKw), which now does not require the prelude, and I tend to not have prelude in most cases. When I do, it's in a very specific use case, as seen in the Rust Web App code base (to avoid repetitive similar includes in some sub-modules, but its an exception, not the rule). (e.g., github.com/rust10x/rust-web-app/tree/main/crates/libs/lib-rpc/src/rpcs) I am planning to do a new version of this video! The 2024 edition. Thanks for sharing your perspective. While there are more bad ways than good ways, there could be multiple good ways. Happy coding!
@esphix
3 ай бұрын
@@JeremyChone Your points do not pertain to what I argued. My contention is that it should never be necessary to use them. It seems you misunderstood or inferred that my statement was advising against their use, which it was not. Please re-read my statement more carefully and attentively next time.
@freshlix9554
3 ай бұрын
util is ugly. I was taught, that you don't need utils. You need better abstraction. Although I get the idea of a quickstart project, for real applications I would prefer to pick software Design patterns such as Atomic, Foundations and Structures, Base and Composites (etc.) or in other words any abstraction that suits your suitcase best, by structuring your dev-experience around the goal you try to achieve, so it does not rely on an utility dump.
@JeremyChone
3 ай бұрын
I do not think there is an absolute truth on this. You might not expose utils outside of your lib/crate, but there's nothing wrong with having common utils under utils. In fact, a pattern that worked very well for me is to have some custom traits and implementations under utils for Value, Vec, etc. It fits very well with the Rust pattern and cleans up the code. A complementary technique I use is to have a support module for more specific modules or submodules, containing utilities for that part of the system. Anyway, what has been working well for me is to be pragmatic, consistent, and open to changing things as the core matures. Being too dogmatic, especially following dogmas from books or other sources, has mostly been counterproductive for me. That being said, if you have patterns that work well for you and your team, there's nothing wrong with that.
@donwinston
4 ай бұрын
Ooof. Rust ain't for me. Sticking with Java. Scala would be more appropriate for most Java programmers looking to for something more modern.
Пікірлер: 101