“方法应返回值或具有副作用,但不能同时具有两者”的来源


12

我读过一次,一个方法应该具有返回值(并且是参照透明的),或者具有副作用,但不能同时具有两者。我找不到对此规则的任何引用,但想了解更多有关此规则的信息。

该建议的来源是什么?它是由什么人或社区产生的?

额外的功劳:遵循此建议有什么好处?


1
@gnat是的,它主要是关于历史的。我担心额外的信贷部分过于主观而无法独立生存,而且历史更有可能避免破产。我将添加标签。
韦恩·康拉德

一些堆积如山的答案使我想知道您是问这个建议的作者所要求的利益,还是要列出所有可能要求的利益?
蚊蚋

@gnat我问由作者(再次,担心关闭)声称的好处,但我肯定不介意桩上的原因-它们回答其实我的问题请教。如果我要从问题中删除“已声明”,使问题在主题上堆积如山,这是否会使问题过于主观?
韦恩·康拉德

“堆放的理由”可能使问题过于笼统。如果你喜欢它“留在开放侧”,我认为这将是更安全的范围缩小到由作者声称的好处
蚊蚋

好处之一是,如果按代码量付费,这将产生更多收益。“ doSomething; GetResultOfSomething; HandleErrorsFromSomething;”
Ⴖuі15年

Answers:


13

根据格雷格·扬(Greg Young)的说法,该思想源自Bertrand Meyer命令查询分离

它指出,每个方法都应该是执行操作的命令,或者是将数据返回给调用方的查询,但不能同时是两者。换句话说,提出问题不应改变答案1 更正式地讲,方法仅在引用透明且没有副作用的情况下才应返回值。

1:Eiffel:软件工程幻灯片43-48 的语言

在域驱动设计中,这类似于Greg Young命名的命令查询读取分离/隔离(CQRS)。

格雷格·杨(Greg Young)从伯特兰(Bertrand)提出了CQS的想法,将其命名为CQRS,正如Martin Fowler在本CQRS文章中提到的那样

好处

  • 可以与写(命令)部分不同地缩放/调整读取(查询)部分。当优化/性能是关键时,将两者分开可以防止彼此妨碍。

阅读Martin Fowler链接中文章以获取更多信息。


1
自然地,在许多情况产生一个有用的结果并做一些修改在同一时间不大于做两个独立的较硬更昂贵。
Deduplicator 2015年

1
@Deduplicator一个老套的例子是InterlockedCompareExchange吗?
2015年

1
当返回的内容是有关命令中执行的操作的某些信息时,此建议显然不适用,但是-从数据集中删除行的方法几乎可以更改数据集状态,根据给定条件删除指示的行,并且然后返回删除的行数,甚至返回包含所述行的列表。
T. Sar,

4

我不知道它来自哪里,但这是一个很好的建议,而且很容易理解。

任何理智设计的程序都将分解为各个部分,以各种方式组合和组成。对某个特定部分的功能进行推理的难度越大,确保程序以可预测的方式做出响应的难度就越大。

隔离产生副作用的零件,可使其余零件更易于推理,测试和调试。减少确实产生副作用的每个零件中的副作用数量,将使该零件更易于以相同的方式使用。

如果进一步分解,则返回值是有效的。副作用是一种效果。一个功能(如果可能)应该只产生1个效果,因为一个功能具有更多的输入和效果,推理出它实际作用的难度就越大。


这甚至都没有尝试解决所问的问题,请参阅“ 如何回答
咬住

@gnat我的问题分为两部分:主要问题(“谁”)和额外信用(“为什么”),这不解决额外信用部分吗?
Wayne Conrad

根据我的阅读(“ 要求的利益”),为什么部分应该是引文作者提出的建议。问题似乎并没有被要求一个列表的所有可能的好处
蚊蚋

2
@gnat我将这个问题理解为试图理解此建议的尝试,包括其背后的原因以及给出该建议的上下文。我认为仅解决部分问题是不合适的。
摩根(Morgen)2015年

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
}

建议作者要求这是一项好处吗?
蚊蚋

@gnat,我担心历史和实践会混在一起。
尼克·阿列克谢耶夫

1
注释和代码不匹配,如果FooWithSideEffects返回false
jk
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.