繰り返しのimport問題
中規模以上のSwiftプロジェクトでは、ほぼすべてのファイルの先頭に同じimportのセットが並ぶことになります。Foundation、SwiftUI、OSLog、場合によってはObservation。新しいフレームワークを採用するたびにリストは増え続けます。OSLogによる構造化ログへの移行に伴い、いつものimportに加えてimport OSLogをほぼすべてのファイルに追加していることに気づきました。
解決策は、よく使うものすべてを単一のimportで再エクスポートするラッパーモジュールです。
ラッパーモジュールのセットアップ
SwiftパッケージまたはXcodeプロジェクトに新しいターゲットを作成します。私の場合はAppFoundationと名付けました。モジュール全体は1つのファイルで構成されます:
// Sources/AppFoundation/Exports.swift
@_exported import Foundation
@_exported import SwiftUI
@_exported import OSLog
@_exported import Observation@_exported属性により、各フレームワークのすべてのパブリックシンボルがAppFoundationをインポートする任意のファイルで利用可能になります。これで、アプリ内のすべてのファイルに必要なのは以下だけです:
import AppFoundationPackage.swiftでは、このターゲットにはエクスポートファイル以外のソースコードはありません。アプリターゲットがAppFoundationへの依存を宣言すると、再エクスポートされたすべてのフレームワークがどこでも利用可能になります。
考慮すべきトレードオフ
このアプローチには明確な利点があります:ボイラープレートの削減、importセクションでのマージコンフリクトの減少、新しいフレームワークimportを追加する場所の一元化。しかし、トレードオフもあります。
まず、@_exportedはアンダースコア付きの属性であり、安定版のSwift APIの正式な一部ではありません。実際には長年安定しておりエコシステムで広く使われていますが、正式な保証はありません。
次に、暗黙の依存関係により、ファイルが実際に何を使用しているかを理解しにくくなる可能性があります。すべてのファイルがすべてにアクセスできると、明示的なimportのドキュメントとしての価値が失われます。後でモジュールをスタンドアロンパッケージとして抽出する場合は、明示的なimportを再び追加する必要があります。
厳密なモジュール性よりも利便性が重要なアプリターゲットでは、ラッパーモジュールパターンは本当に時間を節約します。再利用可能なライブラリでは、明示的なimportが引き続きより良い選択です。
