改进代码的 12 个步骤
|
如果你把這 12 件事做好了,你將擁有一支紀(jì)律嚴(yán)明的團(tuán)隊(duì),能夠始終如一地交付。
1. 你使用源代碼管理嗎?
我使用過(guò)商業(yè)源代碼管理包,也使用過(guò)免費(fèi)的 CVS,讓我告訴你,CVS 很好。但是,如果你沒(méi)有源代碼管理,你就會(huì)在試圖讓程序員一起工作時(shí)感到壓力。程序員無(wú)法知道其他人做了什么。錯(cuò)誤不能輕易回滾。源代碼管理系統(tǒng)的另一個(gè)巧妙之處在于,源代碼本身在每個(gè)程序員的硬盤上都簽出——我從未聽說(shuō)過(guò)使用源代碼管理的項(xiàng)目會(huì)丟失大量代碼。
2. 你能一步到位地完成構(gòu)建嗎?
我的意思是:從最新的源快照進(jìn)行交付構(gòu)建需要多少步驟?在優(yōu)秀的團(tuán)隊(duì)中,你可以運(yùn)行一個(gè)腳本,從頭開始進(jìn)行完整的檢出,重新構(gòu)建每一行代碼,制作各種版本、語(yǔ)言和 #ifdef 組合的 EXE,創(chuàng)建安裝包,并創(chuàng)建最終媒體——CDROM 布局、下載網(wǎng)站等等。
如果該過(guò)程需要多個(gè)步驟,則容易出錯(cuò)。當(dāng)你接近發(fā)貨時(shí),你希望有一個(gè)非常快的周期來(lái)修復(fù)“最后一個(gè)”錯(cuò)誤,制作最終的EXE等。如果編譯代碼、運(yùn)行安裝構(gòu)建器等需要 20 個(gè)步驟,你會(huì)發(fā)瘋,你會(huì)犯愚蠢的錯(cuò)誤。
正是出于這個(gè)原因,我工作的最后一家公司從 WISE 切換到 InstallShield:我們要求安裝過(guò)程能夠使用 NT 調(diào)度程序從腳本自動(dòng)運(yùn)行,而 WISE 不能在一夜之間從調(diào)度程序運(yùn)行,所以我們把它扔掉了。(WISE的好心人向我保證,他們的最新版本確實(shí)支持夜間構(gòu)建。
3. 你每天都會(huì)做構(gòu)建嗎?
使用源代碼管理時(shí),有時(shí)一個(gè)程序員會(huì)意外簽入破壞生成的內(nèi)容。例如,他們添加了一個(gè)新的源文件,并且在他們的機(jī)器上一切都編譯良好,但他們忘記將源文件添加到代碼存儲(chǔ)庫(kù)中。于是他們鎖上機(jī)器,回家了,忘乎所以,高興不已。但是沒(méi)有其他人可以工作,所以他們也不得不回家,不開心。
破壞構(gòu)建是如此糟糕(而且如此普遍),以至于它有助于進(jìn)行日常構(gòu)建,以確保不會(huì)忽視任何損壞。在大型團(tuán)隊(duì)中,確保立即修復(fù)破損的一個(gè)好方法是每天下午在午餐時(shí)間進(jìn)行每日構(gòu)建。每個(gè)人都在午餐前盡可能多地簽到。當(dāng)他們回來(lái)時(shí),構(gòu)建就完成了。如果它有效,那就太好了!每個(gè)人都檢查了最新版本的源代碼并繼續(xù)工作。如果構(gòu)建失敗,您可以修復(fù)它,但每個(gè)人都可以繼續(xù)使用預(yù)構(gòu)建的、完整的源代碼版本。
在 Excel 團(tuán)隊(duì)中,我們有一個(gè)規(guī)則,即作為他們的“懲罰”,無(wú)論誰(shuí)破壞了構(gòu)建,都有責(zé)任照看構(gòu)建,直到其他人破壞它。這是一個(gè)很好的激勵(lì)措施,可以不破壞構(gòu)建,也是一種在構(gòu)建過(guò)程中輪換每個(gè)人的好方法,這樣每個(gè)人都可以了解它是如何工作的。
在我的文章《每日構(gòu)建是你的朋友》中閱讀有關(guān)每日構(gòu)建的更多信息。
4. 你有錯(cuò)誤數(shù)據(jù)庫(kù)嗎?
我不在乎你說(shuō)什么。如果你正在開發(fā)代碼,即使是在一個(gè)團(tuán)隊(duì)中,如果沒(méi)有一個(gè)有組織的數(shù)據(jù)庫(kù)列出代碼中所有已知的錯(cuò)誤,你就會(huì)發(fā)布低質(zhì)量的代碼。許多程序員認(rèn)為他們可以把錯(cuò)誤列表記在腦子里。廢話。我一次記不住超過(guò)兩三個(gè)蟲子,第二天早上,或者在匆忙的運(yùn)輸中,它們被遺忘了。您絕對(duì)必須正式跟蹤錯(cuò)誤。
Bug 數(shù)據(jù)庫(kù)可以很復(fù)雜,也可以很簡(jiǎn)單。對(duì)于每個(gè) bug,最小、有用的 bug 數(shù)據(jù)庫(kù)必須包含以下數(shù)據(jù):
- 完成重現(xiàn)錯(cuò)誤的步驟
- 預(yù)期行為
- 觀察到的(錯(cuò)誤)行為
- 分配給誰(shuí)
- 是否已修復(fù)
如果錯(cuò)誤跟蹤軟件的復(fù)雜性是唯一阻止您跟蹤錯(cuò)誤的原因,只需使用這些關(guān)鍵字段制作一個(gè)簡(jiǎn)單的 5 列表并開始使用它。
5. 在編寫新代碼之前,你會(huì)修復(fù)錯(cuò)誤嗎?
Microsoft Word for Windows的第一個(gè)版本被認(rèn)為是一個(gè)“死亡行軍”項(xiàng)目。它花了很長(zhǎng)時(shí)間。它一直在滑落。整個(gè)團(tuán)隊(duì)都在荒謬地工作,項(xiàng)目一次又一次地被推遲,壓力令人難以置信。當(dāng)這個(gè)的東西終于發(fā)貨時(shí),晚了好幾年,Microsoft把整個(gè)團(tuán)隊(duì)送到坎昆度假,然后坐下來(lái)進(jìn)行一些認(rèn)真的反省。
他們意識(shí)到,項(xiàng)目經(jīng)理一直堅(jiān)持遵守“時(shí)間表”,以至于程序員只是匆匆忙忙地完成編碼過(guò)程,編寫了極其糟糕的代碼,因?yàn)殄e(cuò)誤修復(fù)階段不是正式時(shí)間表的一部分。沒(méi)有試圖減少錯(cuò)誤倒計(jì)時(shí)。恰恰相反。故事是這樣的,一個(gè)程序員,他必須編寫代碼來(lái)計(jì)算一行文本的高度,他只是寫了“return 12”,然后等待錯(cuò)誤報(bào)告進(jìn)來(lái),說(shuō)明他的函數(shù)并不總是正確的。時(shí)間表只是一個(gè)等待變成錯(cuò)誤的功能清單。在事后分析中,這被稱為“無(wú)限缺陷方法”。
為了糾正這個(gè)問(wèn)題,Microsoft普遍采用了一種叫做“零缺陷方法”的方法。公司里的許多程序員都咯咯地笑了起來(lái),因?yàn)檫@聽起來(lái)像是管理層認(rèn)為他們可以通過(guò)執(zhí)行命令來(lái)減少錯(cuò)誤數(shù)量。實(shí)際上,“零缺陷”意味著在任何給定時(shí)間,最高優(yōu)先級(jí)是在編寫任何新代碼之前消除錯(cuò)誤。原因如下。
一般來(lái)說(shuō),在修復(fù)錯(cuò)誤之前等待的時(shí)間越長(zhǎng),修復(fù)成本(時(shí)間和金錢)就越高。
例如,當(dāng)您犯了編譯器捕獲的拼寫錯(cuò)誤或語(yǔ)法錯(cuò)誤時(shí),修復(fù)它基本上是微不足道的。
當(dāng)你的代碼中有一個(gè)錯(cuò)誤,當(dāng)你第一次嘗試運(yùn)行它時(shí)看到它,你將能夠立即修復(fù)它,因?yàn)樗械拇a在你的腦海中仍然記憶猶新。
如果你在幾天前編寫的某個(gè)代碼中發(fā)現(xiàn)了一個(gè)錯(cuò)誤,你需要一段時(shí)間來(lái)尋找它,但是當(dāng)你重新閱讀你寫的代碼時(shí),你會(huì)記住所有內(nèi)容,并且你將能夠在合理的時(shí)間內(nèi)修復(fù)這個(gè)錯(cuò)誤。
但是,如果你在幾個(gè)月前編寫的代碼中發(fā)現(xiàn)了一個(gè)錯(cuò)誤,你可能已經(jīng)忘記了關(guān)于該代碼的很多事情,而且修復(fù)起來(lái)要困難得多。到那時(shí),你可能正在修復(fù)別人的代碼,而他們可能正在阿魯巴島度假,在這種情況下,修復(fù)錯(cuò)誤就像科學(xué)一樣:你必須緩慢、有條不紊、一絲不茍,而且你不能確定需要多長(zhǎng)時(shí)間才能找到治療方法。
如果你在已經(jīng)發(fā)布的代碼中發(fā)現(xiàn)了一個(gè)錯(cuò)誤,你將產(chǎn)生難以置信的費(fèi)用來(lái)修復(fù)它。
這是立即修復(fù)錯(cuò)誤的原因之一:因?yàn)樗ㄙM(fèi)的時(shí)間更少。還有另一個(gè)原因,它與以下事實(shí)有關(guān):預(yù)測(cè)編寫新代碼所需的時(shí)間比修復(fù)現(xiàn)有錯(cuò)誤更容易。例如,如果我讓你預(yù)測(cè)編寫代碼對(duì)列表進(jìn)行排序需要多長(zhǎng)時(shí)間,你可以給我一個(gè)很好的估計(jì)。但是,如果我問(wèn)你如何預(yù)測(cè)在安裝了 Internet Explorer 5.5 的情況下,修復(fù)代碼不起作用的錯(cuò)誤需要多長(zhǎng)時(shí)間,你甚至無(wú)法猜測(cè),因?yàn)槟悴恢溃ǜ鶕?jù)定義)是什么導(dǎo)致了這個(gè)錯(cuò)誤??赡苄枰?3 天才能找到它,或者可能需要 2 分鐘。
這意味著,如果你的日程安排中還有很多錯(cuò)誤需要修復(fù),那么這個(gè)日程安排是不可靠的。但是,如果您已經(jīng)修復(fù)了所有已知的錯(cuò)誤,并且只剩下新代碼,那么您的日程安排將更加準(zhǔn)確。
將錯(cuò)誤計(jì)數(shù)保持在零的另一個(gè)好處是,您可以更快地響應(yīng)競(jìng)爭(zhēng)。一些程序員認(rèn)為這是讓產(chǎn)品隨時(shí)準(zhǔn)備好發(fā)貨。然后,如果您的競(jìng)爭(zhēng)對(duì)手推出了一項(xiàng)殺手級(jí)新功能,正在竊取您的客戶,您可以僅實(shí)現(xiàn)該功能并立即發(fā)布,而無(wú)需修復(fù)大量累積的錯(cuò)誤。
6. 你有最新的時(shí)間表嗎?
這就把我們帶到了日程安排上。如果你的代碼對(duì)業(yè)務(wù)很重要,那么有很多原因可以解釋為什么知道代碼何時(shí)完成對(duì)業(yè)務(wù)很重要。程序員在制定時(shí)間表方面是出了名的蹩腳。“當(dāng)它完成時(shí),它就會(huì)完成!”他們對(duì)商人大喊大叫。
不幸的是,這并不能解決問(wèn)題。在發(fā)布代碼之前,企業(yè)需要做出太多的規(guī)劃決策:演示、貿(mào)易展覽、廣告等。而做到這一點(diǎn)的唯一方法是制定一個(gè)時(shí)間表,并使其保持最新狀態(tài)。
制定時(shí)間表的另一個(gè)關(guān)鍵因素是,它迫使你決定要做什么功能,然后它迫使你選擇最不重要的功能并削減它們,而不是陷入特征性(又名范圍蔓延)。
7.你有規(guī)格嗎?
編寫規(guī)范就像使用牙線一樣:每個(gè)人都同意這是一件好事,但沒(méi)有人這樣做。
我不確定為什么會(huì)這樣,但這可能是因?yàn)榇蠖鄶?shù)程序員討厭編寫文檔。因此,當(dāng)僅由程序員組成的團(tuán)隊(duì)處理問(wèn)題時(shí),他們更喜歡用代碼而不是文檔來(lái)表達(dá)他們的解決方案。他們寧愿潛心編寫代碼,也不愿先生成規(guī)范。
在設(shè)計(jì)階段,當(dāng)您發(fā)現(xiàn)問(wèn)題時(shí),您可以通過(guò)編輯幾行文本輕松修復(fù)它們。一旦代碼被編寫出來(lái),修復(fù)問(wèn)題的成本就會(huì)大大增加,無(wú)論是在情感上(人們討厭扔掉代碼)還是在時(shí)間上,所以實(shí)際解決問(wèn)題是有阻力的。不是根據(jù)規(guī)范構(gòu)建的軟件通常最終會(huì)設(shè)計(jì)得很糟糕,并且進(jìn)度會(huì)失控。這似乎是 Netscape 的問(wèn)題所在,前四個(gè)版本變得如此混亂,以至于管理層愚蠢地決定扔掉代碼并重新開始。然后他們?cè)贛ozilla上再次犯了這個(gè)錯(cuò)誤,創(chuàng)造了一個(gè)失控的怪物,花了幾年時(shí)間才達(dá)到alpha階段。
我的理論是,這個(gè)問(wèn)題可以通過(guò)教程序員不那么不情愿地成為作家來(lái)解決,方法是讓他們?nèi)⒓訉懽鞯膹?qiáng)化課程。另一種解決方案是聘請(qǐng)聰明的項(xiàng)目經(jīng)理來(lái)制作書面規(guī)范。無(wú)論哪種情況,您都應(yīng)該強(qiáng)制執(zhí)行簡(jiǎn)單的規(guī)則“沒(méi)有規(guī)范就沒(méi)有代碼”。
通過(guò)閱讀我的 4 部分系列,了解有關(guān)編寫規(guī)范的所有信息。
8. 程序員有安靜的工作條件嗎?
通過(guò)為知識(shí)工作者提供空間、安靜和隱私,可以提高生產(chǎn)力。經(jīng)典的軟件管理書籍《Peopleware》廣泛地記錄了這些生產(chǎn)力優(yōu)勢(shì)。
麻煩來(lái)了。我們都知道,知識(shí)工作者通過(guò)進(jìn)入“心流”(也稱為“在區(qū)域”)中才能發(fā)揮最佳效果,在那里他們完全專注于自己的工作并完全脫離環(huán)境。他們忘記了時(shí)間,通過(guò)絕對(duì)的專注創(chuàng)造了偉大的東西。這是他們完成所有生產(chǎn)性工作的時(shí)候。作家、程序員、科學(xué)家,甚至籃球運(yùn)動(dòng)員都會(huì)告訴你關(guān)于在這個(gè)區(qū)域的信息。
麻煩的是,進(jìn)入“區(qū)域”并不容易。當(dāng)您嘗試測(cè)量它時(shí),看起來(lái)平均需要 15 分鐘才能開始以最大生產(chǎn)力工作。有時(shí),如果你累了,或者那天已經(jīng)做了很多創(chuàng)造性的工作,你就無(wú)法進(jìn)入這個(gè)區(qū)域,你把剩下的工作時(shí)間都花在擺弄、閱讀網(wǎng)絡(luò)、玩俄羅斯方塊上。
另一個(gè)麻煩是很容易被淘汰出該區(qū)域。噪音、電話、外出吃午飯、不得不開車 5 分鐘去星巴克喝咖啡,以及同事的打擾——尤其是同事的打擾——都會(huì)讓你離開這個(gè)區(qū)域。如果同事問(wèn)你一個(gè)問(wèn)題,導(dǎo)致 1 分鐘的中斷,但這會(huì)嚴(yán)重影響你,以至于你需要半個(gè)小時(shí)才能再次提高工作效率,那么你的整體工作效率就會(huì)遇到嚴(yán)重的麻煩。如果你處于一個(gè)嘈雜的牛棚環(huán)境中,就像咖啡因的網(wǎng)絡(luò)公司喜歡創(chuàng)造的那種環(huán)境,營(yíng)銷人員在程序員旁邊打電話尖叫,你的生產(chǎn)力就會(huì)直線下降,因?yàn)橹R(shí)工作者一次又一次地被打斷,永遠(yuǎn)不會(huì)進(jìn)入這個(gè)區(qū)域。
對(duì)于程序員來(lái)說(shuō),這尤其困難。生產(chǎn)力取決于能否同時(shí)處理短期記憶中的許多小細(xì)節(jié)。任何形式的中斷都可能導(dǎo)致這些細(xì)節(jié)崩潰。當(dāng)你恢復(fù)工作時(shí),你不記得任何細(xì)節(jié)(比如你正在使用的局部變量名稱,或者你在實(shí)現(xiàn)該搜索算法時(shí)所處的位置),你必須不斷查找這些東西,這會(huì)減慢你的速度,直到你恢復(fù)速度。
這是簡(jiǎn)單的代數(shù)。比方說(shuō)(證據(jù)似乎表明),如果我們打斷一個(gè)程序員,哪怕是一分鐘,我們真的會(huì)浪費(fèi) 15 分鐘的生產(chǎn)力。在這個(gè)例子中,讓我們把兩個(gè)程序員 Jeff 和 Mutt 放在一個(gè)標(biāo)準(zhǔn)的 Dilbert 小牛肉育肥場(chǎng)的開放式隔間里。Mutt 不記得 strcpy 函數(shù)的 Unicode 版本的名稱。他可以查一下,這需要 30 秒,或者他可以問(wèn) Jeff,這需要 15 秒。由于他就坐在杰夫旁邊,他問(wèn)杰夫。Jeff 分心并失去了 15 分鐘的工作效率(為 Mutt 節(jié)省了 15 秒)。
現(xiàn)在讓我們把它們搬到有墻和門的獨(dú)立辦公室里?,F(xiàn)在,當(dāng) Mutt 不記得那個(gè)函數(shù)的名稱時(shí),他可以查找它,這仍然需要 30 秒,或者他可以問(wèn) Jeff,現(xiàn)在需要 45 秒,并且需要站起來(lái)(考慮到程序員的平均身體素質(zhì),這不是一件容易的事!于是他查了一下。所以現(xiàn)在 Mutt 損失了 30 秒的生產(chǎn)力,但我們?yōu)?Jeff 節(jié)省了 15 分鐘。??!
9. 你使用金錢能買到的最好的工具嗎?
用編譯語(yǔ)言編寫代碼是最后一件事,仍然無(wú)法在花園品種的家用計(jì)算機(jī)上立即完成。如果您的編譯過(guò)程需要幾秒鐘以上,那么獲得最新最好的計(jì)算機(jī)將節(jié)省您的時(shí)間。如果編譯只需要 15 秒,程序員就會(huì)在編譯器運(yùn)行時(shí)感到無(wú)聊,這會(huì)讓他們陷入困境并扼殺數(shù)小時(shí)的生產(chǎn)力。
使用單個(gè)監(jiān)視器系統(tǒng)調(diào)試 GUI 代碼即使不是不可能,也是痛苦的。如果您正在編寫 GUI 代碼,兩個(gè)顯示器將使事情變得容易得多。
大多數(shù)程序員最終必須操作圖標(biāo)或工具欄的位圖,而大多數(shù)程序員沒(méi)有可用的好位圖編輯器。嘗試使用 Microsoft Paint 來(lái)操作位圖是一個(gè)笑話,但這是大多數(shù)程序員必須做的。
一流的開發(fā)團(tuán)隊(duì)不會(huì)折磨他們的程序員。即使是因使用功能不足的工具而引起的小挫折也會(huì)加起來(lái),使程序員脾氣暴躁和不開心。一個(gè)脾氣暴躁的程序員是一個(gè)沒(méi)有生產(chǎn)力的程序員。
除此之外,還要補(bǔ)充...程序員很容易通過(guò)向他們提供最酷、最新的東西來(lái)賄賂他們。這是讓他們?yōu)槟ぷ鞅葘?shí)際支付有競(jìng)爭(zhēng)力的薪水便宜得多的方式!
10. 你們有測(cè)試人員嗎?
如果你的團(tuán)隊(duì)沒(méi)有專門的測(cè)試人員,每?jī)扇齻€(gè)程序員至少有一個(gè),你要么在運(yùn)送有缺陷的產(chǎn)品,要么你浪費(fèi)了錢。吝嗇測(cè)試人員是一種令人發(fā)指的虛假經(jīng)濟(jì),以至于我被更多的人不承認(rèn)它所震撼。
11. 新應(yīng)聘者在面試時(shí)會(huì)寫代碼嗎?
你會(huì)聘請(qǐng)魔術(shù)師而不讓他們給你展示一些魔術(shù)嗎?當(dāng)然不是。
你會(huì)在不品嘗他們的食物的情況下為您的婚禮聘請(qǐng)餐飲服務(wù)商嗎?我懷疑。(除非是瑪吉阿姨,如果你不讓她做她“有名”的切碎的肝蛋糕,她會(huì)永遠(yuǎn)討厭你)。
然而,每天,程序員都是根據(jù)令人印象深刻的簡(jiǎn)歷或面試官喜歡與他們聊天而被聘用的。或者他們被問(wèn)到瑣事問(wèn)題(“CreateDialog() 和 DialogBox() 有什么區(qū)別?”),這些問(wèn)題可以通過(guò)查看文檔來(lái)回答。你不在乎他們是否記住了數(shù)千個(gè)關(guān)于編程的瑣事,你關(guān)心他們是否能夠編寫代碼?;蛘?,更糟糕的是,他們被問(wèn)到“啊哈!”問(wèn)題:當(dāng)你知道答案時(shí),這些問(wèn)題似乎很容易,但如果你不知道答案,它們就是不可能的。
12. 你們做走廊可用性測(cè)試嗎?
走廊可用性測(cè)試是你抓住走廊上下一個(gè)經(jīng)過(guò)的人,強(qiáng)迫他們嘗試使用你剛剛寫的代碼。如果你對(duì)五個(gè)人這樣做,你將學(xué)到 95% 的關(guān)于代碼中可用性問(wèn)題的知識(shí)。
好的用戶界面設(shè)計(jì)并不像你想象的那么難,如果你想讓客戶喜歡和購(gòu)買你的產(chǎn)品,這一點(diǎn)至關(guān)重要。你可以閱讀我關(guān)于UI設(shè)計(jì)的免費(fèi)在線書籍,這是一本簡(jiǎn)短的程序員入門書。