學(xué)會(huì)識(shí)別它們蟆肆,養(yǎng)成避免它們的習(xí)慣
讓我先澄清一件事。如果您是初學(xué)者晦款,本文并不是要讓您對(duì)可能犯的錯(cuò)誤感到難過(guò)炎功,而是要讓您意識(shí)到這些錯(cuò)誤,教您發(fā)現(xiàn)它們的跡象柬赐,并提醒您避免它們亡问。
我過(guò)去犯過(guò)這些錯(cuò)誤官紫,并從每一個(gè)錯(cuò)誤中吸取教訓(xùn)肛宋。我很高興養(yǎng)成了編碼習(xí)慣來(lái)幫助我避免它們。你也應(yīng)該這樣做束世。
這些錯(cuò)誤在這里沒(méi)有按任何特定順序列出酝陈。
1)沒(méi)有計(jì)劃地編寫(xiě)代碼
一般來(lái)說(shuō),高質(zhì)量的書(shū)面內(nèi)容不容易創(chuàng)作毁涉。這需要仔細(xì)思考和研究沉帮。優(yōu)質(zhì)節(jié)目也不例外。
編寫(xiě)高質(zhì)量的程序是一個(gè)流程:
思考贫堰。研究穆壕。計(jì)劃。寫(xiě)其屏。驗(yàn)證喇勋。修改。
不幸的是偎行,沒(méi)有好的首字母縮略詞川背。您需要養(yǎng)成習(xí)慣,始終進(jìn)行適量的這些活動(dòng)蛤袒。
作為初學(xué)者熄云,我犯過(guò)的最大錯(cuò)誤之一就是沒(méi)有經(jīng)過(guò)太多思考和研究就立即開(kāi)始編寫(xiě)代碼。雖然這可能適用于小型獨(dú)立應(yīng)用程序妙真,但它對(duì)大型應(yīng)用程序有很大的負(fù)面影響跃惫。
就像您在說(shuō)出任何您可能會(huì)后悔的話之前需要三思一樣,您在編碼任何您可能會(huì)后悔的事情之前也需要三思每聪。編碼也是一種交流想法的方式肚菠。
生氣的時(shí)候,先數(shù)到10再說(shuō)話菱阵。如果很生氣踢俄,一百。
— 托馬斯·杰斐遜晴及。
這是我對(duì)那句話的版本:
檢查代碼時(shí)都办,在重構(gòu)一行之前數(shù)到 10。如果代碼沒(méi)有測(cè)試,一百個(gè)琳钉。
— 薩默·布納
編程主要是關(guān)于閱讀以前的代碼势木,研究需要什么以及它如何適應(yīng)當(dāng)前系統(tǒng),以及計(jì)劃編寫(xiě)具有小的歌懒、可測(cè)試的增量的功能啦桌。實(shí)際寫(xiě)的代碼行大概只占整個(gè)過(guò)程的10%。
不要將編程視為編寫(xiě)代碼行及皂。編程是一種需要培養(yǎng)的基于邏輯的創(chuàng)造力甫男。
2) 寫(xiě)代碼前計(jì)劃太多
是的。在著手編寫(xiě)代碼之前進(jìn)行計(jì)劃是一件好事验烧,但是當(dāng)您做太多事情時(shí)板驳,即使是好的事情也會(huì)傷害您。喝太多水可能會(huì)中毒碍拆。
不要尋找完美的計(jì)劃若治。這在編程世界中是不存在的。尋找一個(gè)足夠好的計(jì)劃感混,你可以用它來(lái)開(kāi)始端幼。事實(shí)上,你的計(jì)劃會(huì)改變弧满,但它的好處是迫使你進(jìn)入某種結(jié)構(gòu)婆跑,使你的代碼更加清晰。太多的計(jì)劃只會(huì)浪費(fèi)你的時(shí)間谱秽。
我只是在談?wù)撘?guī)劃小功能洽蛀。一次規(guī)劃所有功能應(yīng)該被取締!這就是我們所說(shuō)的瀑布法疟赊,它是一個(gè)系統(tǒng)的線性計(jì)劃郊供,有不同的步驟,一個(gè)一個(gè)地完成近哟。您可以想象這種方法需要多少計(jì)劃驮审。這不是我在這里談?wù)摰哪欠N計(jì)劃。瀑布方法不適用于大多數(shù)軟件項(xiàng)目吉执。任何復(fù)雜的事情都只能通過(guò)靈活適應(yīng)現(xiàn)實(shí)來(lái)實(shí)施疯淫。
編寫(xiě)程序必須是一種響應(yīng)式活動(dòng)。您將添加您在瀑布計(jì)劃中永遠(yuǎn)不會(huì)想到的功能戳玫。您將出于在瀑布計(jì)劃中永遠(yuǎn)不會(huì)考慮的原因而刪除功能熙掺。您需要修復(fù)錯(cuò)誤并適應(yīng)變化。你需要敏捷咕宿。
但是币绩,請(qǐng)始終計(jì)劃您接下來(lái)的幾個(gè)功能蜡秽。做這件事要非常小心,因?yàn)橛?jì)劃太少和太多都會(huì)損害代碼的質(zhì)量缆镣,而代碼的質(zhì)量不是你可以冒險(xiǎn)的芽突。
3)低估代碼質(zhì)量的重要性
如果您只能關(guān)注所編寫(xiě)代碼的一個(gè)方面,那應(yīng)該是它的可讀性董瞻。不清楚的代碼是垃圾寞蚌。它甚至不可回收。
永遠(yuǎn)不要低估代碼質(zhì)量的重要性钠糊。將編碼視為一種溝通實(shí)現(xiàn)的方式挟秤。作為編碼人員,您的主要工作是清楚地傳達(dá)您正在處理的任何解決方案的實(shí)現(xiàn)眠蚂。
我最喜歡的關(guān)于編程的名言之一是:
始終編寫(xiě)代碼煞聪,好像最終維護(hù)您的代碼的人將是一個(gè)知道您住在哪里的暴力精神病患者。
— 約翰·伍茲
絕妙的建議逝慧,約翰!
即使是小事也很重要啄糙。例如笛臣,如果您的縮進(jìn)和大小寫(xiě)不一致,您應(yīng)該簡(jiǎn)單地失去您的代碼許可隧饼。
tHIS is
WAY MORE important
than
you think
另一個(gè)簡(jiǎn)單的事情是使用長(zhǎng)線沈堡。任何超過(guò) 80 個(gè)字符的內(nèi)容都很難閱讀。您可能想在同一行中放置一些較長(zhǎng)的條件燕雁,以使 if 語(yǔ)句塊更加可見(jiàn)诞丽。不要那樣做。永遠(yuǎn)不要超過(guò) 80 個(gè)字符的限制拐格。
使用linting和formatting工具可以輕松解決許多像這樣的簡(jiǎn)單問(wèn)題僧免。在 JavaScript 中,我們有兩個(gè)可以完美協(xié)同工作的優(yōu)秀工具:ESLint和Prettier捏浊。幫自己一個(gè)忙懂衩,并始終使用它們。
這里還有一些與代碼質(zhì)量相關(guān)的錯(cuò)誤:
— 在函數(shù)或文件中使用多行金踪。您應(yīng)該始終將長(zhǎng)代碼分成更小的塊浊洞,以便單獨(dú)測(cè)試和管理。我個(gè)人認(rèn)為任何超過(guò) 10 行的函數(shù)都太長(zhǎng)了胡岔,但這只是一個(gè)經(jīng)驗(yàn)法則法希。
— 使用雙重否定。請(qǐng)不要不要那樣做靶瘸。
使用雙重否定是非常正確的
— 使用短的苫亦、通用的或基于類型的變量名尖淘。為您的變量提供描述性和明確的名稱。
計(jì)算機(jī)科學(xué)中只有兩件難事:緩存失效和命名事物著觉。
— 菲爾·卡爾頓
— 沒(méi)有描述的硬編碼原始字符串和數(shù)字村生。如果您想編寫(xiě)依賴于固定原始字符串或數(shù)字值的邏輯,請(qǐng)將該值放入常量中并為其命名饼丘。
const answerToLifeTheUniverseAndEverything = 42;
— 使用草率的捷徑和解決方法來(lái)避免在簡(jiǎn)單問(wèn)題上花費(fèi)更多時(shí)間趁桃。不要繞著問(wèn)題跳舞。面對(duì)你的現(xiàn)實(shí)肄鸽。
— 認(rèn)為代碼越長(zhǎng)越好卫病。在大多數(shù)情況下,越短的代碼越好典徘。只有在使代碼更具可讀性的情況下才編寫(xiě)更長(zhǎng)的版本蟀苛。例如,不要僅僅為了使代碼更短而使用巧妙的單行代碼和嵌套三元表達(dá)式逮诲,也不要在不需要時(shí)故意使代碼更長(zhǎng)帜平。刪除不必要的代碼是您在任何程序中都能做的最好的事情。
用代碼行數(shù)衡量編程進(jìn)度就像用重量衡量飛機(jī)制造進(jìn)度梅鹦。
— 比爾蓋茨
— 過(guò)度使用條件邏輯裆甩。大多數(shù)你認(rèn)為需要條件邏輯的東西都可以在沒(méi)有它的情況下完成∑胨簦考慮所有備選方案嗤栓,并僅根據(jù)可讀性進(jìn)行選擇。除非可以測(cè)量箍邮,否則不要優(yōu)化性能茉帅。相關(guān):避免條件句中的Yoda conditions和賦值。
4) 選擇第一個(gè)解決方案
當(dāng)我開(kāi)始編程時(shí)锭弊,我記得當(dāng)我遇到問(wèn)題時(shí)堪澎,我會(huì)找到解決方案并立即運(yùn)行它。在考慮我第一個(gè)確定的解決方案的復(fù)雜性和潛在失敗之前廷蓉,我會(huì)立即著手實(shí)施全封。
雖然第一個(gè)解決方案可能很誘人,但一旦您開(kāi)始質(zhì)疑找到的所有解決方案桃犬,通常就會(huì)發(fā)現(xiàn)好的解決方案刹悴。如果你想不出一個(gè)問(wèn)題的多種解決方案,這可能表明你沒(méi)有完全理解這個(gè)問(wèn)題攒暇。
作為專業(yè)程序員土匀,您的工作不是找到問(wèn)題的解決方案。就是找到最簡(jiǎn)單的解決問(wèn)題的方法形用。我所說(shuō)的“簡(jiǎn)單”是指解決方案必須能夠正確工作并充分執(zhí)行就轧,但仍然足夠簡(jiǎn)單以供閱讀证杭、理解和維護(hù)。
有兩種構(gòu)建軟件設(shè)計(jì)的方法妒御。一種是簡(jiǎn)單到明顯沒(méi)有缺陷解愤,另一種是復(fù)雜到?jīng)]有明顯缺陷。
— 汽車霍爾
5) 不放棄
另一個(gè)我經(jīng)常犯但不愿承認(rèn)的錯(cuò)誤是乎莉,即使在我確定第一個(gè)解決方案可能不是最簡(jiǎn)單的方法之后送讲,我仍然堅(jiān)持使用第一個(gè)解決方案。這可能與“不放棄”的心理有關(guān)惋啃。這是大多數(shù)活動(dòng)中都應(yīng)有的良好心態(tài)哼鬓,但不適用于編程。其實(shí)寫(xiě)程序边灭,正確的心態(tài)是早點(diǎn)失敗异希,經(jīng)常失敗。
在您開(kāi)始懷疑解決方案的那一刻绒瘦,您應(yīng)該考慮放棄它并重新考慮問(wèn)題称簿。無(wú)論您對(duì)該解決方案投入了多少,這都是事實(shí)椭坚。GIT 等源代碼控制工具可以幫助您分支并試驗(yàn)許多不同的解決方案予跌。利用那個(gè)。
不要因?yàn)槟愀冻隽硕嗌倥蛨?zhí)著于代碼善茎。壞代碼需要被丟棄。
6)不谷歌搜索
在很多情況下频轿,我本應(yīng)首先研究問(wèn)題垂涯,卻浪費(fèi)了寶貴的時(shí)間來(lái)解決問(wèn)題。
除非您使用的是前沿技術(shù)航邢,否則當(dāng)您遇到問(wèn)題時(shí)耕赘,其他人很可能遇到了同樣的問(wèn)題并找到了解決方案。為自己節(jié)省一些時(shí)間并首先使用 Google It膳殷。
有時(shí)操骡,谷歌搜索會(huì)發(fā)現(xiàn)你認(rèn)為是問(wèn)題的東西實(shí)際上不是問(wèn)題,你需要做的不是修復(fù)它赚窃,而是擁抱它册招。不要假設(shè)您知道選擇問(wèn)題解決方案所需的一切。谷歌會(huì)讓你大吃一驚勒极。
但是是掰,請(qǐng)注意您使用 Google 搜索的內(nèi)容。新手的另一個(gè)標(biāo)志是在不理解的情況下照原樣復(fù)制和使用其他代碼辱匿。雖然該代碼可能會(huì)正確解決您的問(wèn)題键痛,但您永遠(yuǎn)不應(yīng)使用您不完全理解的任何代碼行炫彩。
如果你想成為一名有創(chuàng)造力的編碼員,永遠(yuǎn)不要認(rèn)為你知道自己在做什么絮短。
作為一個(gè)有創(chuàng)造力的人江兢,您可能擁有的最危險(xiǎn)的想法就是認(rèn)為您知道自己在做什么。
— 布雷特·維克多
7)不使用封裝
這一點(diǎn)與使用面向?qū)ο蠓妒綗o(wú)關(guān)丁频。封裝概念的使用總是有用的杉允。不使用封裝通常會(huì)導(dǎo)致系統(tǒng)更難維護(hù)。
在一個(gè)應(yīng)用程序中限府,一個(gè)功能應(yīng)該只有一個(gè)地方來(lái)處理它夺颤。這通常是單個(gè)對(duì)象的職責(zé)。該對(duì)象應(yīng)該只顯示應(yīng)用程序的其他對(duì)象使用它所絕對(duì)必要的內(nèi)容胁勺。這與保密無(wú)關(guān)世澜,而是關(guān)于減少應(yīng)用程序不同部分之間依賴性的概念。遵守這些規(guī)則可以讓您安全地對(duì)類署穗、對(duì)象和函數(shù)的內(nèi)部進(jìn)行更改寥裂,而不必?fù)?dān)心在更大范圍內(nèi)破壞事物。
邏輯和狀態(tài)的概念單元應(yīng)該有自己的類案疲。對(duì)于類封恰,我指的是藍(lán)圖模板。這可以是實(shí)際的Class對(duì)象或Function對(duì)象褐啡。您也可以將其標(biāo)識(shí)為Module或Package诺舔。
在一類邏輯中,獨(dú)立的任務(wù)片段應(yīng)該有自己的方法备畦。方法應(yīng)該做一件事并且把那件事做好低飒。相似的類應(yīng)該使用相同的方法名。
作為一名初級(jí)程序員懂盐,我并不總是有為概念單元開(kāi)始新課程的本能褥赊,而且我常常無(wú)法確定什么可以自包含。如果你看到一個(gè)“Util
”類被用作許多不屬于一起的東西的垃圾場(chǎng)莉恼,那就是新手代碼的標(biāo)志拌喉。如果你做了一個(gè)簡(jiǎn)單的改變,然后發(fā)現(xiàn)這個(gè)改變會(huì)產(chǎn)生級(jí)聯(lián)效應(yīng)俐银,你需要在其他地方做很多改變尿背,這是新手代碼的另一個(gè)標(biāo)志。
在向類添加方法或向方法添加更多職責(zé)之前悉患,請(qǐng)思考并質(zhì)疑您的直覺(jué)残家。你在這里需要時(shí)間。不要跳過(guò)或認(rèn)為您稍后會(huì)重構(gòu)它售躁。第一次就做對(duì)坞淮。
這里的主要想法是您希望您的代碼具有高內(nèi)聚和低耦合茴晋,這只是一個(gè)奇特的術(shù)語(yǔ),意味著將相關(guān)代碼放在一起(在一個(gè)類中)并減少不同類之間的依賴性回窘。
8)為未知做計(jì)劃
人們常常想超越您正在編寫(xiě)的解決方案進(jìn)行思考诺擅。隨著您編寫(xiě)的每一行代碼,各種假設(shè)都會(huì)浮現(xiàn)在您的腦海中啡直。這對(duì)于測(cè)試邊緣情況來(lái)說(shuō)是一件好事烁涌,但作為潛在需求的驅(qū)動(dòng)程序則是錯(cuò)誤的。
您需要確定您的假設(shè)屬于這兩個(gè)主要類別中的哪一個(gè)酒觅。不要編寫(xiě)您今天不需要的代碼撮执。不要為未知的未來(lái)做計(jì)劃。
因?yàn)槟J(rèn)為將來(lái)可能需要它而編寫(xiě)功能是完全錯(cuò)誤的舷丹。不要做抒钱。
始終為您正在實(shí)施的解決方案編寫(xiě)您今天需要的最少代碼量。當(dāng)然颜凯,處理邊緣情況谋币,但不要添加邊緣特征。
為了增長(zhǎng)而增長(zhǎng)是癌細(xì)胞的意識(shí)形態(tài)症概。
— 愛(ài)德華·艾比
9) 沒(méi)有使用正確的數(shù)據(jù)結(jié)構(gòu)
在準(zhǔn)備面試時(shí)蕾额,初級(jí)程序員通常會(huì)過(guò)分關(guān)注算法。識(shí)別好的算法并在需要時(shí)使用它們是件好事彼城,但記住它們可能永遠(yuǎn)不會(huì)歸功于你的編程天才诅蝶。
但是,記住您可以在您的語(yǔ)言中使用的各種數(shù)據(jù)結(jié)構(gòu)的優(yōu)點(diǎn)和缺點(diǎn)肯定會(huì)讓您成為更好的開(kāi)發(fā)人員募壕。
使用錯(cuò)誤的數(shù)據(jù)結(jié)構(gòu)是一個(gè)巨大而強(qiáng)烈的廣告牌標(biāo)志秤涩,在這里尖叫著新手代碼。
本文并不是要教您有關(guān)數(shù)據(jù)結(jié)構(gòu)的知識(shí)司抱,但讓我舉幾個(gè)簡(jiǎn)單的例子:
— 使用列表(數(shù)組)代替映射(對(duì)象)來(lái)管理記錄
最常見(jiàn)的數(shù)據(jù)結(jié)構(gòu)錯(cuò)誤可能是使用列表而不是映射來(lái)管理記錄列表。是的黎烈,要管理記錄列表习柠,您應(yīng)該使用 MAP。
請(qǐng)注意照棋,我在這里談?wù)摰氖怯涗浟斜碜世#渲忻織l記錄都有一個(gè)用于查找該記錄的標(biāo)識(shí)符。對(duì)標(biāo)量值使用列表是可以的烈炭,而且通常是更好的選擇溶锭,特別是如果使用的重點(diǎn)是將值“推送”到列表中。
在 JavaScript 中符隙,最常見(jiàn)的列表結(jié)構(gòu)是數(shù)組趴捅,最常見(jiàn)的映射結(jié)構(gòu)是對(duì)象(現(xiàn)代 JavaScript 中也有映射結(jié)構(gòu))垫毙。
使用列表而不是 MAP 來(lái)管理記錄通常是錯(cuò)誤的。雖然這一點(diǎn)實(shí)際上只適用于大型收藏拱绑,但我會(huì)說(shuō)一直堅(jiān)持下去综芥。這很重要的主要原因是因?yàn)樵谑褂脴?biāo)識(shí)符查找記錄時(shí),地圖比列表快得多猎拨。
— 不使用堆棧
在編寫(xiě)任何需要某種形式的遞歸的代碼時(shí)膀藐,使用簡(jiǎn)單的遞歸函數(shù)總是很誘人。但是红省,通常很難優(yōu)化遞歸代碼额各,尤其是在單線程環(huán)境中。
優(yōu)化遞歸代碼取決于遞歸函數(shù)返回什么吧恃。例如虾啦,優(yōu)化返回兩次或更多次調(diào)用自身的遞歸函數(shù)比優(yōu)化僅返回一次調(diào)用自身的遞歸函數(shù)要困難得多。
作為初學(xué)者蚜枢,我們往往會(huì)忽視的是缸逃,除了使用遞歸函數(shù)之外,還有一種替代方法厂抽。您可以只使用Stack結(jié)構(gòu)需频。自己將函數(shù)調(diào)用推送到堆棧,并在準(zhǔn)備好遍歷調(diào)用時(shí)開(kāi)始將它們彈出筷凤。
10) 使現(xiàn)有代碼更糟
想象一下昭殉,你有一個(gè)這樣凌亂的房間:
然后要求您向該房間添加一個(gè)項(xiàng)目。因?yàn)樗呀?jīng)是一團(tuán)糟了藐守,你可能會(huì)想把那個(gè)東西放在任何地方挪丢。您可以在幾秒鐘內(nèi)完成任務(wù)。
不要用混亂的代碼來(lái)做那件事卢厂。不要讓它變得更糟乾蓬!始終讓代碼比開(kāi)始使用它時(shí)更干凈一些。
對(duì)上面的房間正確的做法是清理所需的東西慎恒,以便將新物品放在正確的地方任内。例如,如果該物品是一件需要放在壁櫥中的衣服融柬,則您需要清除通往壁櫥的路徑死嗦。這是正確完成任務(wù)的一部分。
這里有一些錯(cuò)誤的做法粒氧,通常會(huì)使代碼比原來(lái)更亂(不是完整列表):
- 復(fù)制代碼越除。如果你復(fù)制/粘貼一個(gè)代碼部分只是在那之后改變一行,你只是在復(fù)制代碼并制造更大的混亂。在上面凌亂的房間示例的背景下摘盆,這就像引入另一把底座較低的椅子翼雀,而不是投資購(gòu)買高度可調(diào)的新椅子。始終將抽象的概念牢記在心骡澈,并在可能的時(shí)候使用它锅纺。
- 不使用配置文件。如果您需要使用在不同環(huán)境或不同時(shí)間可能不同的值肋殴,則該值屬于配置文件囤锉。如果您需要在代碼中的多個(gè)位置使用一個(gè)值,則該值屬于配置文件护锤。當(dāng)您向代碼中引入新值時(shí)官地,請(qǐng)始終問(wèn)自己這個(gè)問(wèn)題:這個(gè)值是否屬于配置文件?答案很可能是肯定的烙懦。
- 使用不必要的條件語(yǔ)句和臨時(shí)變量驱入。每個(gè) if 語(yǔ)句都是一個(gè)邏輯分支,需要至少進(jìn)行雙重測(cè)試氯析。當(dāng)您可以在不犧牲可讀性的情況下避免條件語(yǔ)句時(shí)亏较,您應(yīng)該這樣做。這樣做的主要問(wèn)題是使用分支邏輯擴(kuò)展功能而不是引入另一個(gè)功能掩缓。每次您認(rèn)為需要一個(gè) if 語(yǔ)句或一個(gè)新的函數(shù)變量時(shí)雪情,您應(yīng)該問(wèn)問(wèn)自己:我是在正確的級(jí)別更改代碼,還是應(yīng)該在更高級(jí)別考慮問(wèn)題你辣?
關(guān)于不必要的 if 語(yǔ)句巡通,請(qǐng)考慮以下代碼:
function isOdd(number) {
if (number % 2 === 1) {
return true;
} else {
return false;
}
}
上面的isOdd
函數(shù)有一些問(wèn)題,但你能看出最明顯的一個(gè)嗎舍哄?
它使用了不必要的 if 語(yǔ)句宴凉。這是等效的代碼:
function isOdd(number) {
return (number % 2 === 1);
};
11)寫(xiě)關(guān)于顯而易見(jiàn)的事情的注釋
我學(xué)會(huì)了盡可能避免寫(xiě)注釋的艱難方法。大多數(shù)注釋都可以替換為代碼中更好命名的元素表悬。
例如弥锄,而不是下面的代碼:
// This function sums only odd numbers in an array
const sum = (val) => {
return val.reduce((a, b) => {
if (b % 2 === 1) { // If the current number is odd
a+=b; // Add current number to accumulator
}
return a; // The accumulator
}, 0);
};
同樣的代碼可以不帶注釋寫(xiě)成這樣:
const sumOddValues = (array) => {
return array.reduce((accumulator, currentNumber) => {
if (isOdd(currentNumber)) {
return accumulator + currentNumber;
}
return accumulator;
}, 0);
};
僅僅為函數(shù)和參數(shù)使用更好的名字就可以讓大多數(shù)注釋變得不必要。在寫(xiě)任何注釋之前請(qǐng)記住這一點(diǎn)蟆沫。
但是叉讥,有時(shí)您會(huì)被迫陷入這樣的境地:您可以通過(guò)注釋為代碼添加的唯一清晰度。這時(shí)你應(yīng)該構(gòu)建你的注釋來(lái)回答為什么這個(gè)代碼的問(wèn)題饥追,而不是這個(gè)代碼在做什么的問(wèn)題。
如果您很想寫(xiě)一個(gè) WHAT 注釋來(lái)澄清代碼罐盔,請(qǐng)不要指出顯而易見(jià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;
}
);
不要成為那個(gè)程序員。不要接受那個(gè)代碼捏顺。如果您必須處理這些注釋六孵,請(qǐng)將其刪除。最重要的是幅骄,教育編寫(xiě)此類注釋的程序員他們有多糟糕劫窒。如果您碰巧雇用了編寫(xiě)上述注釋的程序員,請(qǐng)讓他們知道他們實(shí)際上可能因此而丟掉工作拆座。是的……就是這么糟糕主巍。
12) 不寫(xiě)測(cè)試
我將保持這一點(diǎn)簡(jiǎn)單。如果您認(rèn)為自己是專家級(jí)程序員挪凑,并且這種想法使您有信心在不進(jìn)行測(cè)試的情況下編寫(xiě)代碼孕索,那么您就是我書(shū)中的新手。
如果您沒(méi)有在代碼中編寫(xiě)測(cè)試躏碳,您很可能會(huì)以其他方式手動(dòng)測(cè)試您的程序搞旭。如果您正在構(gòu)建 Web 應(yīng)用程序,您將在每隔幾行代碼后刷新并與應(yīng)用程序交互菇绵。我也這樣做肄渗。手動(dòng)測(cè)試代碼沒(méi)有錯(cuò)。但是咬最,您應(yīng)該手動(dòng)測(cè)試您的代碼以弄清楚如何自動(dòng)測(cè)試它翎嫡。如果您成功測(cè)試了與您的應(yīng)用程序的交互,您應(yīng)該返回到您的代碼編輯器并編寫(xiě)代碼以在您下次向項(xiàng)目添加更多代碼時(shí)自動(dòng)執(zhí)行完全相同的交互丹诀。
你是一個(gè)人钝的。您將忘記在每次代碼更改后測(cè)試所有先前成功的驗(yàn)證。讓電腦為你做這些铆遭!
如果可以硝桩,甚至在編寫(xiě)代碼以滿足它們之前,就可以從猜測(cè)或設(shè)計(jì)驗(yàn)證開(kāi)始枚荣。測(cè)試驅(qū)動(dòng)開(kāi)發(fā) (TDD) 不僅僅是一些花哨的炒作碗脊。它對(duì)您思考功能的方式以及如何為它們提出更好的設(shè)計(jì)產(chǎn)生積極影響。
TDD 并不適合所有人橄妆,也不是對(duì)每個(gè)項(xiàng)目都適用衙伶,但如果你可以利用它(即使是部分),你應(yīng)該完全這樣做害碾。
13)假設(shè)如果事情正常矢劲,那么事情就是對(duì)的
看一下實(shí)現(xiàn)該sumOddValues
功能的函數(shù)。它有什么問(wèn)題嗎慌随?
const sumOddValues = (array) => {
return array.reduce((accumulator, currentNumber) => {
if (currentNumber % 2 === 1) {
return accumulator + currentNumber;
}
return accumulator;
});
};
console.assert(
sumOddValues([1, 2, 3, 4, 5]) === 9
);
斷言通過(guò)芬沉。生活很好躺同。是的是的?
上面代碼的問(wèn)題是它不完整丸逸。它正確地處理了一些情況(并且使用的斷言恰好是這些情況之一)但是除此之外它還有很多問(wèn)題蹋艺。讓我來(lái)看看其中的一些:
— 問(wèn)題 #1:沒(méi)有對(duì)空輸入的處理。當(dāng)函數(shù)在沒(méi)有任何參數(shù)的情況下被調(diào)用時(shí)會(huì)發(fā)生什么黄刚?現(xiàn)在捎谨,當(dāng)發(fā)生這種情況時(shí),您會(huì)收到一條錯(cuò)誤消息憔维,顯示函數(shù)的實(shí)現(xiàn):
TypeError: Cannot read property 'reduce' of undefined.
由于兩個(gè)主要原因涛救,這通常是錯(cuò)誤代碼的標(biāo)志。
- 您函數(shù)的用戶不應(yīng)遇到有關(guān)它的實(shí)現(xiàn)細(xì)節(jié)埋同。
- 該錯(cuò)誤對(duì)用戶沒(méi)有幫助州叠。您的功能對(duì)他們不起作用。但是凶赁,如果錯(cuò)誤更清楚地說(shuō)明使用問(wèn)題咧栗,他們就會(huì)知道他們錯(cuò)誤地使用了該功能。例如虱肄,您可以選擇讓函數(shù)拋出一個(gè)用戶定義的異常致板,如下所示:
TypeError: Cannot execute function for empty list.
也許不是拋出錯(cuò)誤,而是需要將函數(shù)設(shè)計(jì)為忽略空輸入并返回0
咏窿。無(wú)論如何斟或,必須為這種情況做點(diǎn)什么。
— 問(wèn)題 #2:沒(méi)有對(duì)無(wú)效輸入的處理集嵌。如果使用字符串萝挤、整數(shù)或?qū)ο笾刀皇菙?shù)組調(diào)用函數(shù),會(huì)發(fā)生什么情況根欧?
這是該函數(shù)現(xiàn)在將拋出的內(nèi)容:
sumOddValues(42);
TypeError: array.reduce is not a function
好吧怜珍,這很不幸,因?yàn)?code>array.reduce它絕對(duì)是一個(gè)函數(shù)凤粗!
因?yàn)槲覀兠撕瘮?shù)的參數(shù)array
酥泛,所以你調(diào)用函數(shù)的任何東西(42
在上面的例子中)都被標(biāo)記為array
在函數(shù)內(nèi)。錯(cuò)誤基本上是說(shuō)這42.reduce
不是一個(gè)函數(shù)嫌拣。
你看到那個(gè)錯(cuò)誤是多么令人困惑柔袁,對(duì)吧?也許更有幫助的錯(cuò)誤是:
TypeError: 42 is not an array, dude.
問(wèn)題 #1 和 #2 有時(shí)被稱為邊緣情況异逐。這些是一些需要規(guī)劃的常見(jiàn)邊緣情況捶索,但通常還有一些不太明顯的邊緣情況需要您考慮。例如灰瞻,如果我們使用負(fù)數(shù)會(huì)怎樣情组?
sumOddValues([1, 2, 3, 4, 5, -13]) // => still 9
嗯燥筷,-13
是奇數(shù)。這是您希望此功能具有的行為嗎院崇?它應(yīng)該拋出錯(cuò)誤嗎?它應(yīng)該在總和中包括負(fù)數(shù)嗎袍祖?或者它應(yīng)該像現(xiàn)在這樣簡(jiǎn)單地忽略負(fù)數(shù)嗎底瓣?也許您會(huì)意識(shí)到該函數(shù)應(yīng)該命名為sumPositiveOddNumbers
。
在這種情況下做出決定很容易蕉陋。更重要的一點(diǎn)是捐凭,如果您不編寫(xiě)測(cè)試用例來(lái)記錄您的決定,那么您函數(shù)的未來(lái)維護(hù)者將不知道您忽略負(fù)數(shù)是有意還是錯(cuò)誤凳鬓。
這不是錯(cuò)誤茁肠。這是一個(gè)特點(diǎn)。
— 忘記測(cè)試用例的人
— 問(wèn)題 #3:并非所有有效案例都經(jīng)過(guò)測(cè)試缩举。忘掉邊緣情況吧垦梆,這個(gè)函數(shù)有一個(gè)合法且非常簡(jiǎn)單的情況,但它無(wú)法正確處理:
sumOddValues([2, 1, 3, 4, 5]) // => 11
以上2
不應(yīng)該包含在總和中仅孩。
解決方案很簡(jiǎn)單托猩,reduce
接受第二個(gè)參數(shù)作為accumulator
。如果未提供該參數(shù)(如上面的代碼)辽慕,reduce
將僅使用集合中的第一個(gè)值作為accumulator
京腥。這就是為什么上面測(cè)試用例中的第一個(gè)偶數(shù)值被包含在總和中的原因。
雖然您可能馬上或在編寫(xiě)代碼時(shí)就發(fā)現(xiàn)了這個(gè)問(wèn)題溅蛉,但這個(gè)揭示它的測(cè)試用例應(yīng)該首先包含在測(cè)試中公浪,連同許多其他測(cè)試用例,如全偶數(shù)船侧、列表里面有0
欠气,還有一個(gè)空列表。
如果您看到不處理許多情況或忽略邊緣情況的最小測(cè)試勺爱,那是新手代碼的另一個(gè)標(biāo)志晃琳。
14) 不質(zhì)疑現(xiàn)有代碼
除非你是一個(gè)總是獨(dú)自工作的超級(jí)編碼員,否則毫無(wú)疑問(wèn)你會(huì)在生活中遇到某種愚蠢的代碼琐鲁。初學(xué)者不會(huì)認(rèn)出它卫旱,他們通常認(rèn)為它是好的代碼,因?yàn)樗坪蹩梢怨ぷ魑Ф危⑶宜呀?jīng)成為代碼庫(kù)的一部分很長(zhǎng)時(shí)間了顾翼。
更糟糕的是,如果糟糕的代碼使用了糟糕的做法奈泪,初學(xué)者可能會(huì)試圖在代碼庫(kù)的其他地方重復(fù)這種糟糕的做法适贸,因?yàn)樗麄兪菑乃麄冋J(rèn)為好的代碼中學(xué)到的灸芳。
有些代碼看起來(lái)很糟糕,但它可能有一個(gè)特殊的條件拜姿,迫使開(kāi)發(fā)人員以這種方式編寫(xiě)它烙样。這是一個(gè)詳細(xì)注釋的好地方,可以教初學(xué)者了解該條件以及為什么以這種方式編寫(xiě)代碼蕊肥。
作為初學(xué)者谒获,您應(yīng)該假設(shè)您不理解的任何未記錄的代碼都可能是錯(cuò)誤的。質(zhì)疑它壁却。詢問(wèn)它批狱。git blame
它!
如果該代碼的作者早已不在或不記得了展东,請(qǐng)研究該代碼并嘗試了解它的所有內(nèi)容赔硫。只有當(dāng)您完全理解代碼時(shí),您才能形成對(duì)代碼好壞的看法盐肃。在此之前不要假設(shè)任何事情爪膊。
15) 執(zhí)著于最佳實(shí)踐
我認(rèn)為“最佳實(shí)踐”這個(gè)詞實(shí)際上是有害的。這意味著不需要進(jìn)一步的研究恼蓬。這是有史以來(lái)最好的做法惊完。不要質(zhì)疑它!
沒(méi)有最佳實(shí)踐处硬。對(duì)于這種編程語(yǔ)言小槐,今天可能有一些好的做法。
我們以前認(rèn)為是編程最佳實(shí)踐的一些東西今天被標(biāo)記為不良實(shí)踐荷辕。
如果您投入足夠的時(shí)間凿跳,您總能找到更好的做法。不要再擔(dān)心最佳實(shí)踐疮方,而是專注于您最擅長(zhǎng)的事情控嗜。
不要因?yàn)槟阍谀程幾x到的引述,或者因?yàn)槟憧吹絼e人這樣做骡显,或者因?yàn)橛腥苏f(shuō)這是最佳實(shí)踐而做某事疆栏。這包括我在本文中給出的所有建議!質(zhì)疑一切惫谤,挑戰(zhàn)所有理論壁顶,了解所有選擇,只做出有根據(jù)的決定溜歪。
16) 執(zhí)著于表現(xiàn)
過(guò)早的優(yōu)化是編程中萬(wàn)惡之源(或至少是萬(wàn)惡之源)
— 唐納德·高德納 (1974)
盡管自 Donald Knuth 寫(xiě)下上述聲明以來(lái)編程已經(jīng)發(fā)生了顯著變化若专,但我認(rèn)為它在今天仍然具有寶貴的建議。
記住這一點(diǎn)的好規(guī)則是:如果您無(wú)法用代碼測(cè)量可疑的性能問(wèn)題蝴猪,請(qǐng)不要嘗試優(yōu)化它调衰。
如果您在執(zhí)行代碼之前進(jìn)行優(yōu)化膊爪,那么您很可能過(guò)早地進(jìn)行了優(yōu)化。您投入時(shí)間進(jìn)行的優(yōu)化也很有可能完全沒(méi)有必要嚎莉。
當(dāng)然米酬,在引入新代碼之前,您應(yīng)該始終考慮一些明顯的優(yōu)化趋箩。例如淮逻,在 Node.js 中,不要淹沒(méi)事件循環(huán)或阻塞調(diào)用堆棧是極其重要的阁簸。這是您應(yīng)該始終牢記的早期優(yōu)化示例。問(wèn)問(wèn)自己:我正在考慮的代碼會(huì)阻塞調(diào)用堆棧嗎哼丈?
在沒(méi)有測(cè)量的情況下對(duì)任何現(xiàn)有代碼執(zhí)行的任何非顯而易見(jiàn)的優(yōu)化都被認(rèn)為是有害的启妹,應(yīng)該避免。你認(rèn)為可能會(huì)帶來(lái)性能提升的東西醉旦,如果完成了饶米,可能會(huì)成為新的、意想不到的錯(cuò)誤的來(lái)源车胡。
不要浪費(fèi)時(shí)間優(yōu)化無(wú)法測(cè)量的性能問(wèn)題檬输。
17) 不以最終用戶體驗(yàn)為目標(biāo)
向應(yīng)用程序添加功能的最簡(jiǎn)單方法是什么?從你自己的角度來(lái)看它匈棘,或者它如何適應(yīng)當(dāng)前的用戶界面丧慈。正確的?如果該功能是從用戶那里捕獲某種輸入主卫,則將其附加到您已有的表單中。如果該功能是向頁(yè)面添加鏈接,則將其添加到您已有的嵌套鏈接菜單中凛篙。
不要成為那個(gè)開(kāi)發(fā)者嘱朽。成為設(shè)身處地為最終用戶著想的專業(yè)人士之一。他們想象這個(gè)特定功能的用戶需要什么以及他們的行為方式瘩将。他們考慮如何讓用戶更容易找到和使用該功能吟税,而不是考慮以某種方式使該功能存在于應(yīng)用程序中而不考慮該功能的可發(fā)現(xiàn)性和可用性的簡(jiǎn)單方法。
18) 沒(méi)有為工作選擇合適的工具
每個(gè)人都有自己最喜歡的工具列表姿现,以幫助他們進(jìn)行與編程相關(guān)的活動(dòng)肠仪。有些工具很棒,有些則很差建钥,但大多數(shù)工具對(duì)某一特定事物非常有用藤韵,而對(duì)其他許多工具則不是那么好。
錘子是將釘子釘入墻壁的好工具熊经,但它是與螺釘一起使用的最糟糕的工具泽艘。不要僅僅因?yàn)槟跋矚g”那把錘子就在螺絲上使用錘子欲险。不要僅僅因?yàn)樗莵嗰R遜上最受歡迎的錘子,用戶評(píng)論為 5.0匹涮,就在螺絲上使用錘子天试。
依賴工具的受歡迎程度而不是它對(duì)問(wèn)題的適用程度是真正的新手的標(biāo)志。
關(guān)于這一點(diǎn)的一個(gè)問(wèn)題是然低,您可能不知道針對(duì)某項(xiàng)工作的“更好”工具喜每。在您目前的知識(shí)范圍內(nèi),工具可能是您所知道的最好的工具雳攘。但是带兜,與其他選項(xiàng)相比,它不會(huì)排在首位吨灭。您需要熟悉可用的工具刚照,并對(duì)可以開(kāi)始使用的新工具保持開(kāi)放的心態(tài)。
一些程序員拒絕使用新工具喧兄。他們對(duì)現(xiàn)有工具很滿意无畔,可能不想學(xué)習(xí)任何新工具。我明白這一點(diǎn)吠冤,我也能理解浑彰,但這完全是錯(cuò)誤的。
您可以使用原始工具建造房屋并享受美好時(shí)光拯辙,或者您可以花一些時(shí)間和金錢購(gòu)買優(yōu)質(zhì)工具并更快地建造更好的房屋郭变。工具在不斷改進(jìn),您需要輕松地了解和使用它們薄风。
19) 不理解代碼問(wèn)題會(huì)導(dǎo)致數(shù)據(jù)問(wèn)題
程序的一個(gè)重要方面通常是某種形式的數(shù)據(jù)的管理饵较。該程序?qū)⑹翘砑有掠涗浹摺h除舊記錄和修改其他記錄的界面茄猫。
即使是程序代碼中最小的錯(cuò)誤也會(huì)導(dǎo)致其管理的數(shù)據(jù)處于不可預(yù)測(cè)的狀態(tài)勇劣。如果對(duì)數(shù)據(jù)的所有驗(yàn)證都完全通過(guò)同一個(gè)錯(cuò)誤程序完成篡九,則尤其如此沛善。
當(dāng)談到代碼 - 數(shù)據(jù)關(guān)系時(shí),初學(xué)者可能不會(huì)立即將這些點(diǎn)聯(lián)系起來(lái)庆锦。他們可能會(huì)覺(jué)得繼續(xù)在生產(chǎn)中使用一些有缺陷的代碼是可以的焰雕,因?yàn)椴黄鹱饔玫墓δ?X 并不是特別重要。問(wèn)題是有缺陷的代碼可能會(huì)不斷引入一開(kāi)始并不明顯的數(shù)據(jù)完整性問(wèn)題。
更糟糕的是,發(fā)布修復(fù)錯(cuò)誤的代碼而不修復(fù)由這些錯(cuò)誤引起的細(xì)微數(shù)據(jù)問(wèn)題只會(huì)積累更多的數(shù)據(jù)問(wèn)題己肮,使案例成為“不可恢復(fù)級(jí)別”標(biāo)簽。
您如何保護(hù)自己免受此類問(wèn)題的困擾航夺?您可以簡(jiǎn)單地使用多層數(shù)據(jù)完整性驗(yàn)證。不要依賴單一的用戶界面诸老。在前端、后端、網(wǎng)絡(luò)通信和數(shù)據(jù)庫(kù)上創(chuàng)建驗(yàn)證苞尝。如果那不是一個(gè)選項(xiàng)溯捆,那么您至少必須使用數(shù)據(jù)庫(kù)級(jí)約束煮仇。
熟悉數(shù)據(jù)庫(kù)約束并在向數(shù)據(jù)庫(kù)添加列和表時(shí)使用所有這些約束:
- 列上的NOT NULL約束意味著該列將拒絕空值劳跃。如果您的應(yīng)用程序假定該字段存在值,則其源在您的數(shù)據(jù)庫(kù)中應(yīng)定義為非空夹姥。
- 列上的UNIQUE約束意味著該列不能在整個(gè)表中具有重復(fù)值杉武。例如,這非常適合用戶表中的用戶名或電子郵件字段辙售。
- CHECK約束是自定義表達(dá)式艺智,必須計(jì)算為 true 才能接受數(shù)據(jù)。例如圾亏,如果您有一個(gè)正常的百分比列,其值必須在 0 到 100 之間封拧,您可以使用檢查約束來(lái)強(qiáng)制執(zhí)行該列志鹃。
- PRIMARY KEY約束意味著該列的值既非空又是唯一的。你可能正在使用這個(gè)泽西。數(shù)據(jù)庫(kù)中的每個(gè)表都應(yīng)該有一個(gè)主鍵來(lái)標(biāo)識(shí)其記錄曹铃。
- FOREIGN KEY約束意味著該列的值必須與另一個(gè)表列(通常是主鍵)中的值相匹配。
另一個(gè)與數(shù)據(jù)完整性相關(guān)的新手問(wèn)題是缺乏交易方面的思考捧杉。如果多個(gè)操作需要更改同一個(gè)數(shù)據(jù)源并且它們相互依賴陕见,則它們必須包裝在一個(gè)事務(wù)中,該事務(wù)可以在其中一個(gè)操作失敗時(shí)回滾味抖。
20) 重新發(fā)明輪子
這是一個(gè)棘手的問(wèn)題评甜。在編程中,有些輪子值得重新發(fā)明仔涩。編程不是一個(gè)定義明確的領(lǐng)域忍坷。很多事情變化得如此之快,新需求的引入速度比任何團(tuán)隊(duì)都快。
例如佩研,如果您需要一個(gè)根據(jù)一天中的時(shí)間以不同速度旋轉(zhuǎn)的輪子柑肴,而不是定制我們都知道和喜愛(ài)的輪子,也許我們需要重新考慮它旬薯。然而晰骑,除非你真的需要一個(gè)在典型設(shè)計(jì)中沒(méi)有使用的輪子,否則不要重新發(fā)明它绊序。只需使用該死的輪子硕舆。
在眾多可用選項(xiàng)中選擇所需車輪的品牌有時(shí)具有挑戰(zhàn)性。做一些研究政模,然后再購(gòu)買岗宣!軟件“輪子”最酷的地方在于它們中的大多數(shù)都是免費(fèi)的,并且可以讓你看到它們的內(nèi)部設(shè)計(jì)淋样。您可以通過(guò)內(nèi)部設(shè)計(jì)質(zhì)量輕松判斷編碼輪耗式。如果可以,請(qǐng)使用開(kāi)源輪子趁猴】龋可以輕松調(diào)試和修復(fù)開(kāi)源包。它們也可以很容易地更換儡司。此外娱挨,更容易在內(nèi)部支持他們。
但是捕犬,如果您需要一個(gè)輪子跷坝,請(qǐng)不要購(gòu)買一輛全新的汽車,而是將您正在保養(yǎng)的汽車放在新車的上面碉碉。不要為了使用其中的一兩個(gè)函數(shù)而包括整個(gè)庫(kù)柴钻。最好的例子是 JavaScript 中的lodash庫(kù)。如果您只需要打亂一個(gè)數(shù)組垢粮,只需導(dǎo)入該shuffle
方法即可贴届。不要導(dǎo)入整個(gè)該死的 lodash 庫(kù)。
21) 對(duì)代碼審查的錯(cuò)誤態(tài)度
編碼新手的一個(gè)標(biāo)志是他們經(jīng)常將代碼審查視為批評(píng)蜡吧。他們不喜歡他們毫蚓。他們不欣賞他們。他們甚至害怕他們昔善。
這是錯(cuò)誤的元潘。如果你有這種感覺(jué),你需要立即改變這種態(tài)度君仆。將每次代碼審查視為一次學(xué)習(xí)機(jī)會(huì)柬批。歡迎他們并感謝他們啸澡。向他們學(xué)習(xí)。最重要的是氮帐,感謝審稿人教給你一些東西嗅虏。
你是一個(gè)永遠(yuǎn)的代碼學(xué)習(xí)者。你需要接受這一點(diǎn)上沐。大多數(shù)代碼審查都會(huì)教你一些你不知道的東西皮服。將它們歸類為學(xué)習(xí)資源。
有時(shí)参咙,審稿人會(huì)出錯(cuò)龄广,輪到你教他們一些東西。但是蕴侧,如果僅從您的代碼中看不出來(lái)择同,那么在這種情況下您的代碼可能需要修改。如果無(wú)論如何你都需要教你的審閱者一些東西净宵,只要知道教學(xué)是你作為程序員可以做的最有價(jià)值的活動(dòng)之一敲才。
22) 不使用源代碼管理
新手有時(shí)會(huì)低估一個(gè)好的源/版本控制系統(tǒng)的力量,我指的是Git择葡。
源代碼控制不僅僅是將您的更改推送給其他人使用和構(gòu)建紧武。它比那大得多。源代碼控制是關(guān)于清除歷史的敏储。代碼將受到質(zhì)疑阻星,該代碼的進(jìn)展歷史將有助于回答一些棘手的問(wèn)題。這就是我們關(guān)心提交消息的原因已添。它們是另一個(gè)溝通您的實(shí)現(xiàn)的渠道妥箕,將它們與小的提交一起使用可以幫助您的代碼的未來(lái)維護(hù)者弄清楚代碼是如何達(dá)到現(xiàn)在所處的狀態(tài)的。
經(jīng)常提交并盡早提交更舞,為了保持一致性畦幢,請(qǐng)?jiān)谔峤恢黝}行中使用現(xiàn)在時(shí)動(dòng)詞。詳細(xì)說(shuō)明您的消息疏哗,但請(qǐng)記住它們應(yīng)該是摘要。如果您需要其中的幾行以上禾怠,這可能表明您的提交太長(zhǎng)了返奉。變基!
不要在提交消息中包含任何不必要的內(nèi)容吗氏。例如芽偏,不要在提交摘要中列出添加、修改或刪除的文件弦讽。該列表存在于提交對(duì)象本身中污尉,并且可以使用一些 Git 命令參數(shù)輕松顯示膀哲。它只是摘要消息中的噪音。有些團(tuán)隊(duì)喜歡更改每個(gè)文件的不同摘要被碗,我認(rèn)為這是提交過(guò)大的另一個(gè)標(biāo)志某宪。
源代碼控制也與可發(fā)現(xiàn)性有關(guān)。如果您遇到一個(gè)功能并開(kāi)始質(zhì)疑它的需求或設(shè)計(jì)锐朴,您可以找到引入它的提交并查看該功能的上下文兴喂。提交甚至可以幫助您確定哪些代碼將錯(cuò)誤引入了程序。Git 甚至在提交(bisect
命令)中提供二進(jìn)制搜索來(lái)定位引入錯(cuò)誤的單個(gè)有罪提交焚志。
即使在更改成為正式提交之前衣迷,也可以以美妙的方式利用源代碼控制。暫存更改酱酬、有選擇地修補(bǔ)壶谒、重置、存儲(chǔ)膳沽、修改汗菜、應(yīng)用、差異化贵少、反轉(zhuǎn)等功能的使用為您的編碼流程添加了一些豐富的工具呵俏。了解它們、學(xué)習(xí)它們滔灶、使用它們并欣賞它們普碎。
您知道的 Git 功能越少,在我的書(shū)中您就越像個(gè)新手录平。
23) 過(guò)度使用共享狀態(tài)
同樣麻车,這不是關(guān)于函數(shù)式編程與其他范例的區(qū)別。這是另一篇文章的主題斗这。
這只是因?yàn)楣蚕頎顟B(tài)是問(wèn)題的根源动猬,應(yīng)該盡可能避免。如果那不可能表箭,則共享狀態(tài)的使用應(yīng)保持在絕對(duì)最低限度赁咙。
作為初學(xué)者,我沒(méi)有意識(shí)到的是免钻,我們定義的每個(gè)變量都代表一個(gè)共享狀態(tài)彼水。它保存的數(shù)據(jù)可以被與該變量處于同一范圍內(nèi)的所有元素更改。范圍越大极舔,這種共享狀態(tài)的跨度就越差凤覆。嘗試將新?tīng)顟B(tài)包含在小范圍內(nèi),并確保它們不會(huì)向上泄漏拆魏。
當(dāng)多個(gè)資源需要在事件循環(huán)的同一滴答中(在基于事件循環(huán)的環(huán)境中)一起更改該狀態(tài)時(shí)盯桦,共享狀態(tài)的大問(wèn)題開(kāi)始發(fā)生慈俯。競(jìng)爭(zhēng)條件將會(huì)發(fā)生。
事情是這樣的:新手可能會(huì)想使用計(jì)時(shí)器作為這種共享狀態(tài)競(jìng)爭(zhēng)條件問(wèn)題的變通方法拥峦,尤其是當(dāng)他們必須處理數(shù)據(jù)鎖定問(wèn)題時(shí)贴膘。這是一個(gè)很大的危險(xiǎn)信號(hào)。不要做事镣。注意它步鉴,在代碼審查中指出它,永遠(yuǎn)不要接受它璃哟。
24) 對(duì)錯(cuò)誤有錯(cuò)誤的態(tài)度
錯(cuò)誤是一件好事氛琢。他們意味著你正在取得進(jìn)步。它們意味著您可以輕松進(jìn)行后續(xù)更改以取得更多進(jìn)展随闪。
專業(yè)程序員喜歡錯(cuò)誤阳似。新手討厭他們。
如果看到這些美妙的紅色小錯(cuò)誤消息讓您感到困擾铐伴,您需要改變這種態(tài)度撮奏。您需要將他們視為幫手。你需要對(duì)付他們当宴。您需要利用它們來(lái)取得進(jìn)步畜吊。
有些錯(cuò)誤需要升級(jí)為異常。異常是您需要計(jì)劃的用戶定義的錯(cuò)誤户矢。有些錯(cuò)誤需要單獨(dú)處理玲献。他們需要使應(yīng)用程序崩潰并使其退出。
25) 不休息
你是一個(gè)人梯浪,你的大腦需要休息捌年。你的身體需要休息。你會(huì)經(jīng)常在區(qū)域中而忘記休息挂洛。我認(rèn)為這是新手的另一個(gè)標(biāo)志礼预。這不是你可以妥協(xié)的事情。在你的工作流程中加入一些東西來(lái)迫使你休息一下虏劲。多做短暫的休息托酸。離開(kāi)你的椅子,走一小段路柒巫,用它來(lái)思考你下一步需要做什么励堡。以全新的眼光回到代碼。
這是一篇很長(zhǎng)的文章吻育。你應(yīng)該休息一下念秧。
更多資源
我每天都為軟件開(kāi)發(fā)人員寫(xiě)一些新東西淤井。進(jìn)入每日列表以接收更新布疼。
如果你喜歡我的文章摊趾,點(diǎn)贊,關(guān)注游两,轉(zhuǎn)發(fā)砾层!