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

308 Views Asked by At

These two snippets are from the JDK source code:

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;
}

Command-query separation (CQS) states that every method should either be a command that performs an action or a query that returns data to the caller, but not both. Do these two snippets from the JDK source code violate the CQS principle?

2

There are 2 best solutions below

0
On BEST ANSWER

Yes, the code you've quoted is an explicit violation of Command-Query Separation as defined by Bertrand Meyer, who coined the term in 1988 in Object Oriented Software Construction. CQS forbids any routine that has side effects from returning a value - even a status code to indicate success or failure. The only CQS-compliant way to communicate such status codes would be to have the "Command" set the status code somewhere where a subsequent "Query" can retrieve it.

In section 4.7 of his book, Meyer distinguishes between "procedures", which may not return a result, and "functions", which do return a result:

“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.)

He goes on to define the Command-Query Separation principle as follows in section 23.1:

Functions should not produce abstract side effects.

This is explicit. It is not a vague suggestion that your routines should either "do something" or "retrieve some data" but not both. It is an explicit requirement that routines either have no side effects or no return value.

It should not be surprising that the JDK violates this principle, because CQS is not widely accepted. Meyer himself remarks in his book:

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

I had not been born when he wrote his book, but his remark remains true three decades later. Whether the blame for this properly lies with CQS being impractical or with programmers' dominant practices being impure is a question I leave to the reader.

1
On

both add and remove are methods changing the state, not queries. They return a meaningful result. I don't think that this is a violation of the CQS. The question is what value would CQS at all bring to operations like these.