Design patterns in the test of timeCommand
The command pattern is a behavioral design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time.
I adore this pattern. If this pattern had a paypal account, I would donate it money on a regular basis.
In general, the notion of encapsulating the method call into an object (like the functor sin C++) is an incredibly powerful idea, because is separate the idea of selecting what to invoke and when to invoke it. Commands are used pretty much every where, WPF is probably the most obvious place, because it actually have the notion of Command as a base class that you are supposed to be using.
Other variations, like encapsulating a bunch of code to be executed later (job / task), or just being able to isolate a complex behavior into its own object, is also very useful. I base quite a lot of my architectural advice on the notion that you can decompose a system to a series of commands that you can compose and shuffle at will.
Recommendation: Use it. Often. In fact, if you go so far as to say that the only reason we have classes is to have a nice vehicle for creating commands, you wouldn’t be going far enough.
Okay, I am kidding, but I really like this pattern, and it is a useful one quite often. The thing that you want to watch for are commands that are too granular. IncrementAgeCommand that is basically wrapping Age++ is probably too much, for example. Commands are supposed to be doing something meaningful from the scope of the entire application.
More posts in "Design patterns in the test of time" series:
- (21 Jan 2013) Mediator
- (18 Jan 2013) Iterator
- (17 Jan 2013) Interpreter
- (21 Nov 2012) Command, Redux
- (19 Nov 2012) Command
- (16 Nov 2012) Chain of responsibility
- (15 Nov 2012) Proxy
- (14 Nov 2012) Flyweight
- (09 Nov 2012) Façade
- (07 Nov 2012) Decorator
- (05 Nov 2012) Composite
- (02 Nov 2012) Bridge
- (01 Nov 2012) Adapter
- (31 Oct 2012) Singleton
- (29 Oct 2012) Prototype
- (26 Oct 2012) Factory Method
- (25 Oct 2012) Builder
- (24 Oct 2012) A modern alternative to Abstract Factory–filtered dependencies
- (23 Oct 2012) Abstract Factory
Comments
Added to that: you can extend commands to implement undo/redo easily, by adding a state and an 'undo' action next to the actual do action. Shameless plug: I implemented this in Algorithmia (OSS, bsd license), where I added a command implementation, which is able to undo actions by the command, and various data structures which are command aware (and thus undo aware) like graphs and lists: http://algorithmia.codeplex.com
As well as undo\redo support we've had great success combining the command pattern with the visitor pattern. You have a selection of items and a single command which visits each item in the selection performing the action.
If each visit pushes its undo state on to a stack up can easily undo the operation again.
Only when I started looking at how you used this pattern in RacoonBlog did I really get why it was so useful to me as a C# .Net developer.
The ability to unit test tasks themselves and then just confirm there existence in other places (MVC Controller) was amazing. Really helped me focus and write meaningful unit tests.
Jimmy Bogard at CodeBetter even goes as far as to turn the command pattern into a Query pattern. He encapsulates complex queries into a class that returns a dataset.
A nice extension of Command is CompoundCommand (or CompositeCommand, or whatever). A single command that contains an ordered list of commands. Iterate through your commands and call Execute(). Iterate backwards and call Undo(). A nice, single object responsible for a large piece of work, but still following the single responsibility principal by delegating actual meaningful work onto more granular commands.
Also nice for dependency injection.
Ayende - while I do agree with you that the Command pattern is very useful in the various cases you specified, I see it get abused too many times (sometimes really using it as an anti-pattern). For example, I've seen many architects design entire interfaces around the Command pattern (defining a single method which accepts a command derived object), resulting in a very generic definition and implementation - where more specifics would have greatly simplified the code and its maintainability over time.
I'd say let's not exaggerate. Command is extremely useful when you need to generate commands in one place and run them in another. It's also the only decent way I'm aware of to properly implement unlimited undo. But there are situations in which not using command yields smaller and simpler code, which wouldn't have significant benefits if using command.
Do you consider using lambda functions and delegates as an instance of the Command pattern? If you do, then yes, I also use them heavily. They are particularly interesting because you can achieve the same as implementing a interface but not committing to a particular one at compile time.
This is particularly useful when you can not assume a common interface for your objects (such as when they come from a third party library), and implementing several facades would be too much hassle for little benefit. Instead, you can map object methods to delegates on site and have your algorithm control the third-party objects without an explicitly interface definition.
I completely agree. I see that very frequently the business object of importance is a process, e.g. NotifyShipping, SaveProfile, etc. And, I like how "object-izing" a process is a straight-forward modeling of what computers do: input, processing, output, (storage).
I like what Anonymous had to say about using delegates, although I haven't found wrapping up an external dependency in an interface to be as significant an annoyance for me. I played around with constructor-based dependency injection with delegates as declared dependencies, and I liked that a method didn't have to be tied to the delegate definition, unlike a defined interface. I used StructureMap to inject dependencies on delegates, which worked great, but part of me felt like it wasn't cohesive enough. I guess I haven't completely resolved how I feel about it yet or when and when not to do it.
Don't forget the ever popular MacroCommand where you wrap a series of commands into another command that you can then execute / unexecute as a batch... super useful, indeed.
Anonymous, Lambdas are commands, yes. But in many cases I find it useful to wrap them in a real class, because it make it explicit how / why we capture the parameters for the command to execute.
Hey Ayende, you really should spend some time with F# if you haven't already. With first class functions, it's a much more natural way to represent and encapsulate units of computation, you can even compose/chain them together to build up more complex computations (such as the combinator-based family of parsers).
I think you'll really like it! :-)
Is the way you've designed RhinoETL an implementation of the command pattern?
Comment preview