本篇讀書筆記的內容大部分是來自我剛參與的掘金的讀書打卡活動。我在此次讀書打卡活動選擇了《簡約之美:軟件設計之道》這本書。我把這幾回打卡的內容做了整合,也加了一點沒有在打卡活動裏面寫的內容構成了這篇讀書筆記,但願讀者能夠有些收穫。git
「程序中複雜的部分必須以某種簡單的方式組織起來。。。這就是編程所要用到的藝術和才能 - 化繁爲簡。程序員
‘差程序員’是不會化繁爲簡的。他們總覺得編程語言「能跑通」的程序,就已經化解了複雜性,而沒考慮下降其餘程序員須要面對的複雜性。。。在這些程序員看來,他們寫出來的東西是能用的,這就是他們的老闆須要的,看來也應該是客戶須要的。。。他們把結果交給其它程序員,其餘程序員又會在這之上增添複雜性,完成本身的工做。github
程序員對化解複雜性考慮得越少,程序就越難懂。。。因此,‘好程序員’應當不遺餘力,把程序寫得讓其餘程序員容易理解。由於他寫的東西都很好懂,因此要找出bug是至關容易的。編程
-- 來自《簡約之美:軟件設計之道》」瀏覽器
這裏提到的化繁爲簡,我認爲就是將複雜的系統以清晰的結構與高可讀性的代碼呈現出來的過程。做者認爲不能僅僅爲了完成需求來寫代碼,這是一種應付老闆和客戶的行爲。他認爲寫代碼的時候還要考慮到代碼是否可讓人容易理解,固然也包括是否易修改,易擴展,易維護。由於隨着需求的不斷增長,代碼的維護成本會愈來愈高。安全
其實這自己就是認知高度和自我要求的問題:你是選擇追求卓越,仍是選擇得過且過?我相信兩種態度隨着時間的推移,所形成影響的差異應該是很是巨大的;不只是寫代碼,作任何事情都是。性能優化
「其實,所有軟件都有一個相同的目標:幫助其餘人。編程語言
文字處理軟件幫助你們編輯文檔,瀏覽器幫助你們瀏覽網頁。。。服務於動物或植物的軟件,其目的仍是幫助人類。。。即便你寫的是程序庫,它們也是爲程序員服務的,程序員也是人。。。軟件歷來都不是用來幫助無生命事物的。軟件要幫助的不是計算機,而是人。post
軟件的目標不是‘賺錢’或者‘炫耀智商’。。。即使賺錢和炫耀智商能夠‘幫助’你,但這只是很是狹隘的幫助;相比爲幫助別人而設計的,知足其餘人需求的軟件,僅僅考慮狹隘目標的設計,極可能收穫糟糕的軟件。性能
任何狀況下,你所賺的錢都直接維繫於你的軟件能爲他人提供多少幫助。。。。在作與軟件有關的決策時,指導法則就是判斷能提供什麼樣的幫助。各項需求也能夠照這個標準排除前後順序。哪項需求能爲人們提供最大的幫助,就應當賦予最高的優先級。
因此,軟件設計科學的目標應該是:
- 確保軟件能提供儘量多的幫助
- 確保軟件能持續提供儘量多的幫助
- 設計出程序員能儘量容易開發和維護軟件系統,這樣的系統才能爲用戶提供儘量多的幫助,並且能持續提供儘量多的幫助
-- 來自《簡約之美:軟件設計之道》」
做者認爲軟件的目的是服務他人,並且軟件是否成功在很大程度上取決於軟件自己對人的幫助有多大。
這一點很值得程序員,設計,產品經理思考:
如今這個需求或設計是否真的能夠幫助咱們的目標客戶;若是有,幫助大仍是小?若是幫助小,那如何改進能夠更好地幫助他們?
如今這個代碼庫是否真的能夠幫助咱們的業務方?這些功能真的都是能夠解決業務方的問題麼?是否有些功能是無關緊要的?業務方接過來用是否會以爲不方便?或者同事看了個人以後是否能立刻理解我代碼的意思,不須要花費太多的時間和精力去理解和修改它們?
另外,做者所說的須要可持續提供幫助這一點也很是好。
我認爲這是一個格局的問題:
格局決定高度。
「公式:D = (Vn + Vf)/(Ei + Em)
其中:
- D:可取程度
- Vn:當前價值
- Vf:將來價值
- Ei:實現成本
- Em:維護成本
將來價值和維護成本都取決於時間。。。通常來講,軟件系統都須要維護很長時間,大多數狀況下,將來長期收益和維護成本纔是真正須要考慮的。與之相比,當前價值和實現成本變得無足輕重。
若是咱們忽視事實,放棄對將來的思考,只考慮當下「能用」的軟件,那麼咱們軟件在將來就會很難維護。若是軟件很難維護,就很難確保它可以幫助別人(而這正是軟件設計的目標)。
相比短時間,長期的將來對咱們來講更重要,由於我沒打呢的是決策會在將來更長的時間裏產生更大的影響。
在軟件設計時,能夠根據已知的信息作某些決策,目的是爲了創造更好的將來(提高價值,下降維護成本),而沒必要預測將來究竟會發生什麼具體的事情。
-- 來自《簡約之美:軟件設計之道》」
不少事情咱們都須要把時間一同考慮進去:好比蛀牙會隨着時間的推移可能會致使後面整個牙都拔掉,可是有的人缺忽視了時間的做用,一拖再拖致使最後要把整顆牙拔掉;再好比基金可能會長期持有才會有一個比較好的收益,可是有的人在看到一跌再跌就忍不住殺跌,對行業的發展沒有關注,更沒有想法,然後面再回來看的時候基金又漲回去了。。
軟件開發也是如此,咱們不只僅須要解決當下的難題,還要考慮當前的設計在將來的可維護性(也包括可擴展性)。咱們不能僅圖一時時快,爲了應付需求,設計最求短平快,給將來絕不留餘地。
咱們應該在動手寫代碼以前要多考慮一下當前設計的可維護性,可擴展性,也就是這個設計在將來會帶給咱們多大的便利和好處,而不是一步一步讓它把咱們推向無盡的深淵。
「你並不須要預測什麼會變化,你須要知道的是,變化必然會發生。程序應該保證儘量合理的靈活性,這樣,>無論將來發生什麼變化,均可以應付得了。
請回顧整個過程當中的每次修改。問問本身,最初寫這個文件時,你能預測到這些變化嗎?是否一開始寫好就可以減輕後期的工做量。總的來講,就是要嘗試理解每次修改,看看是否能從中獲得一些關於軟件開發的新的收穫。
漸進式開發及設計:它要求按照特定順序,一點一點地設計和構建系統。
舉一個實現一個支持加減乘除計算器的例子。
- 設計一個只能進行加法運算的系統。
- 修改現有的設計,讓它支持減法運算。
- 實現減法運算功能。如今系統支持加法和減法。
- 再次修改現有的設計,讓它支持乘法運算。
- 實現乘法運算功能。如今系統支持加法,減法和乘法了。
- 再次修改現有的設計,讓它支持除法運算。
- 添加除法的功能。最後獲得一個咱們指望的能夠加減乘除的計算器。
這個方法的精妙之處在於,它是根據實現的順序來決策的。總的來講,在其中的每一個階段,下一步都只作最容易的事情:首先選擇加法,由於這是最簡單的運算;其次選擇減法,由於從邏輯上說它與加法只有很小的差別;第二步也能夠選擇乘法,由於乘法無非是把加法執行不少次而已。而惟一不該當選擇的是除法,由於從加法到除法的距離太遠了,步子太大了。而從乘法到除法卻相對簡單不少。
這裏混合了兩種作法:一種叫作‘漸進開發’,另外一種叫作‘漸進設計’。 漸進式開發是一種經過該小步驟構建整個系統的辦法;漸進式設計也是一種相似的方法,它也經過一系列小步驟來建立和改進系統的設計。
-- 來自《簡約之美:軟件設計之道》」
做者指出了咱們應該認識到變化是必然會發生的,所以咱們在設計系統的時候要儘量保持靈活,讓系統便於修改。並且在每次改動以後咱們最好也能夠作一個覆盤:這個修改咱們是否當初想到過,當初的設計是否能夠很好地應對這個修改。若是不能,咱們之後應該如何避免相似的狀況發生?或者咱們是否能夠積累一下經驗,對比變化先後的差別,彌補咱們在思考方面的不足?
介紹了漸進式開發和設計:它所追求的是經過小步驟來構建和改進系統的方法,每一步驟相差的距離很小。同時也舉了一個簡單的例子幫助咱們理解。之後在咱們構建複雜系統的時候能夠借鑑做者介紹的這種漸進式的方案。
「永遠不要「 修正」 任何 東西,除非它真的是一個問題,並且有證據代表問題確實存在。
若是至關多的用戶認爲某個行爲是bug,它就是bug;若是隻是少數用戶(好比一兩個)認爲它是bug,那麼它就不算bug。
在你的程序中,真正須要關注速度的部分,應該侷限於你能夠證實的、真正讓用戶體會到有性能問題的那些部分。對程序的其餘部分,最主要關心的仍是靈活和簡潔,而不是速度。
有些開發人員想讓速度儘量快,因此,他們還沒弄清楚速度到底慢不慢,就花時間來優化程序。這就好像作慈善事業時,一邊把食物送給富人,一邊說「咱們只是但願幫助他人。
在動手解決以前,真正拿到證據,證實問題確實存在。
-- 來自《簡約之美:軟件設計之道》」
做者強調了在解決問題以前應該先確認這個是否是問題。若是確認了是問題才須要去解決。
其實這就是「把錢用在刀刃上」在軟件開發中的實踐:咱們的開發資源永遠是緊張的,由於不管是如今仍是將來都要有不少事情要作。所以咱們須要解決的是那些明確的,有證據證實的,真正須要解決的問題。
「某一部分的代碼越簡潔,將來進行變化的難度就越低。
若是你的代碼寫得簡潔、自洽,那麼修正問題、維護系統就很容易。
要簡潔到什麼程度呢? 簡單到傻子也能看懂!
許多程序員在這方面作得尤爲差勁。他們覺得別人都願意花不少時間來學習本身寫的代碼,畢竟這是本身花不少時間寫出來的。這些程序員很重視本身的代碼,因此對其餘人也應當一樣重視。沒錯,程序員一般都是很是聰明的人。可是「噢,其餘程序員會理解我寫的全部代碼,不必簡化或者註釋」的見解仍然是不對的。這個問題與智商無關,而與背景知識有關。第一次接觸你代碼的程序員徹底沒有任何背景知識,他必須學習。學習的難度越低,找出問題的速度也就越快,使用起來也越容易。
下降代碼學習難度的方法有不少:簡潔的註釋,簡單的設計,按部就班的引導,等等。不過,若是你的代碼沒有作到傻子都能看懂,其餘人學起來就會遇到困難。他們會誤解,會製造bug,會把事情搞得一團糟。等這一切發生的時候,他們會找誰?對,就是你。這時候你就得花時間回答他們的各類問題。
-- 來自《簡約之美:軟件設計之道》」
做者提倡咱們要寫簡潔的代碼來提升代碼的可維護性。還提到了兩個方法:用小模塊構建系統以及正確使用註釋。咱們須要儘可能作到不須要讓別人和將來的本身花費太多成原本讀懂代碼,這纔是對本身負責,對他人負責的態度,由於它符合這本書中提到的「寫軟件是爲了幫助他人」的中心思想。
「你正開發的任何系統,其基本用途應當至關簡單。這樣開發出來的系統,既知足實際需求,總體來講也是簡單的。可是,若是你給系統添加新功能去知足其餘目標,事情就馬上變複雜了。
舉例來講,文字處理軟件的基本功能就是幫助用戶寫做文檔。若是忽然要求它可以閱讀郵件,最終就會獲得的很是荒唐複雜的玩意。咱們都知道,這不是文字處理軟件原本的用途。這麼作,甚至都不是在擴展軟件的用途,而是增添與目的無關的功能。
有時候,營銷人員或者經理會給軟件設定一些目標,可是這些目標其實並不符合程序的基本用途,好比「要好玩一些」、「設計要更有衝擊感」、「要受新媒體歡迎」,「要使用最新的技術」等等。這些人多是公司裏的重要人物,但他們不是那些決定程序應當作什麼的人。身爲軟件設計師或是技術經理,你的職責是保證軟件的基本用途,防止它偏離正軌,這個責任其餘人誰也擔不起。
最受用戶喜歡的軟件是專一而簡潔的,而且始終執着於基本用途。
-- 來自《簡約之美:軟件設計之道》」
這段做者呼籲你們在作軟件的時候要保持專一,讓軟件變得純粹,不要經過試圖增長多樣化的功能來給軟件帶來更多複雜性,致使提高後面的維護成本。
由於軟件也是產品,它只須要知足特定人羣的特定需求就行了,把這一點作到極致便可,而不須要去浪費成本去解決其餘的問題。
並且若是是做爲軟件設計師或者是技術經理,也要有義務保證軟件不偏離原有的目標。
「你能夠經過三個因素來判斷技術是否「糟糕」:生存潛力、互通性、對品質的重視。
生存潛力:某種技術的生存潛力,就是它持續得到維護的可能性。若是某種類庫或依賴項已通過時,沒有人維護,你卻死守着它們,就有麻煩在等着你了。
接受普遍程度:應當從符合需求的技術中選擇接受最普遍的。從某種程度上說這是真的,被接受的技術通常都是有至關大的生存潛力。不過,你仍是必須辨別,究竟是通過考驗才被你們接受,仍是僅僅是由於某種壟斷而被接受。有些技術之因此被普遍接受,是由於用戶暫時別無選擇。
互通性:所謂互通性,指的是若是須要,從一種技術切換到另外一種技術有多難。要了解技術的互通性,就得問問本身:「咱們能不能以某種標準方式來交互,這樣就更容易切換到遵循一樣標準的其餘系統?」
品質:這是一種更主觀的衡量,其思想是考察最近的發佈中,產品是否更加完善了。若是你能夠看到源代碼,檢查一下開發人員是否進行了重構,清理了代碼。產品是更容易使用了,仍是更難用了?維護它的人真的在意產品的質量嗎?最近是否屢次出現彷佛由糟糕的編程所引起的嚴重安全問題?
還有其餘因素須要考慮,主要是它是否簡潔,是否符合軟件的基本用途。在衡量完全部實際因素以後,也能夠考慮我的喜愛。
-- 來自《簡約之美:軟件設計之道》」
這段文字給咱們在從此作技術選型的時候提供了建議:從生存潛力、互通性、對品質的重視這三個維度來判斷選擇該項技術是否是可取的,很是有借鑑意義。
若是你設計的是龐大繁雜的模塊,那麼每一部分都須要花費大量精力,也很難作到足夠精緻。這樣的系統就很難維護,並且必須常常打補丁才能夠正常運行。那麼,爲何會有人編程時要採用龐大繁雜的模塊,而不採用小巧簡潔的模塊呢?在軟件第一次編寫時,採用大模塊表面上能夠節省下至關多的時間。若是使用衆多小模塊,就必須花不少時間來組合。若是採用大模塊則不會這樣,零件不多,並且很容易對接。
若是系統中某個部分太過複雜,有個好辦法來解決:把它分解成幾個獨立的小部分,逐步從新設計。每次修改都應該足夠小,這樣能夠放心動手,不會讓事情更復雜。
而有時候你受命去解決一些自己就很是複雜的問題,好比編寫拼寫檢查或國際象棋的程序。問題複雜,解法不必定會複雜;相反,在處理此類問題時,你必須更努力地追求代碼的簡潔。若是你在解決複雜問題時遇到了麻煩,那麼用簡單易懂的文字把它寫在紙上,或者畫出來。有些最優秀的程序設計就是在紙上完成的,真的。把它輸入到計算機裏只是次要的細節。大多數麻煩的設計問題,均可以用在紙上畫圖或寫出來的辦法找到答案。
-- 來自《簡約之美:軟件設計之道》」
做者提倡小模塊構建系統來下降程序的維護和修改爲本。並且在遇到複雜問題的時候,能夠將你的設計落在紙上,能夠更形象地看到你設計的樣子,也更加便於發現問題和修改。
「你不能專門花很長的時間來從新設計,中止開發新功能。變化定律告訴咱們,程序所處的環境是持續變化的,因此程序的功能也必須去適應這些變化。若是在至關長的時間裏,你都不能從用戶角度出發來調適和改進,就可能失去本身的用戶,把項目弄死。
好在平衡開發新功能和應對複雜性這兩項任務的方法有不少。最好的一個辦法就是,從新設計時只考慮讓新功能更容易實現,而後實現這個功能。這樣,你就能夠在從新設計和開發新功能之間按期切換。它一樣有助於保證新設計可以適應需求,由於設計時會考慮到實際的應用。系統的複雜性也會逐漸降低,並且你一直都跟得上用戶的需求。你甚至能夠這樣來處理bug:若是發現修改設計以後,某些bug更容易修復,那麼先從新設計代碼再修復bug。
-- 來自《簡約之美:軟件設計之道》」
(通常狀況下)咱們的軟件不斷會有新功能,同時,咱們也應該讓咱們的程序愈來愈好,進行適當的重構和從新設計。那麼新功能的開發和從新設計的工做應該如何平衡呢?做者給出了本身的建議:從新設計時只考慮讓新功能更容易實現,而後實現這個功能。
本篇已同步到我的博客:《簡約之美:軟件設計之道》- 讀書筆記