JDK 源代码是否违反命令查询分离 (CQS)?

Does the JDK source code violate command-query separation (CQS)?

这两个片段来自 JDK 源代码:

public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false; }

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // increments modCount
    elementData[size++] = e;
    return true;
}

命令-查询分离 (CQS) 规定每个方法要么是执行操作的命令,要么是 returns 向调用者发送数据的查询,但不能同时是两者。 JDK 源代码中的这两个片段是否违反了 CQS 原则?

addremove 都是改变状态的方法,而不是查询。他们 return 一个有意义的结果。我不认为这违反了 CQS。问题是 CQS 会给这些操作带来什么价值。

是的,您引用的代码明显违反了 Bertrand Meyer 定义的命令-查询分离,他于 1988 年在 Object Oriented Software Construction 中创造了这个术语。 CQS 禁止任何因 returning 值而产生副作用的例程 - 甚至是指示成功或失败的状态代码。传达此类状态代码的唯一符合 CQS 的方式是让 "Command" 将状态代码设置在后续 "Query" 可以检索它的地方。

在他的书的第 4.7 节中,Meyer 区分了可能不是 return 结果的 "procedures" 和 return 结果的 "functions":

“Procedure” will be used in the sense of a routine which does not return a result, so that we have two disjoint categories of routine: procedures and functions. (In discussions of the C language the term “function” itself is sometimes used for the general notion of routine, but here it will always denote a routine that returns a result.)

他在第 23.1 节中继续定义命令-查询分离原则如下:

Functions should not produce abstract side effects.

这是明确的。这并不是一个模糊的建议,您的例程应该 "do something" 或 "retrieve some data" 而不是两者。明确要求例程要么没有副作用,要么没有 return 值。

JDK 违反这一原则不足为奇,因为 CQS 并未被广泛接受。迈耶本人在他的书中评论道:

As you may have realized, this style is very different from the dominant practices of today...

他写这本书的时候我还没有出生,但他的话在三十年后仍然是正确的。这是否应该归咎于 CQS 不切实际或程序员的主导做法不纯是我留给 reader.

的问题