我用Java开发了很多代码,并尝试使用Groovy和Haskell, 这让我接触到了Scala。
我在Scala的函数式方面感觉比较熟练,但是对象导向设计上感觉有些不稳定,因为它与Java有所不同,特别是由于traits/mix-ins的存在。
我的目标是编写尽可能易于测试的代码,在我的Java开发中,这通常转化为关注:
- 在可能的情况下保持不可变性
- 尽量使用构造函数来注入状态
- 始终使用组合而不是继承(受此SO帖子的影响,很可能是一种过度反应)
现在我正在努力适应这个新的Scala领域,但我很难弄清楚我应该采用什么方法,特别是是否应该开始为某些目的使用继承。
Programming Scala(Wampler and Payne; O'Reilly, 2nd Edition)中有一个考虑因素的部分(“良好的面向对象设计:一次偏离”),我已经阅读了一些SO的帖子,但我没有看到显式提到测试性的设计考虑。该书提供了有关使用继承的建议:
- 一个抽象的基类或trait被具体类(包括case classes)子类化一级。
- 除两种情况外,不会对具体类进行子类化:
- 混合其他在traits中定义的行为的类(...)
- 仅用于促进自动化单元测试的测试版本。
- 当子类化似乎是正确的方法时,请考虑将行为划分为traits并混入这些traits。
- 永远不要将逻辑状态分裂在父-子类型边界上。
因此,本质上我有两个问题:
有常见情况需要使用继承吗?即使考虑到可测试性,是使用继承更好的选择吗?
混入是否提供了增强代码可测试性的良好方式?