軟件開發的簡單設計觀
作者 | 袁慎建
保持簡單
簡單是一個成年人司空見慣的詞,然而,大部分成年人卻覺得純真的孩子才是簡單的。
很多時候,人們習慣把“簡單”跟“容易”理解成一個意思。簡單和復雜多用于形容事物或人的屬性或狀態,容易和困難一般形容達到某種目標的過程。生活中經常聽到這樣的感慨:「人活簡單點真難啊!」、「系統一不小心就搞復雜了」。這些感慨背后流露出一種心愿 -- 保持簡單。
對于人來說,保持簡單可能意味著人情世故的簡單、工作關系的簡單、心態的簡單。對于軟件系統來說,則意味著系統設計的簡單、部署運維的簡單等等。
三重境
看山是山,看水是水;看山不是山,看水不是水;看山是山,看水是水。
保持簡單的確不是一件容易的事情。禪宗提出的人生三境界中也詮釋了這個理:人從簡單開始,以復雜貫穿了大部分甚至整個人生,最后返璞歸真。
對應到一個需求簡單的軟件系統中,系統的設計一開始處于簡單的狀態。然而軟件開發的核心問題是復雜多變的業務需求,隨著時間的推移,軟件系統可能呈現出以下三個狀態:
正常情況下,沒有人希望系統處于第三個狀態,而是希望從第二個狀態回到第一個狀態。映射到禪宗的人生三境界,系統的理想三境界是:
- 清晰 -- 單一化
- 復雜 -- 層級化
- 清晰 -- 模塊化
在面臨復雜多變的業務需求,如何設計一個恰好簡單夠用的系統?如何保持系統的高響應力?程序員們一直都沒有停止對最佳實踐的探索,始終為這些目標奮斗。軟件開發的所有問題最終都能歸結到人身上,那么驅動程序員不斷改進的力量是什么?
我心中有一個答案:對簡單設計、高響應力價值的認可,對簡單設計價值觀的深層內化。
核心觀
價值觀往往給人一種感覺:看著這些高大上的詞匯,缺點什么,卻總又說不上來。比如極限編程(XP)的價值觀:溝通、簡單、反饋、勇氣、尊重。再比如 Scrum 的價值觀:專注、開放、承諾、勇氣、尊重。尤其是剛開始接觸這些知識體系的新人,每個詞都能看懂,只是不知道如何用它們去指導 XP 和 Scrum。
在 Thoughtworks 工作這么多年,我親自實踐過 XP 和 Scrum,也在很多場合傳授過它們,再回過頭來看,我深刻體會到一點——XP 和 Scrum 的那些實踐跟它們的價值觀都非常吻合。我能夠在日常開發以及培訓和練習中去落地簡單設計,這背后驅使我不斷探索的是已內化于心的觀念:
專注
在 Scrum 中,專注強調的是所有人都專注于 Sprint 目標,團隊同為一個目標努力。對于簡單設計,要專注在哪里呢?我結合自身經歷的幾個典型的場景來看:
- 一上來匆匆忙忙編寫業務代碼,沒有Tasking,沒有測試,沒有設計,業務Scope逐步偏離或擴大
- 在編碼階段,聽到聲音:“你這個設計太土氣了,都沒用設計模式”,于是琢磨著怎么去套設計模式
- 在系統架構設計階段,有人說:“什么年代了,你還不拆出幾個微服務”,于是嘗試拍腦袋拆出一個分布式單體
上述三個場景,究其根本,是沒能很好地專注于自己要實現的真實業務價值,要么缺乏思考和設計,要么受外界影響,舍本琢末。你可能會質問:不應該多做點設計來兼容后期可能出現的情況嗎?為未來做設計,難免會摻入不合時宜的猜測,不僅增加系統當前的復雜度,還可能浪費成本。
我覺得要始終保持對當下真實業務價值的專注,專注理解業務本質,專注于剛好夠用的設計,時刻讓系統保持簡單,盡可能跟業務模型保持匹配和同步。
克制
克制力是一項非常重要且需要長期培養的能力。由于受到太多外界的干擾而難以定靜,程序員經常會因為沉浸在自己的世界里,可能出現樂觀估算,還可能經常過度設計。
而實際上,大部分樂觀的估算會讓團隊交付面臨更多風險,大部分健壯性設計會讓系統難以理解和修改。我想起來自己曾經面試過的一個候選人,一個很簡單的業務需求,硬生生地套用了5種設計模式,嘆為觀止。
在日常交付項目和工作坊中,我會較為留意開發人員嘴里發出的 “我覺得”、“假如”、“萬一”、“以后”等用語,這些用語背后所隱藏的溢念(溢出的想法),很可能促使該開發人員交付一個不滿足需求的軟件,或者一個難以維護的系統。
我覺得程序員克制自己一個有效的方式是培養業務視角,站在用戶使用系統的視角嘗試深刻理解業務,通過將業務需求進一步拆解成小顆粒度的任務來讓自己保持聚焦。Think Big(深刻理解業務問題并拆分),Start Small(每次只聚焦在某一個小的任務),Move Fast(快速完成一個個小的任務并獲得反饋)。
潔癖
我經常在 Code Review 中被同事開玩笑說有代碼潔癖,比如對命名太較真了。一開始我會有所妥協,畢竟軟件開發是一個團隊來完成的,如果因為某個人的潔癖而讓其他人不舒適,可能不利于團隊協作。可是時間后來告訴我,那些身披“不認真”或者“不嚴格”標簽的小魔頭會在后面出來制造各種噪音,比如命名看不懂、結構不一致、架構混亂臃腫等等。
做程序員這幾年,潔癖潛移默化影響著我的編碼和設計風格,小到變量命名、代碼注釋、文檔管理,大到系統架構,我都會時刻保持警惕,盡其所能去消除噪音污染。在沒有其他不可抗拒的因素前提下,我都會盡力嘗試讓團隊接納自己對代碼潔癖的追求。
潔癖更側重于團隊個體成員,對于個體,可以通過不斷提升自己的整潔代碼認知來強化它,并嘗試在實踐中去運用它們。而對于團隊,我想到一條指導原則:任何有助于提升系統質量的潔癖都不應該被忽視,團隊應該盡力接納并落實。
懶惰
恰當的“懶惰”是一個優秀的程序員必備的特質,因為 Ta 總是勤于思考如何才能少做重復的事情。
懶惰聽起來是一個負面的詞,中國幾千年的文化價值觀在告訴每一個人要做勤奮努力的人。在軟件開發領域,我認為恰當的懶惰是解放程序員生產力、保持系統簡單的助推劑,比如:
- 需求或設計變更,懶得改太多代碼。怎么辦?消除代碼重復,隔離和封裝變化,分離關注點
- 手工集成和測試,懶得重復做。怎么辦?增加自動化測試并做好CI/CD
- 用戶鑒權分散在各個服務中,懶得修改所有的服務。怎么辦?引入API Gateway
- 新人上項目,搭建環境反復找我,懶得重復講。怎么辦?編寫自動化腳本和文檔指南
如果每次面對相同的問題,不得不花精力去處理,在這種毫無挑戰的重復性工作中,人通常很容易犯錯,所以,當手懶得去做這些事情,懶惰會驅使大腦去思考一種更加高效的方式,比如隔離變化將其封裝,引入自動化,從而取代一遍遍重復的操作,并且大腦還會思考如何運用 KISS(Keep it Simple and Stupid),Yagni,如無必要,勿增實體。
有一種看似很”勤快”的CCCV(CMD + C | CMD + V)編碼行為,這些行為背后跟我提倡的懶惰大相徑庭。CCCV行為是思想上的懶惰,在這種思維的指導下,雙手會樂此不疲去重復做很多重復的事情,CCCV當規避之。
勤于思考,惰于盲行,做一個具備恰當惰性的程序員是一種快樂。
需要勇氣
在 XP 和 Scrum 鼓勵人們要有勇氣去做正確的事情、處理棘手的問題、做出承諾、堅持原則、拒絕損害工作的行為、暴露自己的不足并尋求幫助、提供有建設性的意見等。
要保持簡單,這些勇氣也是不可或缺的。同時,我提倡程序員培養 保持專注、克制溢念、養成代碼潔癖、滋養恰當的懶惰的勇氣。