面向对象设计实践指南-Ruby语言描述

设计是保留可变性的艺术,而非达到完美性的行为。

编写出的代码应该具有如下几个特点:

  • 透明性(Transportation): 在所更改的代码,以及在远处依赖于它的代码里,更改所产生的后果应该显而易见。
  • 合理性(Reasonable): 任何更改所产生的成本都应该于更改所要带来的效益成正比。
  • 可用性(Usable): 现有代码在新的环境和意想不到的环境里都能使用。
  • 典范性(Exemplary): 代码本身应该鼓励那些为了延续这些特点面对它进行的更改。

这四个特点简写为TRUE。

选择依赖方向:

  • 有些类比其他类更容易发生需求变化。
  • 具体类比抽象类更容易发生变化。
  • 更改拥有许多依赖关系的类会造成广泛的影响。

从基于消息的角度比从基于类的角度更能产生出灵活的应用程序。将那个基本设计问题从“我知道我需要这个类,那该怎么办?”转变为“我需要发送这条消息,谁该响应它呢?”
你发送消息不是因为你有对象,你有了对象是因为你要发送消息。

请询问“要什么”,别告知“如何做”。
“我知道我需要什么,并且我知道你是怎么做的。” >> “我知道我需要什么,并且我知道你会做什么。” >> “我知道你需要什么,并且我相信你回做好你的本职工作。”
这种模式可以不用修改调用者,便能达到扩展它的目的。
PS: 感觉这个和做管理是同样的道理,面对新手是第一句,面对胜任者是第二句,面对专家则是第三句。

子类是其父类的特殊化。子类应该包含父类的一切内容,外加更多内容。任何期待父类的对象都应该能与子类进行交互,完全不需要知道它实际的类。

有些问题需要在其他不相关的对象之间共享行为。这种公共行为对类来说正交的,它是对象所扮演的角色。这些关系与经典继承要求的子类/父类关系有所不同。许多语言都提供了某种方式,可以一次定义一组命名方法。这些命名方法独立于类,并且可以混入任何对象。在Ruby里,这种混入内容都被称为模块(module)。

继承和模块的差别在于“是一个”还是“像一个”。

抽象父类里的所有代码都应该适用于每一个继承它的类。父类不应该包含只适用于部分(而非全部)子类的代码。这个限制也适用于模块: 在模块里的代码必须能够适用于所有使用它的那些类型。

钩子方法的局限性在于它仅适用于创建浅层结构。为了把自身的钩子和父类的钩子进行组合,子类将被迫改写钩子,并在其内部发送super消息。

  • 将继承用于“是什么”关系
  • 将鸭子类型用于“表现得像什么”关系
  • 将组合用于“有什么”关系

保留未使用的代码比删除之后再恢复它们所花费的成本更高。

测试应该把私有方法隐藏起来,而不应该将它们暴露出来。

  • 这种测试有些冗余
  • 私有方法不稳定
  • 测试私有方法会误导人去使用它们

如果你的对象拥有大量私有方法,以至于你必须对它们进行测试,那么请考虑将这些方法提取为新对象。提取出来的方法可以作为这个新对象的责任核心,并因此构成它的公共接口。


上一篇
网页渲染数学公式 网页渲染数学公式
数学公式一般使用 LaTeX,但是在网页上一般将 LaTeX 渲染成为图片。 在一堆文字中放进几个图片难看又麻烦,稍微找了一下发现一个神器: MathJax 使用它很简单: <script src='https://cdnjs.cl
2014-10-01
下一篇
Web 文件下载和查看 Web 文件下载和查看
Web 文件下载和查看在浏览器中点击一个文件链接,会被浏览器直接打开或者下载。其实浏览器的行为是可以人为控制的,最简单的方法是使用 HTML5 download Attribute。 <!-- will download as "ex
2014-06-11