【舊文搬家】
(作者注:閱讀本文需要一定的編程經驗和對一些敏捷實踐,如TDD,有一定的了解)
編程,眾所周知被定義為知識工作,所有的知識工作,從業者和門外漢都喜歡把它神秘化,將整個過程以不可知論的風格來解釋。理由往往只是簡單粗暴的講訴一些體力工作時代形成的方法照搬到知識工作中來失敗的故事,也毫無理論依據。偶有幾個人寫理論理由,寫出來的理由跟癔癥者的囈語也無甚差別。我個人是反對將知識工作神秘化的,我是科學管理原理的忠實粉絲,我覺得盡管科學管理原理的具體案例都過時了,但泰勒的研究方法依然是工作的,只是研究者和被研究者發生了一些微妙的變化。
彼得德魯克在《21世紀的管理挑戰》中提到,知識工作者需要自我管理,那么很明顯不是體力工作時代形成的方法不能用在知識工作中,而是不能指望個體之外的人對個體進行簡單的粗暴的分析和命令就可以形成很高的生產效率了。這個分析和下命令的人必須是知識工作者自己,我們需要自己紀錄自己的行為,然后分析、優化,才能得到生產力的提升,任何向外訴求都會很快的撞上一個“天花板”而無法提升。如果非要尋求外部控制,那么我們只能說,對于新時代的管理者的定位,比起老板,更像老師,以引導和幫助訓練為主,每個人真正的效率提升主要還是要靠自己。
那么如文章標題所述,追求知識工作的一種——編程的效率,是本文關注的重點。但我們首先要聲明,本文不是給一個可以直接產生高生產效率的方法,而是給一個可以可視化自己生產效率以找到瓶頸的方法。至少在不改變質量的前提下,可以極大的提升你的效率,如果使用得當,可能會質量和效率雙提升。
本文引入的方法也并不新鮮,簡單說來,就是任務列表法+PDCA的一套組合使用而已。大道至簡,堅持者寡,而堅持下來的人往往都可以獲得數倍的效率提升。
任務列表法
我們做任何事情都應該劃出任務列表,按照任務列表一項項去完成,這不是什么特別少見的工作方式。然而,很多人的問題在于,列出的問題列表不能達到完全窮盡,各自獨立。
完全窮盡是什么意思呢?
當我開始做事情的時候,我不能把所有的事情窮盡,我列出的列表跟我做的事情是不完全等價的,這說明我們的工作行為是非常混沌不可視的,哪怕是對自己。
有時事情看起來在大面上是窮盡了,但是做的時候,發現又出現了新的任務。那說明每一項任務的輸入和輸出沒有想清楚,所以當發現輸入輸出有欠缺的時候(主要是輸入,輸出欠缺的結果也是要補輸入),就需要新的任務來準備輸入,于是任務列表就增加了,這也是一種沒有窮盡。
各自獨立是什么意思呢?
意味著,每一項任務都可以單獨做完,而不需要先做完其中一項任務,才能做完另一項。
假如我有三項任務
# 任務1
# 任務2
# 任務3
我做的時候,必須把任務2做完,任務1才能做完。任務3做完,任務2才能做完。結果我就從任務1開始一路做到任務3,最后再逐步回到任務1,整個過程非常混亂,那就不是各自獨立的。
在現實生活中想做到各項任務都獨立挑戰還是比較大,但是在編程的世界里,挑戰沒有那么大,程序世界做到這一點真的太輕松了。優秀的設計都是要求解耦的,如果做不到,基本等于活兒比較爛。
當我們做到任務的完全窮盡與各自獨立之后,我們任務列表法才算達標,這之后才能高效的工作,然而達到這一點并不是一蹴而就的,沒有誰可以一上來就做到任務劃分可以完全窮盡、各自獨立,需要不停的刻意練習。所以我們稱之為編程的精進之法。
PDCA
PDCA是Plan-Do-Check-Action四個詞的組合。這是著名的戴明環。講究從計劃開始,經過實踐,再反思,產生的改進行動再納入下一輪計劃的持續改進過程。
當我們把這一套從工業領域搬過來的時候,我們對計劃的理解還是工業領域那一套。如果用在個人提升方面,我們應該把PDCA微觀化,這之后就有兩個問題需要被解答,一個是Plan是什么?一個是Check什么?
第一個問題的答案是很顯然的,我們前面講的任務列表法就是在形成這個Plan。
第二個問題本身是一個母問題,每當我們對這個問題的回答,都要回答一個衍生出來的子問題:我們要做點什么才能在需要Check的時候能夠Check。常用的套路有兩個:
- Plan的時候估計一個時間,然后開始做,做的時候計時,做完就要Check這個時間是否達標,無論快了還是慢了(通常是比較明顯的差距才反思,比如20%以上的差距),Check都要反思并產生Action,納入到未來的Plan中去。
- 估計的任務列表和實際做的任務列表是否是一樣多的?往往是會多出來,這時就要反思,自己在哪里有不足導致了這個差別。
這些反思往往是發現自己的問題,比如自己不熟悉的知識點,不熟悉的方法,甚至不熟悉的業務知識,最后的Action也往往都是進行刻意練習來提升生產效率,比如反復練類似題目。有時也會是通過一些效率工具的使用來提升效率,比如抽取live template,使用快捷鍵,只是效率工具的使用往往也需要刻意練習就是了。有時也可以通過復用技術(其實live template已經是復用技術了)來提升生產效率,然而可復用模式的識別與抽取本身也是需要練習的,否則在那里糾結浪費的時間更長。
有些同學會感覺到,記錄了時間卻不知道哪里有問題,這個時候可以跟TDD相結合,把時間劃分為寫測試的時間,寫實現的時間和測試通過的時間。其實除去這幾種時間,還有其他時間消耗,比如調研的時間。不管怎么劃分,將時間消耗結構化掉,一部分一部分的追求最高效率是一種可行的辦法。
舉例
我們做一個簡單的修改用戶信息功能的API。那么我們在某一個Java技術棧上可能的任務列表是長這樣的:
1. 寫UserController (10分鐘)
2. 寫UserDAO (15分鐘)
當你真正開始做的時候,會碰到兩種主要的意外:
- 任務列表擴張
- 時間估計不準
我們下面就這個例子,講一講遇到這兩種意外,我們應該怎么反思和處理。
任務列表擴張
任務列表擴張,顧名思義,就是指我們一開始估計的任務的數量隨著我們開始工作變的比預想的多,可能有兩種主要原因:
- 技術原因
- 業務原因
技術原因,比如在這個案例里面,第二項任務:寫UserDAO,就是一個沒想清楚的事情。我們還需要建數據庫表,我們在一個有migration腳本支持的技術棧設計上工作,我們還需要寫初始化腳本和回滾腳本,也許這是我的第一個表,所以我還得配置數據庫,搞不好還要把ORM的基礎代碼都寫完,所以這些導致了我可能任務估少了。再比如,我們的項目規范要求我們Controller不能直接調DAO,要在中間加一個Service,盡管我個人覺得這是一件很二的規范,然而規范就是規范,我對項目技術規范不熟悉結果導致我畫出來的任務缺少了一些必要的任務。再比如,我們的項目采用的是Jersey,根本沒有Controller這么一個東西,那么不了解技術框架導致我的任務根本就劃錯了。
這種情況屬于我對技術了解不足,通過對任務列表擴張原因的Check,我會得出一些Action:去了解技術規范,去深入了解項目的技術架構,現有的代碼,以防止以后的任務畫錯。
業務原因,也比如在這個例子里,我們的系統需要在更新用戶信息的API里不能更新密碼,所以我們還需要一個專門的修改密碼的API。再比如,這是一個遺留系統,用戶信息的修改會觸發數據庫里的一系列觸發器,從而修改系統的其他數據,然而有些修改是有前提的,那么我就需要更多的任務去處理這些前提條件;或者當數據變化時,要求我去修改系統里的其他數據,那么我就需要更多的任務去完成這些工作。
這種情況屬于我對整個系統的業務了解不足,通過對任務列表擴張原因的Check,我會得出一些Action:通讀數據庫表,通讀代碼,更全面的閱讀需求,或者跟需求方更多的溝通,以了解業務。
時間估計不準
時間估計不準就簡單了很多,在這個例子里,就是這兩個任務我估計的時間與我做的時間不相匹配。可能的主要原因也有三個:
- 任務列表擴張了,但是我沒意識到,比如UserDAO寫起來沒有我想的那么簡單,所以多花了時間;
- 單純的技術不熟練;
- 花了太多時間在糾結上;
對于隱藏的任務列表擴張,時間估計不準給了我們一個很好的線索去發現。一旦發現了,可以前文所述去處理,也就不再贅述
對于單純的技術不熟練,就如前文所述,要去設計刻意練習。比如我就曾設計過對數據庫的增刪改查的一組訓練以提升自己的速度,使得我即便使用TDD依然保持一個極高的速度。我們自己沒有意識到,基礎能力的不熟練對于我們的高級能力的限制有多嚴重,這種體驗也只有基礎能力已經熟練的人去教基礎能力不熟練的人一些高級技能的時候才會發現。這種視而不見的收益,使得大多數人都會輕視基本功的練習。哪怕已經獲得收益的人,也容易鼓吹要更多的啟發而忽略了基本功的價值。
對于花了太多時間在糾結上,這其實也是一種不熟練,是對設計知識和能力的不熟練。之前看的設計知識只能有一個大概的感覺,對于每個知識的邊界、使用之后的發展、如何從一種設計過渡為另一種設計了解不清,從而害怕在那一刻犯錯。實際上真正值得糾結的部分沒有那么多,大多是自己嚇自己,或者引入了過度設計。當然也有一種情況是暴露出了架構級的問題,比如我們對于應該提出的原則性規范沒有提出,所以導致我們每個地方都要現想,大家可以想象沒有RESTful之前設計Web API,我們可能真的是每一個API都現想的,有了它之后,我們的糾結時間就變少了。這種情況下,通過本方法,架構師也算是有了相應的數據支持,那么架構師也就有了發現問題的一種工具。
結論
總的來說,任務列表法+PDCA式工作法形成的組合方法,是一個通過逐漸提升個人能力以達到高效工作的方法。這兩種方法單獨拿出來用,都會由于各自的局限而有各自的天花板,只有有機的結合才能真正突破這個天花板。剛開始使用起來,對于很多人來說會有一些痛苦,這一點上我只能說,提升就是痛苦的,而新的習慣一旦養成,痛苦也就不翼而飛,所以美國心理學之父威廉詹姆士說,“我們需要在盡可能早的時候,讓盡可能多的有用的動作變成自動的和習慣的……一段痛苦的艱難時期之后就是自由的時光”。當我們基礎能力達到一個極高的效率之后,我們會發現我們爭取自由的籌碼會變得更多。
廣告時間
有人可能會覺得列出符合上文所述標準的任務列表比較難,歡迎閱讀拙作《像機器一樣思考》系列文章:
像機器一樣思考(一)—— 宏觀的基礎
像機器一樣思考(二)—— 數據的細節
像機器一樣思考(三)—— 窮盡就是力量
像機器一樣思考(四)—— 一圖抵千言
像機器一樣思考(五)—— 第一個應用
像機器一樣思考(六) —— 腦中的重構
像機器一樣思考(七) —— 跨應用思考