命令查詢分離
2005 年 12 月 5 日
「命令查詢分離」一詞是由伯特蘭·邁爾在他的著作「物件導向軟體建構」中創造的,這本書是物件導向早期最具影響力的 OO 書籍之一。(第一版是最具影響力的版本,第二版也不錯,但你可能需要花幾個月在健身房才能舉起它。)
基本概念是,我們應該將物件的方法分成兩個截然不同的類別
- 查詢:傳回結果,且不變更系統的可觀察狀態(沒有副作用)。
- 命令:變更系統狀態,但不傳回值。
由於「命令」一詞在其他脈絡中廣泛使用,我比較喜歡稱它們為「修改器」,你也可以看到「變異器」一詞。
這個原則中真正有價值的概念是,如果你能清楚地將會變更狀態的方法與不會變更狀態的方法分開,將會非常方便。這是因為你可以在許多情況下更放心地使用查詢,將它們引入任何地方,變更它們的順序。你必須更小心地使用修改器。
這個原則中的概念是,傳回類型是區分的關鍵。這是一個很好的慣例,因為它在大部分時間都能順利運作。考慮用於遍歷集合的 Java 慣用語法:next
方法會提供集合中的下一個項目,並推進迭代器。我個人比較喜歡有獨立的 advance
和 current
方法的風格。
邁爾喜歡絕對地使用命令查詢分離,但也有例外。彈出堆疊是一個會修改狀態的查詢範例。邁爾正確地表示你可以避免使用這個方法,但它是一個有用的慣用語法。因此,我比較喜歡在可以的時候遵循這個原則,但我準備打破它來執行彈出操作。
如果程式語言本身支援這個概念會很好。我可以想像一種語言可以偵測會變更狀態的方法,或至少允許程式設計師標記它們。語言無法自動偵測它們的原因之一是,不變更狀態的規則實際上只適用於系統的 可觀察狀態。使用程式設計師標記似乎比較合理,但很少見。我真正遇到的唯一情況是 C++ 中的 const 修改器。由於我已經很多年沒有使用 C++ 了,因此我難以評估它在實務上的有用性。我的感覺是,優秀的 C++ 程式設計師會大量使用 const,而且喜歡它。