# 利便性の代償 {#the-cost-of-convenience}

**小規模から大規模なプロジェクトまで対応できる**コードエディタを設計するのは難しい課題です。多くのツールは、ソリューションを階層化し拡張性を提供することでこの問題に対処しています。最下層は非常に低レベルで基盤となるビルドシステムに近く、最上層は使い勝手が良いものの柔軟性に欠ける高レベルの抽象化レイヤーです。これにより、簡単なことは容易に行え、その他のことも可能になります。

しかし、**[Apple](https://www.apple.com)はXcodeで異なるアプローチを採用しました**。理由は不明ですが、大規模プロジェクトの課題に対する最適化が彼らの目標ではなかった可能性が高いです。彼らは小規模プロジェクトの利便性への過剰な投資を行い、柔軟性をほとんど提供せず、ツールを基盤となるビルドシステムと強く結合させました。利便性を実現するため、簡単に置き換えられる適切なデフォルト値を提供し、大規模環境で多くの問題を引き起こす原因となる、ビルド時に解決される暗黙的な動作を多数追加しました。

## 明示性とスケール {#explicitness-and-scale}

大規模な開発において、**明示性は不可欠**です。これにより、ビルドシステムは事前にプロジェクト構造と依存関係を分析・理解し、 otherwise 不可能だった最適化を実行できます。同様の明示性は、[SwiftUIプレビュー](https://developer.apple.com/documentation/swiftui/previews-in-xcode)や[Swift Macros](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/macros/)といったエディタ機能が信頼性高く予測可能な動作をするためにも重要です。XcodeおよびXcodeプロジェクトは利便性を実現するために暗黙性を有効な設計選択として受け入れており、この原則はSwift Package Managerにも継承されているため、Xcode使用時の困難さはSwift Package Managerにも存在します。

> [!NOTE]
> **Tuistの役割**
>
> Tuistの役割は、暗黙的に定義されたプロジェクトを防ぎ、明示性を活用してより良い開発者体験（例：検証、最適化）を提供するツールであると要約できます。[Bazel](https://bazel.build)のようなツールは、これをさらに進めてビルドシステムレベルまで持ち込んでいます。


これはコミュニティであまり議論されていないものの、重要な問題です。Tuistの開発中に、多くの組織や開発者が直面している現在の課題は[Swift Package Manager](https://www.swift.org/documentation/package-manager/)によって解決されると考えていることに気づきましたが、彼らが認識していないのは、同じ原則に基づいて構築されているため、よく知られたGitコンフリクトを軽減する一方で、他の領域での開発者体験を低下させ、プロジェクトの最適化不能な状態を継続させていることです。

以下のセクションでは、暗黙性が開発者体験とプロジェクトの健全性にどのように影響するかの実例をいくつか取り上げます。リストは網羅的ではありませんが、XcodeプロジェクトやSwift Packagesを扱う際に直面する可能性のある課題について良い理解を得られるはずです。

## 邪魔になる利便性 {#convenience-getting-in-your-way}

### 共有ビルド成果物ディレクトリ {#shared-built-products-directory}

Xcodeは、各プロダクトに対してDerived Dataディレクトリ内のディレクトリを使用します。その中には、コンパイル済みバイナリ、dSYMファイル、ログなどのビルド成果物が保存されます。プロジェクトのすべてのプロダクトが同じディレクトリに入り、デフォルトで他のターゲットからリンク先として見えるため、**ターゲット同士が暗黙的に依存し合う結果になる可能性があります。** ターゲット数が少ない場合は問題にならないかもしれませんが、プロジェクトが大きくなると、デバッグが困難なビルド失敗として現れることがあります。

この設計判断の結果、多くのプロジェクトが未定義のグラフで偶然コンパイルされてしまいます。

> [!TIP]
> **Tuistによる暗黙的依存関係の検出**
>
> Tuistは暗黙的依存関係を検出するための<.localized_link href="/guides/features/projects/inspect/implicit-dependencies">コマンド</.localized_link>を提供します。このコマンドを使用して、CIですべての依存関係が明示的であることを検証できます。


### スキーム内の暗黙的依存関係を見つける {#find-implicit-dependencies-in-schemes}

Xcodeで依存関係グラフを定義・維持することは、プロジェクトが大きくなるにつれて難しくなります。それが難しいのは、ビルドフェーズやビルド設定として`.pbxproj`ファイルに符号化されており、グラフを可視化・操作するツールが存在せず、グラフの変更（例：新しい動的プリコンパイル済みフレームワークの追加）が上流の設定変更（例：フレームワークをバンドルにコピーするための新しいビルドフェーズの追加）を必要とする可能性があるためです。

Appleはある時点で、グラフモデルを進化させてより管理しやすいものにするのではなく、ビルド時に暗黙的依存関係を解決するオプションを追加する方が理にかなっていると考えました。これも再び疑わしい設計選択であり、ビルド時間の遅延や予測不可能なビルドをもたらす可能性があります。例えば、Derived Data内の何らかの状態（[シングルトン](https://en.wikipedia.org/wiki/Singleton_pattern)として機能する）によりローカルではビルドが成功しても、状態が異なるためCIではコンパイルに失敗することがあります。

> [!TIP]
> プロジェクトのスキームでこれを無効にし、依存関係グラフの管理を容易にするTuistのようなツールを使用することを推奨します。


### SwiftUIプレビューと静的ライブラリ/フレームワーク {#swiftui-previews-and-static-librariesframeworks}

SwiftUIプレビューやSwift Macrosのような一部のエディタ機能は、編集中のファイルから依存関係グラフをコンパイルする必要があります。エディタとのこの統合には、ビルドシステムがあらゆる暗黙性を解決し、それらの機能が動作するために必要な正しい成果物を出力することが求められます。想像できるように、**グラフが暗黙的であればあるほど、ビルドシステムのタスクは難しくなる**ため、これらの機能の多くが信頼性高く動作しないのも不思議ではありません。開発者からは、SwiftUIプレビューが不安定すぎるため、ずっと前に使用をやめたという話をよく聞きます。代わりに、サンプルアプリを使用するか、静的ライブラリの使用やスクリプトビルドフェーズなど、機能を壊す原因となる特定の事項を避けています。

### マージ可能なライブラリ {#mergeable-libraries}

動的フレームワークは柔軟性が高く扱いやすい一方で、アプリの起動時間に悪影響を及ぼします。一方、静的ライブラリは起動が高速ですが、コンパイル時間に影響を与え、特に複雑なグラフ構成では扱いにくくなります。*設定に応じてどちらかを選択できたら素晴らしいと思いませんか？* Appleがマージ可能なライブラリの開発に着手した際、そう考えたに違いありません。しかし再び、彼らはビルド時の推論を増やしてしまいました。依存関係グラフについて考察する際、ターゲットの静的または動的な性質が、一部のターゲット内のビルド設定に基づいてビルド時に解決される状況を想像してみてください。SwiftUIプレビューのような機能が壊れないようにしつつ、それを確実に動作させるのは至難の業です。

**マージ可能なライブラリを使用したいという理由でTuistに多くのユーザーが訪れますが、私たちの答えは常に同じです。必要ありません。** ターゲットの静的または動的な性質を生成時に制御できるため、コンパイル前にグラフが確定したプロジェクトになります。ビルド時に解決すべき変数は存在しません。

```bash
# The value of TUIST_DYNAMIC can be read from the project {#the-value-of-tuist_dynamic-can-be-read-from-the-project}
# to set the product as static or dynamic based on the value. {#to-set-the-product-as-static-or-dynamic-based-on-the-value}
TUIST_DYNAMIC=1 tuist generate
```

## 明示的、明示的、そして明示的 {#explicit-explicit-and-explicit}

Xcodeでの開発をスケールさせたいと考えるすべての開発者や組織に対して推奨する、重要な不文律があります。それは、明示性を重視すべきだという原則です。もし生のXcodeプロジェクトで明示性の管理が困難であれば、[Tuist](https://tuist.io) や [Bazel](https://bazel.build) などの他の手段を検討すべきです。**そうして初めて、信頼性、予測可能性、および最適化が可能になります。**

## 将来 {#future}

Appleが上記の問題すべてを防ぐための措置を講じるかどうかは不明です。XcodeおよびSwift Package Managerに組み込まれ続けている彼らの決定からは、その兆候は見られません。一度、暗黙的な設定を有効な状態として許容してしまうと、**破壊的な変更を導入せずにそこから移行することは困難です。** 基本原則に戻ってツールの設計を見直すことは、長年偶然にもコンパイルできていた多くのXcodeプロジェクトを壊す結果につながる可能性があります。もしそうなったら、コミュニティの大騒ぎを想像してみてください。

Appleはいわゆる「鶏が先か卵が先か」の問題に直面しています。利便性は、開発者が迅速に始め、エコシステム向けにより多くのアプリを構築するのに役立ちます。しかし、その規模で体験を便利にするための彼らの決定は、Xcodeの一部の機能が確実に動作することを保証することを難しくしています。

将来は不明であるため、私たちは**業界標準およびXcodeプロジェクトにできるだけ近づける**よう努めています。上記の問題を防ぎ、持っている知識を活用してより良い開発者体験を提供します。理想的には、そのためにプロジェクト生成に頼る必要はないはずですが、XcodeおよびSwift Package Managerの拡張性の欠如により、それが唯一の実現可能な選択肢となっています。また、Tuistプロジェクトを壊すためにはXcodeプロジェクトを壊さなければならないため、これは安全な選択肢でもあります。

理想的には、**ビルドシステムがより拡張可能であれば**よいのですが、暗黙性の世界と契約するプラグインや拡張機能を持つことは悪い考えではないでしょうか？ それは良いアイデアとは思えません。したがって、より良い開発者体験を提供するには、Tuistや[Bazel](https://bazel.build)のような外部ツールが必要になるようです。あるいは、Appleが私たち全員を驚かせ、Xcodeをより拡張可能で明示的なものにするかもしれません...

それまでは、Xcodeの利便性を受け入れ、それに伴う技術的負債を引き受けるか、より良い開発者体験を提供するためのこの旅路において私たちを信頼するか、選択しなければなりません。私たちはあなたを失望させません。
