No video

Real-Life Case of the Command Design Pattern

  Рет қаралды 42,694

ArjanCodes

ArjanCodes

Күн бұрын

Пікірлер: 94
@ArjanCodes
@ArjanCodes 2 жыл бұрын
The first 1,000 people to use this link will get a 1 month free trial of Skillshare! - skl.sh/arjancodes11211
@havenisse2009
@havenisse2009 2 жыл бұрын
Unfortunately it is not possible to get the free month without giving skillshare a credit card up front. Something they don't advertise until they have your email. If only they could be honest, give a free monht, then force people to add a credit card when trial was over... But now, It's a no thank you from me. Not your fault though.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Yeah... that's standard practice for many subscription services nowadays. If you don't want to give companies access to your credit card, there are services (like privacy.com) that offer temporary credit card numbers you can destroy at any point in time. I haven't used these services myself, but I might in the future as I share some of your concerns.
@XRay777
@XRay777 2 жыл бұрын
Small side note: What Arjan did at the end with the Batch class is actually another pattern that often goes by the name Composite. It is a way to package up primitve classes into groupings that implement the same interface. Consequently, calling code can treat individual parts or groups of parts uniformly. I like this example here a lot, since it is great at highlighting how combining patterns unlocks their true potential. 👍
@wimdegroot6815
@wimdegroot6815 2 жыл бұрын
The command pattern is one of the most satisfying patterns in my opinion.
@biermeester
@biermeester 2 жыл бұрын
One nice feature in Python, that not many people seem to know, is that you can add underscores to numbers to improve readability, eg: account1.withdraw(150_000)
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Indeed! I always forget to use that. It would have been quite useful in this example.
@syberen
@syberen 2 жыл бұрын
Really like your channel. The only feedback I have is that on Friday end of the day, when the new videos drop, my brain is already fried from coding all week 😅
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Haha, I know the feeling :).
@virtualraider
@virtualraider 2 жыл бұрын
I'm in Australia, so I watch it in my morning with breakfast. My wife says that @ArjanCodes has a relaxing voice so she doesn't mind me nerding it out 😅
@MrAlFuture
@MrAlFuture 2 жыл бұрын
@@virtualraider yep I concur. ArjanCodes and coffee are a good Saturday morning here in Tasmania.
@MrAlFuture
@MrAlFuture 2 жыл бұрын
This is a wonderful series (so far!). I really appreciate the non-trivial yet straightforward scenarios you're using to demonstrate the pattern. Thanks, Arjan!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Glad to hear you like it, thanks!
@BiologyIsHot
@BiologyIsHot 2 жыл бұрын
Me who just implemented a messy text-based command system for a project and has never heard of this pattern... 😅😅 time to watch
@red_cape.
@red_cape. 2 жыл бұрын
"Thanks" for the tips Arjan, now I have to rewrite my personal finance desktop app program /s . But now in all seriousness, man your videos are great love the power of this command pattern, I just wish that I've known it earlier, the undo functionality was already planned in my roadmap, but seeing this now I think it should be cooked into the system from the beginning. I feel like a children in a candy shop, each new video is like "Hey I want that!".
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Glad it was helpful!
@n.nikolaev
@n.nikolaev 2 жыл бұрын
Arjan, once again you did an awesome job! The pattern series is truly great and useful. May I, however, as a junior programmer, suggest that you use UML class diagrams to elaborate more on the patterns' concepts and the particular examples that you present. It will be very helpful to inexperienced coders because very often these patterns include more than two layers of abstraction and it gets a little hard to comprehend the entire idea just by looking at you going through multiple modules and classes. I really appreciate your work!
@manumoreno99
@manumoreno99 2 жыл бұрын
Great video Arjan! I've watched most of your videos. They are all very good. I like the way your present your ideas. I'm in the process of creating my own portfolio management system and you're giving me some good ideas -- especially with this video and the follow-up one where you'll be using transactions as the basis for managing state.
@mykhailo_klym
@mykhailo_klym Жыл бұрын
Perfect, what I love is that you give some decent real life examples.
@siddsp02
@siddsp02 2 жыл бұрын
I think this can be simplified by just storing commands in two lists or dicts which can act like stacks anyways. When you want to undo, the second stack's last item is whatever is popped from the first. When you want to redo, the first stack's last item is what is popped from the second. Balance can be calculated by having some sort of dictionary where results are cached, so lookup isn't expensive.
@bab333bab
@bab333bab 2 жыл бұрын
Very well done. Implemented that pattern years ago by myself- now after watching you video I don't remember why I struggled with it ;-).
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thank you! Glad you liked it!
@oreychandan9229
@oreychandan9229 2 жыл бұрын
I love your videos! I get to improve my code quality so much and make my development experience more fun!. Thank you for doing what you do.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Glad to hear the videos are helpful!
@cheebadigga4092
@cheebadigga4092 2 жыл бұрын
Damn this is really powerful! Thanks for sharing!!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
You’re welcome Cheeba!
@marcelohpinheiro
@marcelohpinheiro 2 жыл бұрын
Thanks for your video!
@rohansaraf4493
@rohansaraf4493 2 жыл бұрын
Really liked the way you explained it. Minor suggestion for the future videos, can you also a little bit explanation how to handle the complexities in case of a distributed systems. Lets see we have different machines and each of them have a bank controller (or we have multiple instances of bank controller) with a common database(store). How will undo/redo work in that case? I am just trying to visualize what kind of complexities can occur?
@logicerror
@logicerror 2 жыл бұрын
just a random guess: I'm assuming the reason why it isn't autoimporting dataclass is because you are at line 1 of the file. in other words, it would make sense (though perhaps to be considered a bug) that it wouldn't want to "insert" where you are typing. to test this, you could just first add a new line in a new file, then on line 2 see if it will autoimport when you type @dataclass
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Interesting... That could be the reason - I'm going to experiment with this, thanks :).
@deez_gainz
@deez_gainz 2 жыл бұрын
Hi Arjan, thanks a lot for your design pattern videos, really learning a lot. If you get short on video ideas how about this one "Most useful design patterns for creating your own REST API".
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Great suggestion!
@DS-tj2tu
@DS-tj2tu 2 жыл бұрын
Thank you!
@firefouuu
@firefouuu 2 жыл бұрын
Great video again ! Just a suggestion: maybe you should run your code inside of the python interactive window instead of the terminal. I feel like it's usually more readable.
@pinakadhara7650
@pinakadhara7650 Жыл бұрын
Crazy stuff!
@Lodinn
@Lodinn 2 жыл бұрын
This example was some comedy gold. Otherwise, a very helpful and non-obvious pattern!
@jeffporzio1382
@jeffporzio1382 2 жыл бұрын
I always mix up the command pattern with the strategy pattern. Can you make a video comparing the two like you've done with other concepts?
@qwerty11111122
@qwerty11111122 2 жыл бұрын
It looks like strategy has a time delay between setting and usage and commands are used immediately. If a dog is set to happy strategy, then later, commanding it to speak makes it bark. If the dog is set to scared strategy, then commanding it to speak makes it go "rut's sat, raggy?"
@fennecbesixdouze1794
@fennecbesixdouze1794 2 жыл бұрын
Just because the have similar sounding names or what? They really aren't similar at all. In the command pattern, you have a bunch of different operations that you are frequently executing throughout the application. Usually these commands have completely different interfaces. You take all these different operations, rewrite them so that they are invoked using objects that all implement a common "command" interface with an "execute" method. Each individual command still has to be created with its own interface, but instead of invoking the code directly you can at some later time call "execute" on the command object to run the code. Then rather than calling all the different objects directly, you write a "Controller" that you use to encapsulate the later execution of these methods. You can add any kind of code in the controller to do a number of things, like keep track of undo/redo lists, package the commands into batches if you want them executed transactionally, etc. In the strategy pattern, you have several chunks of code that do similar things and that you notice naturally already have the same interface that is being invoked in the same way. Or you have a chunk of code that you can identify a simple interface for, and you want to encapsulate it into its own object so that you can write other versions of it with that same interface. So you write a Context object that invokes the interface, and pull out the common bits of code that share that interface and encapsulate them in Strategy objects that all share the same interface. Then you pass the strategy object dynamically to the Context, usually at run-time. This allows you e.g. to select between different strategies at runtime without having to write multiple contexts invoking the same interface. Command objects usually all have very different interfaces and you know that you're creating them when you create them. The different interfaces are not abstracted away, instead you use the different interfaces when the different command objects are created, and then you simply call "execute" at a later time to invoke them. In the strategy case, the strategies explicitly have the same interface, you aren't creating strategy objects by using different interfaces, you are usually writing the strategies in code, but then at run time the contexts use the same interface to invoke any one of the strategies. In the example Arjan gave, the transactions all had different interfaces: a deposit and a withdrawal took just an account and an amount, but a transfer took a from account, a to account, and an amount. Withdrawal, deposit, and transfer were not three different strategies because they don't have the same interfaces. And the code he was writing wasn't deciding about whether to run a withdrawal, deposit, or transfer at runtime: he had to know which of each he was invoking as he wrote the code, but he invoked them all through a controller that deferred execution of the commands to some later point and managed their execution.
@XRay777
@XRay777 2 жыл бұрын
The TL:DR version: Command is about decoupling setup from execution as shown in this video. Strategy is about changing the behaviour of your code by swapping components in the code for others with the same interface. E.g. think of swapping the factory containing a tile set to create a level in a video game once you reach the next level.
@JonMarkSearle1
@JonMarkSearle1 2 жыл бұрын
Ajan, I ove your videos. I've been coding since '86, and always find there is more to learn. Recently, I've stated to get a lot more disaplined with the TTD approch; making sure to write a test, failing the test, write code that passes the test, refactor and repeat. I LOVE IT! You don't have to use pytest specifically, but I wonder if you agree with the TDD or BDD approch, whether you might incorporate them into your demos? Also I much prefer the face in the bottom left corner as I'm more interested in the code you write (no offense).
@zhonghuahe3556
@zhonghuahe3556 2 жыл бұрын
also looking forward to seeing more demos accompanying TDD, i found myself difficult using TDD in my daily programming
@virtualraider
@virtualraider 2 жыл бұрын
Great video! I'm slowly coming around to protocols, but it still bugs me a lot that one needs to know the protocol specification from memory - no help from the IDE. Maybe a solution/workaround is to name the protocol used in the class docstring. That way collaborators and future us can get to the details without guessing 🤔
@sticky319
@sticky319 2 жыл бұрын
Could you consider the transaction classes as the memento pattern? They are storing the state that is used to undo and redo which is one of the main uses of the pattern. As always great video!
@RitchieDiamond
@RitchieDiamond 2 жыл бұрын
The memento pattern is related to the usecase presented here, which is to revert an object to a previous state. However, it does this by storing the previous state directly though, instead of modifying the state back and forth like the Command objects are doing here. Mementos are useful to combat side-effects of redoing and undoing which cannot be completely reverted by a Command.
@jeancerrien3016
@jeancerrien3016 2 жыл бұрын
I love how you slip in new pythonisms. I didn't know about "...". I use pass or a comment. Thank you!
@slinky7355
@slinky7355 2 жыл бұрын
I know this is all for the sake of theory, but exception handling at a real bank would need to be able to roll back a batch of transactions so that they never occurred in the first place. This is something UniVerse handles at an OS level. You can start a “transaction” which is just a series of file changes, and the OS will track everything and scrub it all away in the event of a rollback.
@DavidFarnan
@DavidFarnan 2 жыл бұрын
Is there a bug with his last example if he uncomments the undo command after the failed batch execute? The execute of the batch is adding it to the stack even though it failed and undid itself. When he then just loops the transactions in the batch to undo, he is undoing things that didn't succeed in the first place. It seems there are some additional interesting concepts around exception handling for these patterns. He seems to set forth in the batch execute that it should leave the state of the accounts unchanged if an exception occurs, but in the controller you must only be able to undo and redo transactions that succeed thus the failed batch should not have been added to the stack. It seems you could handle this by returning bool from execute indicating if it was successful and thus changed the external state or not, but to me the safest way to handle this is to raise some sort of failed execution exception. Then you could catch that in the controller and not add it to the stack and print the exception failure cause. Now any of my transaction types can raise an exception during execution and the controller can decide is it ok to proceed and not add it to the stack or it is not ok to fail in this execution and the execution bubbles up outside the controller. I'm guessing this is all coming in part 2.
@SirFloIII
@SirFloIII 2 жыл бұрын
I suppose the correct thing would be for the batch command to reraise the ValueError after rolling back.
@alessandroferrari2166
@alessandroferrari2166 2 жыл бұрын
thank you for teaching all these useful patterns! On our way to become 10X developers 😜
@ArjanCodes
@ArjanCodes 2 жыл бұрын
You got this!
@carecavoador
@carecavoador 2 жыл бұрын
I've been watching all your videos and I really like them. I like your style and the way you present your content, which is amazing. But I'm gonna be honest: Abstract Classes, Protocols and Python Typing are things I never wondered. And now I really want to learn more about it. Do you get to these subjects in your course?
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thanks, glad you like the videos! Yes, I cover all those topics in detail in the course.
@btkb1427
@btkb1427 2 жыл бұрын
Yay another pattern :)
@YossiZinger
@YossiZinger 2 жыл бұрын
Arjan: "Google and Microsoft have zero, which is as it should be" (28:51) Google: *DEMONITIZE*
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Haha, yes I have to be careful 😊
@ClemensNyffelerRocks
@ClemensNyffelerRocks 2 жыл бұрын
Thanks for the awesome videos Arjan. Makes those patterns seem so easy and straightforward. I'd love to see your take on the Visitor pattern with python!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thank you Clemens, good suggestion!
@Antuan2911
@Antuan2911 2 жыл бұрын
@ArjanCodes Does "Protocol" inheritance of "Transaction" class give us the ability to pass as argument to "execute" method of "BankController" class various classes as "Deposit" class or "Bach" class? And also because they have the method "execute" implemented? Thank you!
@pthanos
@pthanos 2 жыл бұрын
Thanks man. I wonder of this pattern can be used to create an approval system. For example, operation x can happen when 2 users have given approval.
@LordErnie
@LordErnie 9 ай бұрын
I am a bit new to using behavioral patterns. It to me looks like a couple of things. We want to pass a function, functions aren't values in OO. We pass a command. So, whenever you want to pass a process, or something that represents the executing functionality associated with a process, use a command? It to me really feels like giving a function an explicit type. But now, because classes give us grouping, we associate undo and redo operations with them as well. Is that somewhat accurate? I just really cant thing of an example where i'd use this instead of passing a (sometimes lazy) function. Can you help me out?
@bombdrive3880
@bombdrive3880 2 жыл бұрын
15:43 Sorry, I am new to this. But I feel like the code is deeply couple... we call a reference of object's method in "execute, undo, redo" method. So the Deposit class is now couple with Account class. Is it expected?
2 жыл бұрын
... and part 3 would be the double entry accounting version? Jokes aside, great video.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Haha, that would be nice 😊.
2 жыл бұрын
@@ArjanCodes after bookkeeping for my sports club for 10 years I can only think on double entry. Where transactions are immutable and each contains two or more (account, amount) tuples with a total amount of zero.
@maddruid840
@maddruid840 2 жыл бұрын
I'm on the lower side of intermediate, so this may be a dumb question. Would this be a good pattern to use if you think you might move to an MQ system at some point? It seems like it would set you up well to receive and process messages (commands) that were handled by an external queue management system if you wanted to distribute the load. Would this be the right pattern or is there something else more specific to that scenario?
@shaikirrted2767
@shaikirrted2767 2 жыл бұрын
In class what it is it called? from account : Account to account : Account ?
@PerisMartin
@PerisMartin 2 жыл бұрын
3:32 are you talking about Bitcoin here?
@southpole76
@southpole76 2 ай бұрын
Maybe i'm missing something but why are the commands not inheriting the defined transaction protocol class?
@ArjanCodes
@ArjanCodes 2 ай бұрын
Protocol classes in Python work with duck typing. There’s no need to inherit from a protocol class as Python will infer the type from the methods and properties that are present on the object you pass to a function or method.
@addcoding8150
@addcoding8150 2 жыл бұрын
Arjan Darkmode: 14:00 Arjan Lightmode: 21:00
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Haha, yeah - I'm still figuring out the optimal settings for my camera, but I'm getting there!
@mitchedmunds
@mitchedmunds 2 жыл бұрын
Thanks Arjan, your videos are giving me a lot of ideas to refactor my project using the OOP paradigm. I think I spotted a keyboard shortcut at 27:53 to automatically reposition comma separated values on a single line to each value being on it's own line. Is that one that is readily available in VS Code? Been looking for one that does it without success lately, care to share? Thanks!
@rdean150
@rdean150 2 жыл бұрын
That's likely from his use of the automatic code formatter called "black". VS Code allows you to define a code style engine such as black, autopep8, prettier, and others that will automatically enforce their style rules on your source code while you edit, or apply them across the entire document every time you save the file. Some people love these formatters, some people can't stand them.
@JGnLAU8OAWF6
@JGnLAU8OAWF6 Жыл бұрын
Undo stack doesn't make sense to me in that context, you generally want to undo specific transactions, not the last one.
@mishkasensei
@mishkasensei 2 жыл бұрын
Good video! If you show command design pattern on real simple gui text editor it will be more demonstrably. PS My English maybe is bad, it is not my native:/
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thanks for the tip!
@user-ei3op3me5c
@user-ei3op3me5c 9 ай бұрын
music volume is too high
@XRay777
@XRay777 2 жыл бұрын
Does that hint at the end mean we are going to see Flyweight next week? :^)
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Not really. I’m going to show what happens when you change the design to not store the state (account balance) at all but rely on the transaction history instead.
@XRay777
@XRay777 2 жыл бұрын
@@ArjanCodes Looking forward to that. I was thinking that if you want to store a large number of transactions in the history you would turn them into flyweights to save memory 🤔
@DrSpooglemon
@DrSpooglemon 2 жыл бұрын
I think this is why OOP leads to so much bloat. Instead of just keeping a stack of all the changes and having a undo function all of these classes need to be written. I am creating a chess game in python and I wanted to add undo functionality but I just couldn't justify to myself writing all these classes to handle it. So I have a list named 'history' that I can pop off the previous move. If you wanted redo functionality then all you need is another stack to append the undone actions to.
@foible2085
@foible2085 2 жыл бұрын
Undo transaction could just create a new transaction with accounts swapped and call execute on that. DRY.
@XRay777
@XRay777 2 жыл бұрын
I am bit on the fence about that, since it clashes with the single responsibility principle. Then the class would have 2 reasons for changing: when its logic changes and when it's dependency changes.
@taylormonacelli
@taylormonacelli 2 жыл бұрын
You can't really print a bank but if a bank can print money, it's only fair that we should be able to print a bank. Thats funny. Seems fair enough.
@eilmiv
@eilmiv Жыл бұрын
How to get rich: 1. Withdraw lots of Money from your account as a batch 2. Undo 🤑
@eilmiv
@eilmiv Жыл бұрын
... assuming you don't have "lots of money" already.
@zknarc
@zknarc 2 жыл бұрын
Most of your classes are dataclasses even when they have behaviour (methods). Why is this?
@fennecbesixdouze1794
@fennecbesixdouze1794 2 жыл бұрын
This is a bizarre question. Of course his dataclasses have behavior: they're classes for crying out loud! It's even in the name: dataCLASS. If they were just containers for data with no behavior, he could use named tuples or lists or dicts or some other data container (although he may prefer using dataclasses even in that case, idk or care). But a dataclass is a *class*, i.e. an outline for objects that have both data and behavior. What characterizes them among other classes is that their objects require no special initialization apart from providing values to the fields. The assumption that your object's behavior and identity depends only on its fields, because there is no special initialization, gives you a lot of nice guarantees and enables you to build out all kinds of nice functionality in such a class for free with a bit of boilerplate. With Python, a lot of the boilerplate for that nice functionality is done for you with the dataclass decorator.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
The main reason is that I find dataclasses help a lot in reducing boilerplate code, in particular writing class initializers and methods to convert an object into a string.
@doitbeforeyoudieful
@doitbeforeyoudieful Жыл бұрын
Too difficult to follow
@AloisMahdal
@AloisMahdal Жыл бұрын
Withdraw all money from Google and Microsoft and watch the world BURN from Bahamas! 😀
@davidmurphy563
@davidmurphy563 2 жыл бұрын
Nah, I tried that approach with my marriage. Didn't work.
7 Python Code Smells to AVOID at All Costs
22:10
ArjanCodes
Рет қаралды 370 М.
Zombie Boy Saved My Life 💚
00:29
Alan Chikin Chow
Рет қаралды 28 МЛН
Glow Stick Secret Pt.4 😱 #shorts
00:35
Mr DegrEE
Рет қаралды 10 МЛН
Чёрная ДЫРА 🕳️ | WICSUR #shorts
00:49
Бискас
Рет қаралды 6 МЛН
ROLLING DOWN
00:20
Natan por Aí
Рет қаралды 11 МЛН
Design Patterns in Plain English | Mosh Hamedani
1:20:01
Programming with Mosh
Рет қаралды 1,3 МЛН
Why the Plugin Architecture Gives You CRAZY Flexibility
24:06
ArjanCodes
Рет қаралды 112 М.
Golang: The Last Interface Explanation You'll Ever Need
17:58
Flo Woelki
Рет қаралды 9 М.
Master Go Programming With These Concurrency Patterns (in 40 minutes)
46:15
How To Reduce Coupling With Facade | Design Pattern Tutorial
28:29
When RESTful architecture isn't enough...
21:02
Dreams of Code
Рет қаралды 273 М.
Every Developer Should Know This
15:38
ArjanCodes
Рет қаралды 25 М.
Protocol Or ABC In Python - When to Use Which One?
23:45
ArjanCodes
Рет қаралды 201 М.
Purge These 7 Code Smells From Your Python Code
29:43
ArjanCodes
Рет қаралды 66 М.
Rust Data Modelling Without Classes
11:25
No Boilerplate
Рет қаралды 170 М.
Zombie Boy Saved My Life 💚
00:29
Alan Chikin Chow
Рет қаралды 28 МЛН