Rust Programming: The Ultimate Builder Pattern Tutorial

Поділитися
Вставка
  • Опубліковано 14 гру 2024

КОМЕНТАРІ • 92

  • @chaqua1559
    @chaqua1559 2 роки тому +109

    I love the new style with the multiple windows

    • @JeremyChone
      @JeremyChone  2 роки тому +11

      Good to know. Thanks for the note.

    • @Mr.BinarySniper
      @Mr.BinarySniper 10 місяців тому

      yeah.. its really awesome.. very easy to understand the point. but surely it takes much more effort.

  • @PledgeBass
    @PledgeBass Місяць тому +1

    I've watched a lot of youtube tutorials on a lot of different topics (not just programming related). Doubt you will see this, but I just gotta say this is some of the best written, edited, and paced educational content I've ever seen. You are extremely talented! Just the right speed, everything is super clear - Wish there was more content of this quality on youtube.

  • @ayoubes
    @ayoubes 2 роки тому +10

    I just love the way you explain concepts nicely, clearly and progressively. I hope to see more Rust videos like this.

  • @jca6148
    @jca6148 2 роки тому +4

    Incredible video, I'm a maintainer of Hurl, an Open source project and just have an issue about major version breaking change. One solution proposed is to implement the "Pattern builder", so here we go, I just have to follow the video !!! Thanks, crystal clear, subscribed!

    • @JeremyChone
      @JeremyChone  2 роки тому +2

      Thanks, upcoming video about TypeState in Rust, and how to combine it with the builder pattern. Basically, makes the .url check compiled time v.s runtime. If you go to the github repo, the code is already there.
      Happy coding!

  • @hamzamohd.zubair1709
    @hamzamohd.zubair1709 Рік тому +2

    jam packed with information. this 20 minutes is packed with years of experience in rust.

  • @gogudelagaze1585
    @gogudelagaze1585 2 роки тому +13

    i just want to point out that there is a derive_builder crate, which removes quite a bit of the boilerplate on complex structs. Thanks for the video, great stuff!

  • @SniffleSneeze
    @SniffleSneeze 9 місяців тому

    I'm a mid-lvl PHP dev and my company as recently been bought and I found myself having to learn Rust now.
    This video on the Builder Pattern is exactly the kind of video you don't find anywhere else I feel very lucky to have find surch gems!
    please do continue ! would love to hear about other patterns and code standar for Rust.
    Thanks a lot for sharing your precious knoledge

  • @excelfan85
    @excelfan85 2 роки тому +7

    This video is just brilliant, i had so many ah huh moments watching please do more. I love this video specifically because it leads be towards understanding what is happening. Brilliant

  • @dr-maybe
    @dr-maybe 2 роки тому +8

    These tutorials are just perfect

  • @TheLastEinherjar
    @TheLastEinherjar Рік тому +1

    Dam I learned a lot, not just about builder patterns.
    Well done!

  • @unorthodox1430
    @unorthodox1430 2 роки тому +12

    Very well made, I learned a lot, thank you

  • @codeshowbr
    @codeshowbr 2 роки тому +3

    Awesome, the multiple windows style is great, thank you

  • @KresnaPermana
    @KresnaPermana Рік тому +1

    Dude, thanks for bringing this quality of rust tutorial, your content is very good and straightforward

  • @MattBolt35
    @MattBolt35 Рік тому +3

    Your videos are so well constructed and very informative - Thank you!

  • @learnityourself
    @learnityourself 2 роки тому +3

    Eyyy, thanks for this one glad that you got time to do this one. Superbly done Jeremy.

    • @JeremyChone
      @JeremyChone  2 роки тому

      Thanks. This one was from your suggestion.

  • @axeld.santacruz4659
    @axeld.santacruz4659 Рік тому +1

    Great example, so far the best video on Builder Patterns on Rust.

    • @JeremyChone
      @JeremyChone  Рік тому

      Thanks. Builder with type state coming soon!

  • @tsalVlog
    @tsalVlog 2 роки тому +3

    today I learned about the `insert` method on the Option enum. that will clean up a bit of my code..

  • @JeffHanke
    @JeffHanke 2 роки тому +8

    Great video! I like destructuring the builder on the first line of the build function, it avoids all the "self." and feels cleaner to me. It might not make sense for really short builder functions though.
    let Self { /* builder field names */ } = self;

    • @JeremyChone
      @JeremyChone  2 роки тому +1

      Interesting. So, you put the builder properties public, right?

  • @cthutu
    @cthutu 2 роки тому +3

    I tend to use '&mut self' for all the configuration methods and then use 'self' on the build method to consume it finally.

    • @JeremyChone
      @JeremyChone  2 роки тому +1

      That would work. But the catch is that we cannot chain all the way to the build, right?

  • @TON-vz3pe
    @TON-vz3pe 11 місяців тому +1

    Awesome tutorial. Rust is just addictive. Keep it up Jeremy. 👏

  • @none_of_your_business
    @none_of_your_business 2 роки тому +1

    i was thinking just the other day that i would like a book on design patterns implemented in rust, then the youtube algorithm recommends you, not bad at all

  • @syaPK
    @syaPK 2 роки тому +2

    i love this reminder

  • @jaredthanemartin
    @jaredthanemartin Рік тому

    I love your videos. you have taught me so me great little rust tricks and patterns. Keep up the great work!

  • @S4ntia60
    @S4ntia60 Рік тому +2

    I'm new to Rust and I wonder if you can create a builder class of a struct by just adding an annotated macro. I see this in other languages and can't help to stop thinking in non-rust ways of doing things. I this is not good advice, I'd like to know why. Thanks!

    • @JeremyChone
      @JeremyChone  Рік тому +1

      Yes, some crates allow you to annotate your struct to provide a builder implementation.
      One popular option is derive_builder: crates.io/crates/derive_builder.

    • @S4ntia60
      @S4ntia60 Рік тому +1

      @@JeremyChone thanks for the reply. Ill take a look. Keep on with the great content

  • @HagbardCelineOnRust
    @HagbardCelineOnRust 2 роки тому

    Thanks for the new video @jeremy

  • @nm6x
    @nm6x 2 роки тому +2

    I really need a quick vid explaining clone cloned take as_ref etc etc

  • @seblund
    @seblund 2 роки тому +2

    I was hoping that you would take it a step further with the consuming builder and use type state to ensure that the request has an url, it would get rid of the result on the build method; making the API infallible if it compiles!

    • @JeremyChone
      @JeremyChone  2 роки тому +2

      Yes, very good point. Somehow I forgot about it.
      I might do another video at some point.
      Thanks for this great feedback!

    • @JeremyChone
      @JeremyChone  2 роки тому +2

      In the meantime, here is a great link about State Builder Pattern: www.greyblake.com/blog/builder-with-typestate-in-rust/
      I will add it to the video description.

    • @JeremyChone
      @JeremyChone  Рік тому +2

      Thanks to your suggestion, I did the video about the TypesState Builder pattern: ua-cam.com/video/pwmIQzLuYl0/v-deo.html
      Interesting enough, somehow, after explaining everything, I forgot to mention in the video that now build() can just return Request rather than Result of Request. But I added it in the description after someone told me.
      Anyway, thanks for the feedback!

  • @markday3145
    @markday3145 2 роки тому +1

    Thanks! Before, I didn't really understand the point of the builder pattern. Your explanation helped.
    At 5:54, you had "String" selected, and then it suddenly became "Option". Do you have some special keyboard shortcut that wraps the selected text in "Option"?

    • @JeremyChone
      @JeremyChone  2 роки тому +1

      About the String to Option, that was a video editing trick.
      Now, there is something in VSCode/RustAnalyzer.
      If you select "String" and go to refactor, then, you have an option "Surround with Option". There should be a way to make it a shortcut.
      We could also do a surround snippet. I did not do any of those yet, I might at some point.

  • @databasemadness
    @databasemadness 2 роки тому +1

    Pure gold.

  • @emvdl
    @emvdl 2 роки тому +1

    Thanks Jeremy, great job 👍

  • @meowsqueak
    @meowsqueak Рік тому

    Thank you for making this video, it's really clear and informative.
    One thing I noticed: when I changed `self.url = Some(url.into())` to `self.url.insert(url.into())`, clippy complained about the Unused Return Value (from Option::insert()) - so I prefix with `let _ = `, but that seems inelegant. Is there a nicer way to use insert without triggering clippy?

  • @artxiom
    @artxiom 6 місяців тому

    Great video!
    Just a question: is there any reason why you don't use the newtype pattern `struct RequestBuilder(Request);` instead of copying all the fields in a new struct?
    I mean I understand that you loose a little bit of flexibility because now the fields are not Option's (unless they are in the constructed type) and in your example you would have to check if the url is empty - but I think that's also fine. I would anyway argue that when something isn't optional it's better to add it as a parameter to new, and then you also don't need to return a Result, because it can't fail.
    I just feel that with newtype it's clearer, there is way less repetition and code and you work on the constructed object directly.

  • @julesoscar8921
    @julesoscar8921 Рік тому

    Nice video, idk what is the most impressive between you're lvl in Rust or Vscode 😅

  • @julesoscar8921
    @julesoscar8921 Рік тому

    is there a good way to make it mandatory to call .url() before build()?

  • @dragonmax2000
    @dragonmax2000 2 роки тому +1

    Have you considered making a longer video with more comprehensive detail for API building?

    • @JeremyChone
      @JeremyChone  2 роки тому +1

      That is an excellent and timely question.
      The Awesome-App series will be about this in a way, but more from an entire application point of view. The first video was an introduction, ua-cam.com/video/BY_ZjPGqJJk/v-deo.html, but I plan to make enhancements as videos, and some of them will include API designs.
      One of those enhancements I am working on is a utility ModQL (for Model Query Language), which I might make a "rebuild from scratch" video if I find a way to make it not too overwhelming. However, this would be a great lib tutorial as it uses a lot of patterns, including procedural drive macros and Serde deserialization implementation.
      For now, ModQL (crates.io/crates/modql) implementation is still experimental, but the concept/design (.e.g., joql - joql.org/) is something we use in our production applications, so it is relatively mature and value-tested.
      The challenge is how much context and information I can put in a video before it becomes overwhelming and confusing. In my previous video, I found I could go up to 500 to 1k loc without getting too confusing. The catch is that ModQL might need a lot of contexts, as it follows the JSON-RPC model over REST, and could be seen as an alternative to GraphQL, and mistaken for an ORM.
      Now, I am all ears if you have a more straightforward API suggestion.

  • @peterthecoderd.1210
    @peterthecoderd.1210 2 роки тому +1

    Very interesting and timely. Thank you again.
    I'm trying to learn "iced" while learning rust. The language is confusing enough, but I am determined. In the first example supplied from the iced site, the code does not compile. With the help of the compiler, I was able to fix all but one error. This error is based on the use of the .into() function. I cannot figure it out.
    Would it be possible for you to do a video on "iced?" If not, can I send you the short code?
    I come from years of using Delphi (Pascal) so a lot of this is quite understandable, but some things are really difficult. I need a GUI so I can make the kinds of applications people ask me for.
    Merci beaucoup pour votre temps!

    • @JeremyChone
      @JeremyChone  2 роки тому

      Thank you for the kind words. Iced is an interesting UI technology, but for now, we are focusing Tauri and UIWebView/TypeScript for frontends.

  • @LiiittleBigPlanet
    @LiiittleBigPlanet 2 роки тому +1

    I can only agree with the other comments! The quality is amazing, with the overlaying windows! Love it! keep up the good work!

  • @logeshkumarrajkumar861
    @logeshkumarrajkumar861 2 роки тому

    Hi thanks for your effort. I watched your video on ownership and jumped to this video. Its really hard for me to follow up. Can you suggest the order I should follow in watching your videos to understand this video. I mean what videos I should watch before watching this?

  • @floriansalihovic3697
    @floriansalihovic3697 2 роки тому

    Great video! Which tools did you use? I am thinking of creating a couple of videos myself.

  • @ricardokullock2535
    @ricardokullock2535 16 днів тому

    It would seem the '.insert()' method returns a &mut to self, so you should need at least a "let _ = ...", but I see no errors showing up there. Or am I getting this wrong?

    • @JeremyChone
      @JeremyChone  16 днів тому

      In this particular example, the design ensures that the insert operation cannot fail. If it can fail, you should definitely return a Result.
      By the way, I usually prefer the consuming pattern, but there’s nothing fundamentally wrong with the ref mut approach.

    • @ricardokullock2535
      @ricardokullock2535 16 днів тому

      @@JeremyChone The function signature that I see is this:
      core::option::Option
      impl Option
      pub fn insert(&mut self, value: T) -> &mut T
      Since it has a return type, you would need to assign it to some variable, but in the video you don't. Maybe the compiler doesn't complain for some other reason?

    • @ricardokullock2535
      @ricardokullock2535 16 днів тому

      @@JeremyChone I've just taken a closer look, and it's actually just a warning here: "#[warn(unused_must_use)]" is on by default

  • @Jsmenzies
    @Jsmenzies 2 роки тому

    Basic question but how can you have a function return type as: Result
    do you not require 2 arguments like Result?

    • @JeremyChone
      @JeremyChone  2 роки тому +1

      Good question.
      It is because the Result type is aliased in the prelude.rs.
      This is a common pattern in Rust. It allows normalizing all of the Results of your crate.
      So, in the prelude.rs, I have
      // re-export the crate Error
      pub use crate::error::Error;
      // alias Result to be the crate Result
      pub type Result = core::result::Result;
      And because I typically import the prelude
      use crate::prelude::*
      Then, I can just use this Result type alias.
      Here the video about the code layout I use : ua-cam.com/video/oxx7MmN4Ib0/v-deo.html

    • @Jsmenzies
      @Jsmenzies 2 роки тому +1

      @@JeremyChone I really appreciate you taking the time to answer. I find your videos incredibly helpful so thank you so much

  • @peterklemenc6194
    @peterklemenc6194 Рік тому

    I really love these videos, going through quite a few of yours! The only thing that keeps bothering me is that your editor hides code, leaving us, with normal editors that don't auto-import missing dependencies in the dark (a bit) about what's needed. I wish you would always display the full code and instead perhaps highlight, or at least show the full code, then hide/omit it while continuing on it.
    Thank you for making these lovely videos!

    • @JeremyChone
      @JeremyChone  Рік тому

      Thank you for your feedback.
      Are you saying you don't have the small pop-up that displays the import? The difficulty is that I can't show everything. In the upcoming videos, I'm planning to pause a bit more when a decision needs to be made, but will still present the obvious ones briefly. I'm doing this with the pop-up feature in mind, as I assume most editors come equipped with this functionality.
      Is that a fair assumption?

  • @chouaibsam4381
    @chouaibsam4381 2 роки тому

    let else doesn't work for me and I updated before but it says le else is unstable and I'm stuck can't find how to write in a match close

    • @JeremyChone
      @JeremyChone  2 роки тому

      What do you get if you do: rustc -V
      I get: rustc 1.65.0 (897e37553 2022-11-02)

    • @chouaibsam4381
      @chouaibsam4381 2 роки тому +1

      @@JeremyChone yeah you are right I'm on 1.64 my bad

  • @peternierop3241
    @peternierop3241 2 роки тому +1

    Where is the ten upvote button... This is very eye opening.

  • @NOISCALE
    @NOISCALE Рік тому

    ❤❤❤

  • @clementdato6328
    @clementdato6328 2 роки тому +3

    Implicit clone seems to be bad API performance-wise. Consuming pattern seems to be more rusty.

    • @JeremyChone
      @JeremyChone  2 роки тому +6

      Agree,
      1) non consuming pattern .build(&self) is ok, but mostly when the builder data are not directly used for building the object (so, no implicit clone, because no clone is needed).
      2) non consuming pattern with .build(&mut self) is bad IMO. I do not see why that would be a good idea.
      3) The consuming pattern, with build(self) is the one most aligned with Rust IMO, and my default go to when I need a builder pattern.

    • @rumplstiltztinkerstein
      @rumplstiltztinkerstein 2 роки тому

      That depends. Does the clone happen only once or is it called several times? If there's only one clone when doing thousands or millions of operations, it is okay. But if clone happens several times during the runtime, then it might slow the CPU by a lot. Creating and copying memory is extremely slow in comparison to just CPU calculations.

  • @kamertonaudiophileplayer847

    Define method from enum, it is better than String.

    • @JeremyChone
      @JeremyChone  Рік тому +1

      Ho yes, I think there was a comment for this on the code. I just simplified this part for the example.

  • @TheGreatSpiff
    @TheGreatSpiff 2 роки тому

    Hope this won't come off as rude but, have you considered doing subtitles for your content? It's probably because I am just a beginner so I'm not familiar with all of the lingo (and also don't have any friends who speak with your specific accent) , but there are times when I just cannot understand a word or sentence of your narration.

    • @JeremyChone
      @JeremyChone  2 роки тому +2

      I think UA-cam does the auto CC, and it is not too bad. Try to press the CC icon somewhere. Sometime I have to correct couple of words, but overall it should be ok.

    • @FROST8ytes
      @FROST8ytes 2 роки тому +1

      @@JeremyChone I am willing to contribute to adding subtitles to your videos

    • @herrbanane
      @herrbanane 2 роки тому +4

      Actually, as a non-native, I find it very easy to understand.

  • @jak4596
    @jak4596 2 роки тому

    Voudrais tu faire un cours de rust en français ? Le "voilà" ta démasqué

    • @JeremyChone
      @JeremyChone  2 роки тому +2

      One day I might, but I am in a catch-22 situation. I still have my airport accent when I speak English, but it's tough for me to talk tech in French (I have been living in San Francisco most of my tech life).
      I will give it some thought, though. My planned 2023 Full Rust Course could be a good candidate for a VF.

  • @phenanrithe
    @phenanrithe 2 роки тому

    The build pattern is one of the Achilles' heel of Rust because of the borrow checker. The "-> &mut self" denies the fluent method and the "-> Self" denies later addition before doing the build without reassigning, so there's no escaping boilerplate code. I would definitely avoid to copy all the fields in the builder though, that's unnecessary. Instead, only add one field with the target object (Request) which is preset to default, it will simplify a lot. You can hand it over in the build() method without overhead.

    • @diadetediotedio6918
      @diadetediotedio6918 2 роки тому

      You can literally have a macro to generate the boilerplate for you

    • @phenanrithe
      @phenanrithe 2 роки тому

      @@diadetediotedio6918 What do you mean by "literally"? And for which part? Generally speaking, I don't think macros are the solution to every shortcoming, you would just have macro boilerplate code instead, that you would need to include in each crate. I'd rather fancy a way to tell the compiler that when an object is not actually moved in a function that takes ownership, it can be considered as still owned by the original owner. Or maybe that's something the compiler will be able to work out on its own one day. In this case, the setters could benefit from it, but I've seen this annoying pattern in other situations.

    • @JeremyChone
      @JeremyChone  2 роки тому +2

      I would differ. I think the Rust data model suits the builder pattern very well, especially for the consuming builder pattern.
      The Rust mutable model makes them thread-safe and efficient while making cloning explicit. The builder re-assignment is a minor cosmetic oddity but a totally logical one.
      Now, I would agree that the Builder Pattern should not be abused. It should be an exception for those "structures" that would gain to be built in steps or are relatively complex. Good examples of well-thought-out are Bevy, Tauri plugins, Clap command tree, and many Web framework routing/service structures. SQL Builders are an excellent fit for this pattern as well.
      I used to avoid builder patterns in Java, but now, in Rust, when appropriate, I find them very productive.
      The TypeState builder pattern can also be powerful and relatively natural in Rust (I remember in my Java days having issues trying to chain methods that return variation of the self type). TypeState Builder Pattern video coming soon...

    • @phenanrithe
      @phenanrithe 2 роки тому

      The re-assignment and the other ways to work around the borrow checker make the code noisier, but you're right, it's not a blocking issue. Hopefully it will get smarter with time when ownership transfer in functions can be detected by the way they are used.
      I think build patterns are hard to avoid especially in Rust because there are not many alternatives if you want to avoid mutable fields. Another good pattern is optional named arguments: in languages like Kotlin or Python for example, they are a huge benefit in that regard. That's another feature Rust would greatly benefit from.

  • @bobby9568
    @bobby9568 2 роки тому

    Subtitles please 🥺

    • @JeremyChone
      @JeremyChone  2 роки тому

      Does the CC does not show for you? YoutTube auto caption is quite impressive with accents. I reviewed it, and seems to be ok.
      Let me know if the CC does not work for you.

    • @bobby9568
      @bobby9568 2 роки тому +1

      @@JeremyChone Yes it works fine, thanks!

    • @markday3145
      @markday3145 2 роки тому +1

      @@JeremyChone At 2:32, you said "trait", but the CC said "trade". That's minor.
      Slightly more difficult is that the CC text obscures the bottom of the video. The alpha value for the CC text is a little less than 1.0, which makes it a little harder to read when there is other text underneath. If only UA-cam would make the content taller so that the CC text appears beneath the video...
      I ended up turning CC off, and then using the keyboard shortcut to jump back 10 seconds if I needed to hear something repeated. Slowing playback speed to 75% is sometimes helpful.
      I think what you're doing is fine. I have several alternatives to help me if I'm having a hard time understanding.

    • @JeremyChone
      @JeremyChone  2 роки тому +1

      @@markday3145 First, thanks for the "trade" CC miss. I missed it in my quick review. I just fixed it.
      Second, thanks for the detailed and constructive feedback.
      I will see what I can do for the CC location, but it is hard to factor this in and have an optimum code layout. But I get your point.
      The accent and mispronunciation are bugs I have tried to fix for a while, but it is hard to fix something you can't see (i.e., hear). I will work on enunciating better (it might take some time).
      Now the good news is that it has been said that people that listen to me speak English end up understanding French better. So, time to plan a Paris vacation!

    • @markday3145
      @markday3145 2 роки тому +1

      @@JeremyChone I assume you're a non-native English speaker. In that case, I think your English is actually pretty good. Your accent is... you; and it's not that hard for me, either.
      I've got tinnitus and sensory processing disorder. Both make it more challenging for me understand human speech in general, and especially in videos.
      Dialogue in videos is harder if I'm trying to concentrate on both the visual and the audio at the same time. Not speaking while the visuals are changing helps, but I'm not asking you to try to accommodate that. Being able to jump back 10 or 30 seconds, or to slow down playback, both go a long way to making it easier for me.