整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          JavaScript 前端框架維護者對 2024 年的預測

          者 | Loraine Lawson

          譯者 | 張衛(wèi)濱

          策劃 | Tina

          本文最初發(fā)表于The New Stack網(wǎng)站,由 InfoQ 中文站翻譯分享。


          在 2024 年,前端領(lǐng)域會有怎樣的發(fā)展呢?因為沒有人能夠預見未來,所以 The New Stack 與來自 Angular、Next.js、React 和 Solid 的創(chuàng)建者和維護者討論了他們 2024 年的計劃。以下是前端開發(fā)者對未來一年的展望。


          Angular:可選的 Zone.js


          來自谷歌的 Angular DevRel 技術(shù)主管和經(jīng)理Minko Gechev說,在過去的一年里,Angular 的兩大成就是引入了基于Signals的細粒度反應(yīng)性和可延遲視圖。他告訴 The NewStack,新的一年將會在此基礎(chǔ)上進一步關(guān)注細粒度的反應(yīng)性,并使 Zone.js 成為可選的。


          在 Angular 中,Zone 是一個執(zhí)行上下文,它能夠跨異步任務(wù)持續(xù)存在。在這個GitHub倉庫中詳細介紹了Zone,它有五個職責,包括攔截異步任務(wù)調(diào)度和包裝回調(diào)以便于進行錯誤處理,以及跨異步操作的 zone 跟蹤。Zone.js 可以創(chuàng)建跨異步操作而持久化存在的上下文,也可以為異步操作提供生命周期鉤子。


          Gechev 說,“我們正在探索為現(xiàn)有的項目實現(xiàn)可選的 Zone.js,開發(fā)人員可以通過重構(gòu)現(xiàn)有的應(yīng)用程序來利用這一特性”。“借助可選的 Zone.js,我們期待加載時間能夠得以改善,并實現(xiàn)更快的初始渲染。對細粒度反應(yīng)式的處理將提升到一個新的層次,使我們能夠僅探測組件模板的部分變更。”


          他說,這些特性將會帶來更快的運行時。


          在關(guān)于性能的另一個方面,Angular 正在考慮是否默認啟用混合渲染。他補充說,選擇避免混合渲染是可能實現(xiàn)的,因為這會增加托管需求和成本。


          Gechev 說,“我們看到了 SSG(靜態(tài)站點生成,static site generation)和 SSR(服務(wù)器端渲染,server-side rendering)的很多價值,而且在 v17 中奠定了堅實的基礎(chǔ),我們正在進行最后的潤色工作,以便從一開始就實現(xiàn)這種體驗。”


          他補充到,另一個優(yōu)先事項是完成Signals請求的評論(Request for Comment)。


          開發(fā)人員還可以看到 Angular 文檔的改進。根據(jù)對開發(fā)人員的調(diào)查,他們希望能有一個升級的學習體驗,其中包括讓 Angular.dev 成為該框架新的托管地。他補充說,開發(fā)人員還優(yōu)先考慮了初始加載時間(混合渲染、部分填充和可選的 Zone.js 應(yīng)該可以部分解決該問題)和組件編寫,Angular 計劃會進一步簡化組件的編寫。


          Gechev 說,“我們致力于迭代式地交付特性,并隨著時間的推移逐步增強它們”。“開發(fā)人員將能夠從 2024 年的所有改進中受益,并在接下來的幾年里獲得更好的開發(fā)體驗和性能。”


          Next.js:新的編譯器


          Next.js 在 2023 年引入了一個新的應(yīng)用服務(wù)器,旨在支持 React 服務(wù)器組件(React Server Component,RSC)和Server Action。Vercel(該框架的監(jiān)管者)的產(chǎn)品負責人 Lee Robinson 說,該框架會繼續(xù)支持舊的服務(wù)器,并且其路由系統(tǒng)可以在兩者實現(xiàn)互操作性。這種互操作性意味著可以繼續(xù)花時間添加新的特性。


          Robinson 說,“有些客戶已經(jīng)使用 Next.js 進行開發(fā)有五六年之久了,他們也會需要花費幾年的時間來采用這些新特性。在這個過程中,我們希望他們的工作能夠盡可能地順暢。”


          在新的一年中,Next.js 希望要解決很多問題,其中一個優(yōu)先事項就是簡化緩存。他說,從開發(fā)人員的體驗來看,這可能會使其更加容易。


          Robinson 說到,“通常情況下,生態(tài)系統(tǒng)中的許多開發(fā)人員必須引入一堆額外的包,或者學習如何使用其他的工具來進行數(shù)據(jù)抓取、緩存和重現(xiàn)校驗”。“現(xiàn)在,Next.js 已經(jīng)構(gòu)建了很多這樣的特性,而且非常強大,但是這也意味著需要學習更多的東西,我們得到的初步反饋是,‘這非常棒,也很強大,但是我們希望它能更簡單一些’”。


          Next.js 團隊還將繼續(xù)關(guān)注性能的改進,他將其稱之為“我們的持續(xù)投資”。


          他補充到,在新的一年里,這很可能會以新編譯器的形式出現(xiàn),它將加快在開發(fā)人員的機器上啟動 Next.js 的速度。該編譯器相關(guān)的工作已經(jīng)進行了大約一年的時間,Vercel 一直在其內(nèi)部產(chǎn)品和應(yīng)用中使用它。他說,這個使用 Rust 編寫的編譯器即便在沒有使用的緩存的情況下也比之前啟用緩存的編譯器更快。


          Robinson 說,“距離推出這個功能已經(jīng)近在咫尺了,甚至到了每個人都可以默認啟用它的程度,而且它比現(xiàn)有基于 Webpack 的編譯方案更快”。“開發(fā)人員總是希望他們的工具能夠更快。他們對工具運行速度的追求永無止境。因此,很有意思的一件事是,工具的制造商,而不是工具的使用者在開始轉(zhuǎn)向像 Rust 這樣的底層工具,從而幫他們實現(xiàn)性能方面的最終勝利。”


          他們的第三個目標是為未來十年的 Next.js 奠定基礎(chǔ)。


          他說,“我們對這個新的路由系統(tǒng)感到非常興奮。我們相信這是未來的基礎(chǔ)。但是,這也需要時間。人們會嘗試使用,從而有特性方面的需求,并且希望能夠看到實際的改變。我們將其視為未來五年至十年的長期投資。”


          他補充說,一個“某天”可能會實現(xiàn)的目標是在 Next.js 中找到更好方式來處理內(nèi)容,不過這應(yīng)該不會新的一年中實現(xiàn)。


          他補充說,“現(xiàn)在,它依然能夠正常運行,你依然可以連接到任何你想要的內(nèi)容源,但是會有一些潛在的方式能夠簡化開發(fā)人員的體驗”。“這更像是一件錦上添花的事情,而不是必須要做的事情,這就是為什么我認為在 2024 年我們不會實現(xiàn)它,但我希望未來會為其做一些相關(guān)的工作。”


          React:2024 預覽

          Meta 的 React 工程主管 Eli White 說,React 團隊希望在新的一年里會有更多的框架采用 React 服務(wù)器組件(RSC,React Server Component)。


          White 說,“對大多數(shù)人來講,他們認為 RSC 是 React 領(lǐng)域的重要變化,從一個單純的 UI 層,變成對如何架構(gòu)應(yīng)用程序的方式都能產(chǎn)生更大的影響,以獲得最佳的用戶和開發(fā)人員體驗,特別是對于單頁應(yīng)用程序(SPA,single page application)方式表現(xiàn)不夠好的應(yīng)用程序。”


          雖然他沒有明確說明 2024 年的新動向,但是 White 表示他們將發(fā)布和分享 2023 年相關(guān)事項的更多進展。比如,在 React Advanced 會議上,團隊向與會者展示了 React Forget,這是 React 的自動記憶編譯器。White 說,有了React Forget之后,將意味著開發(fā)者不再需要使用useMemo和useCallback。


          White 補充說,“在 React Native EU 會議上,我們分享了從 0.73 版本開始將 web 開發(fā)人員熟悉的 Chrome 開發(fā)工具引入 React Native。我們還初步展示了對 Static Hermes 的研究成果,這是針對 JavaScript 的原生編譯器,它不僅有可能加快 React Native 應(yīng)用程序的速度,而且會從根本上改變 JavaScript 的用途。”


          Solid:專注于基本元素(Primitive)

          Solid 創(chuàng)始人 Ryan Carniato 表示,在 2024 年,Solid 開發(fā)人員可以期待即將推出的SolidStart 1.0和 Solid.js 2.0。SolidStart 是一個元框架,這意味著它建立在框架 Solid.js 之上。他說,這類似于Svelte的SvelteKit。


          SolidStart的文檔是這樣描述的:

          “Web 應(yīng)用程序通常包含很多組件,比如數(shù)據(jù)庫、服務(wù)器、前端、打包器、數(shù)據(jù)抓取/變更、緩存和基礎(chǔ)設(shè)施。編排這些組件很具挑戰(zhàn)性,并且通常需要跨應(yīng)用程序技術(shù)棧共享大量的狀態(tài)和冗余邏輯。這就是 SolidStart 的用武之地,它是一個元框架,提供了一個將所有這些組件組合在一起的平臺。”


          由于 SolidStart 仍處于 beta 階段,Carniato 有機會利用生態(tài)系統(tǒng)中已有的東西將其變得更好。

          Carniato 說,“其中很重要的一點是,我們現(xiàn)在不再需要編寫自己的部署適配器,而是可以使用 Nitro,它也支撐了 Nuxt 框架,這使得我們可以將其部署到所有的不同平臺上。”


          另外一個樣例是任何 Solid 路由器都能在 SolidStart 中運行。


          他說,“這意味著對路由器的底層部分進行了大量更新,這樣它們才能一起運行,但最終結(jié)果令我非常高興,因為我們小團隊的志愿者需要維護的代碼量要少得多,這給了開發(fā)人員很大的靈活性。”“他們不必被迫采用單一的解決方案,這對我來說非常重要,因為每個人都有自己的需求。正如我所言,如果你構(gòu)建了正確的組件并且能夠弄清楚構(gòu)建基塊(building block),那么人們可以做更多的事情。”


          他說,最終的結(jié)果是由“可互換”的組件所組成的元框架,而不是具有很強的傾向性。Solid 團隊一直在思考,在由越來越多的元框架決定開發(fā)人員能夠使用什么的世界中,正確的基本元素所帶來的影響。


          他說,“對我來講,最重要的一直是基本元素形成的構(gòu)建基塊,這是一個非常工程化的關(guān)注點,我認為這也是它與眾不同的原因之一。”“我一直喜歡給別人選擇的權(quán)力,并且我認為如果有正確的基本元素,正確的構(gòu)建基塊,就可以構(gòu)建出正確的解決方案。”


          他表示,Solid 2.0 應(yīng)該會在 2024 年中后期發(fā)布。現(xiàn)在,他們正在實現(xiàn)如何處理異步系統(tǒng)的原型。


          Carniato 說,“Solid 2.0 也將是一個非常重要的版本,因為我們正在重新審視反應(yīng)式系統(tǒng),并思考如何解決異步信號或異步系統(tǒng)的問題。”


          他補充說,Solid 試圖在控制和性能之間取得平衡。


          他說,“在我們的社區(qū)里,有很多非常熱情的人,非常有技術(shù)頭腦的人,他們關(guān)注性能,關(guān)心控制。”“我們確實吸引了很多人,他們真的想控制自己建造的每一個組成部分。”

          原文鏈接:https://www.infoq.cn/article/7ciYZE56w7KENEGOjfQY

          者 | Adrien Joly

          譯者 | 張衛(wèi)濱

          策劃 | 丁曉昀

          有時候,JavaScript(甚至帶有類型檢查的 TypeScript)會因為其不可預測的特性和缺乏約定而遭到批評。對于那些知道 JavaScript 是為 web 瀏覽器設(shè)計的腳本語言的人來說,這就不足為奇了。


          但是,現(xiàn)在它已經(jīng)成為開發(fā)全棧 web 的首選語言,也是跨平臺移動應(yīng)用的熱門方案。那么,當開發(fā)人員的 JavaScript/TypeScript 代碼庫開始老化,由此帶來的復雜性痛苦地增長時,他們該采取什么行動才能最大限度地減少資源浪費并保持工作滿意度呢?


          本文將基于我 10 多年來編寫 JavaScript 代碼的經(jīng)驗和 5 年多拯救 JS/TS 項目的經(jīng)歷,向讀者介紹如下內(nèi)容:


          • 如何評估 JS/TS 代碼庫的質(zhì)量和風險。
          • 對于需要修復的部分,該如何確定其優(yōu)先級。
          • 有哪些非破壞性的方法可以讓 JS/TS 代碼庫逐漸變得更健康。


          清理工作臺

          在開發(fā)下一個特性時,每個警告、類型錯誤或非正常的測試都會讓開發(fā)人員浪費時間、精力和專注度。


          代碼警告尤其令人討厭,因為開發(fā)人員會習慣性地忽略它們,“只要一切按預期運行就好”。因此,它們會迅速累積,當我們遇到缺陷、事故或系統(tǒng)的意外行為時,就很難將其作為有用的線索。


          類型錯誤就是一個很好的樣例。當我們的用戶遵循“快樂路徑(happy path)”時,這些錯誤似乎無關(guān)緊要,因為軟件似乎能夠按照預期運行。所以,我們可能會使用@ts-ignoreany或類型斷言來暫時忽略它們。但是,這樣做的話,就意味著如果有一天用戶選擇不同的路徑,就會面臨運行時錯誤。


          這樣的話,開發(fā)人員就需要調(diào)查、重現(xiàn)和修復一個新的缺陷,而這個缺陷恰恰是他們幾個月前允許走捷徑所造成的。如果你的代碼被各種警告和/或暫時忽略這些警告削弱了質(zhì)量,那么找到這個捷徑將耗費大量的時間。



          當生產(chǎn)環(huán)境的數(shù)據(jù)庫因“內(nèi)存不足”錯誤而崩潰時,該警告可能會幫助開發(fā)人員找到崩潰的原因


          警告和類型錯誤是查找缺陷和事故的線索。我們累積(或忽略)的警告和錯誤越多,開發(fā)人員就會花費越多的時間去調(diào)查。如果代碼是他們很久以前編寫的,那情況就會更糟糕了。


          我們能做些什么呢?


          1. 確保開發(fā)人員在開發(fā)過程中能夠盡快看到警告和類型錯誤。這不應(yīng)該花費額外的成本。如果可能的話,集成到他們的 IDE 中。
          2. 不要讓警告和類型錯誤累積。盡快修復它們。
          3. 提高信噪比。如果團隊一致認為某條引發(fā)警告和類型錯誤的規(guī)則沒有用處的話,就干脆禁用它。
          4. 如果你確信需要在代碼的特定部分忽略掉某條規(guī)則的話(也就是,使用 code>@ts-ignore、any或類型斷言),請?zhí)砑幼⑨屢杂涗浐雎栽撘?guī)則的原因。
          5. 不要在運行時添加 try-catch 代碼塊來捕獲編程錯誤(比如,業(yè)務(wù)邏輯中意料之外的未定義值)。而是要使用這種代碼塊來處理外部系統(tǒng)的預期錯誤(如輸入/輸出異常、校驗、環(huán)境問題等)。在開發(fā)過程中,應(yīng)使用靜態(tài)代碼分析和單元測試來捕獲編程錯誤。
          6. 不要讓帶有警告和類型錯誤的代碼進入生產(chǎn)環(huán)境。使用持續(xù)集成流水線來強制要求這一規(guī)則。



          類型檢查器認為缺少一個預期的屬性。忽略這個錯誤將意味著要承擔持久化不一致數(shù)據(jù)的風險,在幾個月之后,你可能需要花費幾天的時間來調(diào)查和解決這個問題


          我們可以使用哪些工具來實現(xiàn)這一目標呢?


          有許多靜態(tài)代碼分析工具可供使用,最常用的包括:


          • ESLint,能夠用來探測代碼中的語法錯誤和反模式;
          • TypeScript(啟用嚴格的規(guī)則),借助.ts文件或JSDoc注解以探測類型錯誤;
          • 除此之外,SonarCloud、SourceGraph、Codacy或類似的在線工具服務(wù)也有助于跟蹤共享代碼庫中多個代碼質(zhì)量度量指標的變化情況。


          警告也可能來自其他工具:依賴安裝器(如npmyarn)、打包器(如webpack)、代碼處理器(babelscss)和執(zhí)行環(huán)境(CI 運行器)。不要忽視它們!


          如果遵循這些建議會讓你的代碼變得非常冗長和/或復雜(比如防御式代碼),你可以需要對其進行重新設(shè)計。


           "scripts": {
              "lint": "eslint .",
              "lint:fix": "eslint . --fix",
              "lint:errors": "eslint . --quiet",
              "lint:typescript": "tsc --noEmit --skipLibCheck",
              "lint:jsdoc-typing": "tsc --noEmit --allowJs `find ./ -name '*.js' -name '*.d.ts'`"
            },

          復制代碼


          借助靜態(tài)代碼分析器和 npm 腳本,能夠讓開發(fā)人員輕松快速地探測有問題的代碼


          后續(xù)該怎么辦?


          安裝和配置靜態(tài)代碼分析工具是一個良好的開端,但這還不夠。


          要想取得持續(xù)的成功,要確保開發(fā)團隊做到如下幾點:


          • 充分認識到部署不含編程錯誤的代碼的重要性,并相信靜態(tài)代碼分析可以幫助他們實現(xiàn)這一點;
          • 充分理解 TypeScript 的運行原理(參見TypeScript: Handbook)
          • 定期修復警告和類型錯誤,起碼要比引入它們的頻率更高;
          • 保持這些措施,永不間斷。


          如下幾種策略可能會提供幫助:


          • 獎勵提高代碼質(zhì)量的代碼貢獻行為,從而激勵開發(fā)人員。其中,有種方法是使用可插入持續(xù)集成流水線的工具來跟蹤開發(fā)人員推送的每個變更的代碼質(zhì)量變化,例如可以使用 SonarCloud 和/或 Codacy。
          • 讓一名開發(fā)人員負責確保代碼質(zhì)量永不下降。
          • 讓另一名開發(fā)人員負責定期更新依賴,從而能夠讓團隊能夠從它們的邏輯和安全修復中受益。


          為何要把每個角色都交給一個專門的人?


          當某項職責沒有人負責時,集體責任往往會被其他“優(yōu)先事項”所取代(比如,本周多交付一個特性,但是代價是忽略一個警告)。


          定期輪換角色,確保每個人都能參與其中并保持積極性。


          使用(恰當類型的)測試覆蓋關(guān)鍵的業(yè)務(wù)邏輯


          現(xiàn)在,我們有了一支致力于保持代碼庫整潔的團隊,我們相信用戶很少會遇到編程錯誤。


          但是,業(yè)務(wù)邏輯中的錯誤該怎么辦呢?


          例如,如果一個新添加的功能破壞了另一個功能該怎么辦?如果開發(fā)人員從一開始就誤解了該功能的預期行為,又該怎么辦?如果這樣的錯誤最終導致了嚴重的收入損失又該如何處理?


          與編程錯誤類似,業(yè)務(wù)邏輯問題可能會在生產(chǎn)環(huán)境由用戶發(fā)現(xiàn),但我們更希望盡早發(fā)現(xiàn)它們。因此,定期測試軟件非常重要,這個過程可以使用自動化和/或手動測試。


          從業(yè)務(wù)角度看,測試有兩個作用:


          • 符合功能性需求:每個特性的實現(xiàn)都能滿足開發(fā)時的需求。
          • 檢測回歸:在對代碼進行任何修改后,所有現(xiàn)有的特性都能按照預期運行。


          確保功能性測試(也稱為“驗收測試”)涵蓋大多數(shù)關(guān)鍵業(yè)務(wù)特性,單元測試或集成測試涵蓋大多數(shù)關(guān)鍵技術(shù)組件。此外,確保持續(xù)集成在任何測試失敗時都能向開發(fā)人員提供可執(zhí)行的反饋。


          對于有些開發(fā)人員來說,將測試工作委托給其他人(如產(chǎn)品負責人或 QA 團隊)是很有誘惑力的做法。在每個新特性完成后,進行一次這樣的委托測試,以確保特性實現(xiàn)符合功能性需求,并進行協(xié)作迭代,這樣做可能是合理的。


          但是,委托他人進行回歸檢測并不是一個好主意,原因包括:


          • 它增加了合并代碼和部署代碼之間的延遲。
          • 它增加了發(fā)現(xiàn)回歸問題和修正它們之間的延遲。
          • 隨著功能性范圍的不斷擴大,檢測回歸所需的時間也會隨之增長。如果負責這些測試的人沒有將其自動化,他們最終可能會跳過越來越多的測試。因此,一段時間之后,出現(xiàn)回歸測試未發(fā)現(xiàn)問題的風險就會越來越高。


          回歸測試是一項痛苦且可能代價高昂的負擔,尤其是需要不同角色(如產(chǎn)品負責人和開發(fā)人員)必須協(xié)作的情況下。從長遠來看,回歸測試自動化意味著可以節(jié)省大量的時間,而且開發(fā)人員具有編寫自動化測試的技能,所以,開發(fā)人員首先要承擔起檢測回歸的責任,而不必讓其他角色參與進來,這符合他們的利益。


          如果要涵蓋的功能范圍很大該怎么辦?


          從最關(guān)鍵的業(yè)務(wù)特性開始。要找出這些特性,你可以問自己:“就收益和/或減少成本而言,在生產(chǎn)環(huán)境中可能發(fā)生的最糟糕的事情是什么?”


          例如,電子商務(wù)網(wǎng)站的回答可能是如下的特性:


          • “信用卡購物”特性每分鐘可以帶來大約 1000 美元的收入。
          • 如果銷售人員必須要求首席技術(shù)官手動將產(chǎn)品添加到數(shù)據(jù)庫中,則“將產(chǎn)品添加到目錄中”特性每小時的成本約為 500 美元。
          • 如果客戶支持團隊需要手動處理訂單,那么“打印條形碼以退回訂單”將使我們每天損失 500 美元。


          基于這些業(yè)務(wù)關(guān)鍵的用例,從它們開始編寫端到端的自動化測試肯定就是非常有意義的。


          何時運行測試?


          在每次代碼更新或添加到代碼庫之時,在將其部署到生產(chǎn)環(huán)境之前。


          借助git hook,在每次提交時運行測試可能就足夠了,因為它能可靠地運行,而且其持續(xù)時間不會導致開發(fā)人員編寫更少的測試。


          不管是否使用git hook,都要確保每次推送可用于生產(chǎn)環(huán)境的代碼時,測試能在某處運行(例如,最好是在持續(xù)集成環(huán)境中)。



          在持續(xù)集成環(huán)境中,每次提交都會運行代碼檢查和自動化測試。


          我們應(yīng)該編寫什么樣的測試?


          需要優(yōu)化的變量包括:


          • 測試所覆蓋的功能性和技術(shù)性范圍的大小。
          • 從測試中獲得反饋的時間。
          • 修復失敗測試所報告的問題所需的時間。
          • 因為誤報而損失的時間(即由于隨機原因?qū)е率〉臏y試)。


          如果你的團隊在編寫自動化測試和/或可測試代碼方面經(jīng)驗不足,那么可以從一些端到端測試開始。然后,逐步增加對范圍更小的代碼單元的測試。這樣做可以激勵開發(fā)人員編寫易于測試的代碼。例如,通過隔離責任、減少耦合和/或?qū)I(yè)務(wù)邏輯寫成純函數(shù)。遵循依賴注入架構(gòu)是實現(xiàn)這一目標的好方法。(參見六邊形架構(gòu)或簡潔架構(gòu))


          我們是否應(yīng)該 Mock 第三方 API?


          自動化測試(如本文所述)的目的是探測團隊的功能性范圍內(nèi)的回歸,而不是第三方的功能。基于這一點,在測試中 Mock 第三方是合理的。


          也就是說:


          • Mock 應(yīng)始終與當前 API 的行為相匹配。這意味著開發(fā)人員需要持續(xù)關(guān)注 API 的變化,并相應(yīng)的更新它們的 Mock。
          • 當實際 API 的行為與預期不符時,你可能依然希望得到警告。


          探測自己的代碼中的問題和第三方 API 中的問題并不遵循相同的生命周期:


          • 每次代碼進行變更時,所涉及的范圍都應(yīng)該進行測試。
          • 僅在第三方的代碼發(fā)生變更的時候,才應(yīng)該對其進行測試。(也就是說,每次提交代碼變更都測試第三方依賴是沒有什么意義的)。


          你需要持續(xù)監(jiān)控第三方提供商是否能夠正常運行并達到預期效果。但是,第三方錯誤不一定能夠在發(fā)生之時就探測到,因此最好是定期監(jiān)控,而不是在開發(fā)人員每次推送代碼變更的時候進行監(jiān)控。


          所以,需要搭建兩個專門的流水線:


          • 你自己的 CI 流水線會在你的代碼發(fā)生變更的時候測試自己的范圍。
          • 另外一個 CI 流水線定期檢查第三方所涉及的范圍是否按照預期運行。


          為了編寫長期最有用、最健壯的測試,我建議遵循F.I.R.S.T.原則。確保開發(fā)人員不會濫用mock。


          細致保護代碼庫中新的/現(xiàn)代化的部分


          假設(shè)你的代碼庫已經(jīng)或者將要開發(fā)數(shù)年的時間,那么隨著時間的推移,它很可能會在代碼風格和質(zhì)量方面失去內(nèi)聚力。更糟糕的是,由于技術(shù)債務(wù)、缺乏測試或意外復雜性的積累,某些組成部分的維護可能會變得很復雜。


          在這種情況下,要像上文所建議的那樣,在整個代碼庫中對代碼實現(xiàn)一致的內(nèi)聚預期可能會變得很復雜。不過,這也沒有關(guān)系。


          你不希望看到的是期望值降低到一個最低的平均水準。這樣的話,你可以把代碼劃分為不同的范圍,并為每個范圍設(shè)置不同的期望水平。


          例如,考慮一個即將為電子商務(wù)網(wǎng)站實現(xiàn)新特性的團隊。他們希望這個新特性能夠比代碼庫中的其他特性更健壯、更易于維護。為了實現(xiàn)這一點,他們在配置靜態(tài)代碼分析工具(如 ESLint 和 TypeScript)時采用比代碼庫的其他部分更嚴格的規(guī)則,并針對專門為該特性而創(chuàng)建的目錄使用覆蓋的方式啟用更多的規(guī)則。通過這種方式,團隊可以提高新代碼的質(zhì)量,而不必急于對代碼庫中“遺留”的部分進行現(xiàn)代化處理。


          "rules": {
              "prettier/prettier": "error",
              "deprecation/deprecation": "warn"
            },
            "overrides": [
              {
                // Tolerate warnings on non critical issues from legacy JavaScript files
                "files": ["*.js"],
                "rules": {
                  "prefer-const": "warn",
                  "no-inner-declarations": ["warn", "functions"],
                  "@typescript-eslint/ban-ts-comment": "warn",
                  "@typescript-eslint/no-var-requires": "off"
                }
              },
              {
                // Enforce stricter rules on domain / business logic
                "files": ["app/domain/**/*.js", "app/domain/**/*.ts"],
                "extends": ["async", "async/node", "async/typescript"],
                "rules": {
                  "prefer-const": "error",
                  "no-async-promise-executor": "error",
                  "no-await-in-loop": "error",
                  "no-promise-executor-return": "error",
                  "max-nested-callbacks": "error",
                  "no-return-await": "error",
                  "prefer-promise-reject-errors": "error",
                  "node/handle-callback-err": "error",
                  "node/no-callback-literal": "error",
                  "node/no-sync": "error",
                  "@typescript-eslint/await-thenable": "error",
                  "@typescript-eslint/no-floating-promises": "error",
                  "@typescript-eslint/no-misused-promises": "error",
                  "@typescript-eslint/promise-function-async": "error"
                }
              }
            ]

          復制代碼


          通過配置覆蓋,我們可以為不同的部分設(shè)置不同的 ESLint 規(guī)則


          與之類似,如果要對整個代碼庫進行現(xiàn)代化改造,也要循序漸進。你可以創(chuàng)建一個具有更嚴格規(guī)則的專用目錄,并逐漸將遺留代碼遷移至該目錄,同時修復代碼的警告和類型錯誤。


          從何處開始?


          有種方式是逐步將功能范圍中陳舊的部分遷移到更好的設(shè)計中。例如,選擇一個難以編寫自動化測試的特性,并將它的實現(xiàn)遷移到六邊形架構(gòu)中,將業(yè)務(wù)/領(lǐng)域邏輯根據(jù)輸入命令(即“API”)和副作用(即“SPI”)分離開來。通過編寫自動化測試來指導遷移,并將新的實現(xiàn)放在具有更嚴格靜態(tài)代碼分析規(guī)則的專用目錄中。


          import { makeFeatures } = from './domain/features';
          import { userCollection } from './infrastructure/mongodb/UserCollection';
          import { ImageStorage } from './infrastructure/ImageStorage.js';
          
          
          
          
          
          
          
          
          /** @type {import('./domain/api/Features').Features} Features*/
          const features = makeFeatures({
            userRepository: userCollection,
            imageRepository: new ImageStorage(),
          });
          
          
          
          
          
          
          
          
          routes.post('/avatar', (request, response) => {
            features
              .setAvatar(request.session.userId, request.files[0])
              .then(
                () => response.json({ ok: true },
                (error) => response.json({ ok: false })
              );
          });

          復制代碼

          setAvatar特性經(jīng)過了重新設(shè)計,由于采用了依賴反轉(zhuǎn),使其易于單獨進行測試。下面是我們遷移另一項特性的過程,即播放列表刪除


          如果你決定遵循這一路徑,如下是一些建議:


          • 如果你的團隊沒有重新設(shè)計遺留特性的經(jīng)驗,那么就從簡單的小特性開始。否則的話,請選擇一個未來幾周或幾個月內(nèi)要實現(xiàn)的特性最依賴的那個特性。
          • 在編碼之前,明確范圍、業(yè)務(wù)事件和路徑。例如,與你想重新設(shè)計的領(lǐng)域(或限界上下文)所涉及的專家一起組織一次事件風暴。
          • 可視化要遷移范圍的當前架構(gòu),例如使用像ARKit、Dependency-Cruiser或類似的依賴分析工具,并寫明不想在目標架構(gòu)中重復出現(xiàn)的問題,以免重蹈覆轍。
          • 如果有疑問的話,請使用軟件設(shè)計工具(如時序圖、狀態(tài)機圖、ADR)協(xié)作完成恰當?shù)脑O(shè)計。


          在遷移完每個限界上下文之后,你將會得到一個代碼庫,在代碼庫中 100%的代碼都應(yīng)按照更嚴格的規(guī)則進行檢查。


          每日部署,但同樣的錯誤不要犯兩次


          盡管使用了靜態(tài)分析工具來檢測缺陷,使用了自動化測試來探測回歸,但用戶還是會在生產(chǎn)環(huán)境中發(fā)現(xiàn)問題。這是無法避免的。但是,有一種方法可以降低出現(xiàn)此類問題的概率,并縮短團隊修復問題的時間:


          • 每日部署(前提是你確信失敗的風險很低)。
          • 同樣的錯誤不要犯兩次。


          為何要每日部署?


          簡約版答案:因為DORA研究項目發(fā)現(xiàn),大多數(shù)執(zhí)行團隊每天都在進行部署,或者每天部署多次。


          詳盡版答案:

          • 因為這能夠讓開發(fā)人員更快地找到在生產(chǎn)環(huán)境中出現(xiàn)新缺陷的根本原因。也就是說,部署越頻繁,最新部署和上次部署之間的提交次數(shù)就越少。
          • 基于相同的原因,如果最新版本不能按照預期運行,回滾到上一個版本的成本會更低(就回滾代碼提交的次數(shù)而言)。
          • 因為這能鼓勵團隊將工作分成更小、更安全的增量。DORA 認為,這也是表現(xiàn)最好的團隊所遵循的做法。


          如何確保相同的錯誤不犯兩次?


          在生產(chǎn)環(huán)境中出現(xiàn)意料之外的行為是可以的。在有些情況下,這甚至是一件好事。


          當意料之外的行為給企業(yè)和/或開發(fā)團隊帶來巨大損失時(例如,網(wǎng)站中斷,導致幾個小時無法使用),開發(fā)人員應(yīng)該采取措施防止類似的事件再次發(fā)生。


          如何探測生產(chǎn)環(huán)境中的問題?


          有多種方式可以探測生產(chǎn)環(huán)境中的問題:


          • 理想情況:開發(fā)人員發(fā)現(xiàn)問題并立即修復。
          • 常規(guī)情況:員工發(fā)現(xiàn)問題并向開發(fā)團隊報告。
          • 更糟糕的情況:用戶向開發(fā)團隊報告問題。
          • 最糟糕的情況:用戶發(fā)現(xiàn)了問題,但并沒有報告。


          無論是哪種情況,開發(fā)人員都需要以下信息:問題是什么、問題的具體表現(xiàn)(如錯誤信息)、如何重現(xiàn)問題(如環(huán)境+過程),以及用戶的初衷和期望是什么。


          但是,如何在最糟糕的情況下獲得這些數(shù)據(jù)呢?這就是錯誤監(jiān)控工具(如Sentry)的用武之地了。通過將它們注入到生產(chǎn)環(huán)境中運行的產(chǎn)品中,它們就能像探針一樣檢測運行時錯誤,并將它們匯總到已知錯誤的列表中,直到每個錯誤都被開發(fā)人員修復為止。此外,它們還會獲取有關(guān)錯誤上下文的數(shù)據(jù)(如用戶代理、所使用軟件的版本、操作系統(tǒng)、確切的時間戳等),以幫助開發(fā)人員重現(xiàn)錯誤。


          但令人遺憾的是,與靜態(tài)代碼分析器類似,這些工具并不能解決問題。因此,與警告和類型錯誤一樣,要確保盡快處理每個錯誤。團隊讓錯誤累積得越多,使用這些工具的動力和效率就會越低。


          此外,在使用這類監(jiān)控工具時,請確保個人和/或機密數(shù)據(jù)不會從系統(tǒng)中泄露出去。


          從戰(zhàn)術(shù)上講,有許多方法可供選擇。你可以讓一名開發(fā)人員負責修復生產(chǎn)環(huán)境的錯誤,并將其作為最優(yōu)先的事項。這個角色可以定期輪換(比如每天),這樣可以激勵每個人都編寫更健壯的代碼。或者,也可以在每天的會議上將新錯誤單獨分派給志愿開發(fā)人員。


          如何降低復發(fā)風險?


          不必慌張!當生產(chǎn)環(huán)境中發(fā)生事故時,都要遵守如下程序:


          1. 保留事故發(fā)生前、發(fā)生時和發(fā)生后的痕跡,以幫助你進行事后分析(注意:在事故發(fā)生前做好充分的監(jiān)控和日志收集工作)。
          2. 在內(nèi)部和外部就事故進行溝通。
          3. 穩(wěn)定生產(chǎn)環(huán)境,例如,回滾到之前能正常運行的版本。
          4. 編寫并部署修正版本,以修復問題。
          5. 查找并解決導致問題的根本原因,并采取預防措施。


          避免重蹈覆轍的關(guān)鍵在于上述程序的最后一步。


          這也是經(jīng)常被忽視的過程。大多數(shù)情況下,是因為沒人覺得自己有責任這樣做。很多時候,是因為產(chǎn)品負責人(或產(chǎn)品團隊)向開發(fā)人員施壓,要求他們優(yōu)先完成開發(fā)計劃中的特性,而不是保護現(xiàn)有代碼和/或調(diào)整開發(fā)流程。有時,開發(fā)人員自己也會決定開發(fā)更多的特性,而不是避免再次犯錯。



          調(diào)查事故根本原因時的注意事項


          如何查找事故的根本原因?


          在這個方面,“5 個為什么(5 WHY)”技巧是很有用的。例如:


          • 生產(chǎn)系統(tǒng)為什么會崩潰?——因為一個未登錄的用戶訪問了頁面 B。
          • 用戶為什么能夠訪問頁面 B?——因為主頁上有一個鏈接。
          • 用戶在訪問頁面 B 的時候為什么沒有看到登錄頁面?——因為在頁面渲染時,后端還不知道登錄狀態(tài)。
          • 為什么頁面渲染時還不知道登錄狀態(tài)?——因為我們的會話管理后臺很慢,等待這個狀態(tài)會大大降低我們的網(wǎng)絡(luò)性能指標。
          • 為什么會話管理后端很慢?——因為它使用的是未經(jīng)優(yōu)化的遺留數(shù)據(jù)庫。


          在本例中,根本原因是整個網(wǎng)站都依賴于遺留的會話管理后端,這使得導航難以預測,有時還會導致生產(chǎn)環(huán)境崩潰。因此,除非團隊修復傳統(tǒng)的會話管理后端,否則類似的崩潰很可能很快就會在生產(chǎn)環(huán)境中再次發(fā)生。團隊現(xiàn)在應(yīng)該修復遺留的會話管理后端嗎?也許不用。但是他們應(yīng)該努力制定一個能夠?qū)崿F(xiàn)該目標的補救計劃。


          在實踐中,如何實現(xiàn)低故障率的日常部署呢?


          讓一位開發(fā)人員負責確保盡快發(fā)現(xiàn)生產(chǎn)中的意外行為(如運行時錯誤、缺陷、事故……),盡快修復,并采取措施防止今后再次發(fā)生各類問題。


          通過這種方式,開發(fā)人員能夠感受到有能力在良好的條件下開展工作。例如,在生產(chǎn)過程中設(shè)置恰當?shù)谋O(jiān)控和日志,確保撰寫有用的事后報告,并采取預防措施。


          當信心達到良好水平時,逐步增加部署頻率。


          以正確的激勵機制調(diào)整產(chǎn)品開發(fā)團隊


          此時,開發(fā)人員就具備了編寫高質(zhì)量軟件,并盡快發(fā)現(xiàn)缺陷的能力。這些缺陷最好是在設(shè)計或?qū)崿F(xiàn)時發(fā)現(xiàn),而不是在生產(chǎn)環(huán)境中。他們能夠快速發(fā)現(xiàn)并修正生產(chǎn)環(huán)境的錯誤,不會重復犯同樣的錯誤。他們對自己的代碼和開發(fā)流程充滿信心,因此每天都能在生產(chǎn)中實現(xiàn)改善。而且,他們在對軟件功能化范圍進行預期改善的同時,也會逐步改善代碼庫中最古老部分的設(shè)計和質(zhì)量,使其保持健康、穩(wěn)健并易于長期維護。


          但是,令人遺憾的是,這種平衡很快就可能被瓦解。舉例來說:


          • 如果開發(fā)人員失去了長期保持高設(shè)計標準和/或代碼質(zhì)量的動力。
          • 如果部分開發(fā)人員不遵循團隊的質(zhì)量準則,造成系統(tǒng)性返工、挫折和延誤。
          • 如果開發(fā)人員誤解了功能性需求,而急于修復無法達到預期效果的特性,從而犧牲了長期的技術(shù)責任。
          • 如果有人(如經(jīng)理、產(chǎn)品負責人或其他人)向開發(fā)人員施壓,要求他們每周發(fā)布更多的特性,或在緊急的期限內(nèi)完成任務(wù)。
          • 如果激勵和/或獎勵開發(fā)人員的績效指標與其代碼庫的長期質(zhì)量和健壯性不一致。例如,根據(jù)每周交付的特性數(shù)量確定晉升獎金。


          防止或解決這類情況可能會非常困難,因為這需要良好的領(lǐng)導力和/或軟技能。


          一個常見的錯誤是培養(yǎng)某種思維定式,即開發(fā)人員應(yīng)該主要致力于實現(xiàn)優(yōu)先的、計劃好的和設(shè)計好的特性。


          這樣做是有問題的,因為:


          • 它要求開發(fā)人員處于這樣一種狀態(tài),即對軟件做的每一項變更都要有精確和明確的規(guī)范。這可能會導致開發(fā)人員無法與負責制定這些規(guī)范的人員進行健康的雙向合作。對于那些喜歡整天獨自工作的開發(fā)人員來說更是如此。
          • 它讓開發(fā)人員處于這樣一種境地,即難以衡量那些與功能性路線圖沒有直接貢獻的開發(fā)活動,如更新依賴、提高代碼質(zhì)量、培訓更好的設(shè)計和編碼技術(shù)。
          • 這很容易讓人傾向于根據(jù)指標(如用戶故事的開發(fā)速度)來跟蹤開發(fā)人員的績效(或“生產(chǎn)力”),而忽略了對可持續(xù)開發(fā)實踐的投資,即代碼質(zhì)量、阻礙回歸、錯誤管理等。


          下面是一些關(guān)于如何避免上述陷阱的建議:


          • 在詳細闡述業(yè)務(wù)問題的解決方案時,至少讓一名開發(fā)人員參與設(shè)計過程。這將提高開發(fā)人員的責任心,使他們能夠為一個充分理解的問題實現(xiàn)一個好的解決方案。有時,由于開發(fā)人員了解當前的建模和實現(xiàn)方式,他們會提出替代解決方案,從而在滿足需求的同時節(jié)省大量的開發(fā)時間。
          • 確保產(chǎn)品和技術(shù)代表能夠公開、友好地協(xié)商功能性和技術(shù)性項目的優(yōu)先級和規(guī)劃。例如,如果開發(fā)人員需要重新設(shè)計代碼庫的某個部分,那么他們就應(yīng)該說服其他人相信這一點的重要性,解釋這將為下一個特性的開發(fā)帶來哪些具體的改善,以及延遲該項目的風險和成本是什么。同樣的建議也適用于產(chǎn)品經(jīng)理如何對即將開發(fā)的功能改善進行優(yōu)先排序和規(guī)劃:通過解釋來說服開發(fā)團隊并讓他們參與進來。這樣做可以增強參與設(shè)計和實現(xiàn)特性的所有員工的信任、協(xié)作和參與度。
          • 在管理方面,確保開發(fā)人員不會得到這樣的激勵,即“每周盡可能多地發(fā)布特性”。找到使每個開發(fā)人員的職業(yè)目標與團隊的短期和長期期望相匹配的發(fā)展軌道。這樣做的目的是防止出現(xiàn)開發(fā)人員理直氣壯地只從事短期改善相關(guān)工作的情況。
          • 最后,確保為開發(fā)人員提供資源和指導,以不斷提高他們的軟硬技能。為他們提供培訓和/或指導資源。鼓勵他們通過結(jié)對和/或群體編程的方式共同完成任務(wù)。鼓勵他們與其他/非開發(fā)人員角色進行良好的協(xié)作,包括領(lǐng)域?qū)<摇a(chǎn)品負責人、產(chǎn)品設(shè)計師、客戶支持團隊、終端用戶等。


          結(jié)論


          JavaScript 語言及其不斷變化的軟件包和實踐組成的生態(tài)系統(tǒng)會使代碼庫迅速變得難以維護。正如我們在本文所討論的那樣,無需從頭重寫所有的內(nèi)容,也無需暫停新特性的開發(fā),就可以避免由此造成的開發(fā)速度和/或代碼質(zhì)量的下降。


          關(guān)于如何在 TypeScript 和 JavaScript 項目中應(yīng)用這些推薦做法的更多實用建議,我建議你參考Yoni Goldberg的最佳實踐列表。它們是為 Node.js(后端)項目編寫的,但其中很多也適用于前端代碼庫。

          原文鏈接:前端老手10年心得,JavaScript/TypeScript項目保養(yǎng)實用指南_架構(gòu)/框架_InfoQ精選文章

          了在TypeScript中封裝一個獲取當前年前后十年的方法,您可以定義一個函數(shù),接受一個參數(shù)表示偏移量(正數(shù)表示未來年份,負數(shù)表示過去年份),并返回相應(yīng)年份的數(shù)組。以下是一個實現(xiàn)示例:

          function getYearsAroundCurrentDecade(offset: number): number[] {
          const currentYear = new Date().getFullYear();
          const startYear = Math.floor(currentYear / 10) * 10 + offset;
          // Ensure we don't go beyond the year range supported by JavaScript's `Date` object.
          const minYear = 0;
          const maxYear = 9999;
          if (startYear < minYear || startYear > maxYear) {
          throw new Error(`The specified offset ${offset} leads to an out-of-range year.`);
          }
          // Generate an array of years spanning the decade.
          const years = [];
          for (let year = startYear; year < startYear + 10 && year <= maxYear; year++) {
          years.push(year);
          }
          return years;
          }
          // Usage examples:
          console.log(getYearsAroundCurrentDecade(0)); // [2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029]
          console.log(getYearsAroundCurrentDecade(-1)); // [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019]
          console.log(getYearsAroundCurrentDecade(1)); // [2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039]

          這個函數(shù)首先獲取當前年份,然后根據(jù)偏移量計算出目標十年的起始年份。它確保起始年份在JavaScript `Date`對象支持的合理范圍內(nèi)(通常是從公元0年到公元9999年),超出范圍時拋出錯誤。接著,函數(shù)使用循環(huán)生成包含十年內(nèi)所有年份的數(shù)組,并返回該數(shù)組。

          通過調(diào)用此函數(shù)并傳入不同的偏移量值(如`0`表示當前十年,`-1`表示前一個十年,`1`表示下一個十年),您可以輕松獲取所需年份范圍。


          主站蜘蛛池模板: 精品欧洲av无码一区二区14| 一区二区不卡久久精品| 福利国产微拍广场一区视频在线| 亚洲国产综合无码一区二区二三区 | 性色A码一区二区三区天美传媒| 亚洲天堂一区二区三区| 好吊视频一区二区三区| 无码人妻一区二区三区兔费| 国产一区二区精品| 国产午夜精品一区理论片飘花 | 99精品国产一区二区三区2021| 一区二区三区视频观看| 国产一区二区在线观看麻豆| 亚洲欧美日韩中文字幕在线一区| 人妻激情偷乱视频一区二区三区| 日韩社区一区二区三区| 美女视频一区二区三区| 精品一区二区三区视频在线观看| 国产SUV精品一区二区88| 国产一区在线mmai| 午夜影院一区二区| 精品国产乱子伦一区二区三区| 精品成人av一区二区三区| 一区二区免费在线观看| 国产一区在线视频观看| 色一乱一伦一区一直爽| 无码精品久久一区二区三区 | 亚洲AV无码一区东京热久久| 国产裸体歌舞一区二区| 国产一区在线视频| 高清一区二区三区免费视频| 国99精品无码一区二区三区| 日韩人妻一区二区三区蜜桃视频| 少妇激情一区二区三区视频| 亚洲一区二区三区免费在线观看| 亚洲一区二区三区在线| 国精产品一区一区三区有限公司| 国产成人精品无码一区二区老年人| 日美欧韩一区二去三区| chinese国产一区二区| 亚洲色精品vr一区二区三区|