原文連結:12 Things to Help Large Organizations Do Angular Right
在 Nrwl,我們幫助財富500強公司用正確的方式使用 Angular 平臺開發。這些公司很少存在小型應用,大多是多個團隊使用多個共享庫構建的多個應用程式。經歷過此種情況的開發者就知道,如果處理不當它很快就會演變成一個多對多的卷積噩夢。
在本文中,我將會討論:
- 為什麼開發大型 Web 應用在大公司很難
- 為什麼 Angular 是大公司的絕佳選擇
- 怎麼做
文章的末尾——在討論了一些相關因素和關注點之後——我將列出一份大型組織中架構師的12條清單,以提高他們團隊的工作效率。
大型組織面臨的挑戰
從表面上看,大型和小型組織實際上都有同樣的關注點:
- 他們關注一致性。如果每個團隊構建程式碼的方式不統一,則程式碼將難以複用和整合。
- 他們需要編寫健壯,經過驗證的程式碼:包括錯誤處理,竟態條件等。
- 他們需要編寫可維護的,自文件化的程式碼。
- 他們希望能夠放心地更改程式碼。如果開發人員可以快速驗證更改是否安全,那麼他們更有可能保證程式碼庫擁有更少的bug。
大型組織的不同之處在於,他們擁有數百名 Angular 工程師,並且構建了數十個應用程式,擁有大量的程式碼,從而導致了新的挑戰。
- 雖然十名開發人員可以通過午餐聊天達成最佳實踐的共識,但當開發人數達到五百名時就不現實了。你必須建立最佳實踐,團隊標準並使用工具來推廣它們。
- 隨著程式碼量和複雜性的提升,程式碼所有權概念變得非常重要。例如,只有三個專案的情況下,大家往往都知道團隊內誰是 review PR 的最佳人選,但三十個專案的時候就不是這樣了。你必須明確定義所有權模型並使之自動化。
- 例如,在只有三個專案的情況下,開發人員很容易知道在程式碼變更後需要重新測試哪些內容,但有三十個專案時,這不再是一個簡單的過程。管理變更的非正式規定將不再適用於大型團隊,多團隊和多專案協作的情形。你必須依賴自動化 CI 流程。
- …
換句話說,小型組織通常可以通過非正式的臨時流程來實現這些目標,而大型組織卻不能。臨時流程也會使得團隊中新加入的開發人員更加困惑且容易出錯。
Angular 是讓大型組織受益的框架
作為 Angular(2.x及更高版本)的主要貢獻者之一,不出意料地我肯定認為 Angular 是各種規模,無論大小的公司的絕佳選擇。但是,我想強調一下為什麼該框架特別適合大型組織的幾個理由。
沒有碎片
Angular 社群並不分散。幾乎所有應用程式都是由 Angular CLI 構建的,使用 Angular router,許多應用程式使用 NgRx(或計劃使用它)來管理狀態和副作用。 這種統一性導致高度的一致性。因此,當新的開發人員加入團隊時,他可以在幾天內就能變得高產,他也可以在組織內換崗的同時保持高效。
語義化版本控制
Angular 每六個月釋出一個新版本。如果推出重大變更,你將有一年的時間來更新你的應用。雖然這會使得像我這樣的框架貢獻者的工作更加艱難(例如,我無法立馬修復路由設計中的錯誤),但是能讓像我一樣的 Angular 使用者更容易幫助公司業務獲得成功。
Angular ? TypeScript
TypeScript 是 JS 生態系統中最棒的發明之一,它為開發人員提供了開發時警告和錯誤提示,它還能夠幫助我們闡明程式碼意圖並消除歧義(閱讀這裡瞭解更多)。 Angular 並不是唯一適用於 TypeScript 的框架——大多數現代框架都可以。但它是整個生態系統與 TypeScript 配合良好的唯一主流框架:每個工具和每個庫。因此,typings 定義永遠不會過時,API 與型別一起使用時開發體驗很棒,程式碼操作工具背後使用了 TypeScript 編譯器 API。
使用 TypeScript 作為通用語言讓 Angular 與其他框架有著很大的區別。
自動化
大型組織依賴於工具和自動化。這通常意味著原始碼必須是可靜態分析的。而 Angular 就是以此為基礎構建的,它清晰地分離了應用程式的靜態和動態部分,使你能夠編寫可靠的工具來操作 Angular 原始碼。此外,開發人員可以利用工具來構建,測試,執行和打包 Angular 應用程式,而無需開發人員配置任何內容。
怎麼做
對你所在的組織來說,開發大型應用影響最大的四個主要因素分別是:
- 程式碼管理,
- 依賴管理,
- 落地最佳實踐,以及
- 自動化。
我們來詳細闡述一下。
程式碼/依賴關係管理
正如我上面提到的,大型組織存在有很多程式碼,很多開發人員對程式碼,包,部署等進行過更改。因此,弄清楚如何託管它,如何有效地對其進行修改,如何在不同專案之間建立依賴關係,如何構建和釋出它們,是你需要儘早給出方案的問題。一旦開始研究這些問題,你將發現並非所有專案/模組都類似。
在典型的專案配置中,有四類專案/模組:
- Apps,這些是你交付的業務產品。
- 特定於 App 的 lib,這些是可以獨立開發和測試的 app 部分。
- 可複用的 lib,這些是你在多個不同 App 中使用的元件,服務和工具。
- 第三方庫和工具。
在這個模式下,開發人員應該能夠:
- 建立 app 特定的 lib
- 提取可複用的 lib
- 驗證更改可複用 lib 相關的程式碼不會破壞任何依賴它的 app 和 lib
- 同時重構多個 app 和 lib
- 確定 app 和 lib 的負責 Owner
開發人員完成所有這些工作的難易度,對團隊的迭代速度和專案的程式碼質量有很大影響。
如果建立一個新的可複用庫(需要新建一個 repo,配置 CI,釋出到內部 npm 倉庫)需要耗費一天的時間,那麼很少有人會願意這樣做。因此,開發人員會不自覺地複製貼上程式碼,或者把程式碼放到不恰當的地方。 如果能在幾分鐘內(而不是幾天)構建和配置可複用庫...那麼才會促進開發人員建立和維護可重用的庫。
如果多個 app 依賴於多個 lib,則在 lib 更改時,迴歸測試會變得非常困難。如果無法自動驗證可複用庫的更改會不會破壞任何 app,那麼開發人員將害怕進行程式碼更改並編寫防禦性的脆弱程式碼。
如果開發人員無法橫跨不同的 app 和 lib 進行重構,他們就不會改進 API。
當開發人員無法獨立構建和測試 app 部分時,他們將會建立內部模組緊密耦合的單體應用。當他們能夠(使用 app 特定的 lib)做到時,他們就會編寫更多可維護的程式碼並改進他們的應用程式架構。
這主要是因為他們必須明確定義一個特性的依賴以及它的輸出,這個過程必須仔細斟酌,其結果類似於六邊形體系結構,減少了專案之間的耦合。
Angular CLI 擴充套件 (Nrwl/Nx)
Nrwl Nx 是一個用於企業級 Angular 應用的開源工具包,基於 Angular CLI 構建,它解決了很多上面提到的問題。 通過使用 monorepo 的方式,把多個 app 和 lib 託管在同一個 repo (在 這裡閱讀更多相關資訊)。
藉助 Nrwl / Nx 開發人員可以:
- 快速建立 app 特定的 lib
- 快速提取可複用的庫
- 驗證可複用 lib 的程式碼變更不會破壞任何依賴它的 app 和 lib(Nx 附帶增量構建和測試僅受 PR 影響的 app 的命令)
- 同時重構多個 app 和 lib
Nx 強制你使用第三方庫的單一版本(雖然必要時可以繞過它),這一點很重要。如果你的 app 和 lib 依賴於 TypeScript 的不同版本,則它們可能無法被複用。而且使用不同的庫組合可能會導致難以除錯的問題。即使你不使用 Nx,我依然建議建立一個名為 third-party 的軟體包,列出主要的第三方依賴項,並使其他 app 和 lib 依賴於它。
Nx 並不處理程式碼的所有權問題,因為這取決於程式碼的託管方式。如果使用 GitHub,則可以利用 CODEOWNERS 檔案。
無論你是否選擇使用 Nx,請確保明確定義上述五個操作的工作流程,記錄在文件裡,衡量下開發人員執行這些操作的速度。
落地最佳實踐和自動化
Code review 和口耳相傳是落地小團隊最佳實踐的好方法。但是,組織越大,此過程就越耗費資源,容易出錯,並且很難統一。這時我們就需要使用工具來解決此問題。
建立小型可複用 lib
往往最簡單的事情可能會產生最大的影響。
例如,建立可複用的小型 lib。即使只把 30 行程式碼提取到可複用的 lib 中,你也可以提高團隊的工作效率並節省數週的工作量。
例如,Nrwl 團隊觀察到每一個單獨的應用都存在很多竟態條件。其中一些是顯而易見的,而另一些是非常微妙的,很難溯源。即使是經驗最豐富的高階工程師也難免會忽視微妙的竟態條件。
在幫助許多客戶解決這些型別的問題後,我們不得不問自己:“我們能否建立一個小工具來消除(或避免)產生竟態條件的程式碼?”
因此,我們實現了一個 50 行程式碼的 service,該 service 與 NgRx Effects 整合,消除了 Web 應用中出現的許多竟態條件。這個功能的程式碼量非常小,你可以閱讀它的原始碼並能很快了解它的作用。我們把它變成了 Nx 的一部分。你應該鼓勵你團隊的開發人員也這樣做,可以從導致最多問題的三個方面開始:測試,狀態管理和路由。
建立 Schematics 實現程式碼生成
Angular CLI 使用 schematics 庫進行程式碼生成。 Nrwl / Nx 基於 Angular CLI 構建,它通過定製一個自定義的 schematics 集合,為多 app/多 lib 專案定製 CLI 功能。企業團隊應該更進一步,建立一個你所在組織中使用的 schematics 集合。例如,如果在整合測試中使用模擬資料,請建立 schematics 以生成相應填充素材。
通過衡量開發人員實現簡單程式碼生成器所需的時間,只有在花費僅需幾分鐘的時候,人們才會這樣做。
建立自定義 Lint 規則
TSLint 擅長兩件事:確保開發人員不會犯下低階錯誤,並使程式碼風格更加統一。TSLint 可以在 CI上 執行,並且還可以與所有主要編輯器和 IDE 整合。
引入這個工具,做好相關配置,並通過文件記錄執行 TSLint 檢查的流程,以便開發人員可以快速執行。
使一切自動化(使用程式碼格式化工具)
令人驚訝的是,很少有組織會配置程式碼自動格式化等流程。很大程度上,是因為許多人認為這不是開發的重點。如果需要數週的時間才能配置正確,那麼我同意。但是,實際上,它可能只需要30分鐘,並且具有驚人的效果:它使程式碼風格更加統一,並且消除了一大堆問題。
團隊使用格式化工具協作的最大好處是利於程式碼提交和程式碼審查。程式碼的變更作為整個倉庫的增量,不應該引入混亂的格式來影響一些關鍵程式碼的修改。
Nrwl Nx 附帶了一些命令來在本地和 CI 中設定程式碼自動格式化。
TLDR/架構清單
這裡列出了一份大型組織裡架構師的清單列表,可以幫助他們的團隊提高工作效率。
- 定義用於構建 Angular 應用(CLI,Nx,NgRx)的工具集。開發人員喜歡搭建自定義構建工具,但使用標準工具往往是更好的選擇,至少從長遠來看是這樣。建立一個使用這些工具構建的示例倉庫。
- 定義建立/提取新庫的過程。 衡量下需要多長時間。
- 定義一個流程,用於驗證程式碼更改為可複用 lib 不會破壞任何依賴它的 app 和 lib,區分本地開發和 CI 環境。衡量下需要多長時間。
- 定義重構多個 app 和 lib 的流程。
- 定義分配和檢查模組所有權的流程。沒有良好的所有權模式,開發就會產生混亂。
- 定義分支管理策略:基於主幹的開發或基於功能的開發,試著讓所有 app 和 lib 都統一。
- 定義顯式地管理第三方依賴關係的策略。
- 定義狀態管理和副作用管理最佳實踐,使之儘可能自動化。
- 定義測試最佳實踐,使之儘可能自動化。
- 從一開始就建立一個特定於組織的 tslint 包。這是推廣最佳實踐的好方法。
- 從一開始就建立一個特定於組織的 schematics 包。這是推廣最佳實踐的好方法。
- 自動化所有可自動化的內容(例如,配置程式碼自動格式化)。
不出所料,Nrwl Nx 幫助我們實現了很多其中的功能。畢竟,這就是我們創造它的原因。但是這與大多數架構的決策一樣,並不是說僅僅使用某個工具就好,而是要仔細地選擇工具和流程。