跳转至

将查询与修改分开

  • 问题


    你有一个返回值但也改变对象内部某些东西的方法吗?

  • 解决方法


    将该方法拆分为两个单独的方法。如您所料,其中一个应该返回值,另一个修改对象。

为什么重构?

这种分解技术实现了命令和查询责任分离。这个原则告诉我们将负责获取数据的代码与更改对象内部某些内容的代码分开。

获取数据的代码称为查询(query)。在对象的可见状态下改变事物的代码被命名为修饰符(modifier)。当查询和修饰符组合在一起时,您无法在不更改数据条件的情况下获取数据。换句话说,您提出问题并可以在收到答案时更改答案。当调用查询的人可能不知道该方法的“副作用”时,这个问题会变得更加严重,这通常会导致运行时错误。

但请记住,只有在修改器改变对象可见状态的情况下,副作用才是危险的。例如,这些可以是可从对象的公共接口访问的字段、数据库中的条目、文件中的条目等。如果一个修饰符只是将一个复杂的操作缓存起来,保存在类的私有字段中,几乎不会产生任何副作用。

如果您有一个不改变程序状态的查询,您可以随意调用它多次,而不必担心由于您调用该方法这一事实而导致结果发生意外变化。

在某些情况下,执行命令后获取数据很方便。例如,当从数据库中删除某些内容时,您想知道删除了多少行。

如何重构?

  1. 创建一个新的查询方法以返回原始方法所做的事情。
  2. 更改原始方法,使其仅返回调用新查询方法的结果。
  3. 用对查询方法的调用替换对原始方法的所有引用。紧接在这一行之前,调用修饰符方法。如果在条件运算符或循环的条件下使用原始方法,这将使您免受副作用。
  4. 去掉原来方法中的返回值代码,现在变成了一个妥妥的修饰方法。