web-dev-qa-db-ja.com

「メソッドは値を返すか、副作用を伴うべきであるが、両方をもたらすべきではない」の起源

私は、メソッドが戻り値を持っている(そして参照的に透過的である)か副作用を持っている必要があることを一度読んだことがありますが、両方はありません。この規則への言及はありませんが、もっと詳しく知りたいです。

このアドバイスの起源は何ですか?それはどの人またはコミュニティから生じましたか?

追加クレジット:このアドバイスに従うと主張される利点は何ですか?

12
Wayne Conrad

グレッグ・ヤングによると、このアイデアはBertrand MeyerCommand-Query Separation に由来しています。

すべてのメソッドは、アクションを実行するコマンドか、呼び出し元にデータを返すクエリのいずれかである必要がありますが、両方ではないことを示しています。つまり、質問しても答えは変わりません1 より正式には、メソッドは、それらが参照的に透過的であり、したがって副作用がない場合にのみ値を返す必要があります。

1: エッフェル:ソフトウェアエンジニアリングの言語 スライド43-48

ドメイン駆動設計では、これはGreg Youngによって命名されたコマンドクエリリード分離/分離(CQRS)に似ています。

Greg YoungはBertrandからCQSのアイデアを取り入れて、Martin Fowlerがこの CQRS記事 で言及したようにCQRSを命名しました

利点

  • 読み取り(クエリ)部分は、書き込み(コマンド)部分とは異なる方法でスケーリング/調整できます。 2つを分離すると、最適化/パフォーマンスが重要な場合に、どちらかが相互に邪魔になるのを防ぐことができます。

詳細は Martin Fowlerリンクの記事 を参照してください。

13
tunmise fasipe

どこから来たのかはわかりませんが、良いアドバイスであり、理解するのもかなり簡単です。

きちんと設計されたプログラムは、さまざまな部分に分割され、さまざまな方法で結合および構成されます。特定の部分の動作を推論するのが難しいほど、プログラムが予測可能な方法で反応することを確認するのが難しくなります。

副作用を生成する部分を分離すると、残りの部分についての推論、テスト、およびデバッグが容易になります。副作用が発生する各パーツの副作用の数を減らすと、そのパーツを同じ方法で操作しやすくなります。

さらに分解すると、戻り値が影響します。副作用は効果です。関数が持つ入力と効果の数が多いほど、関数が実際に何をしているのかを推論することが難しくなるため、関数は1つの効果(可能な場合)のみを生成する必要があります。

4
Morgen

追加クレジット:とは 最初に主張した このアドバイスに従うメリットは?

戻り値を副作用から分離する利点の1つは、 短絡評価 によって引き起こされる可能性のある潜在的な問題を取り除くことです。

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
}
1
Nick Alexeev