Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I was recently refactoring a method that was both a command and a query method.

After separating it into a one command method and one query method, I found that there are now multiple places in the code where I am calling the command then getting the value from the query, which seems like a violation of the DRY principle.

But if I were to wrap that common code into a method, that method would be both command and a query. Is this acceptable?

share|improve this question
    
okay, i didn't know whether the community was at a consensus, and i couldn't find any discussion of this topic. –  kris welsh Jul 31 '13 at 16:43
    
It's more commonly called CQRS google.com.au/… –  Daniel Little Aug 1 '13 at 3:53
add comment

3 Answers

up vote 10 down vote accepted

There are always trade offs to consider between conflicting design principles. The way to resolve it is to look at the underlying reasons behind the principles. In this case, being unable to run a query without running the command is problematic, but being unable to run a command without running the query is generally harmless. As long as there's a way to run the query standalone, I see no reason not to add the query result to the command, especially if done something like this:

QueryResult command()
{
   // do command stuff
   return query();
}
share|improve this answer
add comment

I haven't heard of Command-Query-Separation(CQS) before, but it seems that it would relate to Single Responsibility Principle(SRP), which states that a function/class ideally should be responsible for doing one thing and one thing only.

If your command code is 20 lines of code and query code is another 30 lines and they are all in one function body, clearly you are violating SRP and I'd assume CQS as well and those two pieces of logic should be separated from each other.

However, going with your hypothetical example, I would most likely create a wrapper method that would combine your command and query so that DRY isn't violated in numerous places in the code. I'd also wouldn't consider this to be SRP (and maybe CQS) violation, because the wrapper still has only one responsibility: to combine command with a query and create a higher level abstraction that is easier to consume.

I think wrapper method is perfectly acceptable solution and to illustrate that, let's take your example one step further. What if you had to run 2 queries instead of 1 and then do a command action based on that. So your 2 lines of code would be 6 or 8. What if there was some data validation/checking between one and the other, so now you have 15 lines of code. Would you think twice about creating a wrapper that does all that, rather than sprinkling those 15 lines in multiple files?

share|improve this answer
    
I think a wrapper's "single principle" should be to keep the other methods that need the command and the query together DRY. –  Droogans Jul 31 '13 at 19:50
    
Google CQRS: google.com.au/… –  Daniel Little Aug 1 '13 at 3:50
    
While Karl's solution to this problem is better, i do find your elaboration on longer wrapper functions to be a very good point. –  kris welsh Aug 1 '13 at 12:05
add comment

DRY is more important, since it solves a much more fundamental need - avoiding redundant, effectively wasted effort. This is a fundamental thing - one need not be a programmer to understand it.

CQS is a response to the difficulty, in languages with no support for tracking effects, of understanding code that is executed both for its results and its effects. However:

  1. The necessity to execute code for its results cannot be avoided, because this is the basis for composing large programs from small units.

  2. The necessity to execute code for its effects cannot be avoided either, because, outside of mathematics and theoretical computer science, the value of running a program lies on what it observably can do for us.

  3. The necessity to cause effects and produce results in the same code cannot be avoided, because, in practice, we need both effects and compositionality, not just one or the other.

The actual solution to the problem of tracking effects being too hard for unaided humans is, of course, to have computers aid us humans! A similar thing can be said about tracking intricate relationships between runtime values (such as the validity of array indices), for which exceptions and runtime-enforced contracts constitute (non-)solutions.

In conclusion, "solutions" like CQS merely get in the way of designing programs according to sound principles based on reality. Go for DRY.

share|improve this answer
    
Sometimes you need to avoid coupling in order to decrease complexity. You should take a look at CQRS. –  Daniel Little Aug 1 '13 at 3:53
    
@Lavinski: The best tool for avoiding complexity (not decreasing it, that is futile) is abstraction - decoupling the generic essence of the problems we are solving from the particular details of the instances of said generic problems. Magical recipes (or "design patterns" as I hear they are called) at best can prevent you from causing too much damage when you get your design wrong, but they cannot turn a wrong design into the right one. –  Eduardo León Aug 1 '13 at 4:04
    
@Lavinski: With respect to CQRS specifically, the conceptually correct alternative solution is 1. understand the data model (no amount of object layers can eliminate the necessity for this), 2. encode as many correctness properties as you can in the database schema. (Sadly, most popular RDBMSes provide rather limited support for the latter, not to mention NoSQL ones, which get this even more wrong. My current research is providing a better solution for this.) –  Eduardo León Aug 1 '13 at 4:16
    
CQRS works completely in line with Domain Driven Design I suggest you do a bit of research. The Domain inside the application should enforce correctness not your data store. –  Daniel Little Aug 1 '13 at 5:05
    
@Lavinski: Sorry, in my line of work, I need a level of confidence in the correctness of my designs that only mathematics can provide. –  Eduardo León Aug 1 '13 at 5:21
show 9 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.