# 原則 {#principles}

本頁介紹構成 Tuist 設計與開發基石的原則。這些原則會隨項目演進，旨在確保可持續增長，並與項目基礎保持一致。

## 預設採用約定 {#default-to-conventions}

Tuist 存在的原因之一，是 Xcode 在約定方面較弱，導致項目複雜、難以擴展和維護。因此，Tuist 採取不同做法，預設採用簡單且經過精心設計的約定。**開發者可以選擇不遵循這些約定，但這是需要刻意做出的決定，感覺並不自然。**

例如，有一項約定是透過提供的公開介面來定義目標之間的依賴關係。這樣做可確保 Tuist 生成的項目具備正確的設定，使連結能夠正常運作。開發者也可以透過建置設定來定義依賴關係，但這種做法是隱式的，因而會破壞依賴某些約定的 Tuist 功能，例如 `tuist graph` 或 `tuist cache`。

我們預設採用約定的原因在於：我們能替開發者做出的決定越多，他們就越能專注於為應用程式打造功能。當像許多項目那樣缺乏約定時，我們不得不做出與其他決定不一致的決策，結果就會產生難以管理的意外複雜性。

## Manifest 檔案是唯一事實來源 {#manifests-are-the-source-of-truth}

多層設定及其之間的合約會導致項目設置難以理解和維護。試想一個普通項目：項目定義位於 `.xcodeproj` 目錄中，CLI 邏輯位於腳本（例如 `Fastfiles`）中，而 CI 邏輯位於管線中。這是三個需要維護且彼此存在合約的層級。*你有多常遇到這種情況：修改了項目中的某些內容，一周後才發現發布腳本出錯？*

我們可以透過單一事實來源（即 manifest 檔案）來簡化這一點。這些檔案為 Tuist 提供生成 Xcode 項目所需的資訊，讓開發者可以用來編輯檔案。此外，它也允許使用標準命令從本地或 CI 環境建置項目。

**Tuist 應承擔複雜性，並提供簡單、安全且易用的介面，盡可能明確地描述項目。**

## 將隱式行為顯式化 {#make-the-implicit-explicit}

Xcode 支援隱式設定。一個很好的例子是推斷隱式定義的依賴關係。雖然隱式行為在設定簡單的小型項目中可以接受，但隨著項目變大，可能會導致速度變慢或出現異常行為。

Tuist 應為隱式的 Xcode 行為提供顯式 API。它也應支援定義 Xcode 的隱式行為，但以鼓勵開發者選擇顯式方式的方式實作。支援 Xcode 的隱式行為和複雜細節有助於推動 Tuist 的採用，之後團隊可以花時間逐步消除隱式行為。

依賴關係的定義就是一個很好的例子。雖然開發者可以透過建置設定和階段來定義依賴關係，但 Tuist 提供了優雅的 API，鼓勵大家採用。

**將 API 設計為顯式，讓 Tuist 能夠對項目執行一些否則無法實現的檢查和最佳化。** 此外，它還啟用了诸如 `tuist graph`（匯出依賴關係圖的表示）或 `tuist cache`（將所有目標快取為二進位檔）等功能。

> [!TIP]
> 我們應將每個從 Xcode 移植功能的要求視為一個機會，透過簡單且顯式的 API 來簡化概念。


## 保持簡單 {#keep-it-simple}

擴展 Xcode 項目時的主要挑戰之一來自於**Xcode 向用戶暴露了大量複雜性。** 因此，團隊的「巴士係數」很高，只有少數人理解項目以及建置系統拋出的錯誤。這是一種糟糕的情況，因為團隊過度依賴少數人。

Xcode 是一款出色的工具，但多年的改進、新平台和程式語言都反映在其表面上，使其難以保持簡單。

Tuist 應把握機會保持簡單，因為處理簡單的事物既有趣又能激勵我們。沒有人願意花時間去除錯編譯過程最後階段發生的錯誤，或搞懂為何無法在裝置上運行應用程式。Xcode 將任務委派給其底層的建置系統，而在某些情況下，它在將錯誤轉化為可操作項目方面做得非常差。你是否曾經遇到 *「找不到 framework X」* 錯誤卻不知如何處理？想像一下，如果我們能得到一份潛在根本原因的清單，情況會好得多。

## 從開發者體驗出發 {#start-from-the-developers-experience}

Xcode 周圍缺乏創新（或者換句話說，不如其他程式環境那麼多）的部分原因在於，**我們經常從現有解決方案開始分析問題。** 結果，如今我們找到的大多數解決方案都圍繞著相同的想法和工作流程。雖然將現有解決方案納入考量是件好事，但不應讓它們限制我們的創造力。

我們喜歡[Tom Preston](https://tom.preston-werner.com/)在[這集播客](https://tom.preston-werner.com/)中所說的觀點：*「大多數事情都能實現，只要在你腦海中的想法符合宇宙的限制，你就很可能用程式碼把它做出來。」* 如果**我們想像理想的開發者體驗是什麼樣子**，實現它只是時間問題——從開發者體驗出發分析問題，為我們提供了獨特的視角，引導我們打造出用戶喜愛的解決方案。

我們可能會忍不住跟隨大眾的做法，即使這意味著要忍受大家一直抱怨的不便。讓我們不要這樣做。我期望如何封存我的應用程式？我希望程式碼簽署流程是什麼樣子？我可以透過 Tuist 簡化哪些流程？例如，加入對 [Fastlane](https://fastlane.tools/) 的支援是解決某個問題的方案，但我們需要先理解該問題。我們可以透過不斷問「為什麼」來找出問題的根本原因。一旦釐清動機來源，我們就能思考 Tuist 如何提供最佳協助。解決方案或許是與 Fastlane 整合，但在做出取捨之前，務必不要忽視其他同樣可行的方案。

## 錯誤難免發生 {#errors-can-and-will-happen}

我們開發者天生容易忽視錯誤發生的可能性。結果，我們在設計和測試軟體時，往往只考慮理想情況。

Swift、其類型系統以及架構良好的程式碼有助於防止某些錯誤，但無法防止所有錯誤，因為有些因素超出我們的控制範圍。我們不能假設用戶永遠有網路連線，或系統指令一定會成功執行。Tuist 運行的環境並非我們控制的沙盒，因此我們需要努力了解這些環境可能如何變化並影響 Tuist。

處理不當的錯誤會導致糟糕的用戶體驗，用戶可能會因此對項目失去信任。我們希望用戶享受 Tuist 的每一個環節，包括我們呈現錯誤的方式。

我們應該換位思考，想像我們期望錯誤訊息告訴我們什麼。如果程式語言是錯誤傳播的溝通渠道，而用戶是錯誤的接收者，那麼錯誤訊息就應該用目標對象（用戶）理解的語言來撰寫。它們應包含足夠資訊讓用戶了解發生了什麼事，並隱藏不相關的資訊。此外，它們應具備可操作性，告訴用戶可以採取哪些步驟來恢復正常。

最後但同樣重要的是，我們的測試案例應涵蓋失敗情境。這不僅能確保我們按預期處理錯誤，也能防止未來的開發者破壞這些邏輯。
