12

I read once that a method should either have a return value (and be referentially transparent), or have side-effect(s), but not both. I cannot find any references to this rule, but want to learn more about it.

What is the origin of this advice? Out of what person or community did it arise?

Extra credit: What is the claimed benefit of following this advice?

  • 1
    @gnat Yes, it is primarily about history. I feared that the extra credit part was too subjective to stand on its own, and that history stood a better chance of escaping closure. I'll add the tag. – Wayne Conrad Jul 16 '15 at 18:51
  • some of the answers that pile on made me wonder whether you ask about benefit that was claimed by an author of this advice or for a list of all benefits that are possible to claim at all? – gnat Jul 16 '15 at 19:10
  • @gnat I ask about the benefit claimed by the author (again, fearing closure), but I sure don't mind the pile-on reasons--they're answering the question I actually wanted to ask. If I were to remove "claimed" from my question, making the pile-on answers on-topic, would that push the question too far into the subjective? – Wayne Conrad Jul 16 '15 at 19:14
  • "pile-on reasons" are likely to push the question to be closed as too broad. If you prefer it "to stay on the open side", I think it would be safer to narrow it down to benefit that was claimed by author – gnat Jul 16 '15 at 19:17
  • One benefit is that if you're paid by volume of code, this produces extra. "doSomething; GetResultOfSomething; HandleErrorsFromSomething;" – Ⴖuі Jul 27 '15 at 21:04
13

According to Greg Young, this idea originated from Bertrand Meyer: Command-Query separation.

It states that every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, Asking a question should not change the answer.1 More formally, methods should return a value only if they are referentially transparent and hence possess no side effects.

1: Eiffel: a language for software engineering slide 43-48

In Domain Driven Design, this is similar to Command-Query-Read Separation/Segregation (CQRS), as named by Greg Young.

Greg Young took the idea of CQS from Bertrand to name CQRS as mentioned by Martin Fowler in this CQRS article

Benefits

  • The Read (Query) part can be scaled/tweaked differently from the Write (command) part. Separating the two would prevent either from getting in the way of each other when optimization/performance is key.

Read the article in the Martin Fowler link for more.

  • 1
    Naturally, in many situation generating a useful result and doing some modification at the same time is no more expensive than the doing the harder of the two separately. – Deduplicator Jul 16 '15 at 20:07
  • 1
    @Deduplicator A cliche example being InterlockedCompareExchange? – Ⴖuі Jul 27 '15 at 21:09
  • 1
    This advice obviously doesn't apply when the return is some information about what was done in the command, however - a method to remove rows from a dataset can pretty much change the dataset state, removing the indicated rows according to a given criteria, and then return the number of rows removed or even a list with said rows. – T. Sar Aug 11 '17 at 13:10
4

I don't know where it comes from, but it is good advice and fairly straight-forward to understand.

Any sanely designed program will be broken up into various parts, combined and composed in various ways. The harder it is to reason about what any particular part does, the harder it will be to make sure that your program will react in a predictable manner.

Isolating the parts that produce side-effects makes the rest easier to reason about, test, and debug. Reducing the number of side-effects in each part that does generate a side-effect will make that part easier to work with in the same manner.

If you decompose it even further, a return value is an effect. Side-effects are an effect. A function should only produce 1 effect (if possible) because the greater number of inputs and effects a function has, the greater the difficulty in reasoning about what it actually does.

  • this doen't even attempt to address the question asked, see How to Answer – gnat Jul 16 '15 at 18:43
  • @gnat My question came in two parts: The main question ("who"), and the extra credit ("why). Doesn't this address the extra credit part? – Wayne Conrad Jul 16 '15 at 18:50
  • per my reading ("claimed benefit"), why-part is expected to be one proposed by the author of the quote. Question doesn't appear to be asking for a list of all possible benefits – gnat Jul 16 '15 at 18:53
  • 2
    @gnat I understood the question as an attempt to understand this advice, both the reason behind it as well as the context in which it was given. I don't believe that it was inappropriate to address only part of the question. – Morgen Jul 16 '15 at 19:47
1

Extra credit: What is the originally claimed benefit of following this advice?

One of the benefits of separating return value from side effects is that it removes a potential problem which may be caused by short-circuit evaluation.

bool FooWithSideEffect() {
    // do query
    // do side effect
    return resultOfQuery;
}

bool BarWithSideEffect() {
    // do query
    // do side effect
    return resultOfQuery;
}

void BadShortCircuitEvaluation()
{
    // the programmer's intent is to have side effects of both functions
    if (FooWithSideEffect() && BarWithSideEffect() ) {
        // do something
    }

    // in case FooWithSideEffect() returns true, 
    // then BarWithSideEffect() is not called at all
    // because of short-circuit evaluation
}
  • is this a benefit claimed by author of the advice? – gnat Jul 16 '15 at 19:09
  • @gnat I have mixed-up historical and practical, I fear. – Nick Alexeev Jul 16 '15 at 19:11
  • 1
    the comment and code do not match, BarWithSideEffects is not called if FooWithSideEffects returns false – jk. Jul 28 '15 at 9:37

Your Answer

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

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