從敲下第一個(gè)字符開始燎含,八阿哥(Bug)就是磨人的小妖精宾濒,形影不離,簡(jiǎn)直比真愛還要真愛屏箍。
隨著項(xiàng)目的擴(kuò)大绘梦,功能的增加,Bug出得越來越快赴魁,越來越多卸奉,Buglist變的越來越長(zhǎng)。
慢慢地颖御,項(xiàng)目的節(jié)奏明顯變慢榄棵,F(xiàn)eature越來越難增加,Bugfix的時(shí)間越來越長(zhǎng)潘拱,團(tuán)隊(duì)逐漸變得死氣沉沉疹鳄,原本溫順的程序猿變得暴躁,進(jìn)而演變成團(tuán)隊(duì)成員流動(dòng)性提高芦岂,流失率提高瘪弓。
總結(jié)我個(gè)人的工作經(jīng)驗(yàn),以及參照業(yè)內(nèi)的一些文章禽最,這種變化的軌跡也非常典型腺怯。
1、一個(gè)新Feature會(huì)與已有的Feature產(chǎn)生聯(lián)系川无,也會(huì)依賴于已有的組件呛占。而這些舊Feature或組件,因?yàn)橛蠦ug還沒處理好懦趋,接口不穩(wěn)定晾虑,行為不可控。一個(gè)依賴于不穩(wěn)定的系統(tǒng)的系統(tǒng),必然是不穩(wěn)定的走贪。
2佛猛、一個(gè)依賴于不穩(wěn)定的組件而組成的系統(tǒng)惑芭,要讓其相對(duì)穩(wěn)定地工作坠狡,必然需要在其內(nèi)部添加修正,也就是workaround遂跟。其內(nèi)部邏輯逃沿,需要實(shí)現(xiàn)原本不應(yīng)當(dāng)自己來承擔(dān)的邏輯。
3幻锁、前兩步還會(huì)繼續(xù)滾起來凯亮,繼而演變成workaround的workaround的workaround。
這時(shí)候問題來了:原有的帶Bug的組件哄尔,是否應(yīng)該調(diào)整或修復(fù)呢假消?
這是一個(gè)兩難的境地:
1、調(diào)整岭接,那么workaround就會(huì)失效富拗。workaround的workaround的workaround也會(huì)失效。
2鸣戴、不調(diào)整啃沪,那么按照以往的步驟,一個(gè)新Feature的實(shí)現(xiàn)窄锅,需要對(duì)其所依賴的所有組件進(jìn)行修正创千,節(jié)奏只會(huì)越來越慢。
當(dāng)開發(fā)節(jié)奏變的緩慢入偷,這是一個(gè)非常不好的征兆追驴,因?yàn)橐坏╅_發(fā)節(jié)奏變的緩慢,除非進(jìn)行根本性的改變疏之,否則只會(huì)越來越慢氯檐。這不是一種時(shí)間可以解決的問題。打個(gè)比方体捏,一輛自行車冠摄,就算是全世界最好的自行車運(yùn)動(dòng)員來騎,比速度也比不過一輛汽車几缭,比行程更是完全不能比河泳。
而面臨這個(gè)兩難境地,決策通常有兩種:
1年栓、放慢拆挥、甚至停下步伐,回顧、整理以前的實(shí)現(xiàn)和需求纸兔,進(jìn)而制定改進(jìn)計(jì)劃和方案惰瓜。但這樣會(huì)面臨市場(chǎng)和用戶的壓力。
2汉矿、招聘更多的工程師來進(jìn)行修復(fù)工作崎坊。前幾天看到一個(gè)新聞,F(xiàn)acebook的iOS工程師有429個(gè)人洲拇。
這里著重討論一下第二種方案奈揍,也就是大多數(shù)公司會(huì)采用的方案。
這種方案有效赋续,需要建立在幾個(gè)前提上:
1男翰、Bug修復(fù)的速度,趕得上Bug出現(xiàn)的速度纽乱。
2蛾绎、Bug修復(fù)的收益,大于成本鸦列。
這里先插入一段租冠,一個(gè)有工作經(jīng)驗(yàn)的工程師,從第一天進(jìn)入公司開始敛熬,到他能貢獻(xiàn)代碼肺稀,需要經(jīng)歷多少步驟。
1应民、每個(gè)產(chǎn)品都有BaseCode话原,熟悉這個(gè)BaseCode的結(jié)構(gòu)和邏輯,需要時(shí)間诲锹,少則1個(gè)月繁仁,多則半年,視具體項(xiàng)目大小而定归园。這段期間黄虱,看文檔,和老司機(jī)聊天是主要工作庸诱∧砥郑看代碼的作用,可以說幾乎為0桥爽。
2朱灿、經(jīng)過了熟悉階段后,可以進(jìn)入到邊角性的修復(fù)工作钠四。一般從修復(fù)和主要功能無關(guān)的UI開始盗扒。
3、再過了一段時(shí)間,等工程師對(duì)產(chǎn)品的后臺(tái)邏輯有了更深入的了解之后侣灶,就可以開始從事一些相對(duì)核心的主干功能的修復(fù)甸祭。
好比手術(shù)一樣,一個(gè)主刀醫(yī)師切你一條血管褥影,只需要幾秒鐘池户。但他要知道切那條,怎么切伪阶,需要幾年煞檩。
簡(jiǎn)單來說处嫌,一個(gè)有行業(yè)經(jīng)驗(yàn)的新員工栅贴,從第一天加入公司,到他可以修復(fù)相對(duì)重要的Bug熏迹,中途至少檐薯,需要幾個(gè)月的時(shí)間。
熟悉代碼庫的邏輯注暗,有幾個(gè)東西起著重要作用坛缕。
一、需求文檔捆昏,但這個(gè)非匙可能落后于進(jìn)度;
二骗卜、實(shí)現(xiàn)的結(jié)構(gòu)的描述文檔宠页,這個(gè)在國(guó)內(nèi)的大環(huán)境下,就是呵呵呵呵寇仓,幾乎沒有举户;
三、老員工的口述遍烦,但由于進(jìn)度逼迫俭嘁,他們一般會(huì)用來處理非常緊急且致命的Bug,同時(shí)服猪,由于他們是對(duì)整個(gè)項(xiàng)目最熟悉的人供填,最趕的任務(wù),最迫切的任務(wù)罢猪,都會(huì)交給他們近她。
回顧一下上個(gè)問題,通過招聘更多的工程師坡脐,能解決Bug積累的問題的前提泄私,有幾個(gè):
1、Bug修復(fù)的速度,趕得上Bug出現(xiàn)的速度晌端。
2捅暴、Bug修復(fù)的收益,大于成本咧纠。
我們?cè)賮砜纯催@兩點(diǎn)能否被滿足蓬痒。
老成員一直保持高強(qiáng)度的輸出狀態(tài),由于一直趕進(jìn)度趕任務(wù)漆羔,沒時(shí)間重構(gòu)梧奢,沒時(shí)間補(bǔ)文檔,也沒時(shí)間和團(tuán)隊(duì)的成員同步設(shè)計(jì)概況和進(jìn)度演痒。而新成員流炕,因?yàn)閷?duì)代碼庫的結(jié)構(gòu)和功能預(yù)期不熟悉,所以無法有效地分擔(dān)相對(duì)重要的開發(fā)和修復(fù)工作员帮。更可怕的是亥贸,在不熟悉代碼結(jié)構(gòu)和功能的情況下,任何的修復(fù)讯嫂,都可能引入更多的Bug蹦锋。所以第一點(diǎn),不能被輕易滿足欧芽。
要熟悉一個(gè)亂糟糟的代碼庫莉掂,對(duì)比起一個(gè)結(jié)構(gòu)清晰的代碼庫,更需要時(shí)間千扔,項(xiàng)目越大憎妙,功能越多,這個(gè)時(shí)間就越長(zhǎng)昏鹃。而軟件開發(fā)的成本尚氛,最大的開銷,是人力成本洞渤。目前一個(gè)有3年工作經(jīng)驗(yàn)的工程師的價(jià)格阅嘶,按照目前市場(chǎng)的價(jià)格,至少至少1萬元起载迄。對(duì)公司而言讯柔,算上社保公積金等等,公司的開銷至少1萬5以上护昧。假如一個(gè)這樣的工程師魂迄,進(jìn)入團(tuán)隊(duì),熟悉一個(gè)代碼庫惋耙,需要3個(gè)月捣炬。3個(gè)月之后熊昌,他走不走,是否能了解清楚代碼庫湿酸,另說婿屹。也就是說,這個(gè)人要發(fā)揮作用推溃,公司至少至少要花接近5萬元昂利。而這個(gè)項(xiàng)目本身值多少錢呢?影響客戶有多少呢铁坎?
招更多的人來填坑蜂奸,各位要不要拿出計(jì)算器計(jì)算一下成本收益呢?
是不是所有的Bug都需要被修復(fù)呢硬萍?這個(gè)問題的深層意思是扩所,“Bug修復(fù)的數(shù)目,是不是越多越好”襟铭。
我的答案是“否”碌奉。大部分的Bug產(chǎn)生的原因短曾,可以歸入以下幾類:1寒砖、需求描述不清,理解嫉拐、實(shí)現(xiàn)有二義性哩都;2、代碼的變化婉徘,沒趕上需求的變化漠嵌;3、需求之間產(chǎn)生內(nèi)在沖突盖呼,實(shí)現(xiàn)了A儒鹿,就不能實(shí)現(xiàn)B。而需求的描述几晤,很大部分又是以“看得見”的方式來描述的约炎,說簡(jiǎn)單點(diǎn),就是界面上蟹瘾、用戶操作順序上去描述的圾浅。而這又是很容易被修改的部分『镀樱“加個(gè)簡(jiǎn)單的按鈕狸捕,這里默認(rèn)值不對(duì)”,這種大多數(shù)可以歸入1或2众雷。這種Bug是產(chǎn)生得最多的灸拍,也是最容易修改的做祝,只是需要時(shí)間去找到實(shí)現(xiàn)的細(xì)節(jié)。
需求間的沖突鸡岗,這種是最難搞的剖淀。說實(shí)話,我覺得這種不能算入Bug纤房,因?yàn)閷?shí)現(xiàn)了A纵隔,就不能實(shí)現(xiàn)B,實(shí)現(xiàn)了B炮姨,就不能滿足A捌刮,無論代碼怎么寫,都是錯(cuò)舒岸。這類Bug往往又是很多Bug的深層原因绅作。
如果一味地追求Bug的修復(fù)數(shù)目,那么很容易得到一種情況蛾派,簡(jiǎn)單的表面的Bug搶著干俄认,也頻繁地出,深層的Bug沒人趕動(dòng)洪乍。如果把KPI考核引進(jìn)來眯杏,把Bug的修復(fù)數(shù)目(而不是影響程度)作為一個(gè)比重不低的標(biāo)準(zhǔn),問題會(huì)變得更加復(fù)雜壳澳。
需求間的沖突岂贩,在項(xiàng)目合并和對(duì)接的時(shí)候,會(huì)更容易暴露巷波。
我最討厭無底洞般的Bugfix的地方萎津,在于根源性的Bug沒人敢動(dòng),因?yàn)闋窟B甚廣抹镊,而大多數(shù)的小修小補(bǔ)锉屈,并不會(huì)解決影響體驗(yàn)、或者是直接決定用戶買不買賬的的根源性問題垮耳。也就是說颈渊,雖然大家都很努力,但是并沒有什么用氨菇,到頭來只耗費(fèi)了時(shí)間儡炼,能否感動(dòng)自己還是一個(gè)未知數(shù)。
就拿Evernote為例查蓉,曾有幾次我動(dòng)過購(gòu)買高級(jí)賬號(hào)的念頭乌询,因?yàn)樗臑g覽器插件、Mac下的客戶端豌研,真的解決了我很多問題妹田。但最終唬党,阻礙我購(gòu)買的,原因就一個(gè):它的編輯器有Bug鬼佣。這個(gè)Bug有多影響體驗(yàn)?zāi)厥还埃颗e個(gè)簡(jiǎn)單的例子,我選定一些字晶衷,設(shè)置了格式蓝纲,undo在redo,結(jié)果居然不一樣晌纫?就更別說莫名其妙的鎖進(jìn)和空行問題了税迷。Evernote放著這個(gè)編輯器不管,轉(zhuǎn)而去開發(fā)協(xié)作锹漱,甚至加入了團(tuán)隊(duì)IM功能箭养。只要分析一下,開發(fā)團(tuán)隊(duì)協(xié)作哥牍,無論怎么搞毕泌,歸根到底還是要回到編輯功能上去。一個(gè)筆記軟件的編輯器不穩(wěn)定嗅辣,你圍繞著這個(gè)不穩(wěn)定的編輯器撼泛,無論你周邊做的多么成功,附帶功能多么完美辩诞,用戶并不買賬坎弯。
而軟件一但走到這個(gè)地步,說句不好聽的話译暂,很有可能回天乏力。
軟件和建筑很類似撩炊,都有結(jié)構(gòu)外永,有規(guī)模,都需要精妙的設(shè)計(jì)和準(zhǔn)確的實(shí)現(xiàn)拧咳。區(qū)別在于伯顶,一個(gè)建筑工人不大可能輕易毀掉一動(dòng)大樓的根基,而工程師骆膝,要?dú)У粢粋€(gè)軟件的結(jié)構(gòu)祭衩,只需要?jiǎng)h掉一行。
軟件項(xiàng)目是一個(gè)系統(tǒng)工程阅签,尤其是在當(dāng)下這個(gè)什么都聯(lián)網(wǎng)的年代掐暮。因?yàn)橐粋€(gè)軟件的設(shè)計(jì),需要考慮自身的需求政钟,在互聯(lián)網(wǎng)時(shí)代路克,更需要考慮他人的需求樟结。一個(gè)軟件的價(jià)值,在于它對(duì)數(shù)據(jù)的操控能力精算。這種操控能力瓢宦,建立在需求、實(shí)現(xiàn)的條理性和精確性之上灰羽。而要得到這種條理性和精確性驮履,需要用系統(tǒng)的眼光去看待問題。而系統(tǒng)廉嚼,是不可能通過散沙般的組織方式得到的疲吸。
互聯(lián)網(wǎng)的世界,是贏者通吃前鹅,弱者渣渣都沒得剩摘悴。因?yàn)橐磺卸悸?lián)網(wǎng)了,聯(lián)網(wǎng)需要標(biāo)準(zhǔn)和統(tǒng)一舰绘。
我一直提倡蹂喻,不要盲頭跑,如果出發(fā)的方向錯(cuò)了捂寿,跑得越快口四,錯(cuò)得越遠(yuǎn)。