Temporal Decoupling and Autonomy
Commands can lend themselves to be issued asynchronously depending upon your Service Level Agreement and hence introduce temporal decoupling in your system, if that is what you need. If you must have your command processed reliably, these commands can further lend themselves to be serialized and stored in some kind of non-volatile storage (like a message queue) until they are processed successfully. This autonomy becomes of critical importance if you are dealing with distributed systems.
Validations are those context-independent rules that do not depend on the state of the domain objects. Business rules, on the other hand, are context-dependent (not very different from Martin Fowler’s idea of Contextual Validation). They check whether or not the command execution will result is valid state transition. Carrying out some of these context-independent validation rules on the command it-self will take the load off the domain layer by pre-filtering commands which will anyways be rejected by the domain objects.
Many people like repeating these validation rules on both places. This will bring value only of you ever need to use your domain layer not in conjunction to your application layer. Is it likely to happen in your case?
Implementing authorization on the command side of the application is essentially asking your-self whether or not the user is allowed to issue the command. Dealing with authorization on queries is a different discussion.
You can store the commands to capture the user’s action which then can be used for auditing purposes.
You can log commands and hence the log the user action and intention. These logs can make root-cause analysis of production issues very easy because you now have the end-to-end data to replicate the issue in your development environment.
Re-play and Undo
Commands lend themselves to be stored which can be used to redo or undo a user action if the use-case requires you to do so.
In a nutshell, commands are programmatic representation of user’s actions and intentions. Thinking of these commands as the building blocks of the application layer can open up a floodgate of interesting possibilities in your DDD architecture and bring a lot of power and flexibility to your design.