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.

Let's pretend we have a service that calls a business process. This process will call on the data layer to create an object of type A in the database.

Afterwards we need to call again on another class of the data layer to create an instance of type B in the database. We need to pass some information about A for a foreign key.

In the first method we create an object (modify state) and return it's ID (query) in a single method.

In the second method we have two methods, one (createA) for the save and the other (getId) for the query.

    public void FirstMethod(Info info)
    {
        var id = firstRepository.createA(info);           
        secondRepository.createB(id);
    }

    public void SecondMethod(Info info)
    {
        firstRepository.createA(info);
        var key = firstRepository.getID(info);
        secondRepository.createB(key);
    }

From my understanding the second method follows command query separation more fully. But I find it wasteful and counter-intuitive to query the database to get the object we have just created.

How do you reconcile CQS with such a scenario?

Does only the second method follow CQS and if so is it preferable to use it in this case?

share|improve this question
2  
if A and B are created together with any frequency I would probably make a stored procedure create both at once, and then you cut out the potential of having a B created first or an A created without a B if those are problems. –  Ryathal Dec 12 '11 at 21:53
    
Stepping in late in the game to offer the option of using an out parameter. It's technically not a return value! ;) –  tuespetre Sep 4 '13 at 3:53
add comment

3 Answers 3

CQS is a guideline rather than an absolute rule. See the wiki article for examples of activities that are impossible under strict CQS.

However, in this case, if you did want to maintain CQS, you could either create the ID on the client side (such as a GUID), or the client could request an ID from the system before creating any objects, which feels cleaner to me than creating the object then querying for it (but is harder than just using an identity column).

Personally I'd just return the ID and call it one of those situations where CQS isn't a good fit.

Another good article with examples: Martin Fowler

share|improve this answer
add comment

Only the second method follows CQS.

I consider CQS to be a guideline to encourage good coding practices. Make use of good coding practices during development, and if you find out later that this method contains resource-critical code, you can still optimize it.

Premature optimization is the root of all evil :)

share|improve this answer
    
What is particularly good in the second method? –  CheatEx Dec 13 '11 at 8:17
    
I did not say the second method is 'good'. I said it follows the CQS paradigm. If you don't follow CQS, I suppose the second method is not good for you. If you want to know why some people try to follow CQS, see http://en.wikipedia.org/wiki/Command-query_separation –  cheeesus Dec 13 '11 at 9:09
    
You said that CQS is encouraging good coding practices, if it is true then we should observe some kind of "goodness" in the second method. Where is it? –  CheatEx Dec 13 '11 at 14:12
    
Apparently you did not read the link I provided. CQS catch-phrase: Asking a question should not change the answer. In your first method, you have a method ('createA') which provides an 'answer', but it changes the answer every time you ask. In the second method you do not have that, this is the 'goodness' in it. To be clear: I'm no CQS purist, I do not follow it every time. –  cheeesus Dec 14 '11 at 11:54
add comment

If you follow a methodology and it seems to take you down bad paths, you should reevaluate it.

I see that the identifier of a newly created object is a valid thing to have as a return parameter- it is not just convenient, but it's also "good"- as you can see code is better when it does.

In any case, I'm not familiar with "command query separation" but I highly doubt that it disallows commands from returning information about the command execution, and if it does, just trash it- success/failure is always there, and I do not think that "your object was created OK" from "your object was created OK and its id is xxx" to be much different.

share|improve this answer
add comment

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.