《簡約之美:軟體設計之道》- 讀書筆記

J_Knight_發表於2019-01-01

本篇讀書筆記的內容大部分是來自我剛參與的掘金的讀書打卡活動。我在這次讀書打卡活動選擇了《簡約之美:軟體設計之道》這本書。我把這幾次打卡的內容作了整合,也加了一點沒有在打卡活動裡面寫的內容構成了這篇讀書筆記,希望讀者可以有些收穫。

追求卓越還是得過且過

《簡約之美:軟體設計之道》- 讀書筆記

“程式中複雜的部分必須以某種簡單的方式組織起來。。。這就是程式設計所要用到的藝術和才能 - 化繁為簡。

‘差程式設計師’是不會化繁為簡的。他們總以為程式語言“能跑通”的程式,就已經化解了複雜性,而沒考慮降低其他程式設計師需要面對的複雜性。。。在這些程式設計師看來,他們寫出來的東西是能用的,這就是他們的老闆需要的,看來也應該是客戶需要的。。。他們把結果交給其它程式設計師,其他程式設計師又會在這之上增添複雜性,完成自己的工作。

程式設計師對化解複雜性考慮得越少,程式就越難懂。。。所以,‘好程式設計師’應當竭盡全力,把程式寫得讓其他程式設計師容易理解。因為他寫的東西都很好懂,所以要找出bug是相當容易的。

-- 來自《簡約之美:軟體設計之道》”

這裡提到的化繁為簡,我認為就是將複雜的系統以清晰的結構與高可讀性的程式碼呈現出來的過程。作者認為不能僅僅為了完成需求來寫程式碼,這是一種應付老闆和客戶的行為。他認為寫程式碼的時候還要考慮到程式碼是否可以讓人容易理解,當然也包括是否易修改,易擴充套件,易維護。因為隨著需求的不斷增加,程式碼的維護成本會越來越高。

其實這本身就是認知高度和自我要求的問題:你是選擇追求卓越,還是選擇得過且過?我相信兩種態度隨著時間的推移,所造成影響的差別應該是非常巨大的;不僅是寫程式碼,做任何事情都是。

你的程式有在幫助他人麼?

《簡約之美:軟體設計之道》- 讀書筆記

“其實,全部軟體都有一個相同的目標:幫助其他人。

文書處理軟體幫助大家編輯文件,瀏覽器幫助大家瀏覽網頁。。。服務於動物或植物的軟體,其目的還是幫助人類。。。即使你寫的是程式庫,它們也是為程式設計師服務的,程式設計師也是人。。。軟體從來都不是用來幫助無生命事物的。軟體要幫助的不是計算機,而是人。

軟體的目標不是‘賺錢’或者‘炫耀智商’。。。即便賺錢和炫耀智商可以‘幫助’你,但這只是非常狹隘的幫助;相比為幫助別人而設計的,滿足其他人需求的軟體,僅僅考慮狹隘目標的設計,很可能收穫糟糕的軟體。

任何情況下,你所賺的錢都直接維繫於你的軟體能為他人提供多少幫助。。。。在做與軟體有關的決策時,指導法則就是判斷能提供什麼樣的幫助。各項需求也可以照這個標準排除先後順序。哪項需求能為人們提供最大的幫助,就應當賦予最高的優先順序。

所以,軟體設計科學的目標應該是:

  1. 確保軟體能提供儘可能多的幫助
  2. 確保軟體能持續提供儘可能多的幫助
  3. 設計出程式設計師能儘可能容易開發和維護軟體系統,這樣的系統才能為使用者提供儘可能多的幫助,而且能持續提供儘可能多的幫助

-- 來自《簡約之美:軟體設計之道》”

作者認為軟體的目的是服務他人,而且軟體是否成功在很大程度上取決於軟體本身對人的幫助有多大。

這一點很值得程式設計師,設計,產品經理思考:

現在這個需求或設計是否真的可以幫助我們的目標客戶;如果有,幫助大還是小?如果幫助小,那如何改進可以更好地幫助他們?

現在這個程式碼庫是否真的可以幫助我們的業務方?這些功能真的都是可以解決業務方的問題麼?是否有些功能是可有可無的?業務方接過來用是否會覺得不方便?或者同事看了我的之後是否能馬上理解我程式碼的意思,不需要花費太多的時間和精力去理解和修改它們?

另外,作者所說的需要可持續提供幫助這一點也非常好。

  • 比如這個需求將來能否還有可以做得更好的可能?
  • 或者這段程式碼或者模組擴充套件性是否很強?是否容易修改?出現問題的時候我們能否積極響應並修復?

我認為這是一個格局的問題:

  • 你是隻為了掙錢,拿到錢就滿足了,還是為了真心想幫助他人,解決他人的問題?
  • 你是隻為了KPI,完成某個特定任務而已,還是為了真心想幫助同事,幫助公司的客戶,讓公司越來越好?

格局決定高度。

價值與成本的時間維度

《簡約之美:軟體設計之道》- 讀書筆記

“公式:D = (Vn + Vf)/(Ei + Em)

其中:

  • D:可取程度
  • Vn:當前價值
  • Vf:未來價值
  • Ei:實現成本
  • Em:維護成本

未來價值和維護成本都取決於時間。。。一般來說,軟體系統都需要維護很長時間,大多數情況下,未來長期收益和維護成本才是真正需要考慮的。與之相比,當前價值和實現成本變得無足輕重。

如果我們忽視事實,放棄對未來的思考,只考慮當下“能用”的軟體,那麼我們軟體在未來就會很難維護。如果軟體很難維護,就很難確保它能夠幫助別人(而這正是軟體設計的目標)。

相比短期,長期的未來對我們來說更重要,因為我沒打呢的是決策會在未來更長的時間裡產生更大的影響。

在軟體設計時,可以根據已知的資訊做某些決策,目的是為了創造更好的未來(提升價值,降低維護成本),而不必預測未來究竟會發生什麼具體的事情。

-- 來自《簡約之美:軟體設計之道》”

很多事情我們都需要把時間一同考慮進去:比如蛀牙會隨著時間的推移可能會導致後面整個牙都拔掉,但是有的人缺忽視了時間的作用,一拖再拖導致最後要把整顆牙拔掉;再比如基金可能會長期持有才會有一個比較好的收益,但是有的人在看到一跌再跌就忍不住殺跌,對行業的發展沒有關注,更沒有想法,而後面再回來看的時候基金又漲回去了。。

軟體開發也是如此,我們不僅僅需要解決當下的難題,還要考慮當前的設計在未來的可維護性(也包括可擴充套件性)。我們不能僅圖一時時快,為了應付需求,設計最求短平快,給未來毫不留餘地。

我們應該在動手寫程式碼之前要多考慮一下當前設計的可維護性,可擴充套件性,也就是這個設計在未來會帶給我們多大的便利和好處,而不是一步一步讓它把我們推向無盡的深淵。

應對變化

《簡約之美:軟體設計之道》- 讀書筆記

“你並不需要預測什麼會變化,你需要知道的是,變化必然會發生。程式應該保證儘可能合理的靈活性,這樣,>不管未來發生什麼變化,都可以應付得了。

請回顧整個過程中的每次修改。問問自己,最初寫這個檔案時,你能預測到這些變化嗎?是否一開始寫好就能夠減輕後期的工作量。總的來說,就是要嘗試理解每次修改,看看是否能從中得到一些關於軟體開發的新的收穫。

漸進式開發及設計:它要求按照特定順序,一點一點地設計和構建系統。

舉一個實現一個支援加減乘除計算器的例子。

  1. 設計一個只能進行加法運算的系統。
  2. 修改現有的設計,讓它支援減法運算。
  3. 實現減法運算功能。現在系統支援加法和減法。
  4. 再次修改現有的設計,讓它支援乘法運算。
  5. 實現乘法運算功能。現在系統支援加法,減法和乘法了。
  6. 再次修改現有的設計,讓它支援除法運算。
  7. 新增除法的功能。最後得到一個我們期望的可以加減乘除的計算器。

這個方法的精妙之處在於,它是根據實現的順序來決策的。總的來說,在其中的每個階段,下一步都只做最容易的事情:首先選擇加法,因為這是最簡單的運算;其次選擇減法,因為從邏輯上說它與加法只有很小的差異;第二步也可以選擇乘法,因為乘法無非是把加法執行很多次而已。而唯一不應當選擇的是除法,因為從加法到除法的距離太遠了,步子太大了。而從乘法到除法卻相對簡單很多。

這裡混合了兩種做法:一種叫做‘漸進開發’,另一種叫做‘漸進設計’。 漸進式開發是一種通過該小步驟構建整個系統的辦法;漸進式設計也是一種類似的方法,它也通過一系列小步驟來建立和改進系統的設計。

-- 來自《簡約之美:軟體設計之道》”

作者指出了我們應該認識到變化是必然會發生的,因此我們在設計系統的時候要儘可能保持靈活,讓系統便於修改。而且在每次改動之後我們最好也可以做一個覆盤:這個修改我們是否當初想到過,當初的設計是否可以很好地應對這個修改。如果不能,我們以後應該如何避免類似的情況發生?或者我們是否可以積累一下經驗,對比變化前後的差異,彌補我們在思考方面的不足?

介紹了漸進式開發和設計:它所追求的是通過小步驟來構建和改進系統的方法,每一步驟相差的距離很小。同時也舉了一個簡單的例子幫助我們理解。以後在我們構建複雜系統的時候可以借鑑作者介紹的這種漸進式的方案。

這是不是問題?

《簡約之美:軟體設計之道》- 讀書筆記

“永遠不要“ 修正” 任何 東西,除非它真的是一個問題,而且有證據表明問題確實存在。

如果相當多的使用者認為某個行為是bug,它就是bug;如果只是少數使用者(比如一兩個)認為它是bug,那麼它就不算bug。

在你的程式中,真正需要關注速度的部分,應該侷限於你可以證明的、真正讓使用者體會到有效能問題的那些部分。對程式的其他部分,最主要關心的還是靈活和簡潔,而不是速度。

有些開發人員想讓速度儘可能快,所以,他們還沒弄清楚速度到底慢不慢,就花時間來優化程式。這就好像做慈善事業時,一邊把食物送給富人,一邊說“我們只是希望幫助他人。

在動手解決之前,真正拿到證據,證明問題確實存在。

-- 來自《簡約之美:軟體設計之道》”

作者強調了在解決問題之前應該先確認這個是不是問題。如果確認了是問題才需要去解決。

  • 關於bug:有多數使用者反饋的bug才是bug,如果極少數使用者反饋的bug,就不應算作bug或者優先順序可以排到後面,它不應該屬於我們首先解決的問題。
  • 關於效能優化:只有可以證明的,使用者體會到效能上有問題的部分才需要去優化效能。

其實這就是“把錢用在刀刃上”在軟體開發中的實踐:我們的開發資源永遠是緊張的,因為無論是現在還是未來都要有很多事情要做。因此我們需要解決的是那些明確的,有證據證明的,真正需要解決的問題。

要寫傻子也能看懂的程式

《簡約之美:軟體設計之道》- 讀書筆記

“某一部分的程式碼越簡潔,未來進行變化的難度就越低。

如果你的程式碼寫得簡潔、自洽,那麼修正問題、維護系統就很容易。

要簡潔到什麼程度呢? 簡單到傻子也能看懂!

許多程式設計師在這方面做得尤其差勁。他們以為別人都願意花很多時間來學習自己寫的程式碼,畢竟這是自己花很多時間寫出來的。這些程式設計師很重視自己的程式碼,所以對其他人也應當同樣重視。沒錯,程式設計師通常都是非常聰明的人。但是“噢,其他程式設計師會理解我寫的所有程式碼,沒必要簡化或者註釋”的看法仍然是不對的。這個問題與智商無關,而與背景知識有關。第一次接觸你程式碼的程式設計師完全沒有任何背景知識,他必須學習。學習的難度越低,找出問題的速度也就越快,使用起來也越容易。

降低程式碼學習難度的方法有很多:簡潔的註釋,簡單的設計,循序漸進的引導,等等。不過,如果你的程式碼沒有做到傻子都能看懂,其他人學起來就會遇到困難。他們會誤解,會製造bug,會把事情搞得一團糟。等這一切發生的時候,他們會找誰?對,就是你。這時候你就得花時間回答他們的各種問題。

-- 來自《簡約之美:軟體設計之道》”

作者提倡我們要寫簡潔的程式碼來提高程式碼的可維護性。還提到了兩個方法:用小模組構建系統以及正確使用註釋。我們需要儘量做到不需要讓別人和未來的自己花費太多成本來讀懂程式碼,這才是對自己負責,對他人負責的態度,因為它符合這本書中提到的“寫軟體是為了幫助他人”的中心思想。

請保持專注

《簡約之美:軟體設計之道》- 讀書筆記

“你正開發的任何系統,其基本用途應當相當簡單。這樣開發出來的系統,既滿足實際需求,整體來說也是簡單的。但是,如果你給系統新增新功能去滿足其他目標,事情就立刻變複雜了。

舉例來說,文書處理軟體的基本功能就是幫助使用者寫作文件。如果突然要求它能夠閱讀郵件,最終就會得到的非常荒唐複雜的玩意。我們都知道,這不是文書處理軟體本來的用途。這麼做,甚至都不是在擴充套件軟體的用途,而是增添與目的無關的功能。

有時候,營銷人員或者經理會給軟體設定一些目標,但是這些目標其實並不符合程式的基本用途,比如“要好玩一些”、“設計要更有衝擊感”、“要受新媒體歡迎”,“要使用最新的技術”等等。這些人可能是公司裡的重要人物,但他們不是那些決定程式應當做什麼的人。身為軟體設計師或是技術經理,你的職責是保證軟體的基本用途,防止它偏離正軌,這個責任其他人誰也擔不起。

最受使用者喜歡的軟體是專注而簡潔的,並且始終執著於基本用途。

-- 來自《簡約之美:軟體設計之道》”

這段作者呼籲大家在做軟體的時候要保持專注,讓軟體變得純粹,不要通過試圖增加多樣化的功能來給軟體帶來更多複雜性,導致提升後面的維護成本。

因為軟體也是產品,它只需要滿足特定人群的特定需求就好了,把這一點做到極致即可,而不需要去浪費成本去解決其他的問題。

而且如果是作為軟體設計師或者是技術經理,也要有義務保證軟體不偏離原有的目標。

這是否是糟糕的技術?

《簡約之美:軟體設計之道》- 讀書筆記

“你可以通過三個因素來判斷技術是否“糟糕”:生存潛力、互通性、對品質的重視。

生存潛力:某種技術的生存潛力,就是它持續獲得維護的可能性。如果某種類庫或依賴項已經過時,沒有人維護,你卻死守著它們,就有麻煩在等著你了。

接受廣泛程度:應當從符合需求的技術中選擇接受最廣泛的。從某種程度上說這是真的,被接受的技術一般都是有相當大的生存潛力。不過,你還是必須辨別,到底是經過考驗才被大家接受,還是僅僅是因為某種壟斷而被接受。有些技術之所以被廣泛接受,是因為使用者暫時別無選擇。

互通性:所謂互通性,指的是如果需要,從一種技術切換到另一種技術有多難。要了解技術的互通性,就得問問自己:“我們能不能以某種標準方式來互動,這樣就更容易切換到遵循同樣標準的其他系統?”

品質:這是一種更主觀的衡量,其思想是考察最近的釋出中,產品是否更加完善了。如果你可以看到原始碼,檢查一下開發人員是否進行了重構,清理了程式碼。產品是更容易使用了,還是更難用了?維護它的人真的在乎產品的質量嗎?最近是否多次出現似乎由糟糕的程式設計所引發的嚴重安全問題?

還有其他因素需要考慮,主要是它是否簡潔,是否符合軟體的基本用途。在衡量完所有實際因素之後,也可以考慮個人喜好。

-- 來自《簡約之美:軟體設計之道》”

這段文字給我們在今後做技術選型的時候提供了建議:從生存潛力、互通性、對品質的重視這三個維度來判斷選擇該項技術是不是可取的,非常有借鑑意義。

應對複雜

《簡約之美:軟體設計之道》- 讀書筆記

如果你設計的是龐大繁雜的模組,那麼每一部分都需要花費大量精力,也很難做到足夠精緻。這樣的系統就很難維護,而且必須經常打補丁才可以正常執行。那麼,為什麼會有人程式設計時要採用龐大繁雜的模組,而不採用小巧簡潔的模組呢?在軟體第一次編寫時,採用大模組表面上可以節省下相當多的時間。如果使用眾多小模組,就必須花很多時間來組合。如果採用大模組則不會這樣,零件很少,而且很容易對接。

如果系統中某個部分太過複雜,有個好辦法來解決:把它分解成幾個獨立的小部分,逐步重新設計。每次修改都應該足夠小,這樣可以放心動手,不會讓事情更復雜。

而有時候你受命去解決一些本身就非常複雜的問題,比如編寫拼寫檢查或國際象棋的程式。問題複雜,解法不一定會複雜;相反,在處理此類問題時,你必須更努力地追求程式碼的簡潔。如果你在解決複雜問題時遇到了麻煩,那麼用簡單易懂的文字把它寫在紙上,或者畫出來。有些最優秀的程式設計就是在紙上完成的,真的。把它輸入到計算機裡只是次要的細節。大多數麻煩的設計問題,都可以用在紙上畫圖或寫出來的辦法找到答案。

-- 來自《簡約之美:軟體設計之道》”

作者提倡小模組構建系統來降低程式的維護和修改成本。而且在遇到複雜問題的時候,可以將你的設計落在紙上,可以更形象地看到你設計的樣子,也更加便於發現問題和修改。

平衡重新設計和新需求開發

《簡約之美:軟體設計之道》- 讀書筆記

“你不能專門花很長的時間來重新設計,停止開發新功能。變化定律告訴我們,程式所處的環境是持續變化的,所以程式的功能也必須去適應這些變化。如果在相當長的時間裡,你都不能從使用者角度出發來調適和改進,就可能失去自己的使用者,把專案弄死。

好在平衡開發新功能和應對複雜性這兩項任務的方法有很多。最好的一個辦法就是,重新設計時只考慮讓新功能更容易實現,然後實現這個功能。這樣,你就可以在重新設計和開發新功能之間定期切換。它同樣有助於保證新設計能夠適應需求,因為設計時會考慮到實際的應用。系統的複雜性也會逐漸下降,而且你一直都跟得上使用者的需求。你甚至可以這樣來處理bug:如果發現修改設計之後,某些bug更容易修復,那麼先重新設計程式碼再修復bug。

-- 來自《簡約之美:軟體設計之道》”

(一般情況下)我們的軟體不斷會有新功能,同時,我們也應該讓我們的程式越來越好,進行適當的重構和重新設計。那麼新功能的開發和重新設計的工作應該如何平衡呢?作者給出了自己的建議:重新設計時只考慮讓新功能更容易實現,然後實現這個功能。


本篇已同步到個人部落格:《簡約之美:軟體設計之道》- 讀書筆記

相關文章