Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Command design pattern - allow different concrete commands to return different types

We are designing a new component and considering using the command design pattern.

We have two main type of commands that will implement our IOurCommand interface (from which other Commands will inherit).

The issue is that the first command CommandDoUpdates does not need to return any value, while the second command CommandGetData is to fetch data, so it needs to return a List of some objects( List<DataRow>)

Things we are considering to deal with the situation:

  1. Return a Class that will contain an indication about the success of the operation (bonus) and a List of objects that will be an empty list for all the CommandDoUpdates.
  2. Keep the List as a member of the concrete command - Potential solution, but makes our life harder for other reasons (shallow copy Vs. Deep copy and so).
  3. Same as #1, but return a base class in the function, and every calling calss will have to down cast the result to the concrete class (Down cast is not a good practice since the client will need to know what is the actual return value).
  4. Splinting the command to two different hierarchies (one that returns a value and one that does not), and using two different Receivers - I really don't like it, but it's an option.

This post is good reading about whether a command should return a value/status or not. This is relevant since in the GoF book the Command design pattern does not return a value.

My actual questions are:

  • Can you think of a better solution?
  • Any pros or cons for options 1,2 and 3, any pros for option 4?

Thanks!

like image 246
asafrob Avatar asked Nov 11 '22 23:11

asafrob


1 Answers

I suspect the command pattern is being extending to the point that it really breaks the pattern here. One of the comments in the post you linked said it well: "The original intention of this pattern is that there is some object that executes the commands but has no knowledge of what they actually do." If one command family is to access data and the other is to mutate it, is there really a common use case that requires abstracting them to a common type? To me, a common interface says that two objects are used the same way, but that isn't really the case here.

As far as a better solution, one common solution is to use an MV* (MVC, MVP, MVVM) pattern and have the command update a model and have observers notified after the update occurs.

If the MV* is too much pattern for you, then I think 4 is your answer, just get rid of the common interface. You don't necessarily have to have two receivers, since you could make the method on the receiver generic. However, I think you have to do something different depending on whether you are processing a CommandDoUpdates or a CommandGetData, so an overload of a method might be more clear than doing a check on the return type of the "command". I think that it is more clear in this case to have the signature for your receiver says that it gets messages from two different types of objects than to say these "commands" are fundamentally the same type.

Also, maybe CommandDoUpdates is better as a Transaction Script and your CommandGetData is better as a Repository, and the two hierarchies can be renamed? There isn't too much information about what in the context led you to the command pattern in the first place, only what makes it not the right choice, so maybe I am completely off because of that.

like image 145
Steve Clanton Avatar answered Nov 14 '22 23:11

Steve Clanton