I need to create some commands that share the method Execute()
and a property that gets the result of such execution: List<IResponse>
. I have the following interface:
public interface Command
{
public IEnumerable<IResponse> Responses;
void Execute();
}
Each class that implements command needs different inputs (parameters), for example:
- GetDeviceNames command needs to know the Ids of the devices.
- SendDeviceData command needs to know the device Id, its Name, its Type, its Status, etc.
At the end the user should use the application sending a json to incapsulate the parameters of each command, something like:
$ application GetDeviceNames --parameters '{"ids" = [0, 1, 2, 3]}'
$ application SendDeviceData --parameters '{"id" = 0, "Name" = "Device1", ...}'
So, my question is, should the command classes receive the parameters as objects, like this?:
public SendDeviceData : ICommand
{
private SendDeviceDataParameters parameters;
public IEnumerable<IResponse> Responses;
public SendDeviceData(SendDeviceDataParameters parameters){/* ... */}
public void Execute(){/* ... /*}
}
So the client uses like:
// parameters object might also be deserialized from json
SendDeviceDataParameters parameters = new SendDeviceDataParameters()
{
Id = 0,
Name = "Device1",
...
}
SendDeviceData command = new SendDeviceData(parameters);
command.Execute();
Or should the command classes set the parameters as properties, like this?:
public SendDeviceData : ICommand
{
public int Id { get; set; }
public string Name { get; set; }
...
public IEnumerable<IResponse> Responses;
public SendDeviceData(){/* ... */}
public void Execute(){/* ... */}
}
So the client uses like:
// The values of parameters might be gotten from json previously
SendDeviceData command = new SendDeviceData()
{
Id = 0,
Name = "Device1",
...
};
command.Execute();
I am confused because I see advantages and disadvantages for each one:
- If I pass the parameters as an object:
- Advantages
- It is easier to serialize to or deserialize from json because parameter classes can be used.
- Disadvantages
- Some kind of details are exposed to the client that create a command.
- The need of creating a parameter class for each command because each command require a different type of input (parameters).
- Advantages
- If I pass the parameters as properties:
- Advantages
- Less details about how commands works are exposed to client.
- Disadvantages
- Serialize to or deserialize from json would require create an "intermediate" class.
- Advantages
What are your thoughts about it?
Execute
just return the result? Having it as a property gives you all sorts of bad temporal coupling. What happens if you access the result before calling Execute? What happens if you call Execute again? What if you do it twice, concurrently?IEnumerable<IResponse> Responses
might suggest that the command tracks its history of responses, at which point it can make sense to fetch responses separately from triggering the command itself. But I do agree with you if there is a strict one execution -> one response interaction between the command and its consumer.