Strategy Pattern, The Best Software Design Pattern

  Рет қаралды 54,331

Jono Williams

Jono Williams

Ай бұрын

The strategy pattern is my favorite software design pattern
👨‍👨‍👦‍👦 Social
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
Github: github.com/jonowilliams26
Twitter: / jonowilliams26

Пікірлер: 99
@jonowilliams26
@jonowilliams26 Ай бұрын
I made a follow up to this showing how we can extend this to send notifications based on a users preference. Check it out here kzbin.info/www/bejne/l3Oyo4mIgLBmnKM
@nanonkay5669
@nanonkay5669 Ай бұрын
I didn't know this was called the strategy pattern, to me its just an example of why and how interfaces are useful lol
@blipojones2114
@blipojones2114 Ай бұрын
honestly, these patterns....once you have written enough software you just refer them all as "abstraction" and you just know how much or how little based purely by feel, business circumstances, team skill, tech stack maturity, product maturity etc etc.... i think attempting to give labels trivalise things which invites devs just slapping on random ones instead of engaging a brain cell. In other words, design patterns was an attempt to short-cut having experience.
@darylphuah
@darylphuah Ай бұрын
​@@blipojones2114 design patterns was supposed to be a communication tool. So if I say "we can use a strategy pattern here", we should both be at ~90% understanding of what that means. Without having to describe the whole abstraction. The problem is when people started using a communication tool as a bible.
@glorfyndel8533
@glorfyndel8533 Ай бұрын
Totally right sir ! The ‘pattern’ is that there is no pattern ! (Also remember that encapsulation is more important than polymorphism in OOP) ;)
@CottidaeSEA
@CottidaeSEA Ай бұрын
@@blipojones2114 Math formulas are an attempt to short-cut having experience. See how that doesn't work in other fields? Design patterns are the same way, they are defined ways of doing a certain thing.
@blipojones2114
@blipojones2114 Ай бұрын
@@CottidaeSEA I do not agree that a mathematical formula and a software design pattern are comparable. Formulas give the same reliable results, software pattens don't.
@eliseusalomao4906
@eliseusalomao4906 Ай бұрын
It's all about interchangeability. Also, those are pretty cool animations it helps to get a better grasp on the examples
@francksgenlecroyant
@francksgenlecroyant Ай бұрын
it added an abstraction layer, everything is happening within that method containing the switch statement, it's just fine cuz the service where the business logic happens does not need to worry about the instanciation of the OrderNotifier type
@guidosalescalvano9862
@guidosalescalvano9862 Ай бұрын
It is also great for finding different calculation strategies
@TESkyrimizer
@TESkyrimizer Ай бұрын
But couldn't I have just extracted the switch statement logic into individual methods? Clean code fans vs monolith class enjoyers But seriously lately I have been bothered about how convoluted it becomes to trace code after adopting proper architecture patterns. Maintainability is easier in some ways but also harder in other ways 😓
@darylphuah
@darylphuah Ай бұрын
Extracting the code into methods still couples the code to the class. So everytime you want to add/remove an implementation of a notifier, you'll have to modify the Order Service. The switch statement is just an example, but the dependency can be injected for the class in many different ways. So a notifier can be implemented without touching the OrderService class. It makes testing much easier too. The layers of abstraction can get ridiculous when implementing design patterns liberally. This is where a senior/tech lead with experience should help guide to make sure things don't get out of hand.
@RaVq91
@RaVq91 Ай бұрын
Abstractions add complexity. Avoid not needed abstractions. Your idea looks good and IMO may work in mentioned scenario.
@pitchwaiz
@pitchwaiz Ай бұрын
@@darylphuah also some of these methods might need their own private methods in the future if they get more complex, so it's better to have their own services so you can keep logic of the sms in the sms service.
@Nellak2011
@Nellak2011 Ай бұрын
FP would solve this, but that is too simple. If you aren't making things convoluted, you aren't a "real programmer" as they say.
@duncanlgeoghegan6333
@duncanlgeoghegan6333 Ай бұрын
@@pitchwaiz yeah that's true but on first writing, sometimes it's easier to keep it all in a single class / function. Clean code wants us to almost anticipate future complexity that might never arrive, and in doing so brings its own overhead. My feeling would be the if else statements are more readable, not running up chains to see what actually happens. If it gets really complex, then yeah, abstract up a layer, but I guess... not prematurely.
@fifty-plus
@fifty-plus Ай бұрын
Nice one. A strategy factory would be nice then you just have a new registration for each type and you're done. OCP FTW.
@alexulag
@alexulag Ай бұрын
excellent explanation Jono. Short and as we said in colomba "Al grano"
@jonowilliams26
@jonowilliams26 Ай бұрын
Thank you!
@SimGunther
@SimGunther Ай бұрын
The interpreter pattern is such a good pattern you can implement every pattern, including itself, in it
@linkernick5379
@linkernick5379 Ай бұрын
Tagless Final the ultimate one 😎
@pacholoamit
@pacholoamit Ай бұрын
Hello! What do you use to create these stunning code presentation videos
@zyph.
@zyph. Ай бұрын
The pattern itself is fine, but the example has a problem in my opinion. An “EmailService” or an “SMSService” should have limited responsibility. The “EmailService” shouldn’t know how to send an order confirmation. This can be the responsibility of a class that implements the interface and uses the “EmailService”. By using composition, your “EmailService” will stay simple and be more portable between implementations.
@seannewell397
@seannewell397 Ай бұрын
I see a switch still! It's just in the DI. You can't always do this if you need to decide based on the request/order/user-preferences
@jordixboy
@jordixboy Ай бұрын
you sound like a senior, not like the one from the video, lol.
@mcdev6868
@mcdev6868 Ай бұрын
Exactly, and even if this notification settings were user settings then you'd have to restart the client in order to take effect.
@dumax97
@dumax97 Ай бұрын
There has to be at least one switch to support multiple implementations unless you want your DI to choose what implementation to pick
@jordixboy
@jordixboy Ай бұрын
@@dumax97 do you get that the switch statement is the same as the if, and you are just moving it somewhere else?
@dumax97
@dumax97 Ай бұрын
@@jordixboy switch statements are usually safer as in case you add additional enum value, it force you to add a case for that new value - you don't get that with if statements
@ricardoduarte442
@ricardoduarte442 Ай бұрын
Would have liked to see an runtime implemention / usage of this examples, because the example u gave was using the Startup of the app to choose one of the implementations, but most times I feel like u would use this in runtime with some kind of Resolver to get the wanted implementation of the Interface. Still very well explained, my favorite pattern as well
@junior.santana
@junior.santana Ай бұрын
If you the implementation can vary in runtime maybe depending on the custom for example one approach could be using the factory pattern. So you inject the factory into the OrderService which is responsible for instantiating the appropriate implementation
@dumax97
@dumax97 Ай бұрын
In that factory, there again will be the same switch
@junior.santana
@junior.santana Ай бұрын
@@dumax97 yeah, no problem with that. The factory will centralize the logic for creating the objects. How they are created is another story, using a switch is not wrong, a hashmap or other techniques are possible as well
@nengforgame8145
@nengforgame8145 24 күн бұрын
good video plz make more content like this.
@jonowilliams26
@jonowilliams26 23 күн бұрын
Thank you!
@greob
@greob Ай бұрын
What if I want only two or three types of notifications out of the 5 you ended up with at the end?
@Tuscani2005GT
@Tuscani2005GT 23 күн бұрын
This is the same thing as the delegate pattern although you could make an argument that delegates have more methods and/or are long lived but still the same imo. Either way this becomes extremely powerful when using mock strategies/delegates for testing.
@karmatraining
@karmatraining Ай бұрын
Good old polymorphism!
@VictorMenge
@VictorMenge Ай бұрын
or you could just pass a closure ¯\_(ツ)_/¯
@user-hk3ej4hk7m
@user-hk3ej4hk7m Ай бұрын
You wouldn't even need to do that. Just a regular function call when you get the order. Strategies are OOP coping hard
@ilyahryapko
@ilyahryapko Ай бұрын
This logic is nice when we have that distinction and comptime. But when there's a need to use customer provided means of communication (whether or not customer added phone and accepted sms notification, added email and accepted email notification and so on) this logic basically will be extracted in another class with same if-else statements? Do we have a pattern for such usecase? Or we will be making more abstractions with something like "IOrderNotificationPossibility.CanAccept(NotificationType.Sms, user)" in order to make it look seamless and easy to extend?
@jonowilliams26
@jonowilliams26 Ай бұрын
You could use the factory pattern along side the strategy pattern. The factory takes in a customer/user which creates the order notifier strategy to be used
@ilyahryapko
@ilyahryapko Ай бұрын
@@jonowilliams26 hi! Thank you for an answer. So it basically means that this "if-else\switch" related to some users properties would be located inside this factory?
@jonowilliams26
@jonowilliams26 Ай бұрын
@@ilyahryapko yeah that’s right
@hc1770
@hc1770 Ай бұрын
My way of doing this is to have a function parameter maybe called "extras" that you can pass in additional information. The service itself will then know how to handle the "extras". That way you can still use the same pattern.
@srki22
@srki22 Ай бұрын
What do you do if a customer wants to receive both email and SMS notifications? What is the best way to deal with that?
@Fanmade1b
@Fanmade1b Ай бұрын
It's my favorite pattern, but usually I has to be combined with another logic and/or pattern to be the most useful. For example I used it in a validator class. There I created an interface for validation rules. They have one "isApplicable" method that accepts the validation rules of the current request and return a boolean, and a "validate" method, that return a validation response with an optional error message bag. The validator has a method for registering validation rules. Whenever it receives a request, it will then loop through all registered validation rules, validate the request for each one that is applicable for it and collect all error messages. Adding new validation rules is very easy and you don't have to touch any existing code apart from the place where the rules are registered. Not a single "switch" used anywhere :)
@ix4564
@ix4564 Ай бұрын
That carrier pigeon notification though is now going to be sent to everybody because of that one client. Clearly there's a flaw in the logic. It needs to be personalized ;)
@sunnypatel1045
@sunnypatel1045 Ай бұрын
I use this pattern with a factory pattern!
@jonowilliams26
@jonowilliams26 Ай бұрын
I do too! It’s really good especially when you need to create a strategy based on some runtime variables
@sunnypatel1045
@sunnypatel1045 Ай бұрын
I like the way you handle DI. Instead of registering each one the scan through the interface and register it via DI and in the calling class I inject Ienumerable
@noahginsburg6140
@noahginsburg6140 Ай бұрын
I does OrderService know which registered implementation to use?
@jamestacular
@jamestacular Ай бұрын
Dependency Injection. In the Project or Startup class in ConfigureServices he is setting which concrete class to use whenever a class takes a IOrderNotifier parameter. The concrete implementation is set in the configuration file. .NETs dependency injection will work behind the scenes after you register a service to give you the implementation later on
@PankajNikam
@PankajNikam Ай бұрын
What if we must send the notification through all the providers (including the pigeon 😁) ?
@jonowilliams26
@jonowilliams26 Ай бұрын
Rather than injecting a single IOrderNotifier, inject an IEnumerable and loop through and call each provider
@ashbjorn
@ashbjorn Ай бұрын
@@jonowilliams26 probably nicer then to perhaps introduce an OrderManager that holds on to that internal collection of providers? Kinda how the logging is implemented maybe? #thought-out-loud
@-solitude.
@-solitude. Ай бұрын
I've been doing this since I started into code, I thought that it was the motive of the existence of functions
@mattymattffs
@mattymattffs Ай бұрын
This is great until you try and figure out which implementation is actually being used... Plus if you want multiple notifies it's now annoying
@DrewTeter
@DrewTeter Ай бұрын
Reminds me of Duck Typing.
@user-hk3ej4hk7m
@user-hk3ej4hk7m Ай бұрын
How is this different from just using a function that takes an order and does the notification thing?
@0xSLN
@0xSLN Ай бұрын
I often like this approach. Higher abstractions only when the need has been proven, unless its clearly a part of the requirements. I come from JS and a lot of enterprise software terminology has been bloated. Di, strategy, adaptor etc. A function is good precisely because it has a lot of those concepts baked into it at a fundamental level.
@matinlh644
@matinlh644 Ай бұрын
I'm confused, it was like dependency invertion
@deepfuchsia7204
@deepfuchsia7204 Ай бұрын
I thought it's a video from prnhub
@seth111yta1
@seth111yta1 Ай бұрын
watch as this if stack (@0:36) gets ✨COMPLETELY TRANSFORMED ✨into a switch statement (@2:05)
@Nellak2011
@Nellak2011 Ай бұрын
My professor introduced this pattern, but had written several Java files to implement it with complex relationships. I implemented it functionally in 7 lines of code. This is one reason why I really really hate OOP related crap.
@maxpaju
@maxpaju Ай бұрын
From my perspective, this is complexity-galore added to solve some problem that could be solved with a simple switch-statement. To me, a lot of OOP is just adding layers of complexity, making the code harder to debug and reason about.
@Nellak2011
@Nellak2011 Ай бұрын
Absolutely correct. Functional Programming is the way to go.
@Disorrder
@Disorrder Ай бұрын
Not sure it’s a strategy pattern
@dustinramsey5940
@dustinramsey5940 Ай бұрын
Julia has this thing called "multiple dispatch" that basically does what you're doing but within the language.
@CamaradaArdi
@CamaradaArdi Ай бұрын
Almost every single language has this feature in one way or another
@seyproductions
@seyproductions Ай бұрын
So the strategy pattern obeys the open-closed principle then.
@jsonkody
@jsonkody Ай бұрын
Cool video, nice animations, excelent explanation .. god how I hate Java-ish verbosity and it's OOP style 🤢🤢😅
@jordixboy
@jordixboy Ай бұрын
You're just moving the conditional elsewhere in this case switch statement... People often misuse and abuse patterns/architectures, they have there place yes, but the problem with a lot of engineers is precisely that, over-engineering, having a hammer and seeing needles everywhere, you're opening clearly demonstrates that by saying "this is my favourite pattern", we should not have favourite "things" this doesn't make us good engineers imho. This only leads to fanboys applying shitty solution to problems, like javascript on the desktop lol
@lpi3
@lpi3 Ай бұрын
Remember kids: the best pattern is a function which gets other functions as an argument
@CamaradaArdi
@CamaradaArdi Ай бұрын
This is almost good. This has a significant performance overhead, it's much better to send in a function pointer or a closure instead of an interface with no downsides.
@chrismoutray9206
@chrismoutray9206 Ай бұрын
What a ridiculous comment.
@thanhtamle4138
@thanhtamle4138 Ай бұрын
A closure is a great idea 👍
@liquidpebbles
@liquidpebbles Ай бұрын
Care to explain?
@CamaradaArdi
@CamaradaArdi Ай бұрын
@@liquidpebbles You don't need a class that implements a method called through a vtable. You can just pass the function directly. It's often clearer (just a function doing what you want or a closure which can be just declared right there) and faster (literally a function call). I'm all for strategy pattern and dependency inversion, I think it's good but OOP tends to make it more convoluted than it needs to be.
@Nellak2011
@Nellak2011 Ай бұрын
@@CamaradaArdi Finally someone sees logic and simplicity. This pattern is literally solvable by higher order functions. Just pass a function as an argument. The argument would be the strategy it employs.
@SlowCarToChina
@SlowCarToChina Ай бұрын
LOL…just moved the if’s somewhere else.
@mennonis
@mennonis Ай бұрын
Ofcourse, in the end the same code has to run. But the idea behind refactoring is to make it readable/maintainable/scalable
@vikkio88
@vikkio88 Ай бұрын
8000 lines of code and 50 files to avoid a switch statement. man I hate enterprise code like this
@nonefvnfvnjnjnjevjenjvonej3384
@nonefvnfvnjnjnjevjenjvonej3384 Ай бұрын
see this is where these software principles break down. you are still doing the switch statement (basically the if statement) in another place now. this is the problem with clean code, uncle bob and design patterns. has made everything messy by hiding different things in different places. dont follow these please. take it from a software dev with over 10 yrs of experience, what you want to do is write simple imperative code with re usability through functions and that is it. if you are an intermediate dev it feels very good to learn these new things, (i went through them myself) but once you gain even more experience you realize this is all bs. code should be as easy to follow as possible. look at how game devs do things. when there is no space to waste time on useless cycles due to real performance reasons, the code becomes much more simpler and streamlined. anyways, reply to my comment if you want me to clarify something further.
@133289ify
@133289ify Ай бұрын
Ughhh classes... meanwhile in JavaScript: const shipOrder = { 'email': () => ... 'sms': () => ... 'push': () => ... } shipOrder['email']()
@jonowilliams26
@jonowilliams26 Ай бұрын
Meanwhile in JavaScript: let x = [2, 10, 1] x.sort() // result = [1, 10, 2]
Dependency Injection, The Best Pattern
13:16
CodeAesthetic
Рет қаралды 750 М.
Smart Sigma Kid #funny #sigma #comedy
00:19
CRAZY GREAPA
Рет қаралды 14 МЛН
ТАМАЕВ vs ВЕНГАЛБИ. Самая Быстрая BMW M5 vs CLS 63
1:15:39
Асхаб Тамаев
Рет қаралды 4,6 МЛН
В ДЕТСТВЕ СТРОИШЬ ДОМ ПОД СТОЛОМ
00:17
SIDELNIKOVVV
Рет қаралды 4,2 МЛН
The 3 Laws of Writing Readable Code
5:28
Kantan Coding
Рет қаралды 245 М.
How Senior Programmers ACTUALLY Write Code
13:37
Thriving Technologist
Рет қаралды 1,3 МЛН
Interpreter - Design Patterns in 5 minutes
3:40
levonog
Рет қаралды 1,4 М.
Clean Code using the Strategy Pattern
12:34
git-amend
Рет қаралды 11 М.
5 Design Patterns That Are ACTUALLY Used By Developers
9:27
Alex Hyett
Рет қаралды 189 М.
8 Design Patterns | Prime Reacts
22:10
ThePrimeTime
Рет қаралды 385 М.
How to structure your .NET / C# API's
8:35
Jono Williams
Рет қаралды 9 М.
10 Design Patterns Explained in 10 Minutes
11:04
Fireship
Рет қаралды 2,2 МЛН
Understanding B-Trees: The Data Structure Behind Modern Databases
12:39
Event-Driven Architecture (EDA) vs Request/Response (RR)
12:00
Confluent
Рет қаралды 116 М.
iPhone 12 socket cleaning #fixit
0:30
Tamar DB (mt)
Рет қаралды 44 МЛН
МОЩНЕЕ ТВОЕГО ПК - iPad Pro M4 (feat. Brickspacer)
28:01
ЗЕ МАККЕРС
Рет қаралды 86 М.
MacBook Air Японский Прикол!
0:42
Sergey Delaisy
Рет қаралды 565 М.
Телефон в воде 🤯
0:28
FATA MORGANA
Рет қаралды 916 М.
Разряженный iPhone может больше Android
0:34
WWDC 2024 - June 10 | Apple
1:43:37
Apple
Рет қаралды 10 МЛН