<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          構(gòu)建大型高質(zhì)量的前端工程完全指南

          共 4732字,需瀏覽 10分鐘

           ·

          2022-04-20 21:20

          點(diǎn)擊上方?前端Q,關(guān)注公眾號

          回復(fù)加群,加入前端Q技術(shù)交流群


          在過去,與大多數(shù)工程師一樣,我認(rèn)為前端代碼的設(shè)計(jì)水平大多與工程師的能力有直接關(guān)系。但隨著接手了幾個多人協(xié)作的大型前端項(xiàng)目,我開始意識到,這種認(rèn)知對短生命周期的小型項(xiàng)目可能適用,但對真正的大型項(xiàng)目,僅靠提升工程師質(zhì)量有時(shí)并不能直接提升代碼的質(zhì)量。

          本文將結(jié)合自己的一些實(shí)際經(jīng)驗(yàn),來闡述自己的一個觀點(diǎn):構(gòu)建大型高質(zhì)量前端工程,合理的代碼約束與正確的團(tuán)隊(duì)運(yùn)轉(zhuǎn)機(jī)制可能更為重要

          什么是高質(zhì)量的工程代碼?

          高質(zhì)量的工程代碼,并不等價(jià)于性能最優(yōu),技術(shù)最新,復(fù)用性最強(qiáng)的技術(shù)選型。回顧幾年前的前端領(lǐng)域:JQuery 時(shí)代,雖然要手動操作 DOM,但其實(shí)在那時(shí), Google Closure 和 Ext.js 團(tuán)隊(duì)就已經(jīng)提供了完整的組件化概念,甚至 Ext.js 還提供了組件冒泡這樣的創(chuàng)新事件機(jī)制。那時(shí)用 Zepto 維護(hù)的代碼,編碼速度甚至比現(xiàn)在寫一些 React 項(xiàng)目還要快。不同的技術(shù)只是工具,怎么用工具,能把工具用到什么程度,最終取決于開發(fā)者自身,所以高質(zhì)量的工程代碼,更多應(yīng)該從業(yè)務(wù)和工程的角度考慮問題,而非技術(shù)選型。

          舉個例子,當(dāng)整個公司都在使用 React 開發(fā)時(shí),雖然我們知道 Vue 使用可能會更簡單便捷,但我們一定不會去用,因?yàn)檫@個時(shí)候,雖然看起來寫代碼更簡單了,但其他人在 React 方向沉淀的經(jīng)驗(yàn),你無法復(fù)用,額外還需要整個團(tuán)隊(duì)去學(xué)習(xí)一套全新的技術(shù),這樣的工程設(shè)計(jì),在這個背景下,顯然是不合理的。

          Thenewstack 做過 2019 年的開發(fā)者數(shù)據(jù)統(tǒng)計(jì),開發(fā)者 32% 的時(shí)間用于業(yè)務(wù)開發(fā),19% 的時(shí)間在維護(hù)代碼,也就是工程師真正能投入到研發(fā)中的時(shí)間也只有工作時(shí)間的一半。對于開發(fā)者來說,這個時(shí)候通過合理的代碼設(shè)計(jì),提升代碼的可擴(kuò)展性,可維護(hù)性,降低開發(fā)和維護(hù)代碼的時(shí)間,才是最強(qiáng)的訴求。

          所以,高質(zhì)量的工程代碼應(yīng)該是結(jié)合業(yè)務(wù)與團(tuán)隊(duì)情況,真正能夠提升研發(fā)效率降低項(xiàng)目維護(hù)成本的代碼。

          誰決定了工程代碼的質(zhì)量?

          這里可以用木桶理論來類比:木桶中的水位,不取決于最高的木板,而取決于最低的木板。同理,前端工程的質(zhì)量,不取決于團(tuán)隊(duì)的平均能力,而取決于團(tuán)隊(duì)經(jīng)驗(yàn)較少的技術(shù)同學(xué)的能力。在工作壓力比較大的情況下,這些同學(xué)由于經(jīng)驗(yàn)不足,短期又要完成需求,所以很多時(shí)候,并沒有考慮過工程上的問題,而是直接面向?qū)崿F(xiàn)功能編程,基本上我們現(xiàn)在面對的難以維護(hù)的代碼,都是在這種條件下產(chǎn)生的。

          我們當(dāng)然可以寄希望于經(jīng)驗(yàn)較少的同學(xué)通過不斷的成長來提升項(xiàng)目的工程質(zhì)量,但實(shí)踐下來,這并不可行。原因在于,工程能力的積累需要大量的編碼經(jīng)驗(yàn),缺少實(shí)踐經(jīng)驗(yàn)的問題并不是短期就能夠迅速解決的,任何好的工程師都是在不斷犯錯學(xué)習(xí)的過程中成長起來的。同時(shí),工程開發(fā)過程中很可能會遭遇人員變動,一個團(tuán)隊(duì)的成員不肯能永遠(yuǎn)全部都是能力很強(qiáng)的。

          那么我們就需要換一個策略來保障我們的代碼質(zhì)量,我們可以換個角度思考:是否可以通過一些規(guī)則,流程,編碼上的約束,讓編碼能力不同的工程師,盡量寫出質(zhì)量相對較高的一致性代碼。

          通過約束提升工程質(zhì)量

          約束讓事情變得更簡單

          工作沒有約束,工作中我們就難以形成共識,也無法判斷工作做的好與壞。寫代碼也是一樣的,沒有約束,那么我們也無法判斷代碼是否合理。在流行的庫和框架中,其實(shí)到處都是約束的影子,這里拿 Redux 和 React 的設(shè)計(jì)來舉例:

          Redux 給出了單一數(shù)據(jù)源,State 只讀,使用純函數(shù)來執(zhí)行修改這三個基本原則,同時(shí)要求通過 Action 的方式觸發(fā)Reducer 的執(zhí)行,這是 Redux 的約束;React 也給出了單向數(shù)據(jù)流這樣的約束概念。

          框架之所以是能夠復(fù)用,能夠得到推廣,就是因?yàn)樗鼈冞M(jìn)行了封裝,僅僅提供有限的約束能力供大家使用,這樣大家才能形成一致的理念,編寫互相能夠讀得懂的代碼。理解了這一點(diǎn),我們再來看業(yè)務(wù)工程的代碼,實(shí)際上要提高開發(fā)效率和擴(kuò)展性,無非也是要提供合理的約束。

          工程代碼的約束,更多帶有一定的工程屬性,如:

          • 規(guī)定相同的請求地址只允許在 API 層出現(xiàn)一次(項(xiàng)目接口數(shù)目多,可減少代碼冗余)
          • 不使用超過 100 行以上的 Hook 代碼(強(qiáng)化邏輯拆分,避免過度復(fù)雜的邏輯)
          • 在復(fù)用性和可維護(hù)性上做選擇時(shí),優(yōu)先選擇可維護(hù)性(避免錯誤封裝,封裝代碼中耦合大量邏輯判斷)
          • 業(yè)務(wù)代碼注釋覆蓋率必須超過 10%(提升代碼可讀性,方便自動化生成文檔)
          • 項(xiàng)目中跨組件通信必須通過 Redux (降低組件傳值代碼的團(tuán)隊(duì)理解成本)
          • 相同功能的 npm 包不允許安裝多個(避免無用依賴安裝,造成維護(hù)成本增加)

          這些業(yè)務(wù)的約束,并不等同于 Eslint,不同的業(yè)務(wù)對代碼的要求有可能千差萬別,所以業(yè)務(wù)上的約束,需要研發(fā)人員充分的溝通交流,碰撞探討,以及堅(jiān)決執(zhí)行。不同團(tuán)隊(duì)的同學(xué),可能討論出的結(jié)果完全不同,但約束的結(jié)論是什么本身不重要,重要的是形成一致的開發(fā)共識

          通過機(jī)制實(shí)現(xiàn)約束的落地

          約束本身并不難制定,對于工程側(cè)的設(shè)計(jì),工程師通過討論比較容易形成博奕后的結(jié)論。但機(jī)制的落地是相對困難的一環(huán)。這里分享幾個可執(zhí)行的保障機(jī)制:

          • CodeReview(每次CR,除了對業(yè)務(wù)進(jìn)行邏輯分析,也需要將是否遵循約束作為審核的一環(huán))
          • 通過工具自動生成部分代碼(比如使用腳手架生成工程代碼中的某個模塊,類似 AngularCLI 中 ng g component header 這樣的指令,就可以幫你約束組件創(chuàng)建的代碼結(jié)構(gòu))
          • 配置化生成代碼(通過配置,生成邏輯或者表單代碼,建立配置項(xiàng)標(biāo)準(zhǔn))
          • 零代碼 / PaaS 平臺(通過平臺生成代碼,直接將用戶與編碼隔離,由平臺保障生成代碼的質(zhì)量)
          • 負(fù)責(zé)人機(jī)制(約束落地直接與績效相關(guān)聯(lián),成為跟進(jìn)明確指標(biāo))
          • 沉淀文檔(通過文檔,沉淀約束機(jī)制)

          通過這樣的一些機(jī)制,保障約束有效的落地,那么我們就可以抹平團(tuán)隊(duì)成員技術(shù)能力的差異,形成一致性的編碼風(fēng)格。雖然這種約束下的代碼并不一定是最優(yōu)雅的代碼,但至少工程質(zhì)量不會差。所以這里我認(rèn)為,約束實(shí)際上幫助我們保障的是工程質(zhì)量的下限,那么接著我們來談如何通過技術(shù)創(chuàng)新,提升工程質(zhì)量的上限。

          在約束之上尋求創(chuàng)新

          大家可能會有這樣的問題:“項(xiàng)目的約束,會不會限制技術(shù)的創(chuàng)新”。針對短生命周期的小型項(xiàng)目,這可能是對的,這種項(xiàng)目,使用更多的新技術(shù)進(jìn)行探索突破可能會帶來更多的團(tuán)隊(duì)技術(shù)儲備;但對于大型項(xiàng)目來說,我們每天所做的代碼設(shè)計(jì)決策,都可能會影響到明天業(yè)務(wù)系統(tǒng)的發(fā)展進(jìn)程,任何技術(shù)升級都一定要慎重,這時(shí)候,我們不應(yīng)該把約束當(dāng)作創(chuàng)新的阻礙,而應(yīng)該把約束當(dāng)作創(chuàng)新的練兵場。

          如果你在大型項(xiàng)目中,想突破約束,使用新技術(shù),進(jìn)行技術(shù)革新,那么一定意味著你要做到以下幾件事情:

          1. 對過去約束限制的背景有充分了解:背景沒有改變,新技術(shù)是否能解決約束所解決的問題,同時(shí)不會帶來新的問題
          2. 能夠充分表述新技術(shù)所能夠帶來的價(jià)值:在形成共識的問題上,新技術(shù)是否能對性能,穩(wěn)定性,體驗(yàn),研發(fā)效率,業(yè)務(wù)提效有明顯作用
          3. 能夠給出技術(shù)升級的整體方案:在確認(rèn)要進(jìn)行技術(shù)升級時(shí),你是否考慮到歷史技術(shù)方案如何優(yōu)雅的實(shí)現(xiàn)替換
          4. 能夠說服團(tuán)隊(duì)認(rèn)可新的技術(shù)升級方案:在當(dāng)前已有技術(shù)的基礎(chǔ)上,你是否能說服團(tuán)隊(duì)成員和你一同推進(jìn)技術(shù)創(chuàng)新
          5. 能夠帶領(lǐng)團(tuán)隊(duì)或者自己將技術(shù)方案落地:你是否具備能力將新技術(shù)或者創(chuàng)新點(diǎn)完成落地

          很多時(shí)候,我們做的技術(shù)創(chuàng)新,其實(shí)只是技術(shù)棧的更新,并沒有為團(tuán)隊(duì)和業(yè)務(wù)側(cè)帶來任何的價(jià)值,但當(dāng)我們想清楚這些問題,能夠有信服力的證明新技術(shù)或者創(chuàng)新點(diǎn)是有價(jià)值的時(shí)候,關(guān)于系統(tǒng)的升級可能才是真正有價(jià)值的。

          在約束上的創(chuàng)新,可以讓工程師結(jié)合業(yè)務(wù)有更多的思考,產(chǎn)出真正有價(jià)值的創(chuàng)新。而這些有質(zhì)量的思考和創(chuàng)新,決定了工程質(zhì)量的上限,同時(shí)也會培養(yǎng)出更多優(yōu)秀的工程師。

          如何提升已有工程質(zhì)量?

          對于一個全新的大型項(xiàng)目,我們可以通過上述的方式,分階段進(jìn)行架構(gòu)設(shè)計(jì)和優(yōu)化。但是,大多數(shù)情況下,我們接手的項(xiàng)目,可能在接手時(shí)就會發(fā)現(xiàn)其工程質(zhì)量較低,那么我們應(yīng)該如何對已有代碼進(jìn)行改良呢?

          判斷你的系統(tǒng)是否需要改良

          一個系統(tǒng)的生命周期,可以總結(jié)為三個階段:

          • 發(fā)展期:業(yè)務(wù)發(fā)展迅速
          • 穩(wěn)定期:業(yè)務(wù)情況穩(wěn)定
          • 衰退期:業(yè)務(wù)逐漸關(guān)停并轉(zhuǎn)

          對于發(fā)展期的系統(tǒng)和穩(wěn)定期的系統(tǒng)來說,合理的工程設(shè)計(jì)未來能帶來的性能,穩(wěn)定性等方面的收益十分明顯,這個時(shí)候,我們可以考慮對系統(tǒng)進(jìn)行技術(shù)升級。而對于衰退期的系統(tǒng),雖然短期開發(fā)維護(hù)效率不高,但無法看到未來系統(tǒng)的發(fā)展?jié)摿Γ@時(shí)候,繼續(xù)維護(hù)老系統(tǒng)可能是一個更好的選擇。并不是每一個系統(tǒng)都必須要改良,精益求精固然好,但是否要做還是要回歸到對業(yè)務(wù)價(jià)值的判斷上。

          如何進(jìn)行工程改進(jìn)

          大型項(xiàng)目的工程改良,可以分為兩種方式,自上而下,和自下而上。對于大型項(xiàng)目來說,自上而下的全部重構(gòu),成本很大,除非你對系統(tǒng)特別了解,否則并不推薦采用這種方法。相反,目前的主流框架,React, Vue 都是可以對局部 DOM 進(jìn)行托管的,所以自下而上的逐步升級可能是更好的策略,這種方法有兩個優(yōu)勢:成本低,風(fēng)險(xiǎn)小。舉個自己工程中的例子,我們需要把 JQuery 升級至 React,采用了這種方式,逐層向上的對 JQuery 中的 Backbone 代碼進(jìn)行替換:

          export?default?View.extend({
          ??componentName:?'AuctionDetailContainer',
          ??initialize(options)?{
          ????const?{?dataSchemaV1,?pageSchema?}?=?options;
          ????this.ref?=?React.createRef();
          ????this.dataSchemaV1?=?dataSchemaV1;
          ????this.children?=?pageSchema.getChildren()[0];
          ????this.attributes?=?pageSchema.getAttributes()?||?{};
          ??},

          ??render()?{
          ????ReactDOM.render((
          ??????<AuctionDetailContainerWithRef
          ????????ref={this.ref}
          ????????taskFields={this.dataSchemaV1}
          ????????attributes={this.attributes}
          ????????crossTableData={this.children}
          ??????/>

          ????),?this.$el[0]);
          ????return?this;
          ??},

          });

          每一次替換,我們只要測試替換部分的邏輯即可,不會影響外部的其他邏輯,這樣逐層替換,在保障穩(wěn)定性和系統(tǒng)升級的雙向要求下,做到了很好的平衡。同時(shí),在接手新項(xiàng)目的時(shí)候,這種升級的方法還可以逐步幫你梳理清楚業(yè)務(wù)的邏輯,了解業(yè)務(wù)。

          在這樣的逐步替換過程中,結(jié)合之前說到的編碼約束,我們就可以將系統(tǒng)的代碼質(zhì)量逐步完成提升。而之后,則可以通過創(chuàng)新的方式,進(jìn)一步對項(xiàng)目優(yōu)化完善,從而完成整個重構(gòu)過程。

          在這個過程中,有一些工具也可以幫助到我們,舉幾個例子:

          • CommintLint + SemVer 語義化版本號控制規(guī)范:幫助團(tuán)隊(duì)明確重構(gòu)可能帶來的風(fēng)險(xiǎn),節(jié)約溝通成本
          • 前端自動化測試工具:通過單元測試保障工程質(zhì)量,降低回歸錯誤產(chǎn)生概率
          • Chrome Coverage:代碼執(zhí)行情況分析工具,幫助你找到無用代碼,梳理項(xiàng)目邏輯

          結(jié)語

          本文涉及到的具體編碼內(nèi)容不多,希望從另一個方面能夠給你帶來一些工程測的啟發(fā)和思考,一些觀點(diǎn)沖突也歡迎大家溝通討論。

          作者:ES2049 Studio
          https://zhuanlan.zhihu.com/p/337694407


          往期推薦


          秒啊!答好這5個問題,就入門Docker了
          (字節(jié)/華為/美團(tuán))前端面經(jīng)記錄冷冷清清的金三銀四
          我就面試個前端,你問我對尤雨溪怎么看??

          最后


          • 歡迎加我微信,拉你進(jìn)技術(shù)群,長期交流學(xué)習(xí)...

          • 歡迎關(guān)注「前端Q」,認(rèn)真學(xué)前端,做個專業(yè)的技術(shù)人...

          點(diǎn)個在看支持我吧

          瀏覽 38
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一本无码免费视频 | 韩国免费猫片 | 五月天色婷婷中文影院 | 99国产在线观看 | 4080yy午夜理论片成人 |