原則
本頁介紹構成 Tuist 設計與開發基石的原則。這些原則會隨項目演進,旨在確保可持續增長,並與項目基礎保持一致。
預設採用約定#
Tuist 存在的原因之一,是 Xcode 在約定方面較弱,導致項目複雜、難以擴展和維護。因此,Tuist 採取不同做法,預設採用簡單且經過精心設計的約定。開發者可以選擇不遵循這些約定,但這是需要刻意做出的決定,感覺並不自然。
例如,有一項約定是透過提供的公開介面來定義目標之間的依賴關係。這樣做可確保 Tuist 生成的項目具備正確的設定,使連結能夠正常運作。開發者也可以透過建置設定來定義依賴關係,但這種做法是隱式的,因而會破壞依賴某些約定的 Tuist 功能,例如 tuist graph 或 tuist cache。
我們預設採用約定的原因在於:我們能替開發者做出的決定越多,他們就越能專注於為應用程式打造功能。當像許多項目那樣缺乏約定時,我們不得不做出與其他決定不一致的決策,結果就會產生難以管理的意外複雜性。
Manifest 檔案是唯一事實來源#
多層設定及其之間的合約會導致項目設置難以理解和維護。試想一個普通項目:項目定義位於 .xcodeproj 目錄中,CLI 邏輯位於腳本(例如 Fastfiles)中,而 CI 邏輯位於管線中。這是三個需要維護且彼此存在合約的層級。你有多常遇到這種情況:修改了項目中的某些內容,一周後才發現發布腳本出錯?
我們可以透過單一事實來源(即 manifest 檔案)來簡化這一點。這些檔案為 Tuist 提供生成 Xcode 項目所需的資訊,讓開發者可以用來編輯檔案。此外,它也允許使用標準命令從本地或 CI 環境建置項目。
Tuist 應承擔複雜性,並提供簡單、安全且易用的介面,盡可能明確地描述項目。
將隱式行為顯式化#
Xcode 支援隱式設定。一個很好的例子是推斷隱式定義的依賴關係。雖然隱式行為在設定簡單的小型項目中可以接受,但隨著項目變大,可能會導致速度變慢或出現異常行為。
Tuist 應為隱式的 Xcode 行為提供顯式 API。它也應支援定義 Xcode 的隱式行為,但以鼓勵開發者選擇顯式方式的方式實作。支援 Xcode 的隱式行為和複雜細節有助於推動 Tuist 的採用,之後團隊可以花時間逐步消除隱式行為。
依賴關係的定義就是一個很好的例子。雖然開發者可以透過建置設定和階段來定義依賴關係,但 Tuist 提供了優雅的 API,鼓勵大家採用。
將 API 設計為顯式,讓 Tuist 能夠對項目執行一些否則無法實現的檢查和最佳化。 此外,它還啟用了诸如 tuist graph(匯出依賴關係圖的表示)或 tuist cache(將所有目標快取為二進位檔)等功能。
我們應將每個從 Xcode 移植功能的要求視為一個機會,透過簡單且顯式的 API 來簡化概念。
保持簡單#
擴展 Xcode 項目時的主要挑戰之一來自於Xcode 向用戶暴露了大量複雜性。 因此,團隊的「巴士係數」很高,只有少數人理解項目以及建置系統拋出的錯誤。這是一種糟糕的情況,因為團隊過度依賴少數人。
Xcode 是一款出色的工具,但多年的改進、新平台和程式語言都反映在其表面上,使其難以保持簡單。
Tuist 應把握機會保持簡單,因為處理簡單的事物既有趣又能激勵我們。沒有人願意花時間去除錯編譯過程最後階段發生的錯誤,或搞懂為何無法在裝置上運行應用程式。Xcode 將任務委派給其底層的建置系統,而在某些情況下,它在將錯誤轉化為可操作項目方面做得非常差。你是否曾經遇到 「找不到 framework X」 錯誤卻不知如何處理?想像一下,如果我們能得到一份潛在根本原因的清單,情況會好得多。
從開發者體驗出發#
Xcode 周圍缺乏創新(或者換句話說,不如其他程式環境那麼多)的部分原因在於,我們經常從現有解決方案開始分析問題。 結果,如今我們找到的大多數解決方案都圍繞著相同的想法和工作流程。雖然將現有解決方案納入考量是件好事,但不應讓它們限制我們的創造力。
我們喜歡Tom Preston在這集播客中所說的觀點:「大多數事情都能實現,只要在你腦海中的想法符合宇宙的限制,你就很可能用程式碼把它做出來。」 如果我們想像理想的開發者體驗是什麼樣子,實現它只是時間問題——從開發者體驗出發分析問題,為我們提供了獨特的視角,引導我們打造出用戶喜愛的解決方案。
我們可能會忍不住跟隨大眾的做法,即使這意味著要忍受大家一直抱怨的不便。讓我們不要這樣做。我期望如何封存我的應用程式?我希望程式碼簽署流程是什麼樣子?我可以透過 Tuist 簡化哪些流程?例如,加入對 Fastlane 的支援是解決某個問題的方案,但我們需要先理解該問題。我們可以透過不斷問「為什麼」來找出問題的根本原因。一旦釐清動機來源,我們就能思考 Tuist 如何提供最佳協助。解決方案或許是與 Fastlane 整合,但在做出取捨之前,務必不要忽視其他同樣可行的方案。
錯誤難免發生#
我們開發者天生容易忽視錯誤發生的可能性。結果,我們在設計和測試軟體時,往往只考慮理想情況。
Swift、其類型系統以及架構良好的程式碼有助於防止某些錯誤,但無法防止所有錯誤,因為有些因素超出我們的控制範圍。我們不能假設用戶永遠有網路連線,或系統指令一定會成功執行。Tuist 運行的環境並非我們控制的沙盒,因此我們需要努力了解這些環境可能如何變化並影響 Tuist。
處理不當的錯誤會導致糟糕的用戶體驗,用戶可能會因此對項目失去信任。我們希望用戶享受 Tuist 的每一個環節,包括我們呈現錯誤的方式。
我們應該換位思考,想像我們期望錯誤訊息告訴我們什麼。如果程式語言是錯誤傳播的溝通渠道,而用戶是錯誤的接收者,那麼錯誤訊息就應該用目標對象(用戶)理解的語言來撰寫。它們應包含足夠資訊讓用戶了解發生了什麼事,並隱藏不相關的資訊。此外,它們應具備可操作性,告訴用戶可以採取哪些步驟來恢復正常。
最後但同樣重要的是,我們的測試案例應涵蓋失敗情境。這不僅能確保我們按預期處理錯誤,也能防止未來的開發者破壞這些邏輯。