在一次milestone開發過程當中,開發者會持續編輯issue列表,每一個issue都有本身的生命週期。燃盡圖預期這些issues會被線性的消滅掉,因此從第一天直接到最後一天畫個直線表示預期進度變化,然而實際開發會遇到各類困難,因此實際的進度變化曲線每每不是線性變化的,下面這篇文章給出了S型燃盡圖:
https://sandofsky.com/blog/the-s-curve.htmlhtml
計算機是基於二進制的,有一句經典的臺詞是:這個世界上有兩種人,一種是懂10進制的,另外一種是懂10進制的。可是在開發中,咱們經常要接觸三進制。程序開發中有一個Keep it simple, stupid的所謂KISS原則,就是說咱們寫程序,在沒有必要的狀況下,不要增長沒必要要的抽象層。例如不少初學者在剛接觸了設計模式以後,就會在很簡單的程序上沒必要要或者不正確的使用各類模式去寫代碼,但實際上那種程度的代碼只須要把面向過程代碼寫好,作好函數這個級別的抽象便可。函數簡潔但並不就簡單,和一般的初學者相反,有經驗的程序員更願意用簡潔的代碼解決問題,而不會爲了用上一堆所謂特性把代碼寫成花拳繡腿。一個函數須要考慮入口條件,出口條件,是否可重入,是否線程安全,所依賴的狀態變化…等等。因此,有時若是你不放棄裝飾,你就得放棄本質。git
可是,程序從開發的第一天開始就被持續迭代。有一句話說:程序從被寫下的第一天開始就開始腐爛的過程,這是說程序會由於需求的不斷變化而須要不斷的被重構,一開始幾行的代碼可能會膨脹,再壓縮,再膨脹,再壓縮。不一樣地方的代碼會出現重複,各類各樣的重複。因而,光有KISS是不夠的,咱們須要另一個東西:Do Not Repeat Yourself,也就是所謂的DRY原則。怎樣才能不自我重複呢?這就是所謂的三進制原則,一樣一件事,重複作三次,就能夠考慮批處理,計算機是最擅長作批量處理的事情,例如for循環,遞歸等。批處理的前提是結構的一致性,結構的一致爲將他們裝到容器裏創造了可能。因此,爲了批處理,咱們經常須要在結構上作抽象。一致性多是數據上的,也多是行爲上的,根據程序即數據的原理,數據的一致性能夠用行爲的一致性表示,因此咱們能夠只對行爲的一致性考慮。在面向過程語言裏,可能就是在函數這個級別考慮,在面嚮對象語言裏,則更多能夠在接口層體現。把共同的結構裝到容器裏的過程,就是組合的過程。程序員
好了,三進制大概說到這裏。設計模式
從我一開始進入程序員這個行業開始,我就也會被軟件開發中的人員配置問題困擾。一個團隊,是否要有專職的項目經理,美工,測試,產品設計,以及並不討人喜歡的行政,人力資源?從程序員的角度來講,屬於技術偏好型,能用技術解決的,毫不願意經過增長一我的去解決,能用工具解決的,必定批量處理之。先進技術和工具,經常在效率上是數量級的壓倒性優點。
回到小題,經過幾年的過程,我想角色上不少時候這些角色都有其必要性,可是,一個角色要有多我的仍是一我的甚至直接由工具取代,則是能夠因團隊而不一樣。怎樣取捨和適應?我認爲關鍵在於:是否有效率的解決問題,例如開發和測試,若是開發和測試兩我的不能很好的協做,共同有效率解決問題,而一個二者皆作的更有效率,那麼明顯後者更好,反之則選擇前者。
所以,角色分離,但人員能夠合一。也就是人劍合一。數組
前面說燃盡圖,軟件開發,經常是一個長期過程。不是一錘子買賣,一個基礎類庫開發加一個上層產品開發就可能兩年。但市場經常不等人,所以咱們要緊湊的過程和質量,那麼就須要持續迭代。持續迭代體如今一個milestone以內的每一天之間,須要天天跟蹤昨天,今天,明天的進度,解決的issue,新產生的issue,代碼的提交,測試的經過率,發佈的版本,用戶的反饋等等。持續迭代同時體如今milestone和milestone之間,粒度會更大一些。
一個理解持續迭代的地方是解bug,任何bug,咱們都須要首先嚐試去重現它,作二分排除定位,作單元測試刷豆子,蒐集證據鏈,一步步掐頭去尾縮小範圍,最後解決。這也須要持續迭代。
持續迭代不只在節奏上保持緊湊,並且把過程漸進展開,咱們都知道軟件開發的敵人是黑盒子,不能預期的時間和進度,因此持續迭代的過程,咱們經過燃盡圖,issue管理,bug跟蹤,反覆把過程dump出來,讓進度可視化,促進軟件開發的正面化學反應和收斂。安全
while(rest>e){ step(); }
軟件開發,涉及到不少須要推理的地方,例如天天的解bug,這裏須要邏輯,也就須要充分必要。一個論點,它的論據是不是充分必要的,就是體現邏輯的地方。
其餘地方,例如作案例分析,咱們訓練思辨和分析,我想也應當是基於邏輯的。例如作需求分析,也是應該以是否符合邏輯爲核心,若是連本身都說服不了,泛泛而談的形式化需求分析,多半是須要被從新作的。因此,原則應當是,寫完本身讀一遍,根據是否充分必要去複審,也許須要補充數據,真實的數據很重要,有數據就能夠拿數聽說話,一個斷言在有數據支撐的狀況下,更可能有效。但使用數據要避免單樣本統計學家式的武斷,同時也要不失管中窺豹的洞察力,這大概須要反覆鍛鍊,反覆成功或者失敗。性能優化
程序員是帶工具屬性的,工程上,每一個小事情均可能有相關的工具能夠利用,若是沒有,咱們就造工具。一樣的管理源代碼,咱們有svn,git,當咱們赤手空拳,咱們合併別人的代碼,可能會先臨時拷貝本身新改動的代碼到某個臨時文件夾S,而後把別人的代碼覆蓋進來,完了再把S和其diff,再修改。用git,這個過程就是git stash,git pull,git stash pop,因此有時候只要想一下一個操做過程當本身沒有工具是是怎麼作的,可能工具也大概就是這麼作的,只是變成了更有效率的命令。工具也是符合邏輯的。
兩個團隊A和B。A沒作事,B不用工具作事,B比A強;A不用工具作事,B用工具作事,期待的是B比A更有效率的解決問題,不然B並不就比A強;若是兩隊都作事也都有效率使用工具,則能夠開始比內容。因此把那些提升效率的工具都用到習覺得常,瓶頸不卡在那些上面,咱們就進入比拼真正的最終目標上。反覆的訓練和使用,能夠達到這點。異步
一個任務,耗時估計的靠譜度跟作過這件事的次數有關,通常來講作過兩三次額估計就靠譜點。這也是有經驗公式可用。若是它是一個廣泛原理,咱們能夠利用它。從機率上來講,一個事情一次的成功率爲a,那麼,屢次以後的成功率是可計算的,手機打字就不展開了。能夠驗證,重試能夠增長成功率。因此,不少事第一次作,能夠預估會有失敗和錯誤,因此失敗和犯錯時冷靜的保存數據,證據,記錄,探測的這些點,均可以用來在重試時作可能的規避。不過不少人只嘗試了一次,這就回到了經典論述:寫100個helloworld不如對一個程序迭代100次。固然,咱們要考慮到人是複雜的,喜新厭舊是常態,並不能一律而論。由於,每一個人都是獨立的個體,選擇的自由正是這種平均值。重試要注意兩次之間是否收斂,若是不收斂,則重試只會致使隊列堆積,甚至引發雪崩,此時要檢查更深的問題。svn
我經常作過一件事之後,發現不少事情並不須要各類奇葩的創新點子之類。作着作着就會看到,作好一件事最須要的並非創新什麼的,而是:概念界定以後的基本功。說概念界定,是由於不少人對本身的職業角色定位不清,就會致使作的事情不能抓住基本點。而一旦界定了角色邊界,明確了基本點,那麼工做就變成如何完美的把那些基本點作到位上面。例如,保持節奏,從不拖延,持續迭代,細節的完備,以及堅持不越界的作不該該本身作(你得讓該作這件事的人去作,有原則對彼此都是一種輕鬆)。把基本功的細節作到位,就是一種職業素養,和專業主義。我想,這是重要的。我最怕角色不清,要麼認爲你應該什麼都作,要麼認爲你什麼都不要作,角色不清,系統的調度會混亂而沒有效率。一我的能夠作不一樣的事情,但最好在角色的語義上區分之。函數
所以,我也以爲不少事,其實能作到這些的人本身也均可以作好,未必得找別人。這和我經歷過處處找控件來組裝,到掌握組合控件的基本原理後不認爲有魔法控件同樣,省去了拿來主義。
當咱們預估,咱們會沒有充裕的時間作完整的過程,咱們能夠打時間差。咱們說對一個系統作性能優化,不外乎在時間和空間上作優化。若是一個系統或者一個過程要到達預期質量所要消耗的最低時間已經不可再壓縮,而且預估到時間總體上將呈現下滑趨勢,那麼就應該在一開始時間還足夠充裕的狀況下打提早量,經過一開始的緊湊有序的節奏把大部分腳手架都搭建起來,那麼越到後期越會從容和有條不紊,反之則會手忙腳亂。凡事預則立,不預則廢。
相反的作法是,對事情作惰性求值,直到咱們真正須要一個事情的結果時,纔會去作這件事,惰性求值有時候能最大限度減小當前要作的事情。可是,惰性求值至關於一次異步投遞任務到隊列的過程,隊列裏等待被作的事情會堆積,當須要在限定時間內求某個事情的結果時,隊列可能已經雪崩了。因此有隊列的地方就要防雪崩,隊列不能過長(根據優先級丟棄),保證你的隊列能夠在最低粒度時間片內被有序求值。若是你不想你必需要作的事情被丟棄,那麼那些事情能夠經過打時間差提早作掉,達到超出預期的效果。再說異步任務,異步任務均可能因爲各類緣由而不會有返回值,因此有異步就要有定時器,作超時監聽,一旦超時,作對應的處理。
不管是10進制,仍是10進制,亦或是點分10進制。它們都是版本號。咱們的人生就是在年輪的版本之間迭代。認真對待每一個版本,麻雀雖小,五臟俱全。每一個版本開始,明確本次版本的目標,屏蔽其餘,只指目標,當其達成,測試經過,打包,發佈,寫上:
版本 0.0.3
版本和版本之間,貴在持續,節奏均勻。版本的發佈日誌,就是一個diff。兩個集合,A和B的對稱差,就是發版的日誌。這讓我想起,從寫程序到如今,在各類場合寫過兩個數組,區間列表等的diff。不少時候,咱們都在作diff,我經常從程序處理的過程獲得一些概念,藉以類比或者理解生活的事情,然而並不將其泛化,人太容易只看到類比事物之間共性的地方,而其實事物的複雜更在於那些不一樣的地方。手裏有一把錘子,就處處找釘子的事情,永遠都有。
經典的生產者,消費者情景是這樣的:
這樣的過程,不斷執行的任務,獲取或者釋放系統資源,而系統資源變化能夠反饋到調度器的容許執行窗口,每一幀則從隊列裏取出窗口內的任務執行。
咱們說,這是一個擁塞控制。不作擁塞控制的狀況下,在執行的任務可能太少而沒有充分利用系統資源,或者在執行的任務太多而把系統資源競爭到卡死,不管怎樣,系統的資源利用率最飽和和任務的執行最多,是一個優化目標。因此,一個健壯的系統,有隊列的狀況下,要作擁塞控制。
擁賽控制的核心法則是:多還少補,在慢啓動、擁賽避免、快速恢復3個階段來回切換。
從瀑布到敏捷,有的人說我是classical的,嚴格的瀑布有序經典;有的人說,我是刪繁就簡的,小步敏捷迭代,螞蟻搬家。 就像我認爲角色須要分開,人員能夠合一。不管是學理上仍是實踐上,過程的不一樣階段是存在的,可是具體實施上可能會壓縮和合並。 Plan, Build,Test,基本的控制點在於這三者,側重點各不相同。全局一次,仍是反覆屢次,只是調度策略的不一樣。 假設過程是一條插值曲線,那麼分段插值曲線比全局插值曲線有更好的局部性,學過數值分析的應該都知道全局插值曲線在控制點多了以後,插值多項式的次數高,會有振盪現象,就是因爲局部性很差。