Logo
Section 1 / 5

业务逻辑代码必须清晰地展现其行为

学习如何让业务逻辑揭示我们的 Rails 应用的行为。

导入

业务逻辑代码必须清晰地展现其行为

学习如何让业务逻辑揭示我们的 Rails 应用的行为。

概述

在课程开始时,我们强调了可持续 Rails 架构的一个核心原则:不要将业务逻辑放在 Active Record 中。这为我们揭示了如何组织包含业务逻辑的类的具体细节,而这正是本章要讨论的内容。

如前所述,关键是要将我们的业务逻辑与 Active Record 以及其他由 Rails 管理的类隔离开来。业务逻辑的具体结构并不那么重要,但也不是无关紧要。

我们可以这样思考:业务逻辑类的 API 就像一个“接口缝合点”。这个缝合点的一侧是 Rails 管理的代码,例如控制器、后台任务或 Rake 任务;另一侧则是我们领域特定的逻辑和某个具体用例的实现,这些逻辑可能使用 Rails,但不受 Rails 的管理(见下图)。本章的重点就是如何定义这个接口缝合点。

...
接口缝合点概览

为了理解这一点,我们需要首先明确:在实现业务逻辑的代码中,哪些方面是重要的,哪些并不那么重要。然后我们将讨论这个接口缝合点本身,它包含三个部分:

  • 一个类
  • 一个方法
  • 一个返回值

我们推荐的策略是:创建一个无状态的类,以具体的流程或用例命名,该类只实现一个方法,接收执行逻辑所需的参数,并可选地返回一个结构丰富、描述操作结果的对象。这种设计为未来应对复杂性提供了最易维护的基础,同时所需的设计决策最少,能快速实现可用的方案。

接下来,我们先讨论实现业务逻辑代码时应关注的关键点:其行为必须尽可能清晰透明。

业务逻辑代码

实现业务逻辑的代码是我们应用中最关键的部分,因为它直接决定了应用所要交付的结果。同时,这也是最不稳定的部分,因为它是迭代开发的,必须能够快速响应变化。因此,除了确保功能正常外,这段代码还必须易于理解——因为只有理解了代码,才能进行修改。

这意味着代码必须是“行为可见”的(而非“意图可见”)。它应该尽可能容易让人看懂实际做了什么。切记这一点,警惕为其他目的而牺牲代码清晰度的改动。

特别需要注意的是,以下几点并不重要:

  • 代码是否面向对象。
  • 是否使用函数式编程。
  • 代码是否可复用。
  • 实现是否优雅或整洁。
  • 是否满足某些代码指标。
  • 是否使用了设计模式。
  • 是否遵循 Ruby 或 Rails 的惯用写法。

我们特意强调这一点,是因为我们反复看到开发者为了上述某一项或多项目标而牺牲了代码的行为清晰度。将代码重构得更“面向对象”是一种表面化的做法。尤其是所谓的 SOLID 原则,如果被广泛应用于整个代码库,反而可能造成严重破坏。我们曾写过一些极其精巧、紧凑的面向对象代码,但后来发现它们最难理解和修改。

这并不是说上述所有内容都没有价值。设计模式、面向对象编程、Ruby 惯用语法确实有其作用,但它们应当服务于更大的目标:写出易于修改的代码。

我们实践中最有效、也看到他人成功采用的方法是:为每一段业务逻辑创建一个单一的类和一个方法,作为该逻辑的入口。这个类、这个方法,以及方法返回的对象,共同构成了一个接口缝合点,分隔了 Rails 管理的通用世界与我们自己的领域世界。该类内部的结构可以自由设计,不受限制。

入门

显式命名的类与显式命名的方法