天天看點

簡單設計落地三闆斧

如果你認同 簡單設計的價值觀,我相信 解析簡單設計原則 對你來說很容易了解并接受,它不像面向對象設計原則(比如:SOLID)那麼晦澀難懂,它給你指明了一條明朗可通行的道路。即便如此,前進的道路依然不是一帆風順,尤其對于新手來說,怎麼将這些已經很接地氣的原則更高效地落地,進而創造更大的價值,本文我将分享幫助我們落地簡單設計的三闆斧:TDD、重構和整潔代碼。

價值體系

假如讓你去建造一幅巨大的廣告牌,你會怎麼做?從大架構來看,首先要打牢地基,再使用結實支柱做支撐,最後在頂部挂上廣告牌。地基和支柱是幫助完成目标的必備條件。那麼,如何實作簡單設計的核心價值?我們可以以簡單設計價值觀、簡單設計原則做為地基,并通過打造TDD、重構 和 整潔代碼 三大支柱來支撐起簡單設計的 “廣告牌”:

簡單設計落地三闆斧

三大支柱

TDD

作為極限程式設計的一項實踐,測試驅動開發經過被大量的開發者證明是一項具有實用價值的實踐。從廣義上講,TDD不限于開發人員在編碼的過程中先寫測試用例,然後驅動出代碼實作,就連我們拿起一個待實作的使用者故事[1],在腦海中開始構思如何去驗收這個功能,也是一個TDD的過程,隻不過這個T存在于你的大腦中,沒有被可視化出來且不能複用。

本文我所要表達的TDD聚焦在編碼層面中的單元測試。它包含了三層含義:

  1. Test Driven Development
  2. Test Driven Design
  3. Task Driven Development

Test Driven Development

測試驅動開發,它是TDD在操作層面的落地方式,也是最普适的含義。它遵循一個基本流程:寫測試 -> 執行測試(紅) -> 寫實作 —> 執行測試(綠)。在TDD中融入重構步驟之後,它的一個具體詳細的完整流程如圖所示:

簡單設計落地三闆斧

Test Driven Design

編碼如藝術,優秀的程式員即是一名設計師,也是一位藝術家

作為一名用代碼改變世界的程式員,我們應該試圖将自己的設計思想融入到代碼中,讓代碼充滿生氣和靈性,進而遠離機械式的僵屍代碼。在解析簡單設計原則 一文中我談到設計不足和設計過度時所催生三類問題:

  1. 難以修改
  2. 難以測試
  3. 難以閱讀

TDD能讓我們在編寫測試的時候就開始思考即将實作的功能代碼的可測試性。試想如果我們在編寫測試階段就舉步維艱,此時不得不逼着自己去思考如何讓API能夠利于測試。這個過程主要面臨了兩方面的挑戰:

  1. 視角切換。從使用者視角出發,将腦海中的隐性驗收測試落地到代碼層面。
  2. API設計。如何讓API更加職責清晰、内聚,進而更加有利于測試。

這些挑戰對開發人員的設計思維提出了較高的要求,是以也能了解不少新手在起步階段頗為痛苦,以至于他們會覺得TDD降低了開發速度,對它的價值産生了懷疑。

從我個人經驗以及身邊一些大牛身上總結出一個結論:掌握TDD最好的捷徑是刻意練習。是以如果你剛起步,不要氣餒,找一些Kata勤加練習[2]

Task Driven Development

任務驅動開發,強調的是将大任務拆解成小任務。人的大腦在處理足夠簡單的問題的時候(比如

1+2-3+4-5 = ?

),能夠快速給出方案。然而,面對較為複雜的問題的時候(比如

2-1*5*3/2+2-3/2-2/1*5+4-5 = ?

),大腦難免捉會襟見肘,此時就有必要借助一些輔助工具來做到事半功倍。

任務驅動的方式會用到一個思維工具 – Tasking[3]。在練習TDD時,建議你将待完成的任務進行分解,然後将分解後的子任務可視化出來。可視化的好處之一是它可以作為溝通的工具,去收集回報,進而完善自己的思路。任務拆解之後的好處是,待實作的功能更加小而單一,有利于編寫測試。

Tasking同樣需要刻意練習,它對分析性思維提出了一定的挑戰,練習分析性思維的四步法:

  1. 定義問題 - 清楚定義問題
  2. 分解問題 - 将問題進行分解
  3. 關聯問題 - 通過輸入和輸出尋找子問題的關聯關系
  4. 限界問題 - 識别出子問題的邊界,明确假設和結果

關于TDD的示例,歡迎觀看我錄制的視訊[4]。

重構

重構,它是極限程式設計中的一項實踐,Martin Flower在 《重構:改善既有代碼設計》[5] 一書中對重構進行了全面的定義。它提倡我們對代碼最佳實踐充滿敬畏之心,在不改變軟體行為的前提下去修改代碼,不斷改善代碼的設計,提升軟體的響應力。

作為程式員,我們經常在修改代碼,在修改之前,建議你先問自己四個問題:

  1. 軟體已經工作,還需要修改這段代碼? - 軟體可工作,可能有壞味道
  2. 如何識别這段代碼浮現出的壞味道? - 換味道是什麼
  3. 針對壞味道,我們應該怎麼修改? - 怎麼去壞味道
  4. 修改完之後,如何確定功能沒有發生變化? - 軟體可工作,壞味道變少

四個問題環環相扣的,始于目标,終于目标。你若能給出答案,并形成閉環,便實作了重構的核心價值。通常最難回答的是最後一個問題,以至于遲遲不敢下手,導緻軟體逐漸惡化。是以重構提倡重構要在測試的保護下進行,人工測試亦或自動化測試,隻要能給出正确的答案。

重構是一門手藝活,在日常編碼中,你應該始終保持警惕,積極思考上述四個問題,另外輔以大量的刻意練習[5],同時我強烈推薦你以*《重構:改善既有代碼設計》*[6] 這本書作為起點。

結合TDD,重構大有用武之地,測試先行保駕護航,重構演奏,方能唱出悠久的歌聲。然而重構到什麼程度?讓整潔代碼來回答這個問題。

整潔代碼

整潔代碼,從其字面來看是要編寫整潔的代碼,但這個問題仁者見仁、智者見智,很難有一個标準答案。回到我們文章的初衷 – 落地簡單設計,是以整潔的代碼至少是:

  1. 盡量不重複
  2. 盡量揭示意圖
  3. 盡量簡單的

小到變量命名,大到類互動設計,我們應該在意識中不斷強化對以上三點的認知,在實踐中養成良好的編碼習慣。

Robert C在*《代碼整潔之道》[6] 一書中提供了很多案例,另外《編寫可讀代碼的藝術》*[6] 也是一個很好的開始。理論結合實踐,在日常開發中,建議你在團隊中組織Code Review[7],它是一個難得的學習提升機會。

價值着陸

TDD、重構和整潔代碼并不能直接讓我們設計出來的代碼就天生符合簡單設計。TDD帶我們開了一個頭,一旦開始了,在過程中不斷地審視自己的代碼,并通過重構來讓代碼變得整潔:

簡單設計落地三闆斧

歡迎你以文中提到的案例和網站作為開始,進行大量的刻意練習進而讓簡單設計的核心價值能夠着陸你所開發的軟體,提升軟體的響應力。

注釋

  1. 使用者故事是極限程式設計中的一個實踐,請參閱 我在ThoughtWorks中的靈活實踐
  2. 關于編碼Kata,歡迎通路 http://www.cyber-dojo.org/
  3. 有關Tasking更多解讀,歡迎閱讀ThoughtWorks仝鍵老師的 像機器一樣思考系列文章
  4. 我已經将 TDD實作斐波那契數 的視訊發表于B站
  5. 關于重構的練習,歡迎以 GlidedRose 案例作為開始
  6. 關于程式設計方面的書籍,歡迎從我的GitHub programming-books 庫中擷取
  7. Code Review是項非常有價值的編碼實踐,它不僅能夠促進團隊互相學習,還能防止代碼庫惡化,更多内容請參閱 我在ThoughtWorks中的靈活實踐

Posted by 袁慎建@ThoughtWorks

版權聲明:自由轉載•非商用•非衍生•保持署名 | Creative Commons BY-NC-ND 4.0

原文連結:http://sjyuan.cc/three-core-practices-of-simple-design/

繼續閱讀