【舊文搬家】
(作者注:閱讀本文需要一定的編程經驗和對一些敏捷實踐芦拿,如TDD支示,有一定的了解)
編程广辰,眾所周知被定義為知識工作暇矫,所有的知識工作,從業(yè)者和門外漢都喜歡把它神秘化轨域,將整個過程以不可知論的風格來解釋袱耽。理由往往只是簡單粗暴的講訴一些體力工作時代形成的方法照搬到知識工作中來失敗的故事,也毫無理論依據干发。偶有幾個人寫理論理由朱巨,寫出來的理由跟癔癥者的囈語也無甚差別。我個人是反對將知識工作神秘化的枉长,我是科學管理原理的忠實粉絲冀续,我覺得盡管科學管理原理的具體案例都過時了,但泰勒的研究方法依然是工作的必峰,只是研究者和被研究者發(fā)生了一些微妙的變化洪唐。
彼得德魯克在《21世紀的管理挑戰(zhàn)》中提到,知識工作者需要自我管理吼蚁,那么很明顯不是體力工作時代形成的方法不能用在知識工作中凭需,而是不能指望個體之外的人對個體進行簡單的粗暴的分析和命令就可以形成很高的生產效率了问欠。這個分析和下命令的人必須是知識工作者自己,我們需要自己紀錄自己的行為粒蜈,然后分析顺献、優(yōu)化,才能得到生產力的提升枯怖,任何向外訴求都會很快的撞上一個“天花板”而無法提升注整。如果非要尋求外部控制,那么我們只能說度硝,對于新時代的管理者的定位肿轨,比起老板,更像老師蕊程,以引導和幫助訓練為主椒袍,每個人真正的效率提升主要還是要靠自己。
那么如文章標題所述藻茂,追求知識工作的一種——編程的效率槐沼,是本文關注的重點。但我們首先要聲明捌治,本文不是給一個可以直接產生高生產效率的方法,而是給一個可以可視化自己生產效率以找到瓶頸的方法纽窟。至少在不改變質量的前提下肖油,可以極大的提升你的效率,如果使用得當臂港,可能會質量和效率雙提升森枪。
本文引入的方法也并不新鮮,簡單說來审孽,就是任務列表法+PDCA的一套組合使用而已县袱。大道至簡,堅持者寡佑力,而堅持下來的人往往都可以獲得數倍的效率提升式散。
任務列表法
我們做任何事情都應該劃出任務列表,按照任務列表一項項去完成打颤,這不是什么特別少見的工作方式暴拄。然而,很多人的問題在于编饺,列出的問題列表不能達到完全窮盡乖篷,各自獨立。
完全窮盡是什么意思呢透且?
當我開始做事情的時候撕蔼,我不能把所有的事情窮盡,我列出的列表跟我做的事情是不完全等價的,這說明我們的工作行為是非尘ň冢混沌不可視的琳骡,哪怕是對自己。
有時事情看起來在大面上是窮盡了诉探,但是做的時候日熬,發(fā)現又出現了新的任務。那說明每一項任務的輸入和輸出沒有想清楚肾胯,所以當發(fā)現輸入輸出有欠缺的時候(主要是輸入竖席,輸出欠缺的結果也是要補輸入),就需要新的任務來準備輸入敬肚,于是任務列表就增加了毕荐,這也是一種沒有窮盡。
各自獨立是什么意思呢艳馒?
意味著憎亚,每一項任務都可以單獨做完,而不需要先做完其中一項任務弄慰,才能做完另一項第美。
假如我有三項任務
# 任務1
# 任務2
# 任務3
我做的時候,必須把任務2做完陆爽,任務1才能做完什往。任務3做完,任務2才能做完慌闭。結果我就從任務1開始一路做到任務3别威,最后再逐步回到任務1,整個過程非陈刻蓿混亂省古,那就不是各自獨立的。
在現實生活中想做到各項任務都獨立挑戰(zhàn)還是比較大丧失,但是在編程的世界里豺妓,挑戰(zhàn)沒有那么大,程序世界做到這一點真的太輕松了利花。優(yōu)秀的設計都是要求解耦的科侈,如果做不到,基本等于活兒比較爛炒事。
當我們做到任務的完全窮盡與各自獨立之后臀栈,我們任務列表法才算達標,這之后才能高效的工作挠乳,然而達到這一點并不是一蹴而就的权薯,沒有誰可以一上來就做到任務劃分可以完全窮盡姑躲、各自獨立,需要不停的刻意練習盟蚣。所以我們稱之為編程的精進之法黍析。
PDCA
PDCA是Plan-Do-Check-Action四個詞的組合。這是著名的戴明環(huán)屎开。講究從計劃開始阐枣,經過實踐,再反思奄抽,產生的改進行動再納入下一輪計劃的持續(xù)改進過程蔼两。
當我們把這一套從工業(yè)領域搬過來的時候,我們對計劃的理解還是工業(yè)領域那一套逞度。如果用在個人提升方面额划,我們應該把PDCA微觀化,這之后就有兩個問題需要被解答档泽,一個是Plan是什么俊戳?一個是Check什么?
第一個問題的答案是很顯然的馆匿,我們前面講的任務列表法就是在形成這個Plan抑胎。
第二個問題本身是一個母問題,每當我們對這個問題的回答渐北,都要回答一個衍生出來的子問題:我們要做點什么才能在需要Check的時候能夠Check圆恤。常用的套路有兩個:
- Plan的時候估計一個時間,然后開始做腔稀,做的時候計時,做完就要Check這個時間是否達標羽历,無論快了還是慢了(通常是比較明顯的差距才反思焊虏,比如20%以上的差距),Check都要反思并產生Action秕磷,納入到未來的Plan中去诵闭。
- 估計的任務列表和實際做的任務列表是否是一樣多的?往往是會多出來澎嚣,這時就要反思疏尿,自己在哪里有不足導致了這個差別。
這些反思往往是發(fā)現自己的問題易桃,比如自己不熟悉的知識點褥琐,不熟悉的方法,甚至不熟悉的業(yè)務知識晤郑,最后的Action也往往都是進行刻意練習來提升生產效率敌呈,比如反復練類似題目贸宏。有時也會是通過一些效率工具的使用來提升效率,比如抽取live template磕洪,使用快捷鍵吭练,只是效率工具的使用往往也需要刻意練習就是了。有時也可以通過復用技術(其實live template已經是復用技術了)來提升生產效率析显,然而可復用模式的識別與抽取本身也是需要練習的鲫咽,否則在那里糾結浪費的時間更長。
有些同學會感覺到谷异,記錄了時間卻不知道哪里有問題分尸,這個時候可以跟TDD相結合,把時間劃分為寫測試的時間晰绎,寫實現的時間和測試通過的時間寓落。其實除去這幾種時間,還有其他時間消耗荞下,比如調研的時間伶选。不管怎么劃分,將時間消耗結構化掉尖昏,一部分一部分的追求最高效率是一種可行的辦法仰税。
舉例
我們做一個簡單的修改用戶信息功能的API。那么我們在某一個Java技術棧上可能的任務列表是長這樣的:
1. 寫UserController (10分鐘)
2. 寫UserDAO (15分鐘)
當你真正開始做的時候抽诉,會碰到兩種主要的意外:
- 任務列表擴張
- 時間估計不準
我們下面就這個例子陨簇,講一講遇到這兩種意外,我們應該怎么反思和處理迹淌。
任務列表擴張
任務列表擴張河绽,顧名思義,就是指我們一開始估計的任務的數量隨著我們開始工作變的比預想的多唉窃,可能有兩種主要原因:
- 技術原因
- 業(yè)務原因
技術原因耙饰,比如在這個案例里面,第二項任務:寫UserDAO纹份,就是一個沒想清楚的事情苟跪。我們還需要建數據庫表,我們在一個有migration腳本支持的技術棧設計上工作蔓涧,我們還需要寫初始化腳本和回滾腳本件已,也許這是我的第一個表,所以我還得配置數據庫元暴,搞不好還要把ORM的基礎代碼都寫完篷扩,所以這些導致了我可能任務估少了。再比如茉盏,我們的項目規(guī)范要求我們Controller不能直接調DAO瞻惋,要在中間加一個Service厦滤,盡管我個人覺得這是一件很二的規(guī)范,然而規(guī)范就是規(guī)范歼狼,我對項目技術規(guī)范不熟悉結果導致我畫出來的任務缺少了一些必要的任務掏导。再比如,我們的項目采用的是Jersey羽峰,根本沒有Controller這么一個東西趟咆,那么不了解技術框架導致我的任務根本就劃錯了。
這種情況屬于我對技術了解不足梅屉,通過對任務列表擴張原因的Check值纱,我會得出一些Action:去了解技術規(guī)范,去深入了解項目的技術架構坯汤,現有的代碼虐唠,以防止以后的任務畫錯。
業(yè)務原因惰聂,也比如在這個例子里疆偿,我們的系統(tǒng)需要在更新用戶信息的API里不能更新密碼,所以我們還需要一個專門的修改密碼的API搓幌。再比如杆故,這是一個遺留系統(tǒng),用戶信息的修改會觸發(fā)數據庫里的一系列觸發(fā)器溉愁,從而修改系統(tǒng)的其他數據处铛,然而有些修改是有前提的,那么我就需要更多的任務去處理這些前提條件拐揭;或者當數據變化時撤蟆,要求我去修改系統(tǒng)里的其他數據,那么我就需要更多的任務去完成這些工作堂污。
這種情況屬于我對整個系統(tǒng)的業(yè)務了解不足枫疆,通過對任務列表擴張原因的Check,我會得出一些Action:通讀數據庫表敷鸦,通讀代碼,更全面的閱讀需求寝贡,或者跟需求方更多的溝通扒披,以了解業(yè)務。
時間估計不準
時間估計不準就簡單了很多圃泡,在這個例子里碟案,就是這兩個任務我估計的時間與我做的時間不相匹配∑睦可能的主要原因也有三個:
- 任務列表擴張了价说,但是我沒意識到辆亏,比如UserDAO寫起來沒有我想的那么簡單,所以多花了時間呢簸;
- 單純的技術不熟練抖韩;
- 花了太多時間在糾結上藤树;
對于隱藏的任務列表擴張,時間估計不準給了我們一個很好的線索去發(fā)現彻磁。一旦發(fā)現了,可以前文所述去處理狸捅,也就不再贅述
對于單純的技術不熟練衷蜓,就如前文所述,要去設計刻意練習尘喝。比如我就曾設計過對數據庫的增刪改查的一組訓練以提升自己的速度磁浇,使得我即便使用TDD依然保持一個極高的速度。我們自己沒有意識到朽褪,基礎能力的不熟練對于我們的高級能力的限制有多嚴重置吓,這種體驗也只有基礎能力已經熟練的人去教基礎能力不熟練的人一些高級技能的時候才會發(fā)現。這種視而不見的收益鞍匾,使得大多數人都會輕視基本功的練習交洗。哪怕已經獲得收益的人,也容易鼓吹要更多的啟發(fā)而忽略了基本功的價值橡淑。
對于花了太多時間在糾結上构拳,這其實也是一種不熟練,是對設計知識和能力的不熟練梁棠。之前看的設計知識只能有一個大概的感覺置森,對于每個知識的邊界、使用之后的發(fā)展符糊、如何從一種設計過渡為另一種設計了解不清凫海,從而害怕在那一刻犯錯。實際上真正值得糾結的部分沒有那么多男娄,大多是自己嚇自己行贪,或者引入了過度設計。當然也有一種情況是暴露出了架構級的問題模闲,比如我們對于應該提出的原則性規(guī)范沒有提出建瘫,所以導致我們每個地方都要現想,大家可以想象沒有RESTful之前設計Web API尸折,我們可能真的是每一個API都現想的啰脚,有了它之后,我們的糾結時間就變少了实夹。這種情況下橄浓,通過本方法粒梦,架構師也算是有了相應的數據支持,那么架構師也就有了發(fā)現問題的一種工具荸实。
結論
總的來說匀们,任務列表法+PDCA式工作法形成的組合方法,是一個通過逐漸提升個人能力以達到高效工作的方法泪勒。這兩種方法單獨拿出來用昼蛀,都會由于各自的局限而有各自的天花板,只有有機的結合才能真正突破這個天花板圆存。剛開始使用起來叼旋,對于很多人來說會有一些痛苦,這一點上我只能說沦辙,提升就是痛苦的夫植,而新的習慣一旦養(yǎng)成,痛苦也就不翼而飛油讯,所以美國心理學之父威廉詹姆士說详民,“我們需要在盡可能早的時候,讓盡可能多的有用的動作變成自動的和習慣的……一段痛苦的艱難時期之后就是自由的時光”陌兑。當我們基礎能力達到一個極高的效率之后沈跨,我們會發(fā)現我們爭取自由的籌碼會變得更多。
廣告時間
有人可能會覺得列出符合上文所述標準的任務列表比較難兔综,歡迎閱讀拙作《像機器一樣思考》系列文章:
像機器一樣思考(一)—— 宏觀的基礎
像機器一樣思考(二)—— 數據的細節(jié)
像機器一樣思考(三)—— 窮盡就是力量
像機器一樣思考(四)—— 一圖抵千言
像機器一樣思考(五)—— 第一個應用
像機器一樣思考(六) —— 腦中的重構
像機器一樣思考(七) —— 跨應用思考