在技術(shù)社區(qū)經(jīng)常看到一些博客推廣各種編程語言的“高級特性”和“高級模式”,并利用這些特性提供一些“優(yōu)雅”的代碼。
但是這種花里胡哨的東西真的可以提升我們的編碼效能嗎?
恐怕 不是的!
許多人以使用語言和框架的晦澀功能為榮,通過利用各種罕見的 API 來展示他們對框架的熟悉程度。
他們認(rèn)為自己的編程和技術(shù)能力比那些寫簡單邏輯的同學(xué)要高。甚至還會產(chǎn)生 “傲慢” 的情緒。
這種觀點(diǎn)是 非常錯誤 的!
我們來看下面的例子:
在招聘開發(fā)人員時(shí),存在一個有趣的現(xiàn)象,即:更高級別的申請人較少審查具體的編碼技能,而更多地審查架構(gòu)能力、業(yè)務(wù)理解和工程質(zhì)量。
請注意,理解架構(gòu)、業(yè)務(wù)和工程并不是關(guān)于溝通或管理等軟技能,這是工程師堅(jiān)實(shí)的專業(yè)能力。
另一方面,技術(shù)社區(qū)中最受歡迎的內(nèi)容通常是各種框架和庫的“入門指南”。
從暢銷的《XXX從初學(xué)者到專家》指南到《一步一步教你如何學(xué)習(xí)XXX》,最熱門的內(nèi)容仍然圍繞著如何操作這些API并應(yīng)用某些技術(shù)知識模式。
考慮到這些現(xiàn)象和一些常識,我們可以得出以下三個條件:
根據(jù)這些條件,我們可以做出一個寬松的推論:最關(guān)心和癡迷于編程技能的人很可能是大多數(shù)處于初級水平的程序員。 因此,炫耀技能并不一定表明技術(shù)水平高超。
需要澄清的是,我們并不認(rèn)為編程技能不重要。相反,高級程序員對技能的理解比初級程序員要深刻得多,許多熟練的代碼可以在數(shù)量級上優(yōu)化和解決問題。
那么我們應(yīng)該如何評估這樣的代碼呢?
能夠應(yīng)用各種高級功能的學(xué)生無疑被認(rèn)為是“聰明”的。然而,何時(shí)以及如何使用它們需要基于所謂“智慧”的判斷。
這與 Facebook 和 Google 的代碼標(biāo)準(zhǔn)中經(jīng)常看到的說法類似:
運(yùn)用你最好的判斷力。
雖然聽起來很悅耳,但這是一個形式上的概念。
下面我們將進(jìn)行一些更具體的討論并提取一些常見的技巧。
幸福的家庭都是相似的;每個不幸的家庭都有自己的不幸。
——列夫·托爾斯泰
好的代碼就像好的文學(xué)作品,壞的代碼有它自己的壞處。
如果我們使用“聰明的技巧”來評估一段代碼,那么這段代碼的質(zhì)量可能不是很好。對于使用各種技術(shù)的代碼,我們還可以找到許多這些技術(shù)應(yīng)用不佳的場景來表明它們各自的問題。
很多人讀完《高級程序設(shè)計(jì)》之類的書后,都會將自己對高級功能的理解運(yùn)用到實(shí)際項(xiàng)目中去炫耀。在前端領(lǐng)域,這些行為包括但不限于:
使用具有這些功能的代碼當(dāng)然可以運(yùn)行,但這里的問題是這些語義都是 危險(xiǎn)的,或者是語言設(shè)計(jì)問題造成的渣滓。
既然知道它們很難使用,并且有成熟的替代解決方案可用,為什么還要用它們來展示自己的技術(shù)技能呢? 然而在前端社區(qū),這樣的行為卻屢屢發(fā)生。
例如:
當(dāng)然,這決不妨礙理解這些所謂的“高級功能”如何工作以及為什么它們會導(dǎo)致令人困惑的行為。
對于每個想要成長的可靠學(xué)生來說,學(xué)習(xí)它們很重要。這里給出的建議是:
每種編程語言在其開發(fā)過程中都不可避免地留下遺留問題。對于JS這樣一個一周誕生、向前兼容性要求非常高的語言來說,這個問題就更加嚴(yán)重了。
然而,隨著軟件工程的發(fā)展,這些設(shè)計(jì)缺陷帶來的危險(xiǎn)語義已經(jīng)慢慢淡入歷史。現(xiàn)在,像深入研究IE6兼容性問題一樣,深入學(xué)習(xí)、掌握和使用它們已經(jīng)逐漸過時(shí)了。
設(shè)計(jì)模式也是技術(shù)文章中非常常見的主題。
例如,很多文章都把《設(shè)計(jì)模式》中的幾十種模式應(yīng)用到了 JavaScript 中,用上面提到的各種“高級特性”來模擬這個、實(shí)現(xiàn)那個。最后,他們還夸夸其談,這些模式都是“優(yōu)秀程序員必知”,所以在簡歷上加上一句“精通各種設(shè)計(jì)模式”,就讓人印象深刻了!
設(shè)計(jì)模式的初衷是為了彌補(bǔ)Java等靜態(tài)語言的缺點(diǎn)。隨著編程語言的發(fā)展,許多“經(jīng)典”設(shè)計(jì)模式已經(jīng)成為語言機(jī)制的一部分。
比如:export 內(nèi)置對單例模式的支持,用函數(shù)層包裝內(nèi)容就是工廠模式,yield 也實(shí)現(xiàn)了迭代器模式等等。
此外,JS 的動態(tài)性使得 JSON 的靈活性大幅超越了反射,而一等公民的函數(shù)設(shè)計(jì)使得 JS 回調(diào)函數(shù)比 Java 的回調(diào)接口或類似 Visitor 的模式更加靈活。
很多提倡設(shè)計(jì)模式的文章之所以沒有傳播開來,是因?yàn)樗鼈內(nèi)藶榈刂圃炝瞬槐匾膹?fù)雜性,反而造成了一種誤解:“如果你不使用XX模式,就意味著你的技能缺乏”。
至少從我個人閱讀優(yōu)秀的開源項(xiàng)目源代碼來看,我還沒有發(fā)現(xiàn)機(jī)械應(yīng)用模式的實(shí)例;相反,需要解決的問題被清楚地描述,然后提供可讀的抽象。
當(dāng)然,我們可以回顧性地識別其中的某些實(shí)施模式;然而,我更愿意相信作者并沒有以“這里我們需要使用XX模式”的心態(tài)來編碼。
許多缺乏經(jīng)驗(yàn)、缺乏洞察力的初學(xué)者可能會因?yàn)槿狈﹂喿x高質(zhì)量代碼的經(jīng)驗(yàn)或受到公司遺留項(xiàng)目中舊代碼的影響而最終遵循嚴(yán)格規(guī)定的方法。在我看來,這是相當(dāng)遺憾的。
我們都知道,通過復(fù)制粘貼生成的冗長且重復(fù)的代碼是不好的。
然而,大多數(shù)復(fù)制粘貼發(fā)生在期限緊迫且沒有時(shí)間進(jìn)行優(yōu)化的情況下。考慮到我們的工作強(qiáng)度,這是可以理解的。
另一方面,還有另一種極端行為,其目的是通過使用各種非常規(guī)手段來“簡化”代碼,從而達(dá)到“最簡潔”的代碼。
例如:
我們再考慮一下這樣的代碼是否增強(qiáng)了可讀性:
這些編碼實(shí)踐可以輕松地替換為具有更好可讀性的表單,而無需太多麻煩。然而,故意創(chuàng)建這樣的代碼可能會讓后續(xù)的維護(hù)者感到不舒服。
對于有關(guān)換行和縮進(jìn)的具體實(shí)踐,JavaScript 標(biāo)準(zhǔn)樣式等工具可以有效地自動處理大多數(shù)情況。
現(xiàn)代工程框架通常提供許多可定制的接口,允許開發(fā)人員輕松修改框架的行為。
例如:React 公開了上下文,而 Redux 和 MobX 等庫則利用此接口來極大地優(yōu)化深度prop傳遞的體驗(yàn)。
然而,框架內(nèi),存在許多隱含的約定和規(guī)范,當(dāng)在典型業(yè)務(wù)代碼中進(jìn)行不合理的定制時(shí),可能會導(dǎo)致重大挑戰(zhàn)。這些類型的修改通常發(fā)生在不顯眼的地方,但可能會產(chǎn)生很大的影響。
例如:在我們之前維護(hù)的一個項(xiàng)目中,進(jìn)行了巧妙的修改,React.Component用基類自己的XXX.BaseComponent行為替換了基類。
定制的組件并沒有涉及任何業(yè)務(wù)邏輯相關(guān)的改動,只是增加了一些莫名其妙的初始化代碼。
結(jié)果,有關(guān) React 組件 Base 的隱含常識變得無效。維護(hù)時(shí),乍一看,替換的組件似乎很普通。但是,修復(fù)就會導(dǎo)致問題。
此外,這些“黑魔法”代碼沒有評論或文檔,也不清楚為什么首先引入它們是為了解決什么問題。對于這樣的編碼做法,也許除了過于聰明之外,沒有其他合理的評價(jià)。
該項(xiàng)目的另一個例子涉及另一種“聰明”的做法:
window.fetch 根據(jù)請求路徑將其替換為三到四個不同的自定義版本。這意味著當(dāng)維護(hù)人員編寫新的獲取請求時(shí),他們不能依賴任何先前有關(guān)獲取的隱式知識,而是必須通過跟蹤前輩的自定義版本來進(jìn)行調(diào)試!
還有一些隱性做法會因副作用而出現(xiàn)問題。例如:當(dāng)看到 user = getUser(id) 時(shí),人們可能不會想到這個getUser函數(shù)不僅查詢用戶,而且還會默默地顯示一條提示消息發(fā)送請求,然后還清除當(dāng)前數(shù)據(jù)。
當(dāng)然,在前端開發(fā)本身中,管理大量與 UI 相關(guān)的網(wǎng)絡(luò)副作用本質(zhì)上會增加復(fù)雜性。
然而,如果調(diào)用一個函數(shù)會導(dǎo)致許多級聯(lián)結(jié)果,導(dǎo)致復(fù)雜性進(jìn)一步增加,許多維護(hù)者可能會選擇棄用和重寫。
在技術(shù)社區(qū)中,經(jīng)常可以看到“最全的前端實(shí)用功能”之類的合集,而且點(diǎn)贊數(shù)往往很高。然而,500合1的小霸王游戲卡比超級馬里奧更好玩嗎?
我有幸讀過一些這樣的文章,發(fā)現(xiàn)這些封裝的函數(shù)往往甚至沒有固定的主題:左邊是“ getCookie”,右邊是“ deepClone”,上面是isEmail,下面是scrollTop。每個實(shí)現(xiàn)在將英文函數(shù)名翻譯成中文的層面上只有幾行注釋,沒有測試用例、依賴配置或文檔。它們被稱為“小而美”。
這樣的代碼值得復(fù)制到你的項(xiàng)目中以供重用嗎?坦白說,它們只是滿足“我能發(fā)明輪子”沖動的產(chǎn)品。
當(dāng)然,我完全相信作者可以毫不費(fèi)力地寫出優(yōu)雅的內(nèi)容。但項(xiàng)目不是采訪;而是項(xiàng)目。對于一個穩(wěn)定可靠的庫,除了簡單的實(shí)現(xiàn)之外,還需要很多與代碼無關(guān)的東西。
根據(jù)《人月神話》中的布魯克斯定律,軟件項(xiàng)目中實(shí)際編碼時(shí)間只占1/6;剩余的大部分時(shí)間用于測試、文檔和溝通。對于具有更高質(zhì)量要求的庫代碼——從在線源匆忙編寫或復(fù)制(哦不!讓我們稱之為內(nèi)聯(lián))代碼是否足夠?
在正式項(xiàng)目中使用庫時(shí),如果穩(wěn)定的現(xiàn)有依賴項(xiàng)能夠令人滿意地滿足要求,那么顯然這應(yīng)該是您的首選。如果你遇到需要自己重新發(fā)明輪子的情況,那么請確保在可靠項(xiàng)目留下的 5/6 之外編寫代碼也做得很好;不要不必要地重復(fù)劣質(zhì)輪子。
本文鏈接:http://www.www897cc.com/showinfo-26-88386-0.html停止使用花哨的技巧來編寫優(yōu)雅的代碼吧!
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com