这是我经常遇到的一个问题:假设有一个具有Product类的网上商店项目。我想添加一个功能,允许用户对产品发表评论。所以我有一个Review类,它引用一个产品。现在,我需要一种列出所有产品评论的方法。有两种可能性:
(一种)
public class Product {
...
public Collection<Review> getReviews() {...}
}
(B)
public class Review {
...
static public Collection<Review> forProduct( Product product ) {...}
}
通过查看代码,我将选择(A):它不是静态的,并且不需要参数。但是,我认为(A)违反了单一责任原则(SRP)和开放式封闭原则(OCP),而(B)没有违反:
(SRP)当我想更改收集产品评论的方式时,我必须更改产品类。但是更改产品类的原因应该只有一个。那当然不是评论。如果我在产品中打包了与产品有关的所有功能,它将很快崩溃。
(OCP)我必须更改Product类以使用此功能对其进行扩展。我认为这违反了原则的“为变革而封闭”部分。在我收到客户的要求以实施评论之前,我认为产品已完成,然后“关闭”。
更重要的是:遵循SOLID原则,还是拥有更简单的界面?
还是我在这里做错了什么?
结果
哇,谢谢您的所有精彩回答!很难选择一个作为官方答案。
让我总结一下答案中的主要论点:
- 赞成(A):OCP不是法律,代码的可读性也很重要。
- 亲(A):实体关系应该是可导航的。两个类都可能知道这种关系。
- pro(A)+(B):同时执行并将(A)中的任务委派给(B),这样就不太可能再次更改产品。
- pro(C):将finder方法放在非静态的第三类(服务)中。
- 反对(B):阻止测试中的嘲笑。
我的大学在工作中还提供了一些其他功能:
- 亲(B):我们的ORM框架可以自动生成(B)的代码。
- 赞成(A):由于我们ORM框架的技术原因,在某些情况下,有必要独立于发现者去向而更改“封闭”实体。因此,无论如何,我将始终无法坚持使用SOLID。
- 对比(C):大惊小怪;-)
结论
我在当前项目中同时使用(A)+(B)和委派。但是,在面向服务的环境中,我将选择(C)。
Assert(5 = Math.Abs(-5));
Abs()
不是问题,测试依赖它的东西是问题。您没有接缝可用于隔离依赖的代码下测试(CUT)以使用模拟。这意味着您不能将其作为原子单元进行测试,并且所有测试都将成为测试单元逻辑的集成测试。测试失败可能发生在CUT或Abs()
(或其相关代码)中,并且消除了单元测试的诊断优势。