程序員在普通人的印象里是一份嚴(yán)(ku)謹(jǐn)(bi)的職業(yè),也是一個(gè)被搞怪吐槽樂(lè)此不疲的職業(yè),程序員們面對(duì)復(fù)雜的代碼敲打電腦時(shí)連眉頭都不會(huì)皺一下,但是有一個(gè)詞卻是他們痛苦的根源,它就是Bug。
千萬(wàn)不要和程序員直接說(shuō)有Bug
程序員遇到Bug時(shí)的30個(gè)反應(yīng)
開(kāi)發(fā)應(yīng)用程序是一個(gè)非常有壓力的工作。沒(méi)有人是完美的,因此在這個(gè)行業(yè)中,代碼中出現(xiàn)Bug是相當(dāng)普遍的現(xiàn)象。
面對(duì)Bug,一些程序員會(huì)生氣,會(huì)沮喪,會(huì)心煩意亂,甚至?xí)倚膯蕷?,而另一些程序員會(huì)依然保持冷靜沉著。因此,如何處理修復(fù)Bug的過(guò)程也值得我們細(xì)細(xì)琢磨。
我想分享一些程序員修復(fù)他們的源代碼時(shí)所經(jīng)歷的想法。我相信很多開(kāi)發(fā)人員和軟件工程師經(jīng)歷過(guò)這些艱辛,然后在事后一笑而過(guò)。以下你經(jīng)歷過(guò)哪些?
1.“我不知道是要?jiǎng)h除還是要重寫(xiě)它”
回顧從前老的源代碼,會(huì)有一種想要返工寫(xiě)成較大塊集群的沖動(dòng)和誘惑。丑陋的邏輯語(yǔ)句,還有冗長(zhǎng)的語(yǔ)法,導(dǎo)致代碼非常難以閱讀!
但話又說(shuō)回來(lái),如果代碼沒(méi)有壞掉的話,那就不要去修復(fù)它。這種洶涌澎拜的斗爭(zhēng)是我經(jīng)常要面對(duì)的,而且顯然會(huì)困擾許多軟件開(kāi)發(fā)人員。
2.“對(duì)于起始框架我應(yīng)該查看Github”
我想大多數(shù)開(kāi)發(fā)人員都知道Github,上面每天都有數(shù)量驚人的開(kāi)源項(xiàng)目發(fā)布。
任何語(yǔ)言的程序員都可以通過(guò)互聯(lián)網(wǎng)借鑒現(xiàn)有項(xiàng)目,加入維基討論,或者創(chuàng)建自己的代碼倉(cāng)庫(kù)。它是各種項(xiàng)目所需插件和模板的超棒資源。
3.“為什么這個(gè)腳本需要這么多庫(kù)?”
尤其是一些比較大眾化的語(yǔ)言,如Java和Objective-C,庫(kù)的數(shù)量可能變得異常兇猛。當(dāng)構(gòu)建一個(gè)需要大量基礎(chǔ)的框架時(shí),所需的庫(kù)的數(shù)量就變得顯而易見(jiàn)得多。
即使是一些適用于JavaScript的插件,也會(huì)額外需要無(wú)數(shù)的文件。有時(shí),這會(huì)讓人覺(jué)得煩雜惱人——但至少是有用的!
4.“在互聯(lián)網(wǎng)的某個(gè)地方一定已經(jīng)有了解決方案。”
我面對(duì)棘手問(wèn)題的第一反應(yīng)是上網(wǎng)查。程序員會(huì)將他們遇到的問(wèn)題通過(guò)帖子發(fā)布到論壇上,然后這個(gè)問(wèn)題最終得到解決并歸檔。
谷歌搜索問(wèn)題關(guān)鍵字的好幫手,可以指點(diǎn)你往正確的討論方向走。不幸的是,有的時(shí)候卻是因?yàn)槭诸^沒(méi)有特定問(wèn)題的太多信息而找不著北。
5.“有沒(méi)有這個(gè)功能的插件?”
為什么要重新發(fā)明輪子?插件是擴(kuò)大任何程序或網(wǎng)站用戶界面的偉大資源。此外,它們還為開(kāi)發(fā)人員提供了一些自定義和獨(dú)特的選項(xiàng)。萬(wàn)一真的沒(méi)有可用插件的話,為什么不自己構(gòu)建一個(gè)呢?
6.“雖然網(wǎng)站可以工作,但我害怕IE瀏覽器。”
在Internet Explorer中渲染網(wǎng)頁(yè)的歷史充滿了艱辛考驗(yàn),是我們有目共睹或親身體驗(yàn)過(guò)的。
從5.5版本升級(jí)到IE9、IE10,總是需要爭(zhēng)取到更高級(jí)瀏覽器的支持。Web開(kāi)發(fā)人員可能會(huì)害怕調(diào)試網(wǎng)頁(yè),因?yàn)樵贗E6中打開(kāi)頁(yè)面是一個(gè)渲染噩夢(mèng)。值得慶幸的是,這樣的日子正在慢慢成為過(guò)去。
7.“對(duì)于邏輯表達(dá)式而言,這似乎并不怎么合乎邏輯。”
對(duì)于if/else循環(huán),for循環(huán),while循環(huán),do循環(huán)等等,都有邏輯表達(dá)式。當(dāng)瀏覽示例代碼時(shí),我試圖指出我的邏輯是如何工作的。
NOT運(yùn)算符和比較標(biāo)記的數(shù)量又是如此之多。我經(jīng)?;剡^(guò)頭去更新我自己的邏輯以便于更好地適合未來(lái)的做法。
8.“我用30分鐘寫(xiě)函數(shù),花2小時(shí)讓它工作。”
這難道不像我們自己的編程故事嗎?你正興致勃勃地在構(gòu)建著什么,但是突然之間,函數(shù)輸出了一個(gè)致命的錯(cuò)誤。
所以,現(xiàn)在你必須回過(guò)頭去刪除一些代碼塊,以找出錯(cuò)誤發(fā)生的行號(hào)。當(dāng)你終于找到罪魁禍?zhǔn)?,并解決它時(shí),雖然有種精疲力竭的感覺(jué),但也滿心安慰。
9.“在閱讀多篇博客文章之后,我意識(shí)到,我之前全都是錯(cuò)的。”
我常常會(huì)一開(kāi)始就根據(jù)自己的編程思想,一頭扎進(jìn)去研究,但是這可能會(huì)導(dǎo)致麻煩,如果事情不像原先設(shè)想地那樣順利的話。
已經(jīng)有很多次在我啟動(dòng)一個(gè)項(xiàng)目之后,陷入了困境,然后只好尋求博客和其他論文的支持。
最后我發(fā)現(xiàn)我的整個(gè)方法實(shí)際上是錯(cuò)誤的,而且從頭來(lái)過(guò)更容易!如果我開(kāi)始的時(shí)候能先做一番研究的話,從長(zhǎng)遠(yuǎn)來(lái)說(shuō),反而節(jié)省時(shí)間。
10.“Stack Overflow上和善的人或許愿意幫助我。”
我已經(jīng)數(shù)不清有多少次我通過(guò)Stack Overflow解決了難題。社區(qū)里都是和善和聰明的人,他們非常愿意提供幫助,如果你邁出第一步的話。
在所有的在線論壇中,Stack Overflow絕對(duì)是對(duì)軟件編程以及前端/后端web開(kāi)發(fā)支持最廣泛的網(wǎng)絡(luò)。
11.“花費(fèi)大力氣才找出問(wèn)題的原因是缺少了右括號(hào)。”
調(diào)試是你必須要采取的步驟,進(jìn)兩步,退一步。盯著代碼數(shù)個(gè)小時(shí),以為函數(shù)名或變量作用域中有哪里搞錯(cuò)了,最后才發(fā)現(xiàn)是遺漏了一個(gè)括號(hào),這滋味,酸爽得不要不要的。所有這些時(shí)間都因?yàn)橐粋€(gè)小小的語(yǔ)法錯(cuò)誤而浪費(fèi)。
12.“喝杯咖啡,休息一下!”
有時(shí)候,你只是需要站起來(lái),遠(yuǎn)離顯示器。將鼠標(biāo)懸停在鍵盤(pán)數(shù)個(gè)小時(shí),反而有助于打破常規(guī)。大多數(shù)健康指導(dǎo)都會(huì)建議我們每隔30-60分鐘休息一會(huì)。
但是這一切都取決于你的需要,如果你覺(jué)得在程序中間休息更令人懊惱的話,那就不要中斷。
13.“我應(yīng)該把這個(gè)項(xiàng)目束之高閣,以后再來(lái)處理它。”
休息的另一個(gè)選擇是離開(kāi)你的項(xiàng)目,而不僅僅是遠(yuǎn)離你的電腦。如果還有其他工作需要做,那么不妨去做其他工作。
相對(duì)于已經(jīng)花費(fèi)了5個(gè)小時(shí)來(lái)解決問(wèn)題依然不得入門(mén)而言的話,這將能更好地分配時(shí)間和資源。
14.“我很懷疑古典音樂(lè)能否激發(fā)我的編程能力。”
有一種說(shuō)法是,古典音樂(lè)可以在生命的早期階段促進(jìn)植物生長(zhǎng)。我個(gè)人非常喜歡在寫(xiě)復(fù)雜筆記時(shí)聆聽(tīng)古典音樂(lè)。爵士樂(lè)、鋼琴、大樂(lè)團(tuán),優(yōu)雅的音樂(lè)在全世界的人類(lèi)文化中都有一席之地。
那么,在編程的同時(shí)傾聽(tīng)智慧的音樂(lè)真的能夠讓你更智慧地調(diào)試嗎?可能不會(huì),不過(guò)希望它不會(huì)讓你變得更笨拙。
15.“喝點(diǎn)酒吧,也許現(xiàn)在是檢驗(yàn)鮑爾默峰值理論的好時(shí)機(jī)。
很多讀者都聽(tīng)說(shuō)過(guò)鮑爾默的峰值理論,根據(jù)一個(gè)特殊XKCD漫畫(huà)而得出。簡(jiǎn)單地說(shuō),這個(gè)理論認(rèn)為程序員的編碼能力在喝了一定量的酒之后,會(huì)達(dá)到一個(gè)峰值。
作者名叫史蒂夫·鮑爾默,他的行為古怪,就像是一個(gè)醉漢,這有一定的諷刺意味,因?yàn)轷U爾默在微軟從來(lái)就不是一名真正的程序員。也許我們需要等待別人來(lái)實(shí)踐證明這個(gè)理論吧。
16.“是不是有人動(dòng)過(guò)了我的源代碼?”
這聽(tīng)起來(lái)有點(diǎn)妄想和偏執(zhí),但有時(shí)你會(huì)不由自主地懷疑,是不是有人在你補(bǔ)覺(jué)的時(shí)候,寫(xiě)過(guò)這個(gè)東西了。
回顧過(guò)去幾周或幾個(gè)月做的項(xiàng)目會(huì)讓你的心不斷地往下沉。有時(shí)候你會(huì)發(fā)現(xiàn)一些你已經(jīng)不記得添加的東西——甚至這個(gè)項(xiàng)目你最近一周才剛剛瀏覽過(guò)!我為代碼而瘋狂,但你永遠(yuǎn)不會(huì)知道…
17.“我不知道這意味著什么。”
你能遇到的最壞情況是,你對(duì)你正在瀏覽的源代碼完全不知道該怎么做??赡苁悄阕约旱捻?xiàng)目,也可能是別人的項(xiàng)目,但問(wèn)題的根源是相同的。
現(xiàn)在,你必須決定是否值得花更多的時(shí)間去搜索替代方案,或仔細(xì)檢查腳本以了解它是如何工作的。
18.“我需要Google錯(cuò)誤信息。”
在PHP中工作了多年之后,我不得不說(shuō),Google是我調(diào)試問(wèn)題時(shí)最好的朋友。使用Objective-C、C++、Java、Python和其他主要語(yǔ)言,也是如此。
錯(cuò)誤信息非常有幫助,但是除非你記得不同的代碼意味著什么,否則它讀起來(lái)更像是翻譯過(guò)的計(jì)算機(jī)語(yǔ)言。值得慶幸的是,有很多在線支持可以幫助我們確定這些錯(cuò)誤信息的真正含義。
19.“我應(yīng)該停下來(lái),收工……但我真的很想解決它!”
我們都有過(guò)極度灰心喪氣,想要放棄的感受,但總感覺(jué)半途而廢不是正確的選擇。于是,你繼續(xù)埋首鉆研,并嘗試新的解決方案來(lái)調(diào)試。
但是,如果這還是意味著另一個(gè)小時(shí)的浪費(fèi)呢?對(duì)于這樣的情況我并不陌生,令人非常令人沮喪。
20.“哦,天哪,我以前為什么不寫(xiě)點(diǎn)注釋呢?”
當(dāng)涉及到比較基礎(chǔ)的前端HTML/CSS/JS時(shí),我們沒(méi)有必要寫(xiě)注釋。但更復(fù)雜的腳本和程序卻需要一定形式的條理組織,當(dāng)你在幾個(gè)月后,甚至若干年之后需要再回過(guò)頭來(lái)看的話。
有時(shí)你會(huì)忘記注釋函數(shù)及其參數(shù)、輸出格式,和其他的必要數(shù)據(jù)。這在一段時(shí)間之后無(wú)疑會(huì)導(dǎo)致混亂。而且,當(dāng)Bug開(kāi)始出現(xiàn)時(shí),你必須調(diào)試整個(gè)腳本來(lái)尋找解決方案。因此,要是有一些有幫助的注釋就會(huì)讓你獲益良多。
21.“20分鐘前它還可以工作的……”
在構(gòu)建程序時(shí),可能最令人沮喪的部分就是,它從能工作到不能工作——而你沒(méi)有更新代碼的任何部分!我發(fā)誓這是真的,而且這是沒(méi)有任何意義的事情——也許是其他程序正在運(yùn)行緩存版本?
有很多次你更新了一丁點(diǎn)代碼,卻導(dǎo)致了整個(gè)程序崩潰出錯(cuò),完全停止了工作?;謴?fù)到最近可工作的復(fù)制文件,然后從那里開(kāi)始一步步前進(jìn)。
22.“只是忘記了一個(gè)分號(hào),然而整個(gè)程序卻因此而轟然倒下。”
幾乎所有我使用的編程語(yǔ)言都需要結(jié)束符。雖然不是所有的語(yǔ)言都有,但在C/C++中是很常見(jiàn)的。
忘記添加結(jié)束符,不過(guò)是一個(gè)很顯然的錯(cuò)誤!但是解析器不知道這一點(diǎn),它會(huì)拋出一個(gè)致命錯(cuò)誤。
于是,你不得不額外花20分鐘去搜索技術(shù)故障,而原本只需要用1秒鐘補(bǔ)上那個(gè)缺少的分號(hào)即可。嗯,這就是調(diào)試軟件的樂(lè)趣。
23.“我不知道讓別人來(lái)修復(fù)我的代碼,得花多少錢(qián)?”
聘請(qǐng)另一個(gè)開(kāi)發(fā)人員的點(diǎn)子是挺誘人的,但從財(cái)政上看顯然沒(méi)有那么可行。而且如果你不親身體驗(yàn)的話,又怎么能從這些錯(cuò)誤中學(xué)到東西呢?
當(dāng)你在經(jīng)歷多次失敗之后,終于理解了某個(gè)編程概念的時(shí)候,那感覺(jué)真是棒極了。盡管如此,我的腦海里依然時(shí)不時(shí)地有一種“讓別人來(lái)修復(fù)代碼”的沖動(dòng)。
24.“快速瀏覽Hackers News可以提高我的工作效率。”
很多程序員最喜歡閱讀的,有關(guān)于軟件和創(chuàng)業(yè)公司等社會(huì)新聞的選擇是Hackers News頭版。它有很多關(guān)于自由職業(yè)、時(shí)間管理、軟件開(kāi)發(fā)、以及創(chuàng)業(yè)發(fā)布和融資的大量信息。
雖然HN可以通過(guò)自我教育讓你感覺(jué)自己變得更有效率了,但同時(shí)它也會(huì)浪費(fèi)你的時(shí)間。每隔幾小時(shí)去快速瀏覽下Hackers News也不是那么糟糕。
25.“這個(gè)API怎么沒(méi)有文檔?!”
在使用帶有壞文檔的插件或框架時(shí),最令人沮喪的是,你必須靠自己去深入鉆研源代碼。我喜歡開(kāi)發(fā)人員花時(shí)間去專(zhuān)門(mén)設(shè)計(jì)可用文檔頁(yè)面的項(xiàng)目。
所有的參數(shù)和選項(xiàng)都解釋得清清楚楚,甚至可能會(huì)被用在一些示例代碼片段中。但可悲的是,事實(shí)并非總是如此。所以最簡(jiǎn)單的方法是遠(yuǎn)離不良文檔,不自找麻煩。
26.“我真希望我保存了那個(gè)數(shù)據(jù)庫(kù)的備份副本……”
在編寫(xiě)和調(diào)試代碼時(shí),我不會(huì)想到要備份。然而,數(shù)據(jù)備份提供了允許我們回過(guò)頭去修改的踏腳石。這在實(shí)時(shí)的服務(wù)器環(huán)境中尤為有用,因?yàn)橛惺裁醋兓瘯?huì)立即執(zhí)行。
以防萬(wàn)一,我們應(yīng)該記得保存網(wǎng)站文件和數(shù)據(jù)庫(kù)的本地副本!雖然這會(huì)是一個(gè)惱人的任務(wù),但其惱人程度遠(yuǎn)遠(yuǎn)比不上重建損壞的SQL數(shù)據(jù)庫(kù)。
27.“讓它正常工作的最快解決辦法是什么?”
在花費(fèi)數(shù)個(gè)小時(shí)苦苦思考自定義的解決方案之后,很明顯你需要一種新的方法。在設(shè)計(jì)漂亮的界面之前,程序員率先想到的是讓功能正常工作。
確定最快、最準(zhǔn)確的解決方案,并實(shí)施這個(gè)解決方案讓其工作才是100%利用了時(shí)間,然后再轉(zhuǎn)移到漂亮美觀方面。
28.“我敢打賭更新我的軟件將解決這個(gè)問(wèn)題。”
管理編程語(yǔ)言依賴和插件的團(tuán)隊(duì)并不需要經(jīng)常發(fā)布版本。有時(shí),在你從計(jì)算機(jī)傳輸文件到實(shí)時(shí)服務(wù)器的時(shí)候,更新PHP/Ruby/Python/SQL版本可以解決調(diào)試問(wèn)題。
本地更新很少能夠幫助修復(fù)源代碼中的Bug,除非你的版本已經(jīng)過(guò)時(shí)得無(wú)可救藥。所以,值得一試!
29.“我應(yīng)該更有條理并且去學(xué)習(xí)Git……下周就去研究它。”
開(kāi)源版本控制包Git在程序員中非常受歡迎。相對(duì)于其他的競(jìng)爭(zhēng)對(duì)手,它提供了更容易的學(xué)習(xí)曲線,并且被許多在線代碼倉(cāng)庫(kù),如Github上和Bitbucket使用。
開(kāi)發(fā)人員很容易拖延去學(xué)習(xí)Git的行動(dòng),因?yàn)樗鼘?duì)于初學(xué)者而言顯然是有難度的。但是一旦你知道了基本命令,那么Git就是小菜一碟。而且它還能使調(diào)試版本控制更加清晰。
30.“算了,我還是從頭再開(kāi)始吧。”
有時(shí)候,在你絞盡腦汁花費(fèi)數(shù)個(gè)小時(shí)之后,可能要做的只是將你的工作文件移動(dòng)到歸檔目錄(或刪除它們),再?gòu)念^開(kāi)始就可以了。但是,考慮到先前已經(jīng)耗費(fèi)的時(shí)間,你很難下定這個(gè)決心。
當(dāng)我一籌莫展時(shí),我往往會(huì)選擇從頭開(kāi)始,因?yàn)檫@樣才有可能找到完成項(xiàng)目的正確道路。
為什么程序員發(fā)現(xiàn)不了自己的Bug?
最近在朋友圈流行了這樣的一個(gè)小學(xué)數(shù)學(xué)題,當(dāng)然結(jié)果是“出乎意料”,看似簡(jiǎn)單的結(jié)果,幾乎很少有人做對(duì),而分析下來(lái)的原因無(wú)非是慣性思維下的粗心導(dǎo)致的完全錯(cuò)誤,今天小編就帶大家一起分析下思考過(guò)程。
看圖可知,貓=X貓頭=Y貓爪=Z,既:
3X=30
X+Y+Y=20
Y+Z+Z=9
所以得出X=10 Y=5 Z=2,故結(jié)果:Y+Z+X=5+2+10=17。
一般大多數(shù)的第一結(jié)果可能都是這樣!等等,注意最后一個(gè)應(yīng)該是Y+Z×X=?
心中一百只草泥馬奔過(guò),再算一遍,Y+Z*X=5+2*10=25。
對(duì)不起還是錯(cuò)的,因?yàn)樨堊?只。
變成了1只。
所以應(yīng)該是Y+Z/2*X=?心中一千只草泥馬奔過(guò),再算一次:Y+Z/2*X=5+2/2*10=15。
對(duì)不起還是錯(cuò)的,因?yàn)樽詈笠恢回埳僖粋€(gè)爪子,所以應(yīng)該是:Y+Z/2*(X-Z/2)=?
心中一萬(wàn)只草泥馬奔過(guò),再算一次:Y+Z/2*(X-Z/2)=5+2/2*(10-2/2)=14。
其實(shí)大家會(huì)發(fā)現(xiàn)這個(gè)題目非常的“坑爹”,不就是故意折騰人么,但是在很多系統(tǒng)中,開(kāi)發(fā)看到測(cè)試提出的Bug也是這樣的感覺(jué)。
作為開(kāi)發(fā)就和我們成人一樣看到問(wèn)題總是以自己的世界觀來(lái)理解,導(dǎo)致理所當(dāng)然的就這樣就對(duì)了,而真正的真相就被隱藏了。
而兒童一般能夠做對(duì)的原因是,老師有引導(dǎo)性的提示細(xì)心的重要性并且長(zhǎng)期踩雷。這也是測(cè)試人員和開(kāi)發(fā)人員的區(qū)別之一,現(xiàn)在知道為啥測(cè)試不是誰(shuí)都能做的工作了吧,開(kāi)發(fā)也為啥找不到Bug了吧。
當(dāng)程序員面對(duì)Bug的時(shí)候,如何機(jī)智甩鍋?
當(dāng)你面對(duì)Bug時(shí),切勿慌張,以下措施教你輕松應(yīng)對(duì)Bug帶來(lái)的困擾。
1.打死不承認(rèn),這代碼不是我寫(xiě)的,將鍋甩出去。
2.睜眼說(shuō)瞎話,在我電腦上是正常的呀,超級(jí)無(wú)辜。
賺取同情分
3.對(duì)方使用了錯(cuò)誤的打開(kāi)方式。
一定是對(duì)方的打開(kāi)方式不對(duì),重新打開(kāi)試試,我神馬都不知道
4.痛斥產(chǎn)品經(jīng)理一頓,自己偷偷改好,氣勢(shì)不能弱,立場(chǎng)要堅(jiān)定,迅速進(jìn)入角色,完全沒(méi)有Bug這回事,我就是王道。
以上模式可任意切換使用,但最終都逃不了,自己背地里偷偷,改Bug的宿命。