見出し画像

mikanのiOSプロジェクトにXcodeGenを導入しました。

こんにちは、noppeです。
最近仕事でXcodeを触ることも減ってきているので、気分転換も兼ねて色んなところに顔を出しています。

mikanはそのうちの1社で、主に言語習得を主軸とするアプリを開発・運用しています。

mikanのiOSプロジェクトは複数人で開発をしているため、xcodeprojのコンフリクトが発生していました。
これらのコンフリクトをXcodeGenの導入をもって無くし、事業の成長速度を加速させるのが今回の目的です。

また全てのxcodeprojの設定値がダンプされるため、不要な設定・ファイル・構造を洗いざらい見つけることができます。

長年改善が繰り返されたxcodeprojを今一度見直し、リアーキテクチャ出来る地盤に整える効果も期待できるでしょう。

導入にあたって

まずXcodeGenの導入にあたって、全員の作業を止めずに導入することを目指しました。
これは自分の稼働時間やプロジェクト規模に対して移行期間を見積もったところ数日で終わらない計算になった為です。
作業を継続しつつXcodeGenへの移行を達成するために、最初にMakefileを用意しました。
チームメンバーにはMakefileを叩いてから作業をすることを習慣化してもらいます。そうすることで、チームメンバーに要求することは、導入開始から完了まで一貫してMakefileを叩くことだけになります。
XcodeGenの導入に必要になる処理は全てMakefileに追記していけば良いからです。

workspace:
    mint run xcodegen --spec Sources/Feature/Books
    mint run xcodegen --spec Sources/Feature/Profiles
    ...    

安全に移行するために

リファクタリングにおいて、注意しなくてはいけないのは変更前と挙動を一致させることです。
XcodeGenで起こりがちな不整合は次のようなものがあります。

・ファイルの参照が消える
・ファイルツリーが壊れる
・設定値が異なる
・xibのアセット参照先が消える

では順に対策を追っていきましょう。

ファイルの参照が消える

Xcode 9より前のXcodeでは、ファイルツリーとディレクトリ構造の関係はそこまで同期的ではありませんでした。
例えば、Xcode上でファイルを生成しても実際はプロジェクトのルート直下にファイルが生成されるようなこともありました。
このような状態のファイル群をXcodeGenで管理しようとすると、迷子になったファイルがXcodeの管理下から外れてしまうことがあります。
しかし、このケースは大抵の場合は非常に簡単に見つけることができます。
基本的にはビルドを実行すれば、コンパイル時に気がつく事が出来るからです。
クラスの定義が見つからないエラーが発生したら、元のxcodeprojを開いてファイルを探しましょう。

ファイルツリーが壊れる

XcodeGenでは、実際のディレクトリ構造をファイルツリーとして構築します。先の項で説明した通り、これらは全く同じ構造である補償はありません。
これを解決するために、venmo/synx を利用する事がオススメです。synxはxcodeprojを解析して、ディレクトリ構造をファイルツリーと同期する事ができます。


設定値が異なる

XcodeGenはymlからxcodeprojを生成する事は出来ますが、それが元々のxcodeprojと同じであることは検証してくれません。
そこで、今回は bloomberg/xcdiff を使って差分を検証しました。
XcodeGenで完全に同じxcodeprojを作ることは出来ませんが、xcdiffを使うことで差分が影響のあるものか否かを判断する材料になります。
また、このdiffをPRに貼り付けることでXcodeGen移行に関わる差分をレビュアーに適切に伝える事ができます。移行のPRでxcodeprojの差分を見るのは嫌ですからね。

xibのアセット参照先が消える

xibにはローカライズや画像を設定する事ができますが、それらの参照が見つからない場合実行時にクラッシュしたり、画像が表示されない挙動になります。
これらはクリティカルな不具合であるにも関わらず、コンパイル時に見つける事ができません。
このような問題は IBDecodable/IBLinter を使う事で検証する事ができます。
XcodeGen移行時に関わらず、xibの参照が消えると気が付きにくいので普段からアセットはコードで書いたりIBLinterを導入しておくと良いと思います。

移行後に確認しておきたいところ

さて、これらに注意しておけば大方の問題は未然に対処する事が出来ますが大きなリファクタリングには大きな問題が起きると考えておいた方が良いでしょう。
しかし、完全な状態でリリースすることはとても難しいことです。まずはリリース前のリグレッションは普段よりも手厚く行い、リリース前には必ずTestFlightで挙動を見ましょう。
完全に移行してからリリースではなく、一部を移行した状態でリリースすることも影響を最小に止める方法として優れています。
またリリース後にはすぐに対応できるようにリリース日やエンジニアの予定を合わせることも重要です。
そうして、問題を最小限に抑えながら大きなメリットを享受する事が出来ます。

mikanではXcodeGenに移行したことで、既にコンフリクトが無くなり、誰が見ても分かりやすいプロジェクト構造になるように変革が始まっています。
全力で開発が出来る環境で、ぜひスキルを奮ってみてください!