为什么 class Money 通过示例扩展 Kent Beck 的 TDD 中的表达式?

Why does class Money extend Expression in Kent Beck's TDD by Example?

我正在学习 TDD by Example 到目前为止,我发现它是一本很棒的书。但有一点他告诉我们要写:

// in class Money:
Expression plus(Money addend) {
    return new Money(amount + addend.amount, currency);
}

除非我们声明,否则不会构建:

class Money implements Expression {...

这对我来说真的没有意义。作者创建 Expression 作为 Sum 的接口,而 MoneySum 没有任何共同之处。后来他为两个 classes 添加了共同的方法 reduce(),但仅减少了 Money returns this.

使 Money 实现 Expression 只是从 plus() 方法中删除错误的最省力的途径,但它用不必要的信息填充代码(它必须由于这个决定而实施 reduce())并增加熵。

我还没有考虑太多,但是做这样的事情不是更干净吗?

class Money {        
    Money plus(Money addend) {
        return new Money(amount + addend.amount, currency).reduce();
    }
}
// edited this, it previously returned Expression

编辑: 在下一章中,作者在另一个 class(名为 Bank)中实现了一个 reduce() 方法,该方法在货币之间转换 Money。我仍然觉得这是一个奇怪的解决方案,SumExpression 名称暗示我们应该为这个任务使用一个转换表达式 class。作者可能打算做的是使用递归来添加不同货币的钱。无论哪种方式,在我看来他都做了一些超前的计划,这似乎与书中介绍的 TDD 不兼容。

关于未雨绸缪

TDD 并不禁止提前计划。这个过程是关于获得对你的计划的快速反馈,而不是浪费数天(或数周)来制定精心设计的计划,只是为了看到它们 'not survive contact with reality'(用 Helmuth von Moltke 的话说)。提前考虑就好了。

不过,Kent Beck 在第 17 章中透露这不是他的第一个牛仔竞技表演:

"I have programmed money in production at least three times that I can think of. I have used it as an example in print another half-dozen times. I have programmed it live on stage [...] another fifteen times. I coded another three or four times preparing for writing [...] Then, while I was writing this, I thought of using expression as a metaphor and the design went in a completely different direction than before."

所以,如果您认为他在作弊:是的,他是。不过,他对此持开放态度。我认为动机是提出一个令人信服的例子。他还写道,这部分是基于对该书的早期评论。

在API

这并不能解释为什么代码看起来像这样,但这是有原因的。这实际上是一个不错的 API.

为什么你不能写类似 return new Expression(amount + addend.amount, currency).reduce() 的东西?

你不能,因为 reduce 方法不是无效的。它需要争论。您必须同时提供银行(持有货币兑换率)和目标货币。

记住代码解决的问题。人们总是弄错这个,我认为 Kent Beck(无意中)通过命名示例 Money.

加剧了混乱

问题不在于对金钱建模,而是对不同货币的投资投资组合建模。如果您有 25.000 美元和 10.000 瑞士法郎的投资组合,将其简化为单一货币会隐藏重要细节。通过多种货币的投资组合,您可以分散风险。投资组合所有者将希望看到其投资组合的不止一种视图。有时,他们希望看到按货币分组的投资组合,而在其他时候,他们希望看到 'the current total worth' 的投资组合以单一货币显示。

书中的API两种观点都可以。

底层 'metaphor' 被称为 表达式 的原因是 API 只是一个专门的表达式树。不过,结果相当不错,因为它是合法的。限于书中介绍的子类型,it informally gives rise to a monoid.