開發中對象命名的一點思考
引言
在我所見過的項目中,大多數團隊都傾向于“功能堆砌式”開發:需求來了就加邏輯或函數,卻很少有人愿意花時間在設計上,尤其是在對象命名花費時間。這看似“快速實現需求”的方式,通常會對代碼的可讀性產生壞的影響,進而影響可維護性。
一個好的對象命名并非只是讓代碼表面看起來整潔;它背后關系到人類和 AI 對系統的認知方式,也會在后續維護和迭代中形塑程序員以及 AI 工具的行為。換句話說,合適的命名不但決定了當前代碼的優雅程度,也會潛移默化地影響未來對代碼進行修改、擴展和重構時的思維路徑與決策過程。
下面,我們將通過幾個示例,探討如何通過合理的命名讓對象真正體現業務含義與自主決策能力,而不是簡單地扮演一個“被動執行者”。
一、避免以er或or結尾的對象命名
想象你走進一家餐廳。你會如何點餐?是要一份宮保雞丁,還是告訴廚師:“你先放油,然后大火爆炒,然后再加調料”?如果你選擇后者,那么對應到程序設計中,大概就是下面的寫法:
class FoodMaker {
public Dish Cook(List<Step> cookingSteps) {
foreach(var step in cookingSteps) {
ExecuteStep(step);
}
return new Dish();
}
}
// 客戶端代碼
var maker = new FoodMaker();
var steps = new List<Step> {
new Step("放油"),
new Step("大火爆炒"),
new Step("加調料")
};
var dish = maker.Cook(steps);
FoodMaker ,它只是一個“做飯的人”或“執行器”,缺乏更多的“主觀能動性”。這不僅增加了使用者在思維層面的負擔,也顯得對專業廚師的經驗和技能不夠尊重。
相比之下,更貼近現實的方式是直接告訴對方“我需要一份宮保雞丁”,廚師會根據自身經驗和對食材的理解來完成這道菜。例如:
Chef {
public Dish PrepareKungPaoChicken() {
// 廚師知道如何準備這道菜
return new KungPaoChicken();
}
}
// 客戶端代碼
var chef = new Chef();
var dish = chef.PrepareKungPaoChicken();
這樣,Chef 完整體現了專業性與自主性:
-
角色名稱直接讓人聯想到一個可自主決策、擁有專業技能的人,而非簡單的“烹飪器”。
-
客戶端只需表達“想要什么菜品”,而不必詳述所有步驟。
-
廚師可以根據具體的食材和場景調整做菜細節,為業務帶來更多靈活性。
值得注意的是,很多以 “-er” 或 “-or” 結尾的對象(如 Manager、Processor、Controller、Validator 等)常常會呈現出類似的“過程化”傾向:它們更多體現的是過程集合而非業務主體。當我們把命名改為更能傳達專業身份或業務角色的名詞時,往往會看到對象的“自我意識”和“主觀能動性”隨之提升,從而讓整個系統的抽象層次更高、可維護性更好。
二、“Service”“Helper”“Utility”等后綴,更容易出現“上帝類”
在 AI 輔助編程工具的普及下,命名的清晰度在大型項目中顯得尤為重要。模糊或過于抽象的名字不僅會增加團隊成員、甚至讓3個月后的你自己的認知負擔,也會讓 AI 在大量上下文中難以理解該對象的真實意圖,甚至產生誤導性補全。我們先來看一個不恰當的示例:
錯誤示例:RestaurantService 集合了一切瑣事
public class RestaurantService {
// 名稱看似管理餐廳的一切,卻混合了做飯、送餐和財務等完全不同的功能
// 烹飪某道菜
public void cookDish(String dishName) {
}
// 將菜品送到指定地址
public void deliverFood(String address) {
}
// 安排廚師、服務員等員工的工作排班
public void scheduleStaff(String staffName, String shift) {
}
// 處理餐廳每天或每月的財務結算
public void handleBilling() {
}
}
問題:
-
過于寬泛、抽象的類名:RestaurantService 似乎負責所有與餐廳相關的功能,從做菜到送餐再到財務結算,遠遠超出了單一職責的范圍。
-
對 AI 的誤導:當 AI 工具在大規模代碼庫中搜索或補全時,見到“RestaurantService”可能以為這里面能找到任何與餐廳運營相關的邏輯,補全時也可能把更多不相干的功能(例如“采購食材”、“營銷活動”等)一股腦塞進來,很容易導致上帝類。
-
難以維護與擴展:假如將來要更改配送方式或財務記賬邏輯,你會發現所有功能都耦合在同一個類里,一次改動極有可能波及整個系統。
更合理的設計:按專業分工拆分類
要讓代碼更易讀、更具可維護性,也讓 AI 分析更準確,我們可以將“餐廳運營”按照現實場景拆分成多個專門對象,讓每個類名更能“自證其職”:
// 專注做菜邏輯
public class Kitchen {
public void cookDish(String dishName) {
// 專業處理做菜流程
}
}
// 專注外賣配送
public class Delivery {
public void deliverFood(String address) {
// 專業處理送餐流程
}
}
// 專注人員排班
public class StaffScheduling {
public void schedule(String staffName, String shift) {
// 專業處理員工排班
}
}
// 專注財務結算
public class Billing {
public void settleAccounts() {
// 專門處理賬務結算
}
}
好處:
-
職責明確:Kitchen 只做烹飪,Delivery 只管外賣,StaffScheduling 只負責排班,Billing 用于結算財務。每個對象都有清晰的專業領域。
-
易于理解:無論是人還是 AI,看到類名便能迅速推斷其功能,降低誤解。
-
便于擴展:將來需要為“配送”加入自動調度,或為“做菜”加入菜單推薦邏輯,也可以在對應的類中單獨迭代,而不會影響其他模塊。
-
匹配現實場景:現實中,餐廳的后廚、配送員、人事、財務等各司其職,軟件設計中也應遵循類似原則。
三、對象命名與對象“智能”屬性:當環境變化時仍能自適應
現實生活中,若宮保雞丁的必需食材(例如花生)突然缺貨,真正的專業廚師會主動尋找替代食材,而不會要求顧客重新“下指令”或“換個點餐方式”。同理,在軟件中,一個設計得足夠“智能”的對象,也應該能在外部條件或業務需求變化時,自行調整內部邏輯,而不影響調用者的使用方式。
示例:面相過程的烹飪
public class CookingProcess {
public Dish cook(String dishName) {
// 無論食材是否缺貨,都執行固定步驟
// ...
return new Dish(dishName); // 返回做好的菜
}
}
局限:
-
一旦食材缺貨,需要調用方自己判斷是否可做這道菜,或修改烹飪流程。
-
每次需求變化,都得改動 cook 方法或調用代碼,無法實現真正的“自適應”。
改進示例:廚師是專業人士,能適配環境變化
下面的 Chef 內部自行決定花生是否可用,如果缺貨就用其他食材替代。這樣,即使后續有更多類似變化(換新調料、臨時供應商等),也能集中在 Chef 內部調整,無需改動客戶端調用代碼。
public class Chef {
// 模擬花生庫存狀態,可來自數據庫或配置文件
private boolean peanutsInStock = false;
public Dish prepareDish(String dishName) {
if ("宮保雞丁".equals(dishName)) {
// 如果花生缺貨,就用其他干果替代
if (!peanutsInStock) {
// ...在內部改用腰果或其他替代食材
}
// ...否則正常使用花生
}
// 其余烹飪邏輯
return new Dish(dishName);
}
}
好處:
-
內聚性強:所有判斷和替代邏輯都放在 Chef 內部,外界無需關心具體做法。
-
客戶端調用不變:無論花生庫存狀態如何變化,調用者依舊只需“一句命令”點餐,即可得到結果。
-
可擴展:將來若再遇到更多類似場景(例如某調料臨時售罄),只需修改 Chef,不會影響已有的調用代碼。
-
客戶端調用示例:環境/需求變化,不影響客戶端調用
public class Main {
public static void main(String[] args) {
Chef chef = new Chef();
// 客戶端只需告訴廚師要做“宮保雞丁”
Dish dish = chef.prepareDish("宮保雞丁");
// 即使花生缺貨,Chef 會自動使用其他食材,無需調用方改動
}
}
無論花生庫存如何,客戶端調用方式始終一致:一個智能的 Chef 能在內部完成相應的“自適應”處理。
小結:命名即設計,把對象當做有生命的實體并能夠自主決策行為
對象的命名,許多人往往只把它當作“好看”或“順口”的問題,卻忽視了它所暗含的業務理解深度與系統思維。當我們刻意避開 “-er” 結尾或“Service”、“utility”后綴等含糊標簽,并讓對象名真實反映其專業角色與業務職責時,能夠有下述好處:
-
減少誤解
新成員或 AI 工具都能迅速理解類的意圖,防止在補全或分析時走偏。 -
提升內聚
各對象的邏輯邊界更加清晰,改變一處功能不必連帶修改全局。 -
易于擴展
每個對象如同靈活的模塊,可獨立維護、替換或升級,而不影響整體架構。 -
貼近業務
與產品或業務團隊在概念層面保持一致,溝通效率提升,也減少了架構設計與業務需求間的鴻溝。
在軟件工程中,命名的重要性通常被忽視,但命名本身潛移默化影響我們的編碼時的思維。只有當我們真正將對象視為擁有“尊嚴”與“自主決策能力”的實體時,才能更容易構建出一個高內聚、易擴展、符合業務本質的系統。
浙公網安備 33010602011771號