Slide 1

Slide 1 text

0

Slide 2

Slide 2 text

相川 健太(Kenta Aikawa) 2020年2⽉に公⽴はこだて未来⼤学⼤学院を中退後、2020年4⽉に Sansan 株式会社に⼊社。在学時は主に Swift や Flutter を⽤いた iOSアプリの開発を⾏ったり、Ruby on Rails を⽤いた Web サイトの 開発を⾏っていた。⼊社後は iOS アプリケーションエンジニアとして 従事し、Sansan の iOS アプリの主要な機能開発や開発環境の改善に 取り組んでいる。 Sansan株式会社 Sansan事業部プロダクト開発部 iOSアプリケーションエンジニア 939_Aikawa_Kenta_bg_mono.jp g 1

Slide 3

Slide 3 text

- Sansan iOS アプリについて - Sansan iOS アプリの紹介 - 2020年の Sansan iOS アプリの状態 - どのような状態が理想だったか - 理想の状態にするための取り組み - XcodeGen の導⼊ - Embedded Framework 化 - Embedded Framework 化時の Good・Problem - 学んだこと アジェンダ 2

Slide 4

Slide 4 text

- Sansan iOS アプリについて - Sansan iOS アプリの紹介 - 2020年の Sansan iOS アプリの状態 - どのような状態が理想だったか - 理想の状態にするための取り組み - XcodeGen の導⼊ - Embedded Framework 化 - Embedded Framework 化時の Good・Problem - 学んだこと アジェンダ 3

Slide 5

Slide 5 text

Sansan iOS アプリの紹介 4

Slide 6

Slide 6 text

Sansan iOS アプリの紹介 5

Slide 7

Slide 7 text

- Sansan iOS アプリについて - Sansan iOS アプリの紹介 - 2020年の Sansan iOS アプリの状態 - どのような状態が理想だったか - 理想の状態にするための取り組み - XcodeGen の導⼊ - Embedded Framework 化 - Embedded Framework 化時の Good・Problem - 学んだこと アジェンダ 6

Slide 8

Slide 8 text

- 開発時のコンフリクト問題が増加していた - 開発メンバーの増加(約10名) - 機能追加のスピードも加速(現在は約100画⾯以上) - project.pbxproj のコンフリクト問題が特に顕著だった - ファイルの追加・削除などを⾏うだけで差分が出てしまうiOS アプリ開発者が 恐れるファイル - 通常ファイルのコンフリクトは⼤きな問題になりにくい - project.pbxproj は⼈が読めるような代物ではないことが難点 開発スピードの加速によるコンフリクトの増加 7

Slide 9

Slide 9 text

- ファイル間の依存関係が不明瞭 - Swift は同モジュール内であれば import が不要なので、ファイル間の 依存関係が不明瞭になっていた > Sansan はほぼ全てのファイルが⼀つのモジュールに定義されていた - 「〇〇ディレクトリのファイルは△△ディレクトリのファイルに依存 させたくないが、依存してしまっている」状態が数多く発⽣していた - レガシーコードも数多く存在 - 現在は VIPER というアーキテクチャを採⽤しているが MVC 時代のディレクトリがいくつも残っている コードにも課題がいくつかあった 8

Slide 10

Slide 10 text

- Sansan iOS アプリについて - Sansan iOS アプリの紹介 - 2020年の Sansan iOS アプリの状態 - どのような状態が理想だったか - 理想の状態にするための取り組み - XcodeGen の導⼊ - Embedded Framework 化 - Embedded Framework 化時の Good・Problem - 学んだこと アジェンダ 9

Slide 11

Slide 11 text

- 理想の状態 1. project.pbxproj から脱却できている 2. ファイル間の依存関係が明確になっている 3. レガシーコードが撤廃・修正されている - 解決⽅法 1. XcodeGen という project.pbxproj ⽣成ツールの利⽤ 2. Embedded Framework 化による import の強制 3. Embedded Framework 化を⾏う中で徐々に撤廃・修正 どのような状態が理想だったか 10

Slide 12

Slide 12 text

- 理想の状態 1. project.pbxproj から脱却できている 2. ファイル間の依存関係が明確になっている 3. レガシーコードが撤廃・修正されている - 解決⽅法 1. XcodeGen という project.pbxproj ⽣成ツールの利⽤ 2. Embedded Framework 化による import の強制 3. Embedded Framework 化を⾏う中で徐々に撤廃・修正 どのような状態が理想だったか 11

Slide 13

Slide 13 text

- Sansan iOS アプリについて - Sansan iOS アプリの紹介 - 2020年の Sansan iOS アプリの状態 - どのような状態が理想だったか - 理想の状態にするための取り組み - XcodeGen の導⼊ - Embedded Framework 化 - Embedded Framework 化時の Good・Problem - 学んだこと アジェンダ 12

Slide 14

Slide 14 text

- project.pbxproj のコンフリクト問題を解決する⽅法として有名な ツールの⼀つ - XcodeGen を⽤いることで project.pbxproj を冪等に⽣成することができる - つまり project.pbxproj を git 管理する必要がなくなる XcodeGen について 13

Slide 15

Slide 15 text

XcodeGen の導⼊・利⽤⽅法 14 project.pbxproj XcodeGen project.yml

Slide 16

Slide 16 text

XcodeGen の導⼊・利⽤⽅法 15 project.pbxproj XcodeGen project.yml

Slide 17

Slide 17 text

- 現状はどうしても⼈の⼿で yml ファイルを作成することになる - yml の記法の学習コストが⽐較的⾼い - プロジェクトの規模が⼤きいほど yml の⾏数が多くなるため 導⼊が難しくなる(Sansan は約 600 ⾏) - プロジェクト⽴ち上がり初期などに XcodeGen を導⼊するとコスパが良い project.yml の作成難易度 16

Slide 18

Slide 18 text

- ⾃分が⼊社する前から導⼊したいという話はあった - 以下のような理由から導⼊には踏み切れていなかった - メンバーの中に XcodeGen 導⼊経験者がおらず⼯数感が不明 - XcodeGen を導⼊することによって開発コストをどの程度 抑えることができるか不透明 XcodeGen 導⼊に⽴ち塞がる壁 17

Slide 19

Slide 19 text

導⼊までの道のり 個⼈的に勉強 案件で取り組み 無事 XcodeGen を導⼊ 開発の合間を⾒て yml を作成 18

Slide 20

Slide 20 text

導⼊までの道のり 案件で取り組み 無事 XcodeGen を導⼊ 開発の合間を⾒て yml を作成 19

Slide 21

Slide 21 text

導⼊までの道のり 案件で取り組み 無事 XcodeGen を導⼊ 開発の合間を⾒て yml を作成 20 時間・知識不⾜を 痛感しながら yml と格闘

Slide 22

Slide 22 text

- project.yml を作成する際には以下のような苦労があった - ドキュメント・記事をひたすら読んで yml 作成⽅法を学習 - 問題ないかどうかをレビュワーとすり合わせながらひたすら修正 project.yml との格闘 21 元の PJ 構成(左)と XcodeGen で⽣成した PJ 構成(右)をひたすら⽐較する作業 運⽤(上)・案件(下)で 取り組んでいた時の PR

Slide 23

Slide 23 text

- ほぼ確実に発⽣していた project.pbxproj のコンフリクト問題が解消された - プロジェクトに関する全ての設定を yml ファイルで設定・確認 できるようになり、設定の変更も容易になった - 後で詳しく説明する「Embedded Framework 化」の実現可能性にも寄与 XcodeGen 導⼊後の開発 22

Slide 24

Slide 24 text

- Sansan iOS アプリについて - Sansan iOS アプリの紹介 - 2020年の Sansan iOS アプリの状態 - どのような状態が理想だったか - 理想の状態にするための取り組み - XcodeGen の導⼊ - Embedded Framework 化 - Embedded Framework 化時の Good・Problem - 学んだこと アジェンダ 23

Slide 25

Slide 25 text

- Embedded Framework について - ファイルの集まりを Framework (モジュール)として分割する仕組み > リソースファイル(画像、Storyboard など)も格納できる > Dynamic Framework の⼀種 - Embedded Framework 化によるメリット > モジュール間の依存関係が明確になる(主にこれを期待) - 別 Framework のコードを呼び出す際は import が強制させられる > ビルド時間の短縮が期待できる - ビルド時間が 3 分ほどかかっている現状があるため、副次的な効果として期待 > ターゲットごとにテストを記述できるようになる Embedded Framework 化(マルチモジュール化) 24

Slide 26

Slide 26 text

- Sansan iOS アプリについて - Sansan iOS アプリの紹介 - 2020年の Sansan iOS アプリの状態 - どのような状態が理想だったか - 理想の状態にするための取り組み - XcodeGen の導⼊ - Embedded Framework 化 - Embedded Framework 化時の Good・Problem - 学んだこと アジェンダ 25

Slide 27

Slide 27 text

- Good - XcodeGen によって Embedded Framework 化が実現しやすくなっていた - Problem - Embedded Framework 化の進め⽅に問題があった - チームメンバー全員と共通認識を固めることができていなかった Embedded Framework 化時の Good・Problem 26

Slide 28

Slide 28 text

- Good - XcodeGen によって Embedded Framework 化が実現しやすくなっていた - Problem - Embedded Framework 化の進め⽅に問題があった - チームメンバー全員と共通認識を固めることができていなかった Embedded Framework 化時の Good・Problem 27

Slide 29

Slide 29 text

- XcodeGen によって各 Embedded Framework の「利⽤ファイル」・ 「設定」などは全てyml に記載すれば良いだけになっていた - XcodeGen を導⼊していない場合は Xcode 上で設定する必要がある - yml なのでコードレビューすることができる(コメントも残せる) Embedded Framework の定義を yml で完結させられる 28

Slide 30

Slide 30 text

複数種類ある Embedded Framework の共通設定部分を容易にまとめる ことができた Embedded Framework のメンテナンス性の向上 29

Slide 31

Slide 31 text

依存がある場合は yml 内の dependencies に記述する必要があるため、 Embedded Framework が依存している対象を明確にできた Embedded Framework 間の依存関係の明確化 30

Slide 32

Slide 32 text

- Good - XcodeGen によって Embedded Framework 化が実現しやすくなっていた - Problem - Embedded Framework 化の進め⽅に問題があった - チームメンバー全員と共通認識を固めることができていなかった Embedded Framework 化時の Good・Problem 31

Slide 33

Slide 33 text

- ⽅針 - Embedded Framework 化しやすそうな部分からまずは⼿を付け、 後続の Embedded Framework 化に繋げる - Embedded Framework 化しやすそうだと考えていた部分 - Entity > API Response のフィールドだけが定義されているシンプルな構造体 - Utility > Utility という名前の通り便利なクラスなどが集まっている - API > API との通信処理、レスポンスのデコード処理などがまとめられている > 似ている役割のエンドポイントごとにファイルが分割されている 当時の Embedded Framework 化⽅針 32

Slide 34

Slide 34 text

Embedded Framework 化の結果 - Entity - ある程度 EF 化することができた - レガシーコードに依存する部分は諦めた - Utility - 責務ごとにディレクトリを分割しながら EF 化した - API - レガシーな Model に依存していたため、 そもそも簡単には EF 化することができなかった 33

Slide 35

Slide 35 text

- 「将来的にどのような状態が理想なのか」まで考えられていなかった - 理想形を考えていないと作業に迷いが⽣じる・チームも混乱させてしまう - 事前調査の不⾜によって作業途中に問題が発覚した - レガシーコードに依存している部分が多く、簡単に切り離せない - ディレクトリ内の全てが整理されているわけではない > 特に Utility(Utility という命名の時点で気づくべきだった) Embedded Framework 化の進め⽅で良くなかった点 34

Slide 36

Slide 36 text

- Good - XcodeGen によって Embedded Framework 化が実現しやすくなっていた - Problem - Embedded Framework 化の進め⽅に問題があった - チームメンバー全員と共通認識を固めることができていなかった Embedded Framework 化時の Good・Problem 35

Slide 37

Slide 37 text

- 開発中すり合わせを密に⾏うことができていたのは⾃分を含めて3名 - それ以外のメンバーには案件終了後に詳細を伝える形となってしまった - 全開発メンバーとすり合わせながら作業するべきだった - Embedded Framework を利⽤した開発スタイルに少なからず 混乱が⽣じてしまっていた - ミーティングなどで共通認識を固めながら導⼊することが重要だった メンバーと EF に対する共通認識を固められていなかった 36

Slide 38

Slide 38 text

- Sansan iOS アプリについて - Sansan iOS アプリの紹介 - 2020年の Sansan iOS アプリの状態 - どのような状態が理想だったか - 理想の状態にするための取り組み - XcodeGen の導⼊ - Embedded Framework 化 - Embedded Framework 化時の Good・Problem - 学んだこと アジェンダ 37

Slide 39

Slide 39 text

- 最初の Embedded Framework 化は中途半端な結果に終わってしまった - しかし学べたことは多かった - アーキテクチャに関わる変更を⾏う場合 > 変更のためにコードにどのような影響があるか具体的に考えること > 将来的にどのような状態が理想か考えること - 開発環境に⼤きな影響を与える変更を⾏う場合 > チームメンバーと共有を徐々に⾏いながら進めること > アイデア段階から共有しておくことが重要 学んだこと 38

Slide 40

Slide 40 text

- 取り組んできたこと - XcodeGen の導⼊ > コンフリクト問題を解消できた > 設定値などを yml で管理できるようになった - Embedded Framework 化 > 結果としては、中途半端な状態で終わってしまった > しかし学べたことは数多くあった - Embedded Framework 化の実現⽅法 - アーキテクチャを変更するために必要な変更・理想形を考えることが重要 - アーキテクチャ・開発環境に⼤きな影響を与える場合は都度共有することが重要 > 今後は失敗を活かし、次以降の Embedded Framework 化に取り組んでいく予定 まとめ 39