建筑商和机械手
這是在OOP中命名方法的簡單原理,我嘗試在我的代碼中遵循: 操作時是動詞 , 構建時是名詞 。 而已。 兩者之間什么都沒有。 諸如saveFile()或getTitle()不適合使用,必須重命名和重構。 此外,“操作”的方法必須始終返回void ,例如print()或save() 。 讓我解釋。
首先,我必須說這個想法與Bertrand Meyer在他的《面向對象的軟件構造》一書中提出的想法非常相似,他在書中建議我們將一個對象的方法分為兩個截然不同的類別:查詢和命令。
該原理背后的思想是很哲學的。 讓我們從構建器開始,這些構建器應該創建或找到一個對象然后返回它。 假設我有一個書店,請我給我一本書的名字:
interface Bookshelf {Book find(String title); }顯然,它是一個“構建者”(或用邁耶的術語來說是一個“查詢”)。 我要一本書,這本書已經送給我了。 但是,問題出在方法的名稱上。 它被稱為“查找”,這意味著我知道如何處理這本書。 將會發現。
但是,這不是我們應該如何對待對象的方式。 我們決不能告訴他們如何做我們希望他們做的工作。 取而代之的是,我們必須讓他們決定是要找到,構造這本書,還是從內存緩存中取出這本書。 當我們查詢時,我們必須說出我們要尋找什么結果,然后讓對象來決定要如何構造該結果。 此方法更合適的名稱是book() :
interface Bookshelf {Book book(String title); }經驗法則是:建造者始終是名詞。 如果該方法返回某些內容,則必須為名詞。 最好其名稱應說明該方法返回的內容。 如果是一本書,則將其命名為book() 。 如果是文件,請調用方法file()等。以下是一些好的構建器示例:
interface Foo {float speed(Actor actor);Money salary(User user);File database();Date deadline(Project project, User user); }相反,以下是一些名稱不正確的生成器的示例:
interface Foo {float calculateSpeed(Actor actor);Money getSalary(User user);File openDatabase();Date readDeadline(Project project, User user); }在構建者名稱中沒有動詞的位置!
順便說一句,不僅是名字。 由于其名稱不包含動詞,因此構建器不應對封裝的實體進行任何修改。 它只能創建或找到某些東西并將其返回。 就像純函數一樣 ,它一定不能有任何副作用。
接下來,有“操縱者”(或用邁耶的術語來說是“命令”)。 它們為我們做了一些工作,修改了對象封裝的實體。 它們與構建者相反,因為它們實際上是對由對象抽象的世界進行更改。 例如,我們要求Bookshelf向其添加一本新書:
interface Bookshelf {void add(Book book); }該方法將書籍添加到存儲中。 我們不知道存儲將如何精確地修改。 但是我們知道,由于方法的名稱是動詞,因此會進行修改。
另外,操縱器不得返回任何東西。 我們將其視為回應的類型始終是void 。 這主要是為了將代碼的命令性部分與聲明性部分分開。 我們要么接收對象,要么告訴他們該怎么做。 我們絕不能將這些活動混為一談。
這些規則的目的是使代碼更簡單。 如果您遵循它們,并且所有構建器僅返回對象,而機械手僅修改世界,則整個設計將變得更易于理解。 方法將更小,其名稱更短。
當然,通常很難找到這些名稱。 您有時會想從操縱器中返回一些東西,或者讓您的構建器進行一些更改,例如對緩存進行更改。 試著抵制這種誘惑并堅持原則:方法要么是構建器,要么是操縱器,中間沒有東西。 上面的示例相當原始,現實生活中的代碼要復雜得多。 但這就是原理將幫助我們的事情-使代碼更簡單。
我也知道名詞/動詞原則,該原則建議始終將類命名為名詞,而將其方法命名為動詞。 我認為這是一個錯誤的主意,因為它不會將制造商與操作員區分開,并鼓勵我們始終根據命令性指令進行思考。 我相信,即使我們有時不得不從其他對象獲取它們,而不是通過構造函數實例化它們,OOP也必須更多地涉及對象的聲明性組合。 這就是為什么我們在大多數情況下確實需要構建器的原因,并且還必須看到它們與其他方法(操縱器)之間的明顯區別。
翻譯自: https://www.javacodegeeks.com/2018/08/builders-and-manipulators.html
總結
- 上一篇: spring安全_Spring安全–幕后
- 下一篇: 如何从零开始打造自己的电脑桌面如何从零开