论坛首页 Java企业应用论坛

讨论一下CQS (命令-查询 分离)原则

浏览 2297 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-12-24   最后修改:2009-01-09
OO
看Craig Larman的书,
里面提到的这个原则.

请看下面两个函数:

// style #1; used in the official solution
public void roll()
{
   faceValue = // random num generation
}


public int getFaceValue()
{
   return faceValue;
}


为什么不是将两个方法合并, 使roll()方法返回新的faceValue呢? 如下所示:

// style #2; why is this poor?
public int roll()
{
   faceValue = // random num generation
   return faceValue;
}


你可以发现大量使用风格2的代码的例子, 但这种方法并不合适, 因为它违反了命令-查询分离原则(Command-Query Separation Principle). CQS是针对方法的经典OO设计原则. 该原则指出, 任何方法都可能是如下情况之一:
1. 执行动作(更新,调整...)的命令方法, 这种方法通常具有改变对象状态等副作用, 并且是void的.
2. 向调用者返回数据的查询, 这种方法没有副作用, 不会永久性的改变任何对象的状态.

关键是, 一个方法不应该同时属于以上两种类型.

CQS被公认为计算机科学理论中具有价值的原则. 因为遵守该原则, 你能够更容易的推测出程序的状态, 在查询状态时不会同时发生变更. 这样使得设计更便于理解和预见. 例如, 如果一致遵循CQS, 那么你还知道查询或者getter方法不会作出任何更改, 而命令也不会有任何返回. 这是个简单的模式. 这通常是要严格遵循的, 因为如果突然采用其它方法, 将会产生令人不快的意外, 从而违反了OOD中的 最小意外(Least Surprise) 原则.
<from Aply UML & patterns>

以上是原文, 昨晚上看书时才看到的, 回想起来以前真的好多次违反这个原则,
但不确定这个原则是否所有情况都适用,
大家怎么看CQS的, 我本来想找出例外情况的, 但一时还没想出例子来, 一起讨论下吧.

--------------
好像清楚一点了, CQS更像准则, 而不是"原则",
会有例外情况出现的, 比如jdk中:

// FileInputStream 
public native int read() throws IOException;

// Vector
public synchronized boolean add(E e)

// HashMap
public V put(K key, V value)


看来学习OOD理论不能太死板,呵呵
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics