Variations of the Strategy Pattern // Using Python Features!

  Рет қаралды 51,954

ArjanCodes

ArjanCodes

Күн бұрын

Visit bit.ly/ARJAN50 to get 50% off the Pro version of Tabnine for 6 months.
This video covers the Strategy pattern, but also looks at a few varieties of the pattern using Python features such as Protocol classes, dataclasses, the _call_ dunder method, and closures.
The code I worked on in this video is available here: github.com/ArjanCodes/2021-py....
💡 Here's my FREE 7-step guide to help you consistently design great software: arjancodes.com/designguide.
🎓 Courses:
The Software Designer Mindset: www.arjancodes.com/mindset
The Software Designer Mindset Team Packages: www.arjancodes.com/sas
The Software Architect Mindset: Pre-register now! www.arjancodes.com/architect
Next Level Python: Become a Python Expert: www.arjancodes.com/next-level...
The 30-Day Design Challenge: www.arjancodes.com/30ddc
🛒 GEAR & RECOMMENDED BOOKS: kit.co/arjancodes.
💬 Join my Discord server here: discord.arjan.codes
🐦Twitter: / arjancodes
🌍LinkedIn: / arjancodes
🕵Facebook: / arjancodes
👀 Channel code reviewer board:
- Yoriz
- Ryan Laursen
- Sybren A. Stüvel
🔖 Chapters:
0:00 Intro
1:23 Explaining the example
3:54 About the Strategy pattern
4:40 #1: Classic OO version
11:58 #2: Using protocols
14:20 #2: Using the _call_ dunder method
16:21 #4: Using functions
22:45 #5: Using closures
26:01 Final thoughts
#arjancodes #softwaredesign #python
DISCLAIMER - The links in this description might be affiliate links. If you purchase a product or service through one of those links, I may receive a small commission. There is no additional charge to you. Thanks for supporting my channel so I can continue to provide you with free content each week!

Пікірлер: 107
@ArjanCodes
@ArjanCodes 9 ай бұрын
💡 Here's my FREE 7-step guide to help you consistently design great software: arjancodes.com/designguide.
@talhaamir9023
@talhaamir9023 2 жыл бұрын
It's been more than two years working as a Python Developer and nothing excites me more than getting a notification, Arjan Codes has uploaded a new video 🔥 Thanks for the premium quality content.
@theyashbhutoria
@theyashbhutoria 2 жыл бұрын
Been binge watching your videos over the weekend. This is theraputic.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thanks, glad you like them!
@user-tj7wj6rd7m
@user-tj7wj6rd7m 2 жыл бұрын
Also adding to the last version. There is `partial` function in `functools` module which returns new callable with pre-defined argumets. So you can create function with any parameters you'd like (as seed) and then pre-define them using partial. from functools import partial def f(x): print(x) zero_printer = partial(f, 0) zero_printer() # prints '0'
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Great addition!
@SkielCast
@SkielCast 2 жыл бұрын
I think everytime one thinks of a closure it can be simplified as a function taking many parameters and then using partial. It "hides" the nesting and beginners can use that without being introduced to neither closures nor classes
@RitchieDiamond
@RitchieDiamond 2 жыл бұрын
I use partials all the time when defining event callback functions in my game, it allows the event handler to call the function of a triggered event without knowing anything about its arguments.
@NoProblem76
@NoProblem76 2 жыл бұрын
Oh no I’m late to the party
@luisandraschnik3001
@luisandraschnik3001 2 жыл бұрын
Where I can learn about this use of partial?
@Alche_mist
@Alche_mist 2 жыл бұрын
I'm glad you're finally deviating from the "write Python like Java" approach. That's my gripe with a lot of the patterns used meticulously "as conceived" - they are often overengineered due to too many classes everywhere and can be made far easier using constructs like closures or dictionary dispatch.
@prakhargarhwal4304
@prakhargarhwal4304 2 жыл бұрын
Thanks a lot for this video, @Arjan. The timing was just perfect as today’s my birthday. Your content is brilliant, and is really helpful. I’ve been binging your videos on Software Design playlist, and saw this video come out. It’s great.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Happy birthday Prakhar. Glad the content is helpful to you.
@dextroz0808
@dextroz0808 2 жыл бұрын
Can you make videos on structuring programs???....been struggling a lot in it...maybe build a game or app.....anyway great vids👍👍
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Noted!
@dextroz0808
@dextroz0808 2 жыл бұрын
@@ArjanCodes thanks! looking forward for it
@Ryan-ww7un
@Ryan-ww7un 2 жыл бұрын
I love working alongside your videos on your examples. Thank you for all of your hard work!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Glad to hear you liked it!
@jeffgruenbaum
@jeffgruenbaum 2 жыл бұрын
great ideas! I had never though about creating an "interface" for functions, using the callable to match the typing patterns is very clever. Thanks for the videos!
@dank8981
@dank8981 6 ай бұрын
I watched this video a while ago then I didn't really have a use case for this so i just toss this info back of my mind somewhere. Today, I just realized that for the problem i was solving this is a great way to attach the problem. Here i am watching again and yes this will be a perfect way to solve my problem. Thanks Arjan!
@ArjanCodes
@ArjanCodes 6 ай бұрын
Glad to hear that you came back and the video was useful to you!
@SiddiqNx
@SiddiqNx 2 жыл бұрын
Always a pleasure to watch your videos!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thanks @Siddique, glad you like them!
@jeffersondperezmadrigal4917
@jeffersondperezmadrigal4917 2 жыл бұрын
Amazing video! I’d love to see architecture patterns like clean architectures to understand how to structure web apps, where does the business logic goes, and stuff like that 👍🏼 - Great work @Arjan
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Great suggestion, thanks!
@ravenecho2410
@ravenecho2410 2 жыл бұрын
ur videos are always so valuable, i super appreciate your work and effort u.u
@xaro6132
@xaro6132 2 жыл бұрын
Thank you Arjan for the video
@ArjanCodes
@ArjanCodes 2 жыл бұрын
You’re most welcome!
@howeichin4103
@howeichin4103 7 ай бұрын
super cool and informative video! thank you for the great effort!
@ArjanCodes
@ArjanCodes 7 ай бұрын
I'm happy you enjoyed the video! :)
@vasilijestosic8331
@vasilijestosic8331 2 жыл бұрын
Excellent examples!!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thanks, happy you like them!
@cameronnorman4188
@cameronnorman4188 2 жыл бұрын
Thanks again Arjan, becoming a better developer every time you release a video! If I ever get rich, ill send a couple million your way!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Glad you enjoy the videos Cameron!
@btonasse
@btonasse 9 ай бұрын
Nice video. Am I the only one who thinks people are trying to shoehorn functional stuff into everything they do? Classes are still the most explicit, intuitive, readable and elegant way to achieve something like this.
@amingholizad
@amingholizad Жыл бұрын
@ArjanCodes Thanks for the rich content you produce here. Is there any performance advantages between these features?
@fjonesjones2
@fjonesjones2 Жыл бұрын
Great video as always, many thanks mate. Also yes, I've been using Tabnine with VS Code for Linux for a while, it's just like 'Magic' and FREE!! ... ;-)
@OrtoInScatola
@OrtoInScatola 2 жыл бұрын
the flexibility of Python really shines in this video - great presentation! Speaking of flexibility, one of the things I dislike the most about KZfaq is that it has a very linear structure, mostly based on the time of posting and the added grouping provided by playlists. Still it doesn't work well with something as complex as programming topics. Do you have a mapping of your videos that goes by patterns, by programming "devices", etc.? Or maybe a recommended viewing order?
@max1cp
@max1cp 2 жыл бұрын
You should use dj to remove 2 lines in a row or d#d to remove any # of lines instead of using dd all the time. :)
@heinrichdj
@heinrichdj 2 жыл бұрын
Awesome, thanks!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thanks Heinrich, glad you liked it!
@multigladiator384
@multigladiator384 2 жыл бұрын
Lets say we have a function which takes argument of type A and returns argument of type B ( A -> B) Then I put them in a dict strategies: {string: A -> B } and thats it... for functions this works very well, if you want to map to classes you have to make an Interface and use it in strategies as the type instead of A -> B and of course your classes shall inherit the interface
@edgeeffect
@edgeeffect 8 ай бұрын
As a JavaScript fanboy, I always used to like to say "YES! but 'my language' has closures and 'yours' doesn't!".... This is becoming less and less valid all the time. ;) I love how you keep your examples so minimal - your videos are never too complex to be able to follow and not everyone realises how important that is.
@imadetheuniverse4fun
@imadetheuniverse4fun 2 жыл бұрын
I really love the idea of using functions instead of classes if the class is just there to hold a single method and no state! I also think it further reduces coupling because the function that is calling the strategy doesn't need to know what the method name is or anything. Might even be good to pass the strategy as a parameter to the calling function where you can provide the type alias as type hint as well.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Absolutely! I notice in my own development work that I use classes less and less. Often, simple functions do the job just as well and are much easier to test. Partial function application is also something that I'm just now discovering the power of. So expect to see more of those things in my upcoming videos :).
@imadetheuniverse4fun
@imadetheuniverse4fun 2 жыл бұрын
@@ArjanCodes That's exciting to hear! I started learning Haskell before knowing anything about paradigms or functional vs OOP or anything like that, so I had no idea what I was getting myself into. But I love the way you can define and compose functions there. It has definitely started affecting how I write Python too. Looking forward to learning more about Partial!
@queueoverflow
@queueoverflow 2 жыл бұрын
In c#, we can also pass an actioin or a func. strategy pattern.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Good to know!
@realplod
@realplod 2 жыл бұрын
Blows my mind how much I don’t know
@anelm.5127
@anelm.5127 2 жыл бұрын
I really think that a series on architectures would be amazing.. This is the senior stuff us noobs need to learn 😄
@joningram
@joningram 2 жыл бұрын
Having got into programming before all these design patterns became the in thing, I'm enjoying your videos, and hope to see more! Your option 4 (just using functions) seems so much more Pythonic than the Byzantine Java-derived 'class with a single function pretending to be a function' options. I wonder whether your insistance on defining the types of everything obscures what is quite a simple idea in option 5 -- calling a function which returns another function is not a particularly obscure thing to do in Python, but I can imagine is quite painful to think about in more formal languages.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thanks, glad you like them! The main reason I insist on using types in the examples is because I find it helpful in clarifying what a function expects or returns. When I work in Typescript, I often use functions that return other functions. But it’s a relatively new thing for me to work more with functional concepts, as before I coded a lot in C++, Java and C#, where these features were not always there.
@dmytrokorbanytskyi1586
@dmytrokorbanytskyi1586 2 жыл бұрын
great work! Could you make a video about typing in Python and cool features that can be used with them?
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thanks for the suggestion!
@MarkWernsdorfer
@MarkWernsdorfer 2 жыл бұрын
Hey @Arjan ! Thanks a lot for your videos. They're really advanced and easy to follow at the same time. I noticed you make your type hints lower case. I'm importing from `typing` instead. I'd be interested in your reasons. Thanks a lot!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Hi Mark, thanks! I switched to the lowercase typing option, because you don’t need an import for this, so it’s much simpler. I expect the uppercase versions from typing are going to be deprecated in the future.
@MarkWernsdorfer
@MarkWernsdorfer 2 жыл бұрын
@@ArjanCodes cool, that makes sense. thanks a lot! i was just starting to convert to lower case when I stumbled upon Optional[] types. i think i'm gonna stick with upper case until I don't have to import any type hints.
@nocodenoblunder6672
@nocodenoblunder6672 2 жыл бұрын
I like the example overall but i dislike that you removed the selection of strategies. It might seem that the strategy pattern chooses the right strategy on its own which is not the case. Most of the time you still need to select a Strategie in the client. The clients needs to know about the strategies and instantiate the appropriate one. This is where pythons new structural pattern matching in gone come in handy I think. Nonetheless great video and very useful pattern that provides great extensibility, decoupling, switching of strategies at runtime.
@astronemir
@astronemir 2 жыл бұрын
You can either use pattern matching, argument parsing (argparse), a config file, or call the script from another script.
@ikopysitsky
@ikopysitsky Жыл бұрын
Is there a way to rewrite the last example with a decorator instead of an explicit closure?
@italobuitron1165
@italobuitron1165 Жыл бұрын
Question: If i add in FIFO another func, still work protocol? or all the strategy tickets must have same funcs?
@lemongraz7295
@lemongraz7295 2 жыл бұрын
Great Video, thanks! What keyboard do you use? Doesn‘t sound like a standard mac one, right?:)
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thanks! I'm using a Keychron K2, can highly recommend it.
@lemongraz7295
@lemongraz7295 2 жыл бұрын
@@ArjanCodes Nice, thanks a lot!
@pacersgo
@pacersgo 2 жыл бұрын
I have the feeling that the classic way would be more readable since it has been introduced for a long time.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
I can definitely see that the variety with the dunder method is harder to read. I think the Protocol version is also easy to understand, and I also regularly use the simple functional approach myself.
@MMarcuzzo
@MMarcuzzo 2 жыл бұрын
Im interested in your shortcuts
@merlonmerlon8722
@merlonmerlon8722 2 жыл бұрын
Great video! But I don't understand the advantage of using Protocol instead of ABC. I see it as a loss of information which can create confusion in the future.
@astronemir
@astronemir Жыл бұрын
you can still explicitly inherit from the protocol class as well if you want to.
@merlonmerlon8722
@merlonmerlon8722 Жыл бұрын
@@astronemir yes, but what's the point of having a protocol if so? more flexibility maybe?
@zacharythatcher7328
@zacharythatcher7328 Жыл бұрын
I am in a bind right now where I want to enforce an interface on a number of object methods, all in the same class, all requiring access to self in order to continue the flow of the program. It would be easy to apply the functional implementation of the strategy pattern to them, but that doesn't enforce kwarg names and I like using the kwarg names wherever possible, especially with an interface in python. One thought that I have is to inject these methods, but then I would have to pass the ingesting object to these methods so that they could call the method in the ingesting object. This feels messy. My next thought is to take the method call to the next method out of the injected methods, and have necessary data bubble back up and then continue the flow. aka it is currently ->originating method -> injected method -> next object method and I would change it to -> originating method -> injected method originating method -> next object method I have ended up going with my final solution. I thought I should post this as a real life example, since it has helped me think and might help someone else. Turns out I forget an old lesson to keep the stack as shallow as possible, and your life will get much easier.
@sirius7584
@sirius7584 2 жыл бұрын
Strategy가 dynamic한 외부 데이터에 의존한다면 class를 쓰는 전통적인 방식이 낫지 않을까? Function을 사용한다면 의존성을 주입한 partial function을 써야할 거 같음.
@sterlingveil
@sterlingveil 2 жыл бұрын
I think it would be helpful if you intentionally made some common mistakes during your refactoring. Let us see what errors pop up if you run it without updating one of your protocol classes, for example. (Either way, thanks for putting these videos out!! They're awesome!)
@PetrSzturc
@PetrSzturc 2 жыл бұрын
I think you should have mentioned that __call__ is only usable/executed after the class has been already instanced.
@tomtrask_YT
@tomtrask_YT 2 жыл бұрын
Am I missing something? It seems like in that last example of a function returning a closure, the closure is always returning the same shuffle (so if [a, b, c] comes back [b, c, a], then [d, e, f] will come back [e, f, d] - though admittedly different length lists would be shuffled differently). All iterables would be shuffled precisely the same in a single run. I would have expected only that the first shuffle of a sequence of calls is shuffled the same from run to run. Thanks for the video. This answered a question in a side project that had been bugging me for a couple days now.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Hi Tom, correct - fixing the seed means that the list is always shuffled in the same way. This can be helpful if you for example want to write unit tests that are deterministic but still rely on random number generation.
@TheCarmacon
@TheCarmacon 2 жыл бұрын
Noob question: why are the ordering strategies located in app.py and not ticket.py?
@WesGann
@WesGann 2 жыл бұрын
@ArjanCodes, could you create or link to a video showing the keyboard shortcuts? I noticed you were deleting lines or data between parans with some keyboard shortcuts. I could probably take time to google these but hey, it's more content for you to make :)
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Actually, I've started using Vim, which is what I use here to do these things. It's an extension you can install in VS Code, and it has lots of possibilities. 'dd' to delete a line, 'ci(' to remove and replace text within parentheses, and much more. I'm still learning, but it definitely helps in editing faster.
@WesGann
@WesGann 2 жыл бұрын
@@ArjanCodes thanks! I have a little experience with the actual vim editor. I knew about dd to delete a line, only when not in insert mode. Guess I'll have to look into this extension and beef up on my vim commands! Also, should have stated this before but I really enjoy your videos. Bought the design patterns book off your recommendation and found it very helpful thus far. Keep up the great work!
2 жыл бұрын
As far as I understand Callable with typed arguments is deprecated in favour of Protocol. You could have kept the Protocol class to type hint the functions.
2 жыл бұрын
BTW, great video
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thanks! I don’t believe Callable is deprecated though. At least not typing.Callable. What is deprecated is collections.abc.Callable, but that’s probably mainly to reduce redundancy.
2 жыл бұрын
@@ArjanCodes Thanks for the clarification.
@XRay777
@XRay777 2 жыл бұрын
Plot twist: functions in python are still just objects :D
@astronemir
@astronemir 2 жыл бұрын
PyGang! We’ve been bamboozled!
@Ryan-ww7un
@Ryan-ww7un 2 жыл бұрын
What extension were you using that automatically imported packages? I am using TabNine pro and it doesn't do this.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
If you install the Python language service in VSCode, that will do automatic imports for you because it installs a couple of other tools as well such as a linter, Pylance and more.
@Ryan-ww7un
@Ryan-ww7un 2 жыл бұрын
@@ArjanCodes Gotcha. I have that installed, but the auto-imports still weren't happening. No matter, it's easy enough to do it manually.
@magnuscarlsson6785
@magnuscarlsson6785 2 жыл бұрын
I like the closure way, but would have referred to it as a factory pattern... What is the distinction between what you call a "closure" and what you call a "factory", don't they both create and return a customised object? Thanks for your great videos!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Hi Magnus, in a sense, strategy and factory are pretty close except a strategy normally provides a method/function and a factory provides an object or a set of objects. What’s more important actually is the separation mechanism, relying either on ABCs, Protocols or types and subtypes. As long as you have that in place, the specific variety of the pattern you use is not that important: use what makes the most sense in that particular context.
@BrockPalmer
@BrockPalmer 2 жыл бұрын
This is somehow the first time I've seen the acronym FILO (first in last out). At a previous job, we had a FILO inventory system, but call it "fish" for "first in still here."
@YossiZinger
@YossiZinger 2 жыл бұрын
I usually call it LIFO (last in first out)
@NostraDavid2
@NostraDavid2 2 жыл бұрын
FILO/LIFO is also known as a Stack, and LILO/FIFO is known as a Queue :)
@jeancerrien3016
@jeancerrien3016 2 жыл бұрын
Yet another wonderful video. Thank you. 🙏 Why do you insist on retyping the signature of create_ordering? It seems more efficient to copy and paste. 😊
@superscatboy
@superscatboy 2 жыл бұрын
I hope I never have to request support from a support system that uses first in last out lol
@ArjanCodes
@ArjanCodes 2 жыл бұрын
You’d be surprised 😉
@CrapE_DM
@CrapE_DM 2 жыл бұрын
I've always seen it as LIFO, not FILO, though both work just fine, I guess
@Jakub1989YTb
@Jakub1989YTb 2 жыл бұрын
8:00 I'd use random.shuffle(tickets.copy()) if len(ticket_list) == 0: ... really?? Just do " if not ticket_list: "
@robertchang5096
@robertchang5096 2 жыл бұрын
Would really appreciate if you can do another video on Closure! I know you already have one here: kzfaq.info/get/bejne/ps5ie81zttutaI0.html, but eager to learn more!
@chikosan99
@chikosan99 2 жыл бұрын
Great but difficult (:
@fringefringe7282
@fringefringe7282 6 ай бұрын
I like your vids, but this background music is annoying.
@no_hurry7000
@no_hurry7000 2 жыл бұрын
There should be one -- and preferably only one -- obvious way to do it.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Yeah... that didn't really work out here :). Which version do you prefer?
@no_hurry7000
@no_hurry7000 2 жыл бұрын
@@ArjanCodes I like the functional one, but the duck typing/protocols approach also seems nice for python. Anyways, many thanks for the high-quality video! 👍
@jamiekydd1049
@jamiekydd1049 2 жыл бұрын
To be honest all this does for me is confirm my preconception that nobody that thinks about design patterns should ever use them. I've never seen an example where a 'strategy' isn't just effectively just a closure/bound function object, and elevating this to being worthy of a named type just results in inexperienced developers wanting to define classes just so they can name them 'BlahBlahStrategy'.
7 Python Code Smells: Olfactory Offenses To Avoid At All Costs
22:10
Became invisible for one day!  #funny #wednesday #memes
00:25
Watch Me
Рет қаралды 56 МЛН
버블티로 체감되는 요즘 물가
00:16
진영민yeongmin
Рет қаралды 123 МЛН
NERF WAR HEAVY: Drone Battle!
00:30
MacDannyGun
Рет қаралды 55 МЛН
Scary Teacher 3D Nick Troll Squid Game in Brush Teeth White or Black Challenge #shorts
00:47
How To Reduce Coupling With Facade | Design Pattern Tutorial
28:29
Python 3.12 is HERE!
12:37
mCoding
Рет қаралды 156 М.
8 Design Patterns | Prime Reacts
22:10
ThePrimeTime
Рет қаралды 392 М.
Here’s a More Pythonic Factory Pattern
23:18
ArjanCodes
Рет қаралды 99 М.
The Power Of The Plugin Architecture In Python
24:06
ArjanCodes
Рет қаралды 111 М.
PLEASE Use These 5 Python Decorators
20:12
Tech With Tim
Рет қаралды 101 М.
"I Hate Agile!" | Allen Holub On Why He Thinks Agile And Scrum Are Broken
8:33
Protocol Or ABC In Python - When to Use Which One?
23:45
ArjanCodes
Рет қаралды 198 М.
Became invisible for one day!  #funny #wednesday #memes
00:25
Watch Me
Рет қаралды 56 МЛН