編程新手入門踩過(guò)的25個(gè)“坑”,你犯過(guò)其中哪些錯(cuò)誤痢虹?

大數(shù)據(jù)文摘作品

編譯:傅一洋被去、汪小七、張南星奖唯、GAO Ning惨缆、夏雅薇

高級(jí)的編程是邏輯思維的流露,會(huì)編程只代表你懂了這門語(yǔ)言的語(yǔ)法丰捷,但是會(huì)寫清晰簡(jiǎn)潔易懂可迭代的代碼才是程序員該追求的境界踪央。編程入門已經(jīng)不容易,但是如果能夠在早期樹(shù)立一些正確的“代碼觀”瓢阴,或許可以讓你的編程之路升級(jí)得更快。作者苦口婆心地給出了25條建議健无,句句真言荣恐。

首先我要聲明的是:如果你是編程新手,本文并不是要讓你對(duì)自己犯的錯(cuò)誤感到愧疚累贤,而是要你對(duì)這些錯(cuò)誤有更好的認(rèn)知叠穆,并避免在未來(lái)再犯。

當(dāng)然臼膏,這些錯(cuò)誤我也經(jīng)歷過(guò)硼被,但是從每個(gè)錯(cuò)誤中都學(xué)到了一些新東西。現(xiàn)在渗磅,我已經(jīng)養(yǎng)成了一些好的編程習(xí)慣嚷硫,我相信你也可以!

下面是這些常見(jiàn)的錯(cuò)誤始鱼,順序不分先后仔掸。

?寫代碼前缺少規(guī)劃

一般來(lái)說(shuō),創(chuàng)作一篇高質(zhì)量的文章不易医清,因?yàn)樗枰磸?fù)推敲研究起暮,而高質(zhì)量的代碼也不例外。

編寫高質(zhì)量代碼是這樣一個(gè)流程:思考会烙、調(diào)研负懦、規(guī)劃筒捺、編寫、驗(yàn)證纸厉、修改系吭。(貌似沒(méi)辦法編成一個(gè)好記的順口溜)

按照這樣的思路走,你會(huì)逐漸形成良好的編程習(xí)慣残腌。

新手最大的錯(cuò)誤之一就是太急于寫代碼村斟,而缺乏足夠的規(guī)劃和研究。雖然對(duì)于編寫小程序而言是沒(méi)多大問(wèn)題的抛猫,但對(duì)于大項(xiàng)目的開(kāi)發(fā)蟆盹,這樣做是很不利的。

為了防止代碼寫完之后發(fā)現(xiàn)重大問(wèn)題闺金,寫之前的深思熟慮是必不可少的逾滥。代碼只是你想法的流露。

生氣的時(shí)候败匹,在開(kāi)口說(shuō)話前先數(shù)到十寨昙。如果非常生氣,就數(shù)到一百掀亩。

——托馬斯·杰斐遜

我把它改成針對(duì)寫代碼的版本:

審查代碼時(shí)舔哪,重構(gòu)每一行之前,先數(shù)到十槽棍。如果代碼還沒(méi)有測(cè)試捉蚤,就數(shù)到一百。

——Samer Buna

編程的過(guò)程主要是研讀之前的代碼炼七,思考還需要修改什么缆巧,如何適應(yīng)當(dāng)前系統(tǒng),并規(guī)劃盡量小的改動(dòng)量豌拙。而實(shí)際編寫代碼的過(guò)程只占整個(gè)過(guò)程時(shí)間花費(fèi)的10%陕悬。

不要總認(rèn)為編程就是寫代碼。編程是基于邏輯的創(chuàng)造按傅,慢工出細(xì)活捉超。

?寫代碼之前規(guī)劃過(guò)度

雖說(shuō)寫代碼前充分規(guī)劃是好,但凡事都有個(gè)度逞敷,還沒(méi)開(kāi)始做狂秦,就思考太多,也是不可取的推捐。

不要期望世界上存在完美的規(guī)劃裂问,至少編程的世界中是不存在填大。好的規(guī)劃可以作為起點(diǎn)弓柱,但實(shí)際情況是蹦狂,規(guī)劃是會(huì)隨后續(xù)進(jìn)行而改變的喘批,規(guī)劃的好處只是能讓程序結(jié)構(gòu)條理更清晰,而規(guī)劃太多只會(huì)浪費(fèi)時(shí)間椭更。

瀑布式開(kāi)發(fā)是一種系統(tǒng)線性規(guī)劃的開(kāi)發(fā)方法哪审,它嚴(yán)格遵循預(yù)先計(jì)劃的需求、分析虑瀑、設(shè)計(jì)湿滓、編碼、測(cè)試的步驟順序進(jìn)行舌狗,步驟成果作為進(jìn)度的衡量標(biāo)準(zhǔn)叽奥。在這種方法中,規(guī)劃是重中之重痛侍。如果只是編寫小程序朝氓,也完全可以采用這種方法,但要對(duì)于大的項(xiàng)目主届,這種方法完全不可取赵哲。任何復(fù)雜的事情都需要根據(jù)實(shí)際情況隨機(jī)應(yīng)變。

編程是一個(gè)隨時(shí)需要根據(jù)實(shí)際情況作出改變的工作君丁。你后續(xù)可能會(huì)因?yàn)橐恍┰蛞砑踊騽h除的某些功能枫夺,但這些情況瀑布計(jì)劃中可能你永遠(yuǎn)也想不到。所以绘闷,你需要敏捷的開(kāi)發(fā)模式筷屡。

但是,每一步之前是要有所規(guī)劃的簸喂,只不過(guò)規(guī)劃的過(guò)少或過(guò)多都會(huì)影響代碼的質(zhì)量,代碼的質(zhì)量非常重要燎潮。

?低估代碼質(zhì)量的重要性

如果你無(wú)法兼顧代碼的多項(xiàng)質(zhì)量指標(biāo)喻鳄,至少要保證它的可讀性。凌亂的代碼就相當(dāng)于廢品确封,而且不可回收除呵。

永遠(yuǎn)不要低估代碼質(zhì)量的重要性。你要將代碼看作溝通的一種方式爪喘,作為程序員颜曾,你的任務(wù)是交代清楚目前任務(wù)是如何實(shí)施的。

我最喜歡一句編程俚語(yǔ)是:

寫代碼的時(shí)候可以這樣想秉剑,維護(hù)你代碼的家伙是一個(gè)知道你住在哪里的暴力精神病患者泛豪。

——John?Woods

很形象是不是?

即便是一些細(xì)節(jié)。例如诡曙,你的代碼可能會(huì)因?yàn)榕虐鎲?wèn)題或大小寫不一致而不被認(rèn)可臀叙。

tHIS is

WAY MORE important

than

you think

還需要注意的是避免語(yǔ)句過(guò)長(zhǎng)。任何超過(guò)80個(gè)字符的文本都是難以閱讀的价卤。你可能想在同一行放置長(zhǎng)條件以便看到完整的if語(yǔ)句劝萤,這是不可取的,一行永遠(yuǎn)不要超過(guò)80個(gè)字符慎璧。

這種小問(wèn)題可以通過(guò)linting工具或格式化工具輕松解決床嫌。比如在JavaScript中兩個(gè)完美結(jié)合的優(yōu)秀工具:ESLint和Prettier。多用它們胸私,讓工作更輕松厌处。

還有一些與代碼質(zhì)量相關(guān)的錯(cuò)誤:

任何超過(guò)10行的函數(shù)都太長(zhǎng)了。

一定不要出現(xiàn)雙重否定句盖文。

使用簡(jiǎn)短的嘱蛋,通用的或基于類型的變量命名。盡量保證變量命名能清晰地表述變量五续。計(jì)算機(jī)科學(xué)領(lǐng)域只有兩件難事:緩存失效和變量命名洒敏。

缺乏描述地插入一些字符串和數(shù)字。如果要使用固定的字符串或數(shù)值疙驾,應(yīng)該將其定義為常量凶伙,并命名。

“對(duì)于簡(jiǎn)單的問(wèn)題它碎,擔(dān)心花費(fèi)時(shí)間而草率地處理”函荣。不要在眾多問(wèn)題中進(jìn)行跳躍式選擇,按部就班地來(lái)扳肛。

認(rèn)為代碼越長(zhǎng)越好傻挂。其實(shí),大多數(shù)情況下挖息,代碼越短越好金拒。只有在追求可讀性的情況下可適當(dāng)詳細(xì)些。比如套腹,不要為了縮短代碼而使用很長(zhǎng)的單行表達(dá)式或嵌套表達(dá)式绪抛,但也不要增加冗余的代碼。最好的是电禀,刪去所有不必要的代碼幢码。

過(guò)多使用條件語(yǔ)句。大部分你認(rèn)為需要條件語(yǔ)句的情況都可以不通過(guò)

它來(lái)解決尖飞。因此症副,考慮盡可能多的備選方案店雅,根據(jù)可讀性進(jìn)行挑選。除非你知道如何測(cè)試代碼性能瓦糕,否則底洗,不要試圖優(yōu)化。還有就是:避免Yoda條件或條件嵌套咕娄。

?選擇1號(hào)方案

當(dāng)我剛開(kāi)始編程時(shí)亥揖,一旦遇到問(wèn)題,我會(huì)立刻尋找解決方案并重新運(yùn)行我的程序圣勒。而不是先考慮我的頭號(hào)方案復(fù)雜性和潛在的失敗原因费变。

雖然1號(hào)方案極具誘惑性,但在研究了所有解決方案后圣贸,通常能發(fā)現(xiàn)更好的挚歧。如果無(wú)法想出多種方案,說(shuō)明你對(duì)問(wèn)題了解不夠吁峻。

作為專業(yè)程序員滑负,你的工作不是找到辦法,而是找到最簡(jiǎn)捷的辦法用含“剑“簡(jiǎn)捷”的意思是方案必須正確,可執(zhí)行啄骇,且足夠簡(jiǎn)單痴鳄,易讀,又便于理解和維護(hù)缸夹。

軟件設(shè)計(jì)有兩種方法痪寻。一種是設(shè)計(jì)的足夠簡(jiǎn)單,沒(méi)有瑕疵虽惭,另一種是設(shè)計(jì)的足夠復(fù)雜橡类,沒(méi)人看得出明顯瑕疵。

——C.A.R.霍爾

?吊死在一棵樹(shù)上

這是我常犯的錯(cuò)誤芽唇,即便確定了我的頭號(hào)方案并不是最簡(jiǎn)單的解決方案猫态,仍然不放手。這可能與我的性格有關(guān)披摄。大多數(shù)情況下這是一種很好的心態(tài),但不適用于編程勇凭。事實(shí)上疚膊,正確的編程心態(tài)是,將早期失敗和經(jīng)常性失敗看成一種常態(tài)虾标。

當(dāng)你開(kāi)始懷疑某個(gè)方案的時(shí)候寓盗,你應(yīng)該考慮放下它并重新思考,不管你之前在它這里投入了多少精力。學(xué)會(huì)利用像GIT這樣的源代碼管理工具傀蚌,它可以幫助你實(shí)現(xiàn)代碼分支基显,嘗試多種方案。

不要認(rèn)為你付出了精力的代碼就是必須采用的善炫。錯(cuò)誤的代碼要摒棄撩幽。

?閉門造車

很多次,在解決問(wèn)題需要查閱資料時(shí)箩艺,我卻直接嘗試解決問(wèn)題窜醉,浪費(fèi)了很多時(shí)間。

除非你正在使用的是某種尖端技術(shù)艺谆,否則榨惰,遇到問(wèn)題時(shí),谷歌一下吧静汤,因?yàn)橐欢〞?huì)有人也遇到了同樣的問(wèn)題琅催,并找到了解決方法,這樣虫给,能節(jié)省很多時(shí)間藤抡。

有時(shí)候谷歌之后,你會(huì)發(fā)現(xiàn)你所認(rèn)為的問(wèn)題并不是問(wèn)題狰右,你需要做的不是修復(fù)而是接受杰捂。不要認(rèn)為你了解一切,Google會(huì)讓你大吃一驚的棋蚌。

不過(guò)嫁佳,要謹(jǐn)慎地使用谷歌。新手會(huì)犯的另一個(gè)錯(cuò)誤是谷暮,在不理解代碼的情況下蒿往,原樣照搬。盡管這可能成功解決了你的問(wèn)題湿弦,但還是不要使用自己不完全了解的代碼瓤漏。

如果想成為一名創(chuàng)造性的程序員,就永遠(yuǎn)不要認(rèn)為颊埃,自己對(duì)在做的事情了如指掌蔬充。

作為一個(gè)有創(chuàng)造力的人,最危險(xiǎn)的想法是認(rèn)為自己知道自己在做什么班利。

——布雷特·維克多

?不使用封裝

這一點(diǎn)不只是針對(duì)使用面向?qū)ο笳Z(yǔ)言的例子饥漫,封裝總是有用的,如果不使用封裝罗标,會(huì)給系統(tǒng)的維護(hù)帶來(lái)很大的困難庸队。

在應(yīng)用程序中积蜻,每個(gè)功能要與用來(lái)處理它的對(duì)象一一對(duì)應(yīng)。在構(gòu)建對(duì)象時(shí)彻消,除了保留被其他對(duì)象調(diào)用時(shí)必須傳遞的參數(shù)竿拆,其他內(nèi)容都應(yīng)該封裝起來(lái)。

這不是出于保密宾尚,而是為減少應(yīng)用程序不同部分之間的依賴丙笋。堅(jiān)持這個(gè)原則,可以使你在對(duì)類央勒,對(duì)象和函數(shù)的內(nèi)部進(jìn)行更改時(shí)不见,更加的安全,無(wú)需擔(dān)心大規(guī)模的毀壞代碼崔步。

對(duì)每一個(gè)邏輯概念單元或者塊都應(yīng)該構(gòu)建對(duì)應(yīng)的類稳吮。通過(guò)類能夠勾畫出程序的藍(lán)圖。這里的類可以是一個(gè)實(shí)際對(duì)象或一個(gè)方法對(duì)象井濒,你也可以將它稱作模塊或包灶似。

在每個(gè)類中,其包含的每套任務(wù)要有對(duì)應(yīng)的方法瑞你,方法只針對(duì)這一任務(wù)的執(zhí)行酪惭,且能成功的完成。相似的類可共同使用一種方法者甲。

作為新手春感,我無(wú)法本能地為每一個(gè)概念單元?jiǎng)?chuàng)建一個(gè)新類,而且經(jīng)常無(wú)法確定哪些單元是獨(dú)立的虏缸。因此鲫懒,如果你看到一套代碼中到處充斥著“Util”類,這套代碼一定是新手編寫的刽辙】遥或者,你做了個(gè)簡(jiǎn)單的修改宰缤,發(fā)現(xiàn)很多地方也要進(jìn)行相應(yīng)地修改颂翼,那么,這也是新手寫的慨灭。

在類中添加方法或在方法中添加更多功能前朦乏,兼顧自己的直覺(jué),花時(shí)間仔細(xì)思考氧骤。不要認(rèn)為過(guò)后有機(jī)會(huì)重構(gòu)而馬虎跳過(guò)呻疹,要在第一次就做對(duì)。

總而言之语淘,希望你的代碼能具有高內(nèi)聚性和低耦合性诲宇,這是一個(gè)特定術(shù)語(yǔ)。意思就是將相關(guān)的代碼放在一起(在一個(gè)類中)惶翻,減少不同類之間的依賴姑蓝。

?試圖規(guī)劃未知

在目前項(xiàng)目還正在編寫的時(shí)候,總是去想其他的解決方案吕粗,這是忌諱的纺荧。所有的謎團(tuán)都會(huì)隨著代碼的一行行編寫而逐一解開(kāi)。如果颅筋,對(duì)于測(cè)試邊緣案例進(jìn)行假設(shè)宙暇,是件好事,但如果總想要滿足潛在需求议泵,是不可取的占贫。

你要明確你的假設(shè)屬于哪一類,避免編寫目前并不需要的代碼先口,也不要空想什么計(jì)劃型奥。

僅憑空想,就認(rèn)為未來(lái)會(huì)需要某種功能碉京,因而嘗試編寫代碼厢汹,是不可取的。

根據(jù)目前的項(xiàng)目谐宙,始終尋求最少的代碼量烫葬。當(dāng)然,邊緣情況是要考慮的凡蜻,但不要過(guò)早落實(shí)到代碼中搭综。

為了增長(zhǎng)而增長(zhǎng)是癌細(xì)胞的意識(shí)形態(tài)。

——Edward?Abbey

?錯(cuò)誤使用數(shù)據(jù)結(jié)構(gòu)

在準(zhǔn)備面試的時(shí)候咽瓷,新手往往太過(guò)于關(guān)注算法设凹。掌握好的算法并在需要時(shí)使用它們固然不錯(cuò),但記住茅姜,這與你的所謂“編程天賦資質(zhì)”無(wú)關(guān)闪朱。

然而,掌握你所用語(yǔ)言中各種數(shù)據(jù)結(jié)構(gòu)的優(yōu)缺點(diǎn)钻洒,對(duì)你成為一名優(yōu)秀的開(kāi)發(fā)者大有裨益奋姿。

一旦你的代碼中使用了錯(cuò)誤的數(shù)據(jù)結(jié)構(gòu),那明擺著素标,你就是個(gè)新手称诗。

盡管本文并不是要教你數(shù)據(jù)結(jié)構(gòu),但我還是要提幾個(gè)錯(cuò)誤示例:

使用list(數(shù)組)來(lái)替代map(對(duì)象)

最常見(jiàn)的數(shù)據(jù)結(jié)構(gòu)錯(cuò)誤是头遭,在管理記錄表時(shí)寓免,使用了list而非map癣诱。其實(shí),要管理記錄表袜香,是應(yīng)該使用map的撕予。

例如,在JavaScript中蜈首,最常見(jiàn)的列表結(jié)構(gòu)是數(shù)組实抡,最常見(jiàn)的map結(jié)構(gòu)是對(duì)象(最新JavaScript版本中也包含圖結(jié)構(gòu))。

因此欢策,用list來(lái)表示map結(jié)構(gòu)的數(shù)據(jù)是不可取的吆寨。雖然這種說(shuō)法只是針對(duì)于大型數(shù)據(jù)集,但我認(rèn)為踩寇,任何情況下都應(yīng)如此啄清,幾乎沒(méi)有什么情況,list能比map更好了姑荷,而且盒延,這些極端情況在新版本的語(yǔ)言中也逐漸消失了。所以鼠冕,只使用map就好添寺。

這一點(diǎn)很重要。主要是由于訪問(wèn)map中的元素會(huì)比訪問(wèn)list中的元素快得多懈费,訪問(wèn)元素又是常有的過(guò)程计露。

在以前,list結(jié)構(gòu)是很重要的憎乙,因?yàn)樗鼙WC元素的順序票罐,但現(xiàn)在,map結(jié)構(gòu)同樣能實(shí)現(xiàn)這個(gè)功能泞边。

不使用棧

在編寫任何需要遞歸的代碼時(shí)该押,總是去使用遞歸函數(shù)。但是阵谚,這樣的遞歸代碼難以優(yōu)化蚕礼,特別在單線程環(huán)境下。

而且梢什,優(yōu)化遞歸代碼還取決于遞歸函數(shù)返回的內(nèi)容奠蹬。比如,優(yōu)化兩個(gè)或多個(gè)返回的遞歸函數(shù)嗡午,就要比優(yōu)化單個(gè)返回值的遞歸函數(shù)困難得多囤躁。

新手常常忽略了使用棧來(lái)替代遞歸函數(shù)的做法。其實(shí),你可以運(yùn)用棧狸演,將遞歸函數(shù)的調(diào)用變?yōu)閴簵_^(guò)程言蛇,而回溯變?yōu)閺棗_^(guò)程。

?把目前的代碼變得更糟

想象一下宵距,給你這樣一間凌亂的房間:

然后猜极,要求你在房間里再增加一個(gè)物件。既然已經(jīng)一團(tuán)糟了消玄,你可能會(huì)想,把它放在任何地方都可以吧丢胚。因此翩瓜,很快就能完成任務(wù)。

但是携龟,在編寫代碼時(shí)兔跌,這樣做只會(huì)讓代碼越來(lái)越糟糕!你要做的是峡蟋,保證代碼隨著開(kāi)發(fā)的進(jìn)行坟桅,變得越來(lái)越清晰。

所以蕊蝗,對(duì)于那間凌亂的房間仅乓,正確的做法是:做必要的清理,以便能將新增的物品放置在正確的位置蓬戚。比如夸楣,你要在衣柜中添置一件衣服,那就需要先清理好地面子漩,留出一條通向衣柜的路豫喧,這是必要的一步。

以下是一些錯(cuò)誤的做法幢泼,通常會(huì)使代碼變得更糟糕(只舉了一部分例子):

復(fù)制代碼紧显。如果你貪圖省事而復(fù)制代碼,那么缕棵,只會(huì)讓代碼更加混亂孵班。就好比,要在混亂的房間中挥吵,添加一把新椅子重父,而不是調(diào)整現(xiàn)有椅子的高度。因此忽匈,頭腦中始終要有抽象的概念房午,并盡可能地去使用它。

不使用配置文件丹允。如果你的某個(gè)值在不同時(shí)間郭厌、不同環(huán)境下是不一樣的袋倔,則該值應(yīng)寫入配置文件中≌勰或者宾娜,你需要在代碼中的多個(gè)位置使用某值,也應(yīng)將它寫入配置文件扇售。這樣的話前塔,當(dāng)你引入一個(gè)新的值時(shí),只需要問(wèn)自己:該值是否已經(jīng)存在于配置文件承冰?答案很可能是肯定的华弓。

使用不必要的條件語(yǔ)句或臨時(shí)變量。每個(gè)if語(yǔ)句都包含邏輯上的分支困乒,需要進(jìn)行雙重測(cè)試寂屏。因此,在不影響可讀性的情況下娜搂,盡量避免使用條件語(yǔ)句迁霎。與之相關(guān)的一個(gè)錯(cuò)誤就是,使用分支邏輯來(lái)擴(kuò)展函數(shù)百宇,而不去引入新函數(shù)考廉。每當(dāng)你認(rèn)為你需要一個(gè)if語(yǔ)句或一個(gè)新的函數(shù)變量時(shí),先問(wèn)問(wèn)自己:是否在將代碼往正確的方向推進(jìn)携御?有沒(méi)有站在更高的層面去思考問(wèn)題芝此?

關(guān)于不必要的if語(yǔ)句的問(wèn)題,參考一段代碼:

functionisOdd(number){

if(number %2===1) {

returntrue;

}else{

returnfalse;

}

}

上面的isOdd函數(shù)是存在一些問(wèn)題的因痛,你能看出最明顯問(wèn)題嗎婚苹?

那就是,它使用了一個(gè)不必要的if語(yǔ)句鸵膏。以下為其等效的代碼:

functionisOdd(number){

return(number %2===1);

};

?注釋泛濫

我已經(jīng)學(xué)會(huì)了膊升,盡量不去寫注釋。因?yàn)榇蠖鄶?shù)的注釋可以通過(guò)對(duì)變量更好的命名來(lái)代替谭企。

例如以下代碼:

// This function sums only odd numbers in an array

constsum = (val) => {

returnval.reduce((a, b) => {

if(b %2===1) {// If the current number is even

a+=b;// Add current number to accumulator

}

returna;// The accumulator

},0);

};

其實(shí)廓译,也可以寫成這樣沒(méi)有注釋的,效果相同:

constsumOddValues = (array) => {

returnarray.reduce((accumulator, currentNumber) => {

if(isOdd(currentNumber)) {

returnaccumulator + currentNumber;

}

returnaccumulator;

},0);

};

所以债查,每次寫注釋前非区,先思考一下:能否通過(guò)改善參數(shù)的命名來(lái)避免寫注釋呢?

但有一些情況下盹廷,是必須寫注釋的征绸。比如,當(dāng)你用需要注釋來(lái)表述代碼的目的,而不是代碼在做什么時(shí)管怠。

如果你實(shí)在想寫注釋的話淆衷,那就不要描述那些過(guò)于明顯的問(wèn)題。以下是一些無(wú)用注釋的例子渤弛,它們只會(huì)干擾代碼的閱讀:

// create a variable and initialize it to 0

let sum =0;

// Loop over array

array.forEach(

// For each number in the array

(number) => {

// Add the current number to the sum variable

sum += number;

}

);

所以祝拯,不要成為這樣的程序員,也不要接受這樣的代碼她肯。如果必須處理這些注釋的話佳头,那就刪掉好了。要是碰巧你雇傭的程序員總是寫出這樣的代碼的話晴氨,快點(diǎn)解雇他們畜晰。

?不寫測(cè)試

我認(rèn)同這一點(diǎn):如果你自認(rèn)為是專家,且有信心在不測(cè)試的情況下編寫代碼瑞筐,那么在我看來(lái),你就是個(gè)新手腊瑟。

如果不編寫測(cè)試代碼聚假,而用手動(dòng)方式測(cè)試程序,比如你正在構(gòu)建一個(gè)Web應(yīng)用闰非,在每寫幾行代碼后就刷新并與應(yīng)用程序交互的話膘格,我也這樣做過(guò),這沒(méi)什么問(wèn)題财松。

但是瘪贱,手動(dòng)測(cè)試代碼,是為了更明確如何在之后進(jìn)行自動(dòng)測(cè)試辆毡。如果成功測(cè)試了與應(yīng)用的交互菜秦,那就應(yīng)該返回到代碼編輯頁(yè),編寫自動(dòng)測(cè)試代碼舶掖,以便下次向項(xiàng)目添加更多代碼時(shí)球昨,自動(dòng)執(zhí)行完全相同的測(cè)試。

畢竟眨攘,作為人類主慰,每次更改代碼后,難免會(huì)有忘記去重新測(cè)試曾經(jīng)成功過(guò)的代碼鲫售,所以共螺,還是把它交給計(jì)算機(jī)完成吧!

如果可以情竹,就在編寫代碼之前藐不,先猜測(cè)或設(shè)計(jì)測(cè)試的過(guò)程。測(cè)試驅(qū)動(dòng)開(kāi)發(fā)(TDD)這種方法不僅僅是流行,它還能使你對(duì)功能的看法發(fā)生積極的變化佳吞,以及為它們提供更好的設(shè)計(jì)方案拱雏。

TDD并不適合每個(gè)人,每個(gè)項(xiàng)目底扳,但是铸抑,至少要會(huì)用它。

?認(rèn)為不出錯(cuò)就是正確的

看看這個(gè)實(shí)現(xiàn)了sumOddValues功能的函數(shù)衷模,有什么問(wèn)題嗎鹊汛?

constsumOddValues = (array) => {

returnarray.reduce((accumulator, currentNumber) => {

if(currentNumber %2===1) {

returnaccumulator + currentNumber;

}

returnaccumulator;

});

};

console.assert(

sumOddValues([1,2,3,4,5]) ===9

);

測(cè)試通過(guò),一切順利阱冶,但情況真是如此刁憋?

上述代碼問(wèn)題在于,沒(méi)有考慮到所有情況木蹬。盡管至耻,它能正確地處理一部分的情況(測(cè)試時(shí)恰好命中這些情況之一)。來(lái)看看其中的幾個(gè)問(wèn)題:

問(wèn)題#1:沒(méi)有考慮輸入為空的情況镊叁。在沒(méi)有傳遞任何參數(shù)的情況下調(diào)用函數(shù)尘颓,會(huì)發(fā)生什么?會(huì)出現(xiàn)如下所示的錯(cuò)誤:

TypeError: Cannot read property'reduce'of undefined.

這通常是個(gè)壞兆頭晦譬,原因主要有二:

1.用戶無(wú)法看到函數(shù)內(nèi)部疤苹,不知其如何實(shí)現(xiàn)的。

2.異常提示對(duì)用戶沒(méi)有任何幫助敛腌,但你的函數(shù)又無(wú)法滿足用戶需求卧土。倘若異常提示表述的更明確些,用戶就能知道自己是如何錯(cuò)誤地調(diào)用了函數(shù)像樊。比如尤莺,可以在函數(shù)中,設(shè)計(jì)拋出一個(gè)異常生棍,提示用戶定義出錯(cuò)了缝裁,如下所示:

TypeError: Cannot execute functionforemptylist.

也可以不拋出異常,忽略空輸入并返回0的總和足绅。但是捷绑,無(wú)論如何,必須對(duì)這些情況有所處理氢妈。

問(wèn)題#2:沒(méi)有處理無(wú)效輸入的情況粹污。如果傳入的參數(shù)是字符串,整數(shù)或?qū)ο蠖皇菙?shù)組首量,會(huì)發(fā)生什么情況壮吩?

出現(xiàn)了下面的情況:

sumOddValues(42);

TypeError:array.reduce is not a function

那么进苍,很不幸,因?yàn)閍rray.reduce確實(shí)是定義過(guò)的鸭叙!

我們命名了函數(shù)的參數(shù)數(shù)組觉啊,因此,在函數(shù)中沈贝,將所有調(diào)用該函數(shù)的對(duì)象(42)標(biāo)記為數(shù)組杠人。所以,就會(huì)拋出異常:42.reduce不是一個(gè)函數(shù)宋下。

這個(gè)錯(cuò)誤很令人困惑不是嗡善?也許,更值得注意的錯(cuò)誤是:

TypeError:42is not anarray, dude.

問(wèn)題#1和#2被稱為邊緣情況学歧,他們都是常見(jiàn)的邊緣案例罩引。但通常,有一些不太明顯的邊緣案例也是需要考慮的枝笨。例如袁铐,我們傳入負(fù)數(shù),會(huì)發(fā)生什么横浑?

sumOddValues([1,2,3,4,5,-13])// => still 9

-13是奇數(shù)剔桨,但結(jié)果是你想要的嗎?或許它應(yīng)該拋出異常伪嫁?求和過(guò)程是否應(yīng)該包括參數(shù)中的負(fù)數(shù)?還是應(yīng)該忽略偶垮?也許你意識(shí)到张咳,該函數(shù)應(yīng)命名為sumPositiveOddNumbers。

這種情況處理起來(lái)很容易似舵,但是脚猾,更重要的一點(diǎn),如果不寫一個(gè)測(cè)試文檔來(lái)記錄測(cè)試案例的話砚哗,后續(xù)的維護(hù)者也將對(duì)此毫無(wú)線索龙助,甚至認(rèn)為忽視負(fù)數(shù)是故意的或是出現(xiàn)了疏忽。

問(wèn)題#3:測(cè)試沒(méi)有涵蓋所有的一般情況蛛芥。除了邊緣情況提鸟,函數(shù)也有可能無(wú)法正確處理某個(gè)合理、有效的情況:

sumOddValues([2,1,3,4,5])// => 11

上例中仅淑,不應(yīng)將2計(jì)入總和称勋。

原因很簡(jiǎn)單:reduce函數(shù)是將第二個(gè)參數(shù)作為累加器的初始值的,如果該參數(shù)為空(如代碼所示)涯竟,reduce將使用數(shù)組中第一個(gè)值作為累加器的初始值赡鲜。這就是為什么在上面測(cè)試用例中空厌,第一個(gè)偶數(shù)值也包含在了總和中。

即便你在編寫的過(guò)程中就發(fā)現(xiàn)了這個(gè)問(wèn)題(并解決了)银酬,也是要編寫相應(yīng)的測(cè)試案例并記錄的嘲更,測(cè)試記錄還應(yīng)包含其他測(cè)試用例,如全偶數(shù)的情況揩瞪,列表中存在0的情況赋朦,列表為空的情況。

如果測(cè)試記錄很少壮韭,又忽略了很多情況北发,忽視了邊緣情況,那么喷屋,這一定是新手干的琳拨。

?對(duì)已經(jīng)存在的代碼不再質(zhì)疑

除非你是超級(jí)程序員,可以獨(dú)當(dāng)一面屯曹。否則狱庇,毫無(wú)疑問(wèn)你會(huì)碰到許多愚蠢的代碼。新手往往意識(shí)不到這些恶耽,他們會(huì)認(rèn)為密任,既然作為代碼庫(kù)一部分,又用了很長(zhǎng)時(shí)間的代碼偷俭,一定是沒(méi)有問(wèn)題的浪讳。

更糟的是,如果這些代碼中存在不妥涌萤,新手可能就會(huì)在其他地方重復(fù)這些不妥淹遵。因?yàn)樗麄冋J(rèn)為,代碼庫(kù)中的代碼是沒(méi)有問(wèn)題的负溪,從中學(xué)到的方法也是沒(méi)有問(wèn)題的透揣。

還有一些代碼,看起來(lái)很糟糕川抡,但是辐真,它可能包含著某種特殊的情況,從而迫使開(kāi)發(fā)人員必須這么寫崖堤。這些地方侍咱,常常會(huì)有詳細(xì)的注釋,以將情況告知給新手密幔,并說(shuō)明放坏,代碼為何要這么寫。

作為新手老玛,你應(yīng)該假設(shè)任何不明白或不正規(guī)的代碼都是不好的淤年。然后钧敞,去提問(wèn),去質(zhì)疑麸粮,去查他的git blame記錄溉苛!

如果代碼的作者無(wú)處可尋,那就仔細(xì)研究代碼本身弄诲,理解其中的所有愚战。只有當(dāng)你完全理解后,才能形成自己的觀點(diǎn)(不論好與壞)齐遵。在此之前寂玲,不要草率地對(duì)代碼下結(jié)論搞隐。

?沉迷于最佳實(shí)踐

我認(rèn)為“最佳實(shí)踐”這個(gè)詞著實(shí)不好从隆,它意味著無(wú)需再深入研究石抡,這已經(jīng)是最好的結(jié)果了摊册,毋庸置疑!

但編程中沒(méi)有最好只有更好贵少,只能說(shuō)對(duì)某種程序而言登钥,目前這已經(jīng)是比較好的方案了拆挥。

甚至某些我們以前認(rèn)為的最佳實(shí)踐糜烹,現(xiàn)在已經(jīng)不是最好的解決方案了违诗。

只要你肯花時(shí)間去研究,總能發(fā)現(xiàn)更好的方案疮蹦,所以不要再執(zhí)著于最佳實(shí)踐诸迟,盡你努力做到最好即可。

不要因?yàn)槟阍谀硞€(gè)地方讀到的一句名言愕乎,或是你看到別人這么做了阵苇,或是聽(tīng)人說(shuō)這是最佳實(shí)踐就去做某件事。

?沉迷于性能優(yōu)化

在編程中過(guò)早優(yōu)化是萬(wàn)惡之源(至少大部分是)妆毕。

——Donald Knuth?(1974年)

自從Donald Knuth發(fā)表了以上觀點(diǎn)之后慎玖,編程就發(fā)生了很大的變化贮尖,至今為止笛粘,我認(rèn)為這個(gè)觀點(diǎn)都是有價(jià)值的。

記住一條好的規(guī)則:如果你不能有效地量化代碼中的問(wèn)題湿硝,那就別試圖去優(yōu)化它薪前。

如果在執(zhí)行代碼前已經(jīng)在優(yōu)化了,那么你很可能過(guò)早的進(jìn)行了優(yōu)化关斜,這是完全沒(méi)必要的示括,只是在浪費(fèi)時(shí)間。

當(dāng)然在你寫新代碼之前一些明顯需要優(yōu)化的內(nèi)容還是要考慮優(yōu)化的痢畜。例如垛膝,在Node.js中鳍侣,你要確保你的代碼中沒(méi)有泛濫的使用循環(huán)或阻止調(diào)用堆棧,這些是非常重要的吼拥,這是你必須牢記要提前優(yōu)化的一個(gè)例子倚聚。所以在編寫過(guò)程中,可以時(shí)常問(wèn)問(wèn)自己:我準(zhǔn)備寫的代碼會(huì)阻止調(diào)用堆棧嗎凿可?

應(yīng)該避免對(duì)任何不能量化的代碼進(jìn)行任何不明顯的優(yōu)化惑折,否則反而會(huì)不利】菖埽可能你認(rèn)為你這樣做會(huì)帶來(lái)性能上的提升惨驶,但事實(shí)上這會(huì)成為新的不可預(yù)料的bug來(lái)源。

因此敛助,不要浪費(fèi)時(shí)間去優(yōu)化那些不能量化的性能問(wèn)題粗卜。

?不以最終的用戶體驗(yàn)為目標(biāo)

在應(yīng)用程序中添加特性最簡(jiǎn)單的方法是什么?從你自己的角度看辜腺,或許是看它如何適應(yīng)當(dāng)前的用戶界面休建,對(duì)吧?如果這個(gè)功能是要捕獲用戶輸入的评疗,那么把它加到已有的那些表單中测砂。如果這個(gè)功能是要添加一個(gè)頁(yè)面鏈接,那就把它加到已有的嵌套鏈接菜單中百匆。

不要自以為是砌些。要站在終端用戶角度來(lái)開(kāi)發(fā),這樣才是真正的專業(yè)人員加匈。這樣的開(kāi)發(fā)者才會(huì)去思考有這個(gè)功能訴求的用戶需要什么存璃,用戶又會(huì)如何操作。而且他們會(huì)考慮如何能讓用戶更便捷地找到和使用這個(gè)功能雕拼,而不是只考慮如何在應(yīng)用程序中添加這個(gè)功能纵东,而不考慮這個(gè)功能的可發(fā)現(xiàn)性和可用性。

?工作時(shí)沒(méi)有選對(duì)適合的工具

每個(gè)人在完成編程的相關(guān)活動(dòng)中啥寇,都有一套自己喜歡使用的工具偎球。其中有一些很好用,也有一些不好用辑甜,但是大多數(shù)工具只是對(duì)某一項(xiàng)特定任務(wù)很棒衰絮,而對(duì)其他任務(wù)來(lái)說(shuō)都沒(méi)有那么好。

如果要把釘子釘在墻上磷醋,錘子確實(shí)是把好工具猫牡,但如果要用錘子來(lái)旋螺絲釘,那就是很糟糕的工具了邓线。不能只是因?yàn)槟恪跋矚g”錘子淌友,就用它來(lái)旋螺絲釘煌恢。也不能因?yàn)殄N子是亞馬遜中最受歡迎的工具,用戶評(píng)價(jià)得分5.0震庭,就用它來(lái)旋螺絲釘症虑。

根據(jù)受歡迎程度來(lái)選擇工具,而不是針對(duì)問(wèn)題的適用性來(lái)選擇工具是新手的一個(gè)標(biāo)志归薛。

對(duì)于新手而言谍憔,另一個(gè)問(wèn)題是:你也許根本不知道對(duì)一項(xiàng)特定工作來(lái)說(shuō)什么工具“更好”。在你當(dāng)前的認(rèn)知范圍內(nèi)主籍,也許某一種工具就是你所知道的最好的工具习贫。但是,跟其他工具相比時(shí)千元,它并不是首選苫昌。你需要熟悉所有可用的工具,并且對(duì)剛開(kāi)始使用的新工具保持開(kāi)放的心態(tài)幸海。

一些程序員是拒絕使用新工具的祟身,他們對(duì)于現(xiàn)有的工具很滿意,而且他們可能也不想去學(xué)習(xí)任何新的工具物独。我明白袜硫,我也能理解,但是這顯然是不對(duì)的挡篓。

工欲善其事婉陷,必先利其器。你可以用原始工具建造一個(gè)小屋官研,并享受你的甜蜜時(shí)光秽澳;你也可以投入時(shí)間和資金去獲得好工具,這樣你就可以更快地建造一座更好的房子戏羽。工具是不斷更新的担神,而你也需要習(xí)慣去不斷學(xué)習(xí)并使用它們。

?不理解代碼問(wèn)題會(huì)造成數(shù)據(jù)問(wèn)題

一個(gè)程序非常重要的一方面就是某種格式數(shù)據(jù)的管理始花,該程序?qū)⑹翘砑有掠涗浲丁h除舊記錄和修改其他記錄的界面。

程序的代碼即使有一點(diǎn)點(diǎn)的小問(wèn)題衙荐,都會(huì)給其管理的數(shù)據(jù)帶來(lái)不可預(yù)估的后果捞挥,尤其當(dāng)你所有的數(shù)據(jù)驗(yàn)證都是通過(guò)那個(gè)漏洞程序完成時(shí)浮创,則更是如此忧吟。

當(dāng)涉及到代碼和數(shù)據(jù)的關(guān)系時(shí),初學(xué)者可能不會(huì)立即將這些點(diǎn)聯(lián)系起來(lái)斩披。他們可能覺(jué)得在生產(chǎn)中繼續(xù)使用一些錯(cuò)誤代碼也是可以的溜族,因?yàn)樘卣鱔是不用運(yùn)行的讹俊,它沒(méi)那么重要。但問(wèn)題是錯(cuò)誤代碼可能會(huì)不斷地導(dǎo)致數(shù)據(jù)完整性問(wèn)題煌抒,雖然這些問(wèn)題在一開(kāi)始的時(shí)候并不明顯仍劈。

更糟糕的是,在修復(fù)漏洞時(shí)寡壮,并沒(méi)有修復(fù)漏洞所導(dǎo)致的細(xì)微的數(shù)據(jù)問(wèn)題贩疙,就這樣交付代碼只會(huì)積累更多的數(shù)據(jù)問(wèn)題,且這樣的問(wèn)題會(huì)被貼上“不可修復(fù)”的標(biāo)簽况既。

那么如何避免讓自己發(fā)生這些問(wèn)題呢这溅?你可以簡(jiǎn)單地使用多層次的數(shù)據(jù)完整性驗(yàn)證,不只依賴于單個(gè)用戶界面棒仍,應(yīng)該在前端悲靴、后端、網(wǎng)絡(luò)通信和數(shù)據(jù)庫(kù)中都創(chuàng)建驗(yàn)證莫其。如果你不想這么做癞尚,那么請(qǐng)至少使用數(shù)據(jù)庫(kù)級(jí)別的約束。

要熟練掌握數(shù)據(jù)庫(kù)約束乱陡,并學(xué)會(huì)在數(shù)據(jù)庫(kù)中添加新列或新表時(shí)使用它們:

NOT NULL是對(duì)列的空值約束浇揩,表示該列不允許使用空值。如果你的應(yīng)用程序中設(shè)定某個(gè)字段必須有值憨颠,那么在數(shù)據(jù)庫(kù)中它的源數(shù)據(jù)就應(yīng)該定義為not null临燃。

UNIQUE是對(duì)列的單一約束,表示在整個(gè)表中該列不允許有重復(fù)值烙心。比如膜廊,用戶信息表的用戶姓名或者電子郵件字段,就適合使用這個(gè)約束淫茵。

CHECK約束是一個(gè)自定義表達(dá)式爪瓜,對(duì)于滿足條件的數(shù)據(jù),計(jì)算結(jié)果為True匙瘪。例如铆铆,如果有一列值必須是介于0到100之間的百分比,則可以使用CHECK約束來(lái)強(qiáng)制執(zhí)行丹喻。

PRINARY KEY(主鍵)約束表示某一列的值必須不為空薄货,且不重復(fù)。你可能一直在用這個(gè)約束碍论,數(shù)據(jù)庫(kù)中的每個(gè)表都必須有一個(gè)主鍵來(lái)識(shí)別不同的記錄谅猾。

FOREIGN KEY(外鍵)約束表示某一列的值必須與另一個(gè)表的某一列值相匹配,通常來(lái)說(shuō)外鍵約束也會(huì)是主鍵約束。

對(duì)于新手來(lái)說(shuō)税娜,另一個(gè)與數(shù)據(jù)完整性相關(guān)的問(wèn)題是缺乏對(duì)事務(wù)處理(transactions)的思考坐搔。如果多個(gè)操作需要更改同一個(gè)數(shù)據(jù)源,且它們相互依賴時(shí)敬矩,則必須把它們包裝在一個(gè)事務(wù)當(dāng)中概行,這樣當(dāng)其中一個(gè)操作失敗時(shí)就可以進(jìn)行回滾。

?推倒重來(lái)

這是一件很麻煩的事情弧岳。編程過(guò)程中凳忙,有時(shí)的確是需要推倒重來(lái)。編程不是一個(gè)界限分明的領(lǐng)域禽炬,變化層出不窮消略,新需求提出的速度遠(yuǎn)超于任何團(tuán)隊(duì)可以應(yīng)對(duì)的能力范圍。

打個(gè)比方瞎抛,基于當(dāng)前的速度艺演,如果你需要不同種類的輪胎,除了改進(jìn)我們都熟悉且喜愛(ài)的輪胎以外桐臊,也許我們需要換一種角度思考胎撤。然而,除非真的需要特殊設(shè)計(jì)的輪胎断凶,否則沒(méi)有必要推倒重來(lái)伤提。就將就用用原來(lái)的輪胎吧。

不要浪費(fèi)寶貴的時(shí)間在尋找所謂的最好的輪胎之上认烁≈啄校快速搜索,然后使用所尋找到的內(nèi)容却嗡。只有在這些輪胎真的沒(méi)法像宣傳的那樣好好工作時(shí)舶沛,再進(jìn)行更換。

編程最酷的一件事就是大多數(shù)輪胎都是透明的窗价,你可以看到它內(nèi)部的構(gòu)造如庭,能夠非常容易地判斷代碼的質(zhì)量高低。

所以盡量使用開(kāi)源代碼撼港。開(kāi)源包的缺陷更容易解決坪它,更容易被替代,也更容易從內(nèi)部支持帝牡。然而往毡,當(dāng)你需要一個(gè)輪子時(shí),不要買一個(gè)全新的車靶溜,然后把你現(xiàn)在的車放在那輛新車上开瞭。

也就是說(shuō),不要在代碼里加載一整個(gè)包,然后只使用里面的一兩個(gè)函數(shù)惩阶。最好的例子就是JavaScript中的lodash程序包。如果你只是想隨機(jī)排列一個(gè)數(shù)組扣汪,只需要加載shuffle方法就好断楷,不要加載一整個(gè)令人絕望的lodash程序包。

?厭惡代碼審查

新程序員們的一個(gè)明顯特征就是把代碼審查當(dāng)做批評(píng)崭别,他們不喜歡冬筒、不珍惜,甚至是恐懼代碼審查茅主。

大錯(cuò)特錯(cuò)舞痰,如果你也有同樣的感受,那么你需要立刻改變你的態(tài)度诀姚。把每次代碼審查都看做是學(xué)習(xí)機(jī)會(huì)响牛,用開(kāi)放的心態(tài)歡迎、珍惜它們赫段,并且從中學(xué)習(xí)呀打。更為重要的是,要向給你提供了指導(dǎo)的審查員們表示感謝糯笙。

你需要接受一個(gè)事實(shí)——每個(gè)人都是終生代碼學(xué)習(xí)者贬丛。大多數(shù)代碼審查都能教給一些你以前可能不知道的知識(shí),所以請(qǐng)將代碼審查當(dāng)做是一項(xiàng)學(xué)習(xí)資源吧给涕。

有時(shí)豺憔,審查員也會(huì)犯錯(cuò)誤,這時(shí)候就輪到你去教他們一些東西了够庙。然而恭应,如果審查出來(lái)的問(wèn)題不僅僅是由于你的代碼導(dǎo)致的錯(cuò)誤,那么也許還是需要進(jìn)行代碼修改耘眨。如果無(wú)論如何你都需要教審查員一些東西的話暮屡,那么謹(jǐn)記:教授別人是你作為程序員最有收獲的一件事。

?不使用源代碼控制

新手們有時(shí)會(huì)低估一個(gè)好的源代碼/版本控制系統(tǒng)毅桃,所謂好的系統(tǒng)褒纲,我指的是Git。

源代碼控制并不僅僅是指把代碼修改推送給別人钥飞,然后進(jìn)行版本變更莺掠,這個(gè)行為的意義遠(yuǎn)不止如此。源代碼控制的主要目的在于清晰的歷史記錄读宙。

代碼需要時(shí)常進(jìn)行回顧彻秆,而代碼的修改過(guò)程的記錄將會(huì)極大助力于一些疑難雜癥的解決,這也是為什么我們會(huì)很在意提交信息。代碼控制同樣也是一個(gè)溝通實(shí)施信息的渠道唇兑,使用這些零碎的提交歷史酒朵,能夠幫助未來(lái)的代碼維護(hù)人員了解代碼的發(fā)展情況以及現(xiàn)在所處的狀態(tài)。

常常提交扎附、盡早提交蔫耽,并且出于對(duì)連貫性的尊重,請(qǐng)?jiān)谔峤粯?biāo)題中使用現(xiàn)在時(shí)態(tài)留夜。信息最好盡量詳盡匙铡,但謹(jǐn)記它們應(yīng)該是經(jīng)過(guò)提煉總結(jié)的。如果你需要好幾行來(lái)闡述想表達(dá)的內(nèi)容碍粥,也許意味著你的提交信息太長(zhǎng)了鳖眼。重來(lái)吧!

不要在提交信息中不要放入任何不必要的信息嚼摩。例如钦讳,不要列出被加載、被修改或者被刪除的文件枕面。

這些列表本身已經(jīng)包含在提交的代碼中了蜂厅,并且能夠通過(guò)一些Git命令參數(shù)實(shí)現(xiàn),它們只會(huì)成為總結(jié)信息中的噪音膊畴。一些團(tuán)隊(duì)喜歡在每個(gè)文件改變中都做一次總結(jié)掘猿,我認(rèn)為這是另一種提交信息太冗長(zhǎng)的標(biāo)志。

源代碼控制和可發(fā)現(xiàn)性也有關(guān)系唇跨。當(dāng)你遇到一個(gè)函數(shù)稠通,需要開(kāi)始了解它的需求或者設(shè)計(jì),你可以尋找介紹它的提交信息买猖,然后閱讀函數(shù)相關(guān)內(nèi)容改橘。

提交信息甚至可以幫你找到程序中導(dǎo)致缺陷的代碼是哪些。Git在提交中提供了一個(gè)二進(jìn)制搜索(bisect命令)來(lái)精準(zhǔn)定位導(dǎo)致缺陷的罪惡源頭玉控。

源代碼控制也可以在代碼變動(dòng)正式生效之前發(fā)揮極大的作用飞主。諸如階段轉(zhuǎn)換、選擇性打補(bǔ)丁高诺、重置碌识、隱藏、修復(fù)虱而、應(yīng)用筏餐、區(qū)分、撤銷以及其他許多對(duì)代碼編輯有用的工具牡拇。所以好好理解魁瞪、學(xué)習(xí)穆律、使用并且珍惜他們吧。

你知道的Git特性越少导俘,那么你離文章中所說(shuō)的新手就越接近峦耘。

?過(guò)度使用共享狀態(tài)

同樣的,這一點(diǎn)并不是在比較函數(shù)式編程與其他算法的優(yōu)劣區(qū)別旅薄,那是另外一篇文章要談?wù)摰脑掝}辅髓。

需要指出的是,共享狀態(tài)往往是問(wèn)題的源頭赋秀,如果可能的話利朵,盡量避免使用它律想。如果無(wú)法避免猎莲,那么需要把使用共享狀態(tài)控制在最低限度。

當(dāng)我還是編程初學(xué)者的時(shí)候技即,我沒(méi)有意識(shí)到我們所定義的每一個(gè)變量都是一個(gè)共享狀態(tài)著洼。變量當(dāng)中包含了數(shù)據(jù),并且可以被該變量所處的域內(nèi)所有元素改變而叼。域的范圍越大身笤,那么這個(gè)共享狀態(tài)的范圍就越廣。盡量把新變量聲明維持在一個(gè)小范圍內(nèi)葵陵,并確保它們不會(huì)向上滲透液荸。

情況比較嚴(yán)重的問(wèn)題就是當(dāng)共享狀態(tài)生效、多個(gè)源頭都會(huì)導(dǎo)致同一個(gè)事件循環(huán)標(biāo)記發(fā)生改變時(shí)(在事件循環(huán)環(huán)境中)脱篙,會(huì)發(fā)生爭(zhēng)用條件娇钱。

事實(shí)是:新手有可能會(huì)采取計(jì)時(shí)器作為共享狀態(tài)爭(zhēng)用條件的曲線救國(guó)之道,特別是當(dāng)他們需要處理數(shù)據(jù)鎖定的問(wèn)題時(shí)绊困。

這是在立flag文搂,別這樣做。切記秤朗,處處留心煤蹭,并且在代碼審查時(shí)指出這個(gè)問(wèn)題,絕對(duì)不要接受這種情況取视。

?不正確地面對(duì)錯(cuò)誤

錯(cuò)誤是一個(gè)好東西硝皂,它們的存在意味著進(jìn)步,意味著你更容易獲得成長(zhǎng)作谭。

編程大牛們對(duì)錯(cuò)誤愛(ài)不釋手吧彪,而新手則恨之入骨。

如果看著這些可愛(ài)的小小紅色錯(cuò)誤信息丢早,會(huì)讓你覺(jué)得心煩姨裸,那么你需要改變一下態(tài)度秧倾,把它們視為助手。你需要好好對(duì)待它們傀缩,并充分發(fā)揮它們的作用那先,促進(jìn)自己的成長(zhǎng)。

有些錯(cuò)誤需要升級(jí)至異常情況赡艰。異常情況是需要你給出解決方法的用戶自定義錯(cuò)誤售淡。有些錯(cuò)誤需要單獨(dú)進(jìn)行處理,它們的存在將會(huì)讓程序崩潰慷垮,并且強(qiáng)制退出揖闸。

?從不休息

程序員也是人類,你的大腦料身、你的身體都需要休息汤纸。常常,當(dāng)你進(jìn)入編程狀態(tài)時(shí)芹血,就忘記了休息贮泞。我把這一點(diǎn)也視為新手的一個(gè)標(biāo)志。這不是你可以妥協(xié)的點(diǎn)幔烛。把一些能夠強(qiáng)制你休息的內(nèi)容整合到你的工作流中啃擦,然后短暫地休息一下。

離開(kāi)椅子饿悬,在附近走走令蛉,同時(shí)想想下面需要做的事情。當(dāng)你回到代碼的世界時(shí)狡恬,就可以用全新的視角看待你的成果珠叔。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市傲宜,隨后出現(xiàn)的幾起案子运杭,更是在濱河造成了極大的恐慌,老刑警劉巖函卒,帶你破解...
    沈念sama閱讀 222,946評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辆憔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡报嵌,警方通過(guò)查閱死者的電腦和手機(jī)虱咧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)锚国,“玉大人腕巡,你說(shuō)我怎么就攤上這事⊙” “怎么了绘沉?”我有些...
    開(kāi)封第一講書人閱讀 169,716評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵煎楣,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我车伞,道長(zhǎng)择懂,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 60,222評(píng)論 1 300
  • 正文 為了忘掉前任另玖,我火速辦了婚禮困曙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谦去。我一直安慰自己慷丽,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布鳄哭。 她就那樣靜靜地躺著要糊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪窃诉。 梳的紋絲不亂的頭發(fā)上杨耙,一...
    開(kāi)封第一講書人閱讀 52,807評(píng)論 1 314
  • 那天赤套,我揣著相機(jī)與錄音飘痛,去河邊找鬼。 笑死容握,一個(gè)胖子當(dāng)著我的面吹牛宣脉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播剔氏,決...
    沈念sama閱讀 41,235評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼塑猖,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了谈跛?” 一聲冷哼從身側(cè)響起羊苟,我...
    開(kāi)封第一講書人閱讀 40,189評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎感憾,沒(méi)想到半個(gè)月后蜡励,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,712評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡阻桅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評(píng)論 3 343
  • 正文 我和宋清朗相戀三年凉倚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嫂沉。...
    茶點(diǎn)故事閱讀 40,926評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡稽寒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出趟章,到底是詐尸還是另有隱情杏糙,我是刑警寧澤慎王,帶...
    沈念sama閱讀 36,580評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站宏侍,受9級(jí)特大地震影響柬祠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜负芋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評(píng)論 3 336
  • 文/蒙蒙 一漫蛔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧旧蛾,春花似錦莽龟、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,750評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至病袄,卻和暖如春搂赋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背益缠。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,867評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工脑奠, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人幅慌。 一個(gè)月前我還...
    沈念sama閱讀 49,368評(píng)論 3 379
  • 正文 我出身青樓宋欺,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親胰伍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子齿诞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,336評(píng)論 25 707
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)骂租,斷路器祷杈,智...
    卡卡羅2017閱讀 134,719評(píng)論 18 139
  • 環(huán)境:win10專業(yè)版+opencv3.4+contrib+VS2015 圣誕前夕,opencv悄悄發(fā)布了3.4版...
    和藹的zhxing閱讀 5,289評(píng)論 0 0
  • 【文 | 一棵花白】 ■1 我在西安霧霾指數(shù)排全國(guó)第二的時(shí)候,機(jī)智的去杭州瀟灑了抽米。不曾想昨天下午返程時(shí)特占,西安的霧霾...
    一棵花白閱讀 660評(píng)論 11 12
  • 1987-2013,26年的時(shí)光過(guò)去是目,我從牙牙學(xué)語(yǔ)的嬰兒到小學(xué)、初中标捺、高中懊纳、大學(xué)揉抵,一步步走過(guò)來(lái),08年開(kāi)始工作嗤疯,一...
    天人321閱讀 954評(píng)論 0 1