Search code examples
design-patternslanguage-agnosticcommand-pattern

command pattern returning status


Once I had a discussion about design, relative to the command pattern. My peer stated that a command object should not return the status (successful, unsuccessful, and why) after the .execute() method is called. The reason is that you should not be concerned if the command gets executed or not, because the command must contain no state. You must however check after the invocation if the command had the expected effect. Another point he argued was that on the Gang of Four, the command pattern does not present this case (of returning status).

I claimed the opposite point. The GoF does not present this case, but a pattern can be modeled to your needs. If a command is unsuccessful, the invoking client must receive a proof of the status, and eventually deploy an appropriate reaction. By forcing the client to check if the action achieved success was error prone and produced duplicated code. Moreover, there are cases where the command produces a result (eg. a command that adds a line to a plot, will somehow have the line id to return to the client), and pretending to have commands with no state meant that you had to "fish out" the new object identifier from the data model.

In the end, we reached a compromise by not returning status but keeping the id's of newly created objects in the command object, and the application worked pretty well anyway, but I am now curious to know your opinion as well.


Solution

  • There are two questions in the question with multiple answers :) The first question is should a command return an error state?

    There is no clear answer for every program every time you apply the pattern you have to think about it again.

    One of the things you need to think about is:

    • Am I adding more coupling to many commands and the clients for only some specific error cases?

    In the worst case you have many commands that don't care about errors but one or two commands do something that is important for the client to know if it worked. You now add checked Exceptions to the Interface and so every client and every Command are bound to do error handling and are coupled to the Exception. If you have a client that only deals with commands that are not throwing the exceptions you have a big overhead in your code.

    This is a thing that you don't want to have. So you can either move the commands that need error handling out of the command structure because they seem to be different from the other commands, or if your language allows it you can add runtime exceptions that are only handled by the clients that care and thrown by the commands that need to throw them.

    The other extreme is that every command can fail and the client has a consistent way of handling the errors this means that the errors doesn't depend on the specific command. The client does not have to know what kind of command failed it can handle every error in the same way. Now you could have the interface of the command return an error state and the client can deal with the errors. But dealing with the errors shouldn't depend on the kind of the command for the client.

    The second question is: Should a command have a state?

    There are architectures where a command needs a state and some where they don't need a state.

    Some possibilities to decide this:

    • If you want to have a undo for your command the commands need to have a state.
    • If the commands are only used for hiding a way a function that works on a small set of parameters and the outcomes only depends on the same of the command like the state pattern there is no need for a state and you can use the same object over and over.

    • If you use the command to communicate between threads and you want to transfer data from one thread to another the command needs a state.

    • ... If there is something you think should be in this list leave a comment.