掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
我之前寫過(guò)一篇叫《加班與效率》的文章,從概念上說(shuō)了一些我對(duì)“效率”的認(rèn)識(shí),但是那篇文章趨于概念化,對(duì)于一些沒(méi)有經(jīng)歷過(guò)這樣的環(huán)境的同學(xué)來(lái)說(shuō),可能會(huì)覺(jué)得太抽象了。很早以前就想寫一篇更具體一點(diǎn)的,可執(zhí)行的文章與《加班與效率》這篇文章相輝映,并再把我兩年前在杭州QCon上的那個(gè)“鼓吹工程師文化”的《建一支強(qiáng)大的小團(tuán)隊(duì)》(新浪微盤)的觀點(diǎn)再加強(qiáng)一下。

但是我遇到了一些思維方式上的麻煩——我講的總是從我的經(jīng)歷背景出發(fā),沒(méi)有從其它人的經(jīng)歷背景來(lái)講。這就好像,我在酷殼里說(shuō)了很多東西(比如:專職的QA,Code Review很重要,編程年齡,創(chuàng)業(yè)的,Rework的……),有好些人覺(jué)得是不可能甚至太理想,其實(shí)我說(shuō)的那些東西都是實(shí)實(shí)在在存在的,也是我所經(jīng)歷過(guò)的。于是,不同的經(jīng)歷,不同的環(huán)境,不同的眼界,造成了——有些人不理解我說(shuō)的,而我也不能理解他們所說(shuō)的。
所以,過(guò)去的這段時(shí)間我一有機(jī)會(huì)就找一些人交流并觀察一些身邊的事情,并去試著跟從和理解那些我不能理解的東西?,F(xiàn)在覺(jué)得差不多了,所以,寫下了這篇文章。(但越是去理解對(duì)方,我就越堅(jiān)持我的觀點(diǎn),所以這篇文章可能還是會(huì)出現(xiàn)雞同鴨講的情形,無(wú)所謂了)
本文不討論任何業(yè)務(wù)上的效率問(wèn)題,只討論軟件開(kāi)發(fā)或是軟件工程中的效率問(wèn)題。雖然產(chǎn)品和業(yè)務(wù)上的效率問(wèn)題是根本,但是因?yàn)楸疚牟皇抢鸷薜?,我也不想混在一起談,所以?qǐng)?jiān)徫以谶@里先說(shuō)開(kāi)發(fā)團(tuán)隊(duì)的,以后重新開(kāi)篇文章專門談產(chǎn)品和業(yè)務(wù)的。
我下面會(huì)羅列幾個(gè)非常典型的開(kāi)發(fā)方式——軟件開(kāi)發(fā)中的“鎖”,接力棒式軟件開(kāi)發(fā),保姆式軟件開(kāi)發(fā),WatchDog軟件開(kāi)發(fā),故障驅(qū)動(dòng)式軟件開(kāi)發(fā)。
如果你搞過(guò)并發(fā)編程,你一定知道什么是“鎖”,鎖就是用來(lái)同步和互斥。我發(fā)現(xiàn)有好些開(kāi)發(fā)部門里的各個(gè)開(kāi)發(fā)團(tuán)隊(duì)間存在很多鎖。比如:
我上面并非瞎扯,這都是事實(shí)。我們可以看到,
有時(shí)候,我們會(huì)覺(jué)得分工和分模塊是產(chǎn)生效率的前提,但是實(shí)際情況并不是這樣。我們也可以看到,所謂的“分工”被徹徹底底的濫用了。他們把“分工”當(dāng)成了永遠(yuǎn)只干一件事的借口。
一個(gè)程序員應(yīng)該能夠掌握多個(gè)語(yǔ)言,也能夠負(fù)責(zé)多個(gè)模塊甚至不同的職責(zé)。如果一個(gè)程序員覺(jué)得多學(xué)習(xí)一門語(yǔ)言,多掌握一個(gè)模塊是件很困難的事,那么這個(gè)程序員本質(zhì)上是不合格的。
在有各種“工作鎖”的軟件開(kāi)發(fā)團(tuán)隊(duì)里,一般都無(wú)法避免“接力棒式”的開(kāi)發(fā)。也就是說(shuō),底層的C程序員干完了,交給上層的Java程序員,然后再交給更上層的前端程序員,***再交給運(yùn)維人員。這就是接力棒式的開(kāi)發(fā)。
而且,更糟糕的是,如果在引入了軟件流程下,這種“接力棒的方式”真是會(huì)把你搞崩潰的。比如下游團(tuán)隊(duì)開(kāi)發(fā)一個(gè)月,交給QA測(cè)試一個(gè)月,再交給運(yùn)維分步上線一個(gè)月,然后,上游團(tuán)隊(duì)拿到下游開(kāi)發(fā)的API后開(kāi)發(fā)一個(gè)月,再交給自己的QA測(cè)試一個(gè)月,然后再交給自己的運(yùn)維上線一個(gè)月,于是,半年就這樣過(guò)去了。這是一個(gè)由一個(gè)一個(gè)小瀑布疊出來(lái)的一個(gè)大瀑布。
哦,你會(huì)說(shuō),這個(gè)好辦啊,上下游不會(huì)先商定好接口么?然后做并行開(kāi)發(fā)么?是的,這是其中的一個(gè)優(yōu)化方式,但是需要很好的接口設(shè)計(jì)。但是,在實(shí)際過(guò)程中,你會(huì)發(fā)現(xiàn)(這時(shí)我并非信口開(kāi)河,我說(shuō)的都是事實(shí)),
我以前寫過(guò)一篇叫《IoC/DIP其實(shí)是一種管理思想》,對(duì)于這種接力棒的方式,應(yīng)該反過(guò)來(lái),如果業(yè)務(wù)應(yīng)用團(tuán)隊(duì)是A團(tuán)隊(duì),那B/C/D團(tuán)隊(duì)?wèi)?yīng)該把自己的做成一個(gè)開(kāi)發(fā)框架也好,服務(wù)化也好,讓應(yīng)用團(tuán)隊(duì)自己來(lái)接入。比如:前端做好一個(gè)前端開(kāi)發(fā)框架,PE做好一個(gè)運(yùn)維開(kāi)發(fā)框架、各種工具,共享模塊團(tuán)隊(duì)做好開(kāi)發(fā)框架,讓應(yīng)用團(tuán)隊(duì)自己來(lái)接入,而不是幫他做。你會(huì)發(fā)現(xiàn),在這么多團(tuán)隊(duì)各自P2P勾兌出來(lái)的很隨意的接口的所帶來(lái)的成本已經(jīng)遠(yuǎn)超過(guò)一個(gè)統(tǒng)一標(biāo)準(zhǔn)的協(xié)議。
所謂“保姆式”軟件開(kāi)發(fā)就是——我只管吃飯,不管做菜洗碗,就像——衣來(lái)伸手,飯來(lái)張口的“小皇帝”一樣,身邊有一堆太監(jiān)或?qū)m女,不然生活不能自理。這種情況經(jīng)常見(jiàn)于開(kāi)發(fā)和測(cè)試,開(kāi)發(fā)和運(yùn)維間的關(guān)系。很多公司,測(cè)試和運(yùn)維都成了開(kāi)發(fā)的保姆。
我就能看到,很多開(kāi)發(fā)快速寫完代碼后基本上都不怎么測(cè)試就交給QA去測(cè)試了,QA一測(cè),我草,各種問(wèn)題,而只會(huì)做黑盒的QA并不能馬上就能確定是代碼的問(wèn)題還是環(huán)境的問(wèn)題,所以還要花大量時(shí)間排除不是環(huán)境問(wèn)題,才給開(kāi)發(fā)報(bào)BUG。很多問(wèn)題,可能只需要做個(gè)Code Review,做個(gè)單測(cè)就可以發(fā)現(xiàn)了,硬要交給QA。運(yùn)維也是一樣的,開(kāi)發(fā)出來(lái)的軟件根本就沒(méi)有考慮什么運(yùn)維的東西,因?yàn)橛羞\(yùn)維人員,所以我才不考慮呢。
這和我們帶孩子的道理是一樣的,對(duì)于孩子來(lái)說(shuō),如果父母幫孩子做得越多,孩子就越覺(jué)得理所應(yīng)當(dāng),就越不會(huì)去做。
“保姆式”開(kāi)發(fā)一般會(huì)進(jìn)化成“保安式”開(kāi)發(fā)。
就這樣,你不行,我找人來(lái)看著你,看你的人不行,我再找人來(lái)看著看你的人……層層保姆,層層保安。于是,你就會(huì)發(fā)現(xiàn),團(tuán)隊(duì)或部門里的人員越來(lái)越多,你整天都在開(kāi)會(huì),整天都在互相解釋,互相爭(zhēng)吵,會(huì)扯淡的人越來(lái)越多。那還有個(gè)屁的效率。
網(wǎng)絡(luò)上一個(gè)非常經(jīng)典的圖片,來(lái)源不詳,程序員在挖坑,其它人站在當(dāng)監(jiān)工
1)不要招只會(huì)寫代碼的“碼農(nóng)”,要招懂“需求”,注重“軟件工程”和“軟件質(zhì)量”和“軟件維護(hù)”的“工程師”。
2)***的管理,不是找人來(lái)管人,而是自己管自己。
3)組織和團(tuán)隊(duì)中支持性工作的人越少越好,***不要。
4)服務(wù)化。我服務(wù)于你并不代表我要幫你干活,而是代表——我要讓你干活干得更爽。
我在微博上說(shuō)過(guò)下面的話,(大家可以體會(huì)一下保姆和服務(wù)的差別)
運(yùn)維要用“云服務(wù)”的思路去做。如果一個(gè)公司內(nèi)的運(yùn)維團(tuán)隊(duì)開(kāi)發(fā)出一堆工具,讓做應(yīng)用開(kāi)發(fā)團(tuán)隊(duì)可以很容易地申請(qǐng)機(jī)器、存儲(chǔ)、網(wǎng)絡(luò)、中間件、安全等資源,并很容易管理、監(jiān)控和部署應(yīng)用,并提供運(yùn)維資詢。而不是幫應(yīng)用開(kāi)發(fā)團(tuán)隊(duì)干活擦屁股當(dāng)保姆。那么,這個(gè)公司就會(huì)不經(jīng)意地做出一個(gè)云計(jì)算平臺(tái)來(lái)了。
什么是WatchDog?就是說(shuō)——為了解決某個(gè)系統(tǒng)的問(wèn)題,我要用一個(gè)新的系統(tǒng)去看著它。
做加法誰(shuí)不會(huì)?就不想去簡(jiǎn)化一樣系統(tǒng)嗎?就不能不拆東墻補(bǔ)西墻么?這些了系統(tǒng)加的越來(lái)越多,我看你以后怎么運(yùn)維。
一開(kāi)始沒(méi)有想清楚就放到線上,然后,出了故障后,也無(wú)法重新設(shè)計(jì)和重新架構(gòu),只能以打補(bǔ)丁地方式往上打,這就好像一個(gè)本來(lái)就有缺陷的樓沒(méi)有蓋好,你要拆了重蓋是不可能的,也只能不停地打補(bǔ)丁了。字是一只狗,越描越丑。
1)設(shè)計(jì)想好了再做,多評(píng)估幾個(gè)設(shè)計(jì)沒(méi)壞處,簡(jiǎn)化,簡(jiǎn)化,簡(jiǎn)化。
2)殘酷無(wú)情地還債,就算是CEO來(lái)了,也無(wú)法阻止我還債的腳步。
WatchDog式的軟件開(kāi)發(fā)通常來(lái)說(shuō)都是“故障驅(qū)動(dòng)式”軟件開(kāi)發(fā)的產(chǎn)物。這種開(kāi)發(fā)方式其實(shí)就是在表明自己智力和能力的不足。以上線為目的,上了線再說(shuō),有什么問(wèn)題出了再改。
上面的老大或是業(yè)務(wù)方基本上會(huì)說(shuō),沒(méi)關(guān)系,我們不一開(kāi)始并不需要一個(gè)***的系統(tǒng),你先上了再說(shuō),先解業(yè)務(wù)的渴,我們后面有時(shí)間再重構(gòu)再完善。而有的技術(shù)人員也會(huì)用“架構(gòu)和設(shè)計(jì)是逐步演化出來(lái)的”這句話來(lái)證明“故障驅(qū)動(dòng)”開(kāi)發(fā)是值得的。
我同意逐步迭代以及架構(gòu)演化論,但是,我覺(jué)得“系統(tǒng)迭代說(shuō)”和“架構(gòu)演化論”被徹徹底底地成為那些能力有限甚至不學(xué)無(wú)術(shù)的人的超級(jí)借口。
你們有沒(méi)有搞錯(cuò)???你們知道什么叫迭代,什么叫演化嗎?你們知道,要定位一個(gè)線上的故障需要花多大的力氣嗎?(看看這篇文章你就知道了)你們知道,隨隨便便去應(yīng)付局部上你會(huì)快,但總體上來(lái)說(shuō)你會(huì)慢。
雖然,我看到那些系統(tǒng)在一個(gè)又一個(gè)的故障后得到一點(diǎn)又一點(diǎn)的改善,但是我想說(shuō),為什么一開(kāi)始不認(rèn)真不嚴(yán)謹(jǐn)一點(diǎn)呢?我從來(lái)就沒(méi)有見(jiàn)過(guò)一個(gè)精良的系統(tǒng)是靠一個(gè)一個(gè)的故障和失敗案例給堆出來(lái)的,就算是Windows 95/98這樣史上最爛的操作系統(tǒng),如果沒(méi)有設(shè)計(jì)精良Windows NT的補(bǔ)位,Windows也早玩完了(看看IE的下場(chǎng)就知道了)。
1)基礎(chǔ)知識(shí)和理論知識(shí)非常重要。多多使用已有的成熟的方案是關(guān)鍵。
2)對(duì)技術(shù)要有一顆嚴(yán)謹(jǐn)和敬畏的心。想清楚了再干,堅(jiān)持高標(biāo)準(zhǔn),Design for failure!很多事情都急不得。
其實(shí),這樣的事情還有很多。比如:
1)配置管理上的問(wèn)題。對(duì)于源代碼的配置管理,其實(shí)并不是一件簡(jiǎn)單的事情。配置管理和軟件和團(tuán)隊(duì)的組構(gòu)的結(jié)構(gòu)非常有關(guān)系。我看到過(guò)兩種非常沒(méi)有效率的配置管理,一種是以開(kāi)項(xiàng)目分支的方式來(lái)做項(xiàng)目,同時(shí)開(kāi)很多分支,分支開(kāi)的時(shí)間還很長(zhǎng),導(dǎo)致merge回主干要花大量的時(shí)間去解決各種沖突,另一種是N多的團(tuán)隊(duì)都在一個(gè)代碼庫(kù)中做修改,導(dǎo)致出現(xiàn)很多復(fù)雜的問(wèn)題,比如某團(tuán)隊(duì)的改動(dòng)出現(xiàn)了一個(gè)bug,要么所有的團(tuán)隊(duì)的功能都得等這個(gè)bug被修復(fù)才能被發(fā)布,要么就是把所有的改動(dòng)回滾到上一個(gè)版本,包括其它團(tuán)隊(duì)開(kāi)發(fā)的功能。很明顯,軟件模塊的結(jié)構(gòu),軟件的架構(gòu),以及團(tuán)隊(duì)的組織形式都會(huì)嚴(yán)重影響開(kāi)發(fā)效率。
2)人肉式的軟件開(kāi)發(fā)。大多數(shù)的軟件團(tuán)隊(duì)和主管都會(huì)用“人手不夠”做為自己開(kāi)發(fā)效率不夠的借口,而大多數(shù)故障發(fā)生的時(shí)候,都會(huì)使用更重的“人肉流程”來(lái)彌補(bǔ)自己能力的不足。他們從來(lái)沒(méi)有想過(guò)使用“技術(shù)”,使用更“聰明”的方式來(lái)解決問(wèn)題。
3)會(huì)議驅(qū)動(dòng)式開(kāi)發(fā)。人多了,團(tuán)隊(duì)多了,想法也就多了,溝通也就多了,于是需要不停得開(kāi)會(huì)開(kāi)會(huì)開(kāi)會(huì)。
綜上所述,我有如下總結(jié):
1)軟件工程師分工分得越細(xì)這個(gè)團(tuán)隊(duì)就越?jīng)]效率,團(tuán)隊(duì)間的服務(wù)化是關(guān)鍵的關(guān)鍵。不管是從語(yǔ)言上還是從軟件模塊上的人員分工,越細(xì)越糟糕。服務(wù)化不是我要幫你做事,而是我讓你做起事來(lái)更容易。
2)你總需要在一個(gè)環(huán)節(jié)上認(rèn)真,這個(gè)環(huán)節(jié)越往前就越有效率,越往后你就越?jīng)]效率。要么你設(shè)計(jì)和編碼認(rèn)真點(diǎn),不然,你就得在測(cè)試上認(rèn)真點(diǎn)。要是你設(shè)計(jì)、編碼、測(cè)試都不認(rèn)真,那你就得在運(yùn)維上認(rèn)真,就得在處理故障上認(rèn)真。你總需要在一個(gè)地方認(rèn)真。另外一篇文章你可以看一下——《多些時(shí)間少寫些代碼》
3)“小而精的團(tuán)隊(duì)”+“條件和資源受限”是效率的根本。只有團(tuán)隊(duì)小,內(nèi)耗才會(huì)小,只有條件或資源受限,才會(huì)逼著你去用最經(jīng)濟(jì)的手段做最有價(jià)值的事,才會(huì)逼著你喜歡簡(jiǎn)單和簡(jiǎn)化。
4)技術(shù)債是不能欠的,要?dú)埧釤o(wú)情地還債。很多事情,一開(kāi)始不會(huì)有,那么就永遠(yuǎn)不會(huì)有。一旦一個(gè)事情爛了,后面只能跟著一起爛,爛得越多,就越?jīng)]有人敢去還債。
5)軟件架構(gòu)上要松耦合,團(tuán)隊(duì)組織上要緊耦合。
6)工程師文化是關(guān)鍵,重視過(guò)程就是重視結(jié)果。只重視結(jié)果的KPI等同于“竭澤而漁”和“飲鴆止渴”。
(全文完)

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流