Immutable Design: Why You Should Care

Поделиться
HTML-код
  • Опубликовано: 10 сен 2024
  • Check out Dometrain and use code ZORAN for 15% off any course ► dometrain.com/...
    The immutable design is when a mutating method returns a new instance, right? Well, not exactly. That is the consequence, indeed, but the immutable design is much more. It is the set of principles and practices that lead to a more expressive code and, not least importantly, code that makes certain categories of bugs impossible or near-impossible to produce.
    Download the source code ► / zoranhorvat
    Join Discord server with topics on C# ► codinghelmet.c...
    Enroll course Beginning Object-Oriented Programming with C# ► codinghelmet.c...
    Subscribe ► / @zoran-horvat
    ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
    👨 About Me 👨
    Hi, I’m Zoran, I have more than 20 years of experience as a software developer, architect, team lead, and more. I have been programming in C# since its inception in the early 2000s. Since 2017 I have started publishing professional video courses at Pluralsight and Udemy and by this point, there are over 100 hours of the highest-quality videos you can watch on those platforms. On my RUclips channel, you can find shorter video forms focused on clarifying practical issues in coding, design, and architecture of .NET applications.❤️
    ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
    ⚡️COPYRIGHT NOTICE:
    The Copyright Laws of the United States recognize a “fair use” of copyrighted content. Section 107 of the U.S. Copyright Act states: “Notwithstanding the provisions of sections 106 and 106A, the fair use of a copyrighted work, including such use by reproduction in copies or phono records or by any other means specified by that section, for purposes such as criticism, comment, news reporting, teaching (including multiple copies for classroom use), scholarship, or research, is not an infringement of copyright." This video and our youtube channel, in general, may contain certain copyrighted works that were not specifically authorized to be used by the copyright holder(s), but which we believe in good faith are protected by federal law and the Fair use doctrine for one or more of the reasons noted above.
    #csharp #dotnet

Комментарии • 36

  • @zoran-horvat
    @zoran-horvat  3 месяца назад +1

    Check out Dometrain and use code ZORAN for 15% off any course ► dometrain.com/?coupon_code=ZORAN
    Download source code ► www.patreon.com/zoranhorvat
    Join Discord server with topics on C# ► codinghelmet.com/go/discord
    Enroll course *Beginning Object-Oriented Programming with C#* ► codinghelmet.com/go/beginning-oop-with-csharp
    Subscribe ► ruclips.net/channel/UCxsWfh8LCcn55mFB6zGBT1g

    •  3 месяца назад

      Check if ArgumentException didn't get ThrowIf... methods to get 21% discount from me 😂

  • @1992jamo
    @1992jamo 3 месяца назад +5

    Extremely interesting. I had never heard of System.Collections.Immutable and had previously wondered how on earth you'd keep record classes with mutable members.
    I need to retrain my brain to read primary constructors more fluently, because I am so used to seeing any member declared within the scope of the object.
    I know the usefulness of extension methods, but I typically avoid them if I have control of the base object because it hides behaviour and implementation. If you were reading the source of a large project, you might not know someone has extended it, and more often than not you'd assume they haven't if they can add the behaviour directly to the type.
    The value of your videos never ceases and every time I learn something new. One more tool in the belt! I've popped you a fiver on patron and joined your discord. I'd love to give more considering how much I have learned, but I'm not in the position to right now.

    • @zoran-horvat
      @zoran-horvat  3 месяца назад +1

      Thanks!
      Your observations about extension methods are sound. The prerequisite for proper use of extension methods is that the type exposes its components publicly. When they start from the type, they begin to make sense. Attaching extension methods to an unsuspecting type usually looks like a hack.

    • @David-id6jw
      @David-id6jw 3 месяца назад +1

      @@zoran-horvat Out of curiosity, do you have any thoughts on how the upcoming extension types might affect how you approach building functional types?

    • @zoran-horvat
      @zoran-horvat  3 месяца назад +1

      @@David-id6jw Extension types look more object-oriented to me, with a caveat: you cannot extend a type which is not ready for it, primarily in that it exposes its components publicly. Doing so already requires immutability of components and then functional design is already at the arm's length. Therefore, it is all tightly connected.
      I personally like extension properties a lot.

  • @osmantas369
    @osmantas369 3 месяца назад +6

    Great and funny to hear rhyme like "immutable mutables mutates mutable immutables" lol

  • @brendonanderson8673
    @brendonanderson8673 16 дней назад +1

    Supporting on Patreon! Thanks for these videos💪

    • @zoran-horvat
      @zoran-horvat  16 дней назад +1

      @@brendonanderson8673 Thanks!

  • @ElOroDelTigre
    @ElOroDelTigre 3 месяца назад +2

    Amazing as always. Thanks, Zoran.

  • @robinheyer708
    @robinheyer708 3 месяца назад +1

    8:18 Hah! Love the humour! I hope to one day encounter a ThisIsSoSmart() method in a codebase out in the wild. Or better yet, write one myself!
    I've been trying F# the last few Saturdays and I'm surprised how easy to pick up the writing style is. I really only use var in C# when I'm constructing some elaborate Linq chain but using the type inference in F# feels very natural. And back in C# I still avoid var as much as I used to.
    I've only done a few Exercism exercises so far but I'm enjoying the emphasis on pattern matching and using discriminated unions. I have had the occasional OOP brain block (where I'll curse at those same things I just mentioned I'm enjoying) but it hasn't been that bad. It has made me consider using extension methods more to write more expressive and concise code. Trying a custom Result Option implementation for low impact error handling which I believe you have also covered in a video. Maybe I'll write a class library with a Book type in F# and see how much of the refactoring you demonstrated here would still be needed if I used that in C#.

    • @zoran-horvat
      @zoran-horvat  3 месяца назад +1

      F# would sever the noise I have in my C# code and make it even shorter.

  • @luc9volts
    @luc9volts 3 месяца назад +1

    Very good examples!!👍🏽

  • @Sydra.
    @Sydra. 3 месяца назад +1

    This is the way!

  • @leos-clockworks335
    @leos-clockworks335 3 месяца назад

    I am slowly moving into a more Immutable design, where possible, and your videos are very helpful, so thanks!
    I was wondering what are your thoughts on having a validation record for specific use cases (Similar to 'Title' in this video and also shown in a different video of yours.).
    For example, having a record for a non-negative number, non-empty string etc. and of course project specific records.
    On one hand, it seems useful, to skip that pesky validation, as some places there are so many checks whenever some string is getting passed and making sure it's not empty.
    On the other, it seems to be a bit overkill, maybe if it was built in (Similar to IPAddress, EndPoint, URI and more), even though creating them is very easy using a record.
    For domain specific data, it's pretty obvious, and creating one seems natural, but going around and creating more 'basic' ones feels a bit overengineered.
    Would love to hear your thoughts!

    • @zoran-horvat
      @zoran-horvat  3 месяца назад

      I am generally avoiding going into that direction because it quickly leads to the explosion of classes. However, I do apply it to domain concepts.

  • @pl4gueis
    @pl4gueis 3 месяца назад

    Do you have resources or a course for a complete end-to-end example of functional domain modeling in a complete application? I feel like connecting the dots between the immutable stuff and mutable stuff with side effects is currently a bottleneck for a lot of people.

    • @zoran-horvat
      @zoran-horvat  3 месяца назад +4

      I am gradually building a set of demos, including in videos like this one, hoping to produce a comprehensive guide with a large demo at one point.

  • @metallixbrother
    @metallixbrother 3 месяца назад

    Thank you for an excellent video as always. I wanted to ask; what is the correct way to maintain value equality when using records that contain a collection, in your opinion? Is it better to create a type that wraps an immutable collection, that provides value equality for the contained collection and using that everywhere? This feels like it would be advantageous in that we don't need to create a custom equality comparer for every class that contains a collection, but a part of me worries that it might be a bit "hacky" as this is more dictated by how records handle equality checking on reference types, rather than being intrinsically meaningful.

    • @zoran-horvat
      @zoran-horvat  3 месяца назад +1

      Collections have more than one way to compare, and that is the principal reason why they do not implement Equals and GetHashCode (besides the fact they would run in O(n) time and space often as much as O(n)). Therefore, I do not insist on maintaining equality in records that contain collections. It is more productive to supply an IComparer implementation that implements the desired comparison and leaves the record simple and focused.

  • @ataadevs
    @ataadevs 3 месяца назад

    I didn't understand how the AnyKeywordSatisfies function parameter went from Func predicate to Func predicate, can you please explain more or if you have any resources about it

    • @DragoGrayLite
      @DragoGrayLite 3 месяца назад +1

      I think i should be called like: AnyKeywordSatisfies(keyword => keyword.Equals(phrase)) where the phrase is in predicate and it is not neccesary to have it in AnyKeywordSatisfies as input value.

    • @zoran-horvat
      @zoran-horvat  3 месяца назад +2

      The missing string can be part of its closure - even more it can be some other type, not only a string!
      You can call that method with a lambda: keyword => keyword.Contains(x), where x is the local variable.
      This kind of solution is much more flexible than the first one.

  • @WalderFrey
    @WalderFrey 3 месяца назад

    How do you ensure that all consumers use a factory function at the 7:17 mark?
    Can't you keep on using the constructor, e.g. new Title("C# for Dummies")?
    I think I'm missing something here 🙂.

    • @zoran-horvat
      @zoran-horvat  3 месяца назад +1

      Code review and automated analyzers (a.k.a. fitness functions).
      The compiler cannot save the team from a member who doesn't follow the coding rules.

    • @eduardpopescu9109
      @eduardpopescu9109 3 месяца назад

      You can have an explicit constructor and make it private, if you wish. You don't have to use the primary constructor if it doesn't help you. By not exposing the constructor, you force the consumers to use the factory method. Keep in mind that records are still classes, unlike record structs.

    • @zoran-horvat
      @zoran-horvat  3 месяца назад

      @@eduardpopescu9109 That defies the purpose of records.
      I don't agree that programmers should write additional code to fight against the syntax and the teammates they don't trust.
      Write one fitness function for the entire project instead and use the language as it is.

    • @chris-pee
      @chris-pee 3 месяца назад

      @@zoran-horvat Interesting. Could you link any resource about creating such an analyzer? I know about libraries such as ArchUnitNET but I'm not sure how you'd go about that in this case.

  • @drbytes68
    @drbytes68 3 месяца назад +1

    Cries in C# 7 maintenance program. Cant even use tuples

    • @zoran-horvat
      @zoran-horvat  3 месяца назад

      True story. The language is so changed now compared to what it used to be.

    • @1992jamo
      @1992jamo 3 месяца назад

      I am stuck with most C#7 to support some legacy systems as well, and until 3 months ago I hadn't heard of ValueTuple, most likely because I wasn't using them and online people referred to them as Tuples, which I had assumed were System.Tuple which I was familiar with. Within the last year I've been given the freedom to develop new applications and I've been trying to modernise my C# syntax & patterns. I'm going to specifically refer to them as ValueTuple in conversation to avoid confusion.
      edit: This comment appears to be publicly invisible for some reason?

    • @zoran-horvat
      @zoran-horvat  3 месяца назад

      I think nobody mentions System.Tuple anymore, so you don't have to say ValueTuple explicitly. ValueTuples, or just tuples, have sent their inefficient and cumbersome predecessor, the System.Tuple, to a graveyard. System.Tuple was so inefficient, that I don't think anyone used them anyway.

  • @baranacikgoz
    @baranacikgoz 3 месяца назад

    It would be interesting if you make a demo using EF Core. If change tracker is not comfortable with this approach which it is not according to my demos, it is hard to use

    • @zoran-horvat
      @zoran-horvat  3 месяца назад

      Entity Framework is designed for entities, whereas immutable classes, and especially records, are meant to design types and values. Those two things don't go together, in a sense that Entity Framework was never intended to operate on them.
      It is common to use plain access to a relational database (e.g. via Dapper and similar solutions), or to apply event sourcing. The latter, when combined with an immutable design, is especially well suited to cloud and network applications.

    • @ghevisartor6005
      @ghevisartor6005 3 месяца назад

      @@zoran-horvat so confronting the two approaches, in your video "Kill Anemic Domain Models with Encapsulation: The Hard Part" you put the factory methods and other business operations inside the entity itself and then use that directly in the razor pages. I guess it wasn't for brevity for the demo, in case of razor pages or blazor server you would just those entities in the UI?
      The latest Blazor allowes you to swap between server or wasm render modes so maybe in that case one should consider the need for dtos unless they change how it works in the future (you need to make http calls in those wasm components anyway)