In our codebase we have a lot of controllers with a very similar structure:


if @my_model.update_attributes(params)
    return render_object(@my_model)
    return render_validation_error(@my_model)

Although the structure is not exactly the same everywhere, it seems feasible to refactor. It could look like:

def update_model_and_render(model)

Certainly, we would save a lot of lines. It would also be helpful for future programmers implementing similar functionality. Calling the new refactored function would prevent them from forgetting to add the @my_model.update_owner() line.

The problem with the new function is that it would be producing a side-effect and also returning a value. Clearly, We would be breaking Command-Query Separation (the new function would be referentially opaque).

Is it ok to bend the rule in cases like this to be more DRY?.

In a lot of code that I have seen, this happens usually at the boundaries of the system (like a controller, where mutations do happen but we always return a value), but I am not sure if there is anything else I could be missing.

  • 2
    It's OK to break the rules if it serves your purposes. Just understand fully what the tradeoffs are. Dec 18, 2017 at 17:06
  • Robert, first and foremost thanks for answering!. I think I get the spirit of CQS and how it gives you different levels of confidence over mutations and queries, the effects that it has when composing software. But I was wondering if there is a (not sure how to put it) more academic perspective or principle written somewhere about how you should implement this especially at the boundaries of your system. Exactly as you said, I wonder if I miss some tradeoff for a case like this, where it seems to me, you want DRY over CQS. Thanks for your time.
    – Jacob
    Dec 18, 2017 at 17:19


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.