This may sound cynical, though I don’t mean it that way (for once), but there’s more than one way to skin a cat, and so I try to avoid advocating strict ways of writing certain types of code. Having said that, I’ve found that writing queries and commands with a certain basic pattern has worked all right for me, at least recently.
Queries can be implemented using the following interfaces:
public interface IQuery
{
TReturnValue Execute();
}
public interface IQuery where TParameterDefinition : IQueryParameterDefinition
{
TReturnValue Execute(TParameterDefinition d);
}
public interface IQueryParameterDefinition {}
Queries that don’t require any input parameters can be used with the first interface, while queries that do require input parameters use the second one.
The IQueryParameterDefinition interface is a marker that allows you to do things like:
public class MyQueryDefinition : IQueryParameterDefinition
{
public int ParameterID { set; }
}
And then pass it into something like:
public class GetMyQuery : IQuery
{
public string Execute(MyQueryDefinition d)
{
return myService.GetQuery(d.ParameterID)
}
Nothing fancy, but it gives you type-safe blah blah blah. Obviously, you can create the QueryDefinition to have as many different parameters as you like.
When it comes to commands, one question that I’ve always ‘struggled’ with (I mean, it doesn’t keep me up at night or anything) is whether a command should return a value (note that this is a separate issue of whether they should execute in an async vs. sync manner). After looking at various things, what I’ve settled with for now is just as basic:
public interface ICommand
{
void Execute();
}
public interface ICommand
{
TReturnValue Execute();
}
I can think of a whole host of philosophical reasons why either or both of these approaches violate some consideration or another, but so far, they’ve worked for me in the situations I’ve needed them. YMMV.