You Will Add Smart Constructor to Your Rich Domain Models When You See This!

  Рет қаралды 8,758

Zoran Horvat

Zoran Horvat

Күн бұрын

The source code is available to sponsors on Patreon: / you-will-add-to-84130393
Have you noticed the limitations of regular class constructors? They are indeed limiting class design in more than one way! This tutorial delves into Smart Constructor - an advanced pattern that addresses the constraints of traditional class constructors, thereby enabling more flexible domain modeling.
The tutorial builds on nullable reference types in C#, a critical element in enhancing constructor robustness. By combining nullable references with the Factory Method and Null Object patterns, we will present a refined approach to deep domain modeling, which helps handle special cases elegantly, while enhancing overall class implementation.
In essence, this tutorial aims to empower you to create classes that are robust, adaptable, and maintainable.
By leveraging Smart Constructors and related concepts, you'll add more efficiency and reliability to your object-oriented programming and domain modeling practices in C#.
Thank you so much for watching! Please like, comment & share this video as it helps me a ton!! Don't forget to subscribe to my channel for more amazing videos and make sure to hit the bell icon to never miss any updates.🔥❤️
✅🔔 Become a patron ► / zoranhorvat
✅🔔 Subscribe ► / @zoran-horvat
⭐ Learn more from video courses:
Beginning Object-oriented Programming with C# ► codinghelmet.com/go/beginning...
⭐ Collections and Generics in C# ► codinghelmet.com/go/collectio...
⭐ Making Your C# Code More Object-oriented ► codinghelmet.com/go/making-yo...
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
⭐ CONNECT WITH ME 📱👨
🌐Become a patron ► / zoranhorvat
🌐Buy me a Coffee ► ko-fi.com/zoranhorvat
🗳 Pluralsight Courses ► codinghelmet.com/go/pluralsight
📸 Udemy Courses ► codinghelmet.com/go/udemy
📸 Join me on Twitter ► / zoranh75
🌐 Read my Articles ► codinghelmet.com/articles
📸 Join me on LinkedIn ► / 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 KZbin channel, you can find shorter video forms focused on clarifying practical issues in coding, design, and architecture of .NET applications.❤️
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
⚡️RIGHT 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 authorised 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.
⭐For copyright or any inquiries, please contact us at zh@codinghelmet.com
#csharp #dotnet #vscode

Пікірлер: 70
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It's hard to explain how much I love your videos 😁😁
@zoran-horvat
@zoran-horvat Жыл бұрын
And vice versa!
@antonionakic2690
@antonionakic2690 Жыл бұрын
Just found Milan's channel through this comment and subscribed. Excellent content on both channels. Thanks, guys!
@obinnaokafor8125
@obinnaokafor8125 Жыл бұрын
Very poetic intro
@ConsoleHelloWorld
@ConsoleHelloWorld 11 ай бұрын
Two of my three favorites youtubers here together! You guys are simply awesome!!!!❤
@elpe21
@elpe21 10 ай бұрын
@@ConsoleHelloWorld Who's the 3rd? Nick ?
@m5s10
@m5s10 Жыл бұрын
The only thing that I'd like to add is to consider moving this smart constructor into a standalone factory class. Money object with the smart constructor feels like it's having too many responsibilities and one red flag is that it knows about other implementations of IMoney. If you extract the smart constructor logic in the separate class, it will know about concrete implementations, which is fine, it will only ever do one thing (create instances IMoney). So it will be small, concise, very easy to unit test and will respect single responsibility principle. Last, but not least, if we ever expand IMoney with new implementation (let's say Debt, where amount does go in negative value), to me it makes more sense to change the MoneyFactory, rather than Money.
@zoran-horvat
@zoran-horvat Жыл бұрын
I usually don't rush with introducing a new class for the purpose, simply because the design might not grow any further. For instance, nothing warrants that there will ever exist the third class implementing IMoney. On a related note, keep in mind that NoMoney is a Null Object implementation and it belongs with the interface, not with other concrete implementations. I often define a static factory (static property getter) on the interface, which returns the single instance of that interface's Null Object. Such static property getter would be called None, Empty, or Zero when speaking of money. If Money were defined in a sub-namespace, NoMoney would remain in the same namespace where the interface is defined. Therefore, any dependency on NoMoney is no more concrete than the dependency on IMoney.
@asdasddas100
@asdasddas100 11 ай бұрын
The whole time I was thinking about how I'd use an Option type instead of null Glad to see you mention it at the end, gives me more confidence in my decision making
@zoran-horvat
@zoran-horvat 11 ай бұрын
Actually, smart constructors come from functional languages which invariably have the Option type, and then use it in smart constructors.
@5cover
@5cover 11 ай бұрын
Awesome video as always 7:52 As a note, using the null-forgiving operator ('!') can lead to confusing exceptions such as NullReferenceException in seemingly unrelated code. I prefer to adopt the "fail fast" principle. If something that shouldn't be null is null, the developer should be warned immediately. Which is why I always implement a simple extension method that asserts that an object isn't null and returns it: public static T NotNull([NotNull] this T? t, string? message = null) { Debug.Assert(t is not null, message); return t; } Throwing a generic Exception() feels like a bad idea, an assertion makes more sense here since if t is null then it means there's a bug in the code.
@zoran-horvat
@zoran-horvat 11 ай бұрын
Good points. BTW I have thrown the Exception without getting into details because I was about to delete that code in a moment.
@GiovanniCostagliola
@GiovanniCostagliola Жыл бұрын
My “smart” constructors return Result ti encapsulate business rules violations, and throw exceptions when the invariant is violated by a corruption (db for example). This approach, as you can guess, enable the beauty of functional composition and the clean propagation of the logic errors from the very deep of the domain. I’m very interested on your opinion. I really enjoy your contents. Bravo
@zoran-horvat
@zoran-horvat Жыл бұрын
Unfortunately, majority of C# programmers are not ready to see their code that way. My production code also returns Option or Either for the same purpose.
@GiovanniCostagliola
@GiovanniCostagliola 11 ай бұрын
​@@zoran-horvat Absolutely agree. Unfortunately.
@jaredlash5002
@jaredlash5002 3 ай бұрын
At 6:02 there is a bug in the Money constructor for lines 10 and 11. It is possible that Math.Round(amount, 2) causes Money to get set to 0 (for instance, amount == 0.001). In this instance, the check from line 10 will already be passed, but you get an invalid Money object.
@jaredlash5002
@jaredlash5002 3 ай бұрын
The smart constructor preserves this bug.
@rakkarajput
@rakkarajput Жыл бұрын
Your awesome as always
@dxs1971
@dxs1971 9 ай бұрын
You can retrun Maybe or even Result and so avoid null reference.
@zoran-horvat
@zoran-horvat 9 ай бұрын
That is what the follow-up video is demonstrating: kzbin.info/www/bejne/bl6VqaWVoKeFpLM However, optional objects are not part of .NET and the whole idea is a bit hard for many C# practitioners to adopt.
@seriyezh
@seriyezh 11 ай бұрын
Thank you so much Zoran for sharing you knowledge and expertise. I definitely can recommend your courses to anyone who wants to improve their skills. I really enjoyed watching your course: Making Your C# 7 Code More Functional. I was wondering if we will see any F# courses from you?
@happy_burger
@happy_burger Жыл бұрын
Smart constructor can also be made async if that is what it takes to initialize an object
@zoran-horvat
@zoran-horvat Жыл бұрын
I'd rather keep asynchronous execution as an orthogonal concern. An object that supports common creation is certainly creatable in a Task.
@AndriyBezkorovayny
@AndriyBezkorovayny 9 ай бұрын
Thank you so much Zoran. WDYT, if the TryCreate method will have the output parameter? In that case, we get the result (true or false) and the instance (out) to conform the Try... pattern.
@zoran-horvat
@zoran-horvat 9 ай бұрын
I'm not fond of out parameters because I cannot chain calls on such methods. They also break a few other common coding patterns, such as passing functions as arguments, etc.
@AndriyBezkorovayny
@AndriyBezkorovayny 9 ай бұрын
@@zoran-horvat thank you, I got the point.
@ruekkart
@ruekkart Жыл бұрын
Great video! Maybe it's just me but I find a bit hard to follow the nested ternary operators and I'm guessing you're doing it that way because you need it to use arrow sintax declaration everywhere is that right? So I have another question, is there any advantage on only using arrow sintax to declare methods/constructors?
@zoran-horvat
@zoran-horvat Жыл бұрын
Let me clarify the bit about ternary operators first. They are not nested, they are chained in my code. The difference is substantial because chained tests act as a pattern-matching expression. And that brings us to the second question. Pattern matching expression is the expression. It is calculated from inputs, so to produce the output. If you can organize your methods to act as expressions, then the expression-bodied syntax is a natural choice. Both concepts come from functional programming. You can witness that they are now an integral part of the C# syntax.
@nick_stelmakh
@nick_stelmakh 11 ай бұрын
🔥🔥🔥
@seandonohue4048
@seandonohue4048 Жыл бұрын
Great video, thank you:-) One thing I've noticed in general is that exceptions often lose details which makes it harder to fix. So in this example, if somewhere on the call stack we catch an ArgumentException from Create, we don't know if it was the amount or the currency that is invalid. If we wanted to keep that detail, you might say: if amount is invalid then throw new ArgumentException("Invalid amount") else if currency is invalid then throw new ArgumentException("Invalid currency") else TryCreate(amount, currency). The drawback of this is that there is now duplicate code in Create and TryCreate. Is there a cleaner way to do this?
@zoran-horvat
@zoran-horvat Жыл бұрын
You are generally right, though there is a caveat. Besides the argument name, you should stay away from including argument values into the exception, because that may open security holes or break privacy laws. While argument values are often the critical piece when debugging from logs, it is usually best not to have them in logs in the first place! Speaking of the video, I have just opted to go with the shortest possible code.
@SuperJMN
@SuperJMN Жыл бұрын
Are you dropping the usage of the Optional (Maybe) type altoghether in favor of nullable reference types? What do you think? Is is still worth using it?
@zoran-horvat
@zoran-horvat Жыл бұрын
Nullable reference types are quite capable today, but solely thanks to the corresponding syntax. A custom optional type cannot compare with that, not until C# language adds syntactic sugar. However, I am using optionals in my projects. Thay are a powerful modeling tool, telling much more than a nullable reference can. I am only avoiding them in regular videos because many viewers would just be confused. For example, smart constructors in my production code invariably return an Option, the same way as it is a norm in Rust.
@SuperJMN
@SuperJMN Жыл бұрын
@@zoran-horvat That's great relief, because I also think that optionals are categorically better. Thanks!
@Mortizul
@Mortizul Жыл бұрын
@@SuperJMN Haha Categorically. Nice play on words!
@i.o.5508
@i.o.5508 11 ай бұрын
In what order should I take your UDEMY courses from start to finish?
@zoran-horvat
@zoran-horvat 11 ай бұрын
The Beginning OOP course is the fundamental one. It covers concepts that every programmer should know well, but quite often even senior programmers are not sure about. I recommend that cou8ti anyone who asks. The other courses are more topic oriented. Refactoring to Patterns and the one on design patterns could be the next pick.
@i.o.5508
@i.o.5508 11 ай бұрын
@@zoran-horvat i want to completly learn about OOP with C#. I know the basics such as inheritance, interface, encapsulation etc...
@zoran-horvat
@zoran-horvat 11 ай бұрын
@@i.o.5508 I'd say that the Beginning OOP course is still the best option.
@Rafa-fp4ih
@Rafa-fp4ih 8 ай бұрын
Maybe it's stupid question but why You do not return NoMoney instead of null in TryCreate example. Returning null force responsibility of handling this null from object to client. Even using Optional will move this responsiblity to client, I wondering if it a "good" approach/idea. Maybe I don't get the difference between Optional/Maybe vs. Null object pattern or do not understand something :)
@zoran-horvat
@zoran-horvat 8 ай бұрын
The accent in smart constructors is on the cases where there is no substitute object to return and we want to force the caller to distinguish that case from a case where there is a valid object. Imagine a function which returns the price of an item, given a timestamp. What would it mean if we returned NoMoney instead? The caller might keep going and put the item into the basket instead of reporting that the item cannot be purchased. It is common to make smart constructors return optional objects instead of nullable references.
@Rafa-fp4ih
@Rafa-fp4ih 8 ай бұрын
@@zoran-horvat Thanks, a lot for answer!
@Ruhrpottpatriot
@Ruhrpottpatriot Жыл бұрын
I never understood what makes constructors so much better than a factory method like `new()`, especially when you consider initializers. I don't even know when the last time was I wrote a constructor aside from making the default one private.
@zoran-horvat
@zoran-horvat Жыл бұрын
Constructors are simple - that is their greatest benefit. If you don't have additional requirements, then you don't need an additional method besides a constructor.
@Ruhrpottpatriot
@Ruhrpottpatriot Жыл бұрын
@@zoran-horvat For that I could also write a parameterless and static `new()` method. Yes, I'm loosing a bit of syntactic sugar, but I'm also gaining a lot, like possible null/optional returns or async.
@yousef.a.k3793
@yousef.a.k3793 Жыл бұрын
Thanks, it's great video. There is optional in DotnetNEXT Project, could you please explain how to use it and what is benefits of that wired implementation of optional
@zoran-horvat
@zoran-horvat Жыл бұрын
I am trying to avoid showing third party libraries, especially if they are not backed by the language team or changes made to the language.
@DavidSilwal
@DavidSilwal Жыл бұрын
where can we get the source code of your awesome videos?
@zoran-horvat
@zoran-horvat Жыл бұрын
Source code is available to patrons only. Here is the page with the source code of this video: www.patreon.com/posts/84130393
@7th_CAV_Trooper
@7th_CAV_Trooper 25 күн бұрын
I know this wasn't the point of the video, but does "NoMoney" have a currency? I mean Zero dollars == Zero euros, right? For some reason this video reminded me of college chemistry conversion factors.
@kantagara
@kantagara Жыл бұрын
wouldn't it be better if TryCreate returned bool and had out IMoney ? Since , at least for me, when I see Try, I always assume it's returning a boolean rather than the actual value.
@zoran-horvat
@zoran-horvat Жыл бұрын
That convention has its drawbacks, too. For one thing, it requires a variable. And even then, the variable must be nullable, for the case when the method returns false. The nullable/optional return method doesn't require a variable. You can chain a call on the result, use it in a null propagation or null coalescing operator or simply return it. All that requires two steps with the out variable.
@SuperJMN
@SuperJMN Жыл бұрын
Out parameters are considered inferior because they don't adapt well to the maxim that methods should either be commands or queries. Also, doing this allows for fluent syntax, that out parameters don't allow.
@larsp5109
@larsp5109 9 ай бұрын
5:51 Your three levels deep nested tertiary statement is terse but isn’t all that readable imho…
@zoran-horvat
@zoran-horvat 9 ай бұрын
It is actually chaining, not nesting. But I agree with you that it lacks readability. It is always the case with pattern matching whenever code becomes more complex than trivial demos. In the extreme cases, it makes sense to turn patterns into calls to methods that give them a readable, meaningful name.
@abj136
@abj136 Жыл бұрын
Make me want to try C++: template class optional_ptr /* like smart_ptr */ { …} class RealMoney : public IMoney { public: optional_ptr construct(parameters) { if (parameters are good) { return optional_ptr
@abj136
@abj136 Жыл бұрын
clarifying detail class NoMoneyClass : public IMoney {…}; static optional_ptr IMoney::NoMoney(&NoMoney); // NoMoney object; will never be destroyed. this concept is not complete; needs more aspects of optional implemented yet.
@abj136
@abj136 Жыл бұрын
i’m not clear I got the right idiom. I’m thinking of a class object that you can invoke its methods, but the methods will generally all be no-op. But I think there’s a different pattern where you cannot invoke an object at all until you first pattern-match and establish the object is valid, and then use the valid object.
@NirWeber
@NirWeber 11 ай бұрын
also - Constructors can not be async...
@zoran-horvat
@zoran-horvat 11 ай бұрын
That is an interesting point that made me think for a moment, but I believe that the smart constructor, even though it *can* be async, should not be. Asynchronous execution is an orthogonal concern to creating objects. You can choose to create an object within or outside an asynchronous context.
@robertmrobo8954
@robertmrobo8954 Жыл бұрын
I dont see the difference between a Smart Constructor and a Factory Method
@zoran-horvat
@zoran-horvat Жыл бұрын
Smart constructor is an augmented factory method. The difference is in its ability to choose not to create the object - a decision we don't expect from a factory method.
@moneymaker7307
@moneymaker7307 11 ай бұрын
Great video, but why not call it a factory method. I would after understanding the context of what you are trying to do within the first 10 seconds of the video if you would have replaced “Smart Constructor” with “Factory Method”
@zoran-horvat
@zoran-horvat 11 ай бұрын
Smart constructor has one additional responsibility compared to a factory method - it can choose to *not* create an object when asked. Even its signature communicates that possibility. A factory method's signature announces that it will return an object of the declared type. Its only way out if it cannot fulfill the promise is to throw. That is the principal difference which grants smart constructor its own name. You will find smart constructors in any functional language alongside common factory functions. It is functional coding style that underlines the distinction between the two concepts.
@ivandrofly
@ivandrofly 9 ай бұрын
impl Money
@m4inline
@m4inline Жыл бұрын
I like your videos but I think you owe Flash Gordon an apology.
Copilot X Is Here and I Just Tried It in VS Code
13:49
Zoran Horvat
Рет қаралды 33 М.
Master the Design of Functional Behavior in C#
19:17
Zoran Horvat
Рет қаралды 2,3 М.
Miracle Doctor Saves Blind Girl ❤️
00:59
Alan Chikin Chow
Рет қаралды 38 МЛН
小路飞姐姐居然让路飞小路飞都消失了#海贼王  #路飞
00:47
路飞与唐舞桐
Рет қаралды 94 МЛН
The most impenetrable game in the world🐶?
00:13
LOL
Рет қаралды 38 МЛН
Wish To Remove Primitive Obsession? Try This Effective Technique!
15:28
Use Null Object Pattern in Your Rich Domain Model
13:16
Zoran Horvat
Рет қаралды 10 М.
The fastest way to iterate a List in C# is NOT what you think
13:42
Nick Chapsas
Рет қаралды 154 М.
How I re-created the rhythm game osu! from scratch in C++!
5:51
Omer Hasanov
Рет қаралды 25 М.
Why Favor Object Composition Over Class Inheritance? A Deep Dive
19:00
Combine Design Patterns To Reveal Their Greatest Power
14:21
Zoran Horvat
Рет қаралды 6 М.
How to Avoid Null Reference Exceptions: Optional Objects in C#
18:13
What are Business Rules? It's not this.
10:58
CodeOpinion
Рет қаралды 27 М.
Топ-3 суперкрутых ПК из CompShop
1:00
CompShop Shorts
Рет қаралды 261 М.
What percentage of charge is on your phone now? #entertainment
0:14
Which Phone Unlock Code Will You Choose? 🤔️
0:14
Game9bit
Рет қаралды 12 МЛН
Как я сделал домашний кинотеатр
0:41
RICARDO
Рет қаралды 1,5 МЛН