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 ► kzbin.info/door/xsWfh8LCcn55mFB6zGBT1g
8 ай бұрын
Check if ArgumentException didn't get ThrowIf... methods to get 21% discount from me 😂
@1992jamo8 ай бұрын
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-horvat8 ай бұрын
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-id6jw8 ай бұрын
@@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-horvat8 ай бұрын
@@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.
@WalderFrey8 ай бұрын
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-horvat8 ай бұрын
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.
@eduardpopescu91098 ай бұрын
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-horvat8 ай бұрын
@@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-pee8 ай бұрын
@@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.
@robinheyer7087 ай бұрын
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-horvat7 ай бұрын
F# would sever the noise I have in my C# code and make it even shorter.
@osmantas3698 ай бұрын
Great and funny to hear rhyme like "immutable mutables mutates mutable immutables" lol
@ElOroDelTigre8 ай бұрын
Amazing as always. Thanks, Zoran.
@brendonanderson86735 ай бұрын
Supporting on Patreon! Thanks for these videos💪
@zoran-horvat5 ай бұрын
@@brendonanderson8673 Thanks!
@leos-clockworks3358 ай бұрын
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-horvat8 ай бұрын
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.
@ataadevs8 ай бұрын
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
@DragoGrayLite8 ай бұрын
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-horvat8 ай бұрын
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.
@metallixbrother8 ай бұрын
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-horvat8 ай бұрын
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.
@pl4gueis8 ай бұрын
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-horvat8 ай бұрын
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.
@luc9volts8 ай бұрын
Very good examples!!👍🏽
@baranacikgoz8 ай бұрын
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-horvat8 ай бұрын
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.
@ghevisartor60058 ай бұрын
@@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)
@Sydra.8 ай бұрын
This is the way!
@drbytes688 ай бұрын
Cries in C# 7 maintenance program. Cant even use tuples
@zoran-horvat8 ай бұрын
True story. The language is so changed now compared to what it used to be.
@1992jamo8 ай бұрын
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-horvat8 ай бұрын
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.
@weluvmusicz2 ай бұрын
Immutables cost too much memory for a real world application!
@zoran-horvat2 ай бұрын
@@weluvmusicz What? You have no idea what you have said.