Become a patron and gain access to source code and exclusive live streams: https://www.patreon.com/posts/are-design-dead-81382714
When was the last time you implemented a proper design pattern in your object-oriented code? Not a factory method, but a proper, complex design pattern!
If it was long ago, then you are not alone. Think of all the decorators, adapters, builders, chains of responsibility, observers, states, and visitors you never made. You never made... because they were there.
This video will show you a glimpse of modern code which will incorporate no design patterns at all. And yet, it will mostly consist of design patterns. How come?
The answer is in libraries, the framework, the language syntax, in all the elements we use when writing code. Those elements are built on top of numerous patterns and they are exposing interfaces and methods that are so simple, that consuming any of these design patterns takes no more than a single method call or instantiation of a single object.
By the end of this video, you will learn that design patterns are still everywhere in our code, the same as they ever were, but that we are not responsible to implement them in most cases.
Corner cases will remain, though. If you are writing low-level library code, extensions, and frameworks, then you will likely keep implementing all those design patterns over and over again. But keep this principle in mind: implement the design patterns in your library, so that its users won't have to.
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
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.🔥❤️
✅🔔 Subscribe ► https://www.youtube.com/channel/UCxsWfh8LCcn55mFB6zGBT1g?sub_confirmation=1
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
⭐ CONNECT WITH ME 📱👨
🌐Buy me a Coffee ► https://ko-fi.com/zoranhorvat
🗳 Pluralsight Courses ► https://codinghelmet.com/go/pluralsight
📸 Udemy Courses ► https://codinghelmet.com/go/udemy
📸 Join me on Twitter ► https://twitter.com/zoranh75
🌐 Read my Articles ► https://codinghelmet.com/articles
📸 Join me on LinkedIn ► https://www.linkedin.com/in/zoran-horvat/
For collaboration or any queries:
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
👨 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 YouTube 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 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.
⭐For copyright or any inquiries, please contact us via a comment
#designpatterns #dotnet #csharp
"... you can use this solution a million
times over without ever doing it the same way twice" - and the authors continue saying
"even though Alexander was talking about patterns in buildings and towns, what he says
is true about object-oriented design patterns." What's true? - "you can use this
solution a million times over without ever doing it the same way twice"?
You can use the solution a million times over and use it the same way every time.
That is because languages today, C# and .NET
today, are not what the languages were in 1994.
And listen, some of the things I plan to demonstrate in code today, you
may have never heard before. Let's start. This is the code from a previous video
where I have implemented an efficient intersection of two sorted sequences.
This method is using the Iterator design pattern explicitly.
I'm manually implementing the consumer of the Iterator.
It begins by calling the GetEnumerator, calling the MoveNext, testing
its result, typically in a loop.
Here is the loop below.
Eventually, either yield break, or just leave the loop to terminate the iteration.
You can watch that previous video. It was dedicated to LINQ.
In that video I have explained why this operator implementation is better than that general
purpose Intersect operator from LINQ, in cases when you know that both sequences are sorted.
Here I want to show you what happens to the Iterator pattern for example
and other design patterns. The point that I want to prove with this
vid
eo is that it is exceptionally hard to find a realistic, real world example,
where this kind of code is required. Here is an example that might request
using the Iterator pattern explicitly. Format a book signature.
Now comes the funny part: an unknown number of authors in this IEnumerable.
We don't know how many people there are. But okay, let's suppose that this IEnumerable
comes from some stream, from the socket stream, from a database, and we really don't know how many
people there are u
ntil all of them are in memory. And we don't want to put them into
memory because we don't need them. We need the printout of the book signature,
like this book was written by these people. There will be several distinct
use cases we must cover. You will see that each of these cases will
produce a substantially different printout. And we must solve all of those separately.
And all of those in this single method. So, I will start by really implementing the
Iterator pattern explicitly, or con
suming it. The Iterator pattern is
implemented by the IEnumerable. I will Implement an explicit
consumer of the Iterator here. If there are no authors, then the
first call to MoveNext return false. In that case we have a book with no known author.
Just return the title and that's it. Otherwise, we must take the title of the book, append "by", and then follow it
by the name of the first author. And again, if there are no more authors than this
one, return what we have done so far and quit. S
o, we have two use cases implemented
so far, in these four lines of code. All other authors should be separated
with a comma except the last one who must be separated with "and".
So, it would be: the book written by this, this, and that author.
That is the specification of requests. Now, that will be complicated.
I need a kind of a state machine for that. Keep the last author seen aside and, while
there are others, that will mean that this latest variable is not really the last
author, but t
he one that precedes the last. Add that one, separated by the comma, and keep
the current one as a possible last author. One day this loop will end and the latest variable
will really be the last author in the list. Separate the latest author with "and"
and return that from the method. Let's run the application and see what it prints.
Well, it has printed all the cases correctly. This is really good.
First case: no author. Second: just one author.
These are right. The third case: two authors
separated by "and".
And the fourth case: all outers separated by commas except the last one separated by "and".
This is just as requested. But again, how likely is it that you will
ever encounter a case where you need to do special attention to the first and the last
element in the sequence and the different attention to all the elements in between?
I don't know, this is really not so realistic. That adds to my point that true requests
to implement a design pattern such as an Iterator explici
tly is really a
rare occurrence in practical coding. Here's the alternative.
What if we really knew the number of authors? How hard can it be to know how
many people wrote the book? The alternate implementation
will be next to trivial. I will use pattern matching
with the switch expression. And I will use list patterns
to implement this method. Look, the first pattern is an empty array.
In that case just return the title. Then the case with a single author.
Note that I'm capturing the singl
e string value into a variable and then
using that variable to format the string. It's all getting very easy with list
patterns that are fairly new in C#. And the most complex pattern comes here.
An unknown array of authors comes first. This range pattern here matches zero or
more elements and it will capture them in the string array I called fore here.
This range of items must be followed by a single string which I will capture
into the variable called last. Now, as I said, the range patter
n
is capturing zero or more strings. But that's not what I need.
I have the single element pattern preceding and if that pattern didn't match, then
there must be at least two elements in the array. So, in practical sense, this array
fore will never be empty in this case. But there is one interesting point to make here.
If you noticed, while I was developing this expression, there was constantly a
compile-time warning at the switch expression. That was so because the compiler was complaining
that the switch expression was not exhaustive. But as soon as I have completed this
last pattern, compiler has figured out that I have covered all possibilities
and compile time warning has disappeared. This expression is exhaustive.
It is checking and matching every conceivable array of strings.
I want to separate those preceding authors with commas, then append
"and" and append the last author. This is the entire expression - three
lines of code - replacing that state machine with the Get
Enumerators and MoveNexts.
This is much simpler, much easier to understand. And here are those same four books we
had before, this time instantiated as the Book record instances.
I will just print them out, using the pattern matching expression.
Let me run the application and we will see. Here, the two printouts are letter-to-letter
exactly the same, which proves my point, I guess. There's really no need to consume the
Iterator explicitly, even in such a complicated case like this one, when t
here are
several different use cases that you must cover. Implementing a state machine with
explicit MoveNext... well that is crazy. How can you know that that code is
correct when it is so complicated? Compare that to three lines of code with the
pattern matching and you will see that the second implementation is certainly correct because
it reads exactly the same like the requests. But this is a video about design
patterns, not just the Iterator. There is more in design
patterns than th
e Iterator. By the way, if you liked this video
so far, please press the like button. That will help others find it, thank you!
Let's move on. What if I wanted to sort the books?
But I will insert a few collisions, intentionally, into this array.
That will put emphasis on comparison used in sorting.
That will be a problem, you will see. One will be the book with the same
title name but a different author. I'm cheating a little bit.
This book is really not named the same. And another one, I als
o made
up, varying in authors list. So, the title is the same again, but
the author list will be a bit different, with the collision on the first author.
This will be Domain-Driven Design written by Eric Evans and nobody else.
Now, title is comparable already. But the array of authors is not.
I will prepare a helper method. It took me a couple of minutes to implement this.
It is comparing two arrays of elements of comparable type T lexicographically, which
means like the way you would sort wo
rds in a dictionary: left-align them and start
comparing until either they're equal or you find a different letter or one of the
words is exhausted - then it is smaller. Funny enough, this implementation
is not using the Iterator. It is procedural, it is using
the for loop with the index. Now, this static method used as the method group
is assignable to the Comparison delegate in .NET and you can pass this method group in any
place into any method that expects comparison, like List's sorti
ng does that.
But what if we needed an IComparer? LINQ's OrderBy expects an IComparer.
Shall we implement the Adapter design pattern to adapt Comparison
delegates to IComparer of T interface? Yes and no.
No because it is already implemented for us. Generic Comparer class has a static method
named Create which wraps a Comparison delegate into an IComparer of T object.
This is adapter design pattern implemented right in the BCL.
Let's get back to sorting books. We need a two level sorting.
One l
evel is to compare titles. But if the titles are equal,
then we need to step to the second level that is comparing author lists.
Well, that sounds like Chain of Responsibility. And I have even published an entire
video using Chain of Responsibility to chain IComparable implementations to
make this very effect I'm showing you here. So, is this the place to
use Chain of Responsibility? Yes, for example, sorting a
list again is the case for that. But we are not using List.Sort here.
I'm using
LINQ and LINQ already implements the Chain of Responsibility with its OrderBy method.
Order by the book's title. And if titles are equal, put the next link
in the chain: ThenBy the authors array, sort using the lexicographical
comparer we prepared before. And this is the Chain of
Responsibility right inside LINQ. Let me write down the patterns
I'm using in this piece of code. Here begins the Chain of Responsibility.
The other one, let me expand it so that you can see it better, that is the
use of the Adapter design pattern. And there was another video I also
made on Decorator design pattern. Now here is the problem.
If you want to invert the sort order, some methods, some classes will not help you with that.
Again, List.Sort - there is no sort descending. You must implement your own Decorator
around it to reverse its decision. Again, there is the entire
video I made on that example. And again I'm not using the
List.Sort here, I'm using LINQ, and LINQ does have a variation whic
h applies the
Decorator to your comparer: ThenByDescending. It will be an inverting
decorator for the comparer. In the end, the almighty Iterator.
This time I'm consuming the Iterator design pattern using the foreach keyword.
It's four lines of code using four different design patterns.
Chain of Responsibility and the Decorator are implemented by LINQ here.
Adapter is implemented in BCL, the framework. And the Iterator consumer is
supported by syntax of C#. Just in case you don't believe me t
hat
this will work, I will run the application. Books are indeed sorted ascending by the
title and then descending by the authors list. The code looks correct to me.
Did I use design patterns in .NET? Yes, all the way.
Did I Implement design patterns? No, none of them.
They are all there for us. You will use design patterns implicitly
today, that is the point of this video. And then, what was that sentence again?
"... you can use this solution a million times over without ever doing it the sa
me way twice."
That was published in 1977. Well, in 1977, I was two years old.
Have you been born then? This sentence may be true if you are
writing code close to bare metal. Every implementation in a library
will potentially be unique. That's why you will develop it, because
there's no library that does it. But if you are writing business
applications today, in 21st century, three decades after this book was published, you
will not be writing it over every time again. You will have framewo
rks, you will have
base classes, you will have the language syntax that will do that for you.
That doesn't mean that design patterns in business applications are dead.
No! It only means that they are buried deep under the surface where you cannot see them.
But you can benefit from them. I hope you have learned
something valuable in this video. Like it, share it, subscribe to my channel
and come again when the new videos appear. Thank you for watching till
the very end and see you again.
Comments
Become a patron and get access to source code and exclusive live streams: https://www.patreon.com/posts/are-design-dead-81382714 Write your thoughts about design patterns in modern business applications! I'd like to hear your opinion on the frequency and place of design patterns in your job today.
Your explanation is amazingly clear and short pauses here and there let the viewer have time to digest the content. I appreciate this video <3
I now watch at least one video on this channel every day!
You should write a book on modern C# design matters!
I thought I never knew what desing patterns were, but the more I study, the more I see them in my daily life as a developer. For example, observers are used a lot in game development to manage signals and in asynchronous tasks, the Future or premise are always an observable
totally agree. i never implemented "chain of responsibilities" myself, but i do use thenby from time to time. usually development (at least for me) looks like "you just use the existing thing and only go dig the internals + implement yours, if the existing one does not work, as you want it to". having powerful means of programming, leads to that we need to have less self-made implementations for day-to-day routine
Well he is like a strict Professor who brings unique ideas and is always correct 😄. Huge respect sir !!
I appreciate your clear explanatory style. I just want to point out you're talking about design patterns used in standard language functions like pattern-matching and LINQ, but as developers, we're usually working within our applications' business domains (where Microsoft isn't writing the code) and so still (occasionally) need to use design patterns for our domain objects. So your title is a bit misleading (maybe intentionally clickbaity?). Nonetheless, it's really nice to have new powerful language features that simplify coding: pattern-matching is a great, simple replacement for the Visitor pattern, which is a bit complicated and not needed in most cases.
Liking this video did help others to find your videos. I'm one of the others and I'm very glad I found your channel.
The outro was very nice! Thanks for those videos, I hope to gather all the knowledge I can
Great content Zoran as usual Always waiting for your videos to learn some C# internal concepts
My mindset was changed forever. Thank you!
Another masterclass, thank you! I was hoping you would finally open up the possibility to become patreons of your channel, so you don't stop making videos!
Love this gentleman’s delivery, he is like Vigo Tarasov dropping OOP knowledge instead of tales of baba yaga
Fantastic explanation! Thanks for sharing your insights.
Crystal clear explanation. 👌
This video highlighted to me, the importance of the Oxford Comma. First, second, third, and fourth.
IEnumerator<T> is disposable, no? important to clean up usings inside of a "yield" function.
The fact that you no longer need to implement the design patterns yourself does not make the Gang of Four book irrelevant for most coders. Their work is still important for you to understand what's actually happening when you use those modern language features. But yes, you should avoid rolling your own whenever possible.
You are a very talented broadcaster. I’ve never seen someone talk about programming on YouTube in such an informative and enjoyable way. Your pacing etc… is perfect. Keep at it and this channel will be huge!