Sansan事業部で "法人向け名刺管理サービス Sansan" のiOSアプリの開発を担当している栗山です。SBBは 去年のiOSDC 2018のレポート 以来となります(余談ですが今年もiOSDC 2019にCfP応募しました)。
さて、今回は Backcasting (逆算思考)
というキーワードを切り口に、我々iOS開発チームの改善活動のこれまでとこれからについて考えてみたいと思います。
未来逆算思考
未来逆算思考
は、2016年4月に展示がスタートした日本科学未来館の展示の一つです。展示とは言うものの、大雑把に言うと 障害物を避けてゴールまで到達できる進路を予想する一発勝負のゲーム
になっています 1。
展示がスタートして既に3年以上経過していますが、お恥ずかしながら先日初めて体験してきました。環境問題という重要かつ重たいテーマを扱うにふさわしい、大変良くできた展示だと思いました。
50年後の既に破滅を迎えてしまった未来 2 で暮らす子孫から届いたメッセージから物語は始まり、その子孫達を(未来)逆算思考と積み上げ思考(後述)を駆使して救うことがプレイヤーである我々の使命となります。
テーマ設定と冒頭のムービーは(良い意味で)後味の悪さと共に心にずっしりと残る内容でありながら、それに負けないくらいシンプルかつ奥深いゲームに仕上がっており、振り返れば振り返るほどよく出来たゲームだと唸らされます。
展示については語りたいことは他にも沢山ありますが、今回のテーマからは外れるのでこのくらいにしておきます。気になった方はぜひ日本科学未来館へ足を運んでみてください!
Backcasting(逆算思考)とForecasting(積み上げ思考)
Backcasting(バックキャスティング)
は、問題解決のためのアプローチ手法の一つで、日本語では 逆算思考
と訳されることが多いです。Backcastingは Forecasting(フォアキャスティング)
という言葉とセットで論じられることが多く、Forecastingは積み上げ思考
と訳されることが一般的です。
Forecastingは、現在を起点として、現在・過去の実績をベースとして未来を予測します。言うなれば 現在の立ち位置から未来を想像する
アプローチといったところでしょうか。
それに対し、Backcastingは、最初にあるべき未来の姿を定義します。その上で、その未来に到達するために何をする必要があるのかを考えていきます。 先に未来を決めてから逆算してやることを決めていく
点で、Forecastingとは完全に逆のアプローチと言えます。
BackcastingとForecastingは問題に対するアプローチの仕方が大きく異なります。様々な解説記事でも、当の未来逆算思考の展示でも言っていましたが、Backcasting的な視点とForecasting的な視点はどちらかが正しいというわけでなく、問題の性質に応じて使い分けることが大事だとされています。
3年後のチームの理想状態を定義する
では、ここからは私の所属する Sansan iOSアプリ開発チーム
の今後をBackcasting的なアプローチで考えてみましょう。
Backcastingにおいては出自的に環境問題や政策立案時に用いられることが多く、そういったケースでは数十年先の未来から逆算することが多いですが、流石に数十年先の未来はチーム状態として現実的な想像になりづらいので、ここでは今から3年後にあたる 2022年のSansan iOSアプリ開発チーム
というテーマでチームの理想状態を考えてみたいと思います。
チームメンバーの増加に対応可能なチーム状態になっている
おかげさまで、Sansanスマホアプリは初リリースされた5年前から考えると比べ物にならないくらい、社内外から注目を浴びるようになりました(有り難い限りです)。
スマホアプリの注目度が上がるにつれて、アプリに対する機能追加や改善に関するご要望は日々増加傾向にあります(有り難い限りです)。
3年後にはきっとこれまで以上に多くの機能追加や改善活動を進めていかねばならず、今よりも多くのiOSエンジニアの力が必要となるでしょう。よって、3年後はiOSエンジニア数がさらに増えているのではないかと考えられます。
ひょっとすると現在の倍の数のメンバーがいる、なんて未来も有りうるかもしれません。
機能追加に迅速に対応できるコードベースになっている
チームメンバーが増加し、かつSansan スマホアプリの機能追加が今後も継続的に行われていくことを考えると、より多くのメンバーが同時にコードベースの到るところに手を入れることが容易に想像できます。そのときに、コンフリクトや機能追加を簡単にできないようでは困ってしまいます。
3年後には現在以上に大規模なソフトウェアとなり、それに相応しい設計になっていることでしょう。
リリースサイクルが今よりも短くなる(現在の月2〜3回から週1回以上)
エンジニアの数が増えるとなると、当然開発スピードは現在よりも速くなっていることと思います(もしくは、今よりも多くの案件を並行して進めることができる状態になっていることでしょう)。
現在は毎月2〜3回程度リリースしているような状況ですが、3年後には毎週1回以上はリリースしているのではないでしょうか。
3年後の状態からBackcastingで今後チームで取り組むべき課題を考える
3年後のチームの理想状態が決まったところで、3年後の理想状態へ向けてチームとして実施すべき課題について考えてきました。
課題を挙げてみると、実はこれまでにチームで取り組んできた改善施策の中に、課題の改善につながるものが含まれていたので、併せてご紹介したいと思います。
なお、Backcastingによりこれから取り組むべき課題が明確化されたので、これを機にさらなる改善施策を検討していきたいと考えています。
チームメンバーの増加に対応可能なチーム状態になっている
チームメンバーが増加するということは、自ずと新規メンバーが加入する機会も増えることを意味します。今後は新規メンバーがスムーズに立ち上がることがチーム全体の生産性を左右するようなことになるかもしれません。
また、人数が増えるということは、運用作業の内容によってはヒューマンエラーの可能性もつきまといます。ヒューマンエラーがインシデントにつながらないよう、日々対策を講じなければなりません。
チームとしてこれまで実施してきた施策の中に、上記のような課題の改善につかがる施策があったので、ご紹介します。
運用マニュアルや新規メンバー向けマニュアルの整備と定期的な見直し
当チームではApp Storeへの申請といったリリース作業や各種証明書の更新なども行っております。更新が滞ったり作業ミスが生じるとクリティカルな問題に発展するため、新規メンバーが運用作業をミス無く遂行するためにも運用マニュアルの整備が不可欠となります。また、新規メンバーがスムーズに立ち上がり、いち早く開発業務に馴染めるようにするためにも開発環境構築に関するマニュアルは欠かせません。
当チームでは、Githubのリポジトリ内にあるWikiに運用マニュアルと環境構築マニュアルを集約して管理しています。新規メンバーはマニュアルの手順をこなしていくことでいち早く開発環境を構築することができます 3 し、初めて証明書の更新作業を実施する際にも作業実施時の道標として日々活用されています。
また、App Store Connectでの申請フローやXcodeなどの開発環境は日々バージョンアップを続けており、マニュアル類の定期的なメンテナンスは重要となってきます。
当チームでは、新規メンバーが入社して1ヶ月経過後に受け入れ担当者と受け入れの振り返りを実施し、新規メンバーから各種マニュアル類に関するフィードバックを受け、もし古い記載があれば修正するようにしています。
ヒューマンエラーを防止するための仕組み化
いくらマニュアルがあっても、ヒューマンエラーの危険性を完全には防ぐことはできません。
当チームではヒューマンエラー防止のための仕組み化を継続的に進めています。
例えば、アプリから接続しているサービスにアクセスするためのトークン情報を誤ってGithubへアップロードしないために cocoapods-keys
を使ってリポジトリとトークン情報を切り離しています 4 。
また、 R.swift
というライブラリを最近導入し、コード内で指定する文言や画像リソースが誤っていた場合(typoなど)にコンパイル段階で検知できる仕組みを構築しました。
機能追加に迅速に対応できるコードベースになっている
今後の機能追加やエンジニアの増加に備えて、スムーズにアプリを開発できるようなコードベースにしていかなければなりません。
Sansan iOSアプリは2017年にコードベースをSwiftへ刷新しましたが、機能も複雑になりメンバーも増え始めている中でやはり設計が古くなってきました。
開発スピードと品質を担保するために次のような指針を策定し徐々に置き換えを進めています。
Clean Architectureの導入
Sansanアプリのシステムアーキテクチャ(主にModel層におけるアーキテクチャ)としては、これまではレイヤードアーキテクチャに近い設計を採用していました。
ただ、UIKitなどの標準SDKや各種ライブラリをはじめとするFrameworkはバージョンアップにより仕様変更される可能性を常に抱えており、これまで以上に変更に強い設計が求められていました。
そこで、Framework層とドメイン・Entity層を明確に分離することを目指してClean Architectureを導入することにしました。
Sansanアプリは全部で50画面以上あるため、全ての実装に対して一斉に対応することは難しいですが、新規実装や機能追加あった部分から、地道にClean Architectureへの置き換えを進めています。
画面遷移におけるRouterパターンの導入
名刺の詳細を表示する画面を中心に画面遷移が複雑化しており、既存のSegueを使った画面遷移の仕組みではViewControllerが肥大化するなどの問題が発生していました。そこで、Clean Architecture導入と併せてRouterパターンを使った画面遷移の制御の仕組みを導入することになりました。
Sansanアプリは全部で50画面以上あり、またSegueを積極的に使ってきた経緯もあって全画面一斉に置き換えることはやはり難しいですが、まずは新規実装画面を中心にRouterパターンを順次導入しています。
Unit Testの整備
これまでは開発リソース的な問題などもあり、Unit Testの整備が後手に回っていましたが、前述のClean Architectureの導入と共にまずはUse Case層におけるUnit Testの整備を進めています。
テストを書くことで、Clean Architectureがより洗練されていっているという実感もあり、アーキテクチャ刷新とUnit Testの整備は今後も両輪として同時に進めていきたいと考えています。
また、これまではXCTestオンリーでテストを実装していましたが、いわゆるMockを必要とする場面が増えてきました。テスト実装の効率化のためにMockライブラリの導入を現在検討してます 5。
リリースサイクルが今よりも短くなる(現在の月2〜3回から週1回以上)
リリースサイクルをこれまで以上に頻繁に回すためには、リリースプロセスをより効率化していく必要があります。また、アーキテクチャ改善といった実装効率向上のほかに、デザイナーやテスト担当者とのコミュニケーションの効率化も必要となってきます。
チームとしてこれまで実施してきた施策の中に、上記のような課題の改善につかがる施策があったので、ご紹介します。
BitriseからTestFlightまでワンストップでアップロードできる仕組みの導入
当チームではCI/CDの基盤として Bitrise
というサービスを利用しています。
つい半年くらい前まではリリースビルドを開始してTestFlightへアップロードするために
- リリースブランチを作る
- バージョン情報を更新する
- Bitriseへログイン
- リリースビルドをスタート
- ビルドしたバイナリをダウンロード
- TestFlightへアップロード
といった作業を毎回実施していました。手作業が多く、ビルドした.ipaファイルをダウンロードしてアップロードするなど、よく考えると無駄な作業もありました。
今後、リリースが今よりも頻繁に行われることを想定し、リリースフローをさらに効率化するべく、リリースフローの改善に着手しました。
何をしたのかというと、まずは kishikawakatsumiさんが作られた deliverbot
を導入し、slack上からBitriseのリリースビルドを開始できるようになりました。deliverbotの凄いところは、slack上からBitriseを操作できるだけでなく、リリースブランチの作成とバージョン情報の更新までslack上で制御できることです。
また、これを機に、BitriseからTestFlightへ直接.ipaファイルをアップロードするようにしました。
以上のような改善を行った結果、リリースビルドを開始してTestFlightへアップロードするフローが
- deliverbotを呼び出す
- リリースブランチ、バージョン情報をBotへ指定する
だけで完結するようになり、劇的なリリースフロー改善に成功しました。
なお、こちらの施策は 当チームメンバーの中川がメインで担当し、 勉強会でも発表しました。
BitriseとDeploygateの連携によるテスト用アプリ配信基盤の構築
日々の開発フローにおいて、デザインチェックと結合テストの実施は開発案件が佳境に差し掛かる度に頻繁に行われるものです。
これまでは、開発中のアプリを入れた端末をデザイナーや結合テストの担当者へ渡していましたが、リリースサイクルが短くなるにつれ、これら確認作業の回数も増加します。また、結合テストは実装内容によっては複数の担当者や複数の端末を使って実施することもあり、テスト用端末を用意するコストが無視できないくらいに増大します。
そこで、当チームでは Deploygate
を導入し、Bitriseと連携させてBitriseでビルド後すぐにDeploygateで配信できる仕組みを構築しました。
これにより、テスト用端末をDeploygateへ登録しておけば、デザインチェックや結合テストの実施タイミングでBitrise上でビルドを行うと、あとは自動で配信されようになり、テスト用アプリを配布するコストが劇的に下がりました。
まとめ
何気ない博物館の展示からインスパイアされてこの記事ができましたが、記事を書いていく中で、Backcastingはチームの改善施策を考える上で有用なツールだと感じました。また、ここ最近のチームの改善施策を俯瞰的に振り返ることもできました。
みなさんも、本記事や参考文献を参考に、自分の組織やチームの未来の姿をBackcastingを使って想像してみてはいかがでしょうか。
なお、既に実施済みの改善施策や具体的な改善案が存在する施策がいくつかありますが、これらの施策はもちろん私一人で実施したわけではなく、チームとしての改善活動の成果でもあります。改善活動や改善提案が活発に行われるのは当チームの素晴らしい文化の一つだと思っています。
参考文献
-
昔のゲームに詳しい人以外にはわからない例えかもしれませんが、クロノトリガーというゲームの
2300A.D.
のような世界観です。↩ -
環境構築時にはRubyのバージョンなどの些細な違いによってビルドできないなどの問題に遭遇しがちですが、
.ruby-version
を使いメンバー間でrubyのバージョンを揃えられるようにするなど、環境構築プロセスの改善も随時行っています。↩ -
cocoapods-keys は大変便利なツールですが、設定情報を変更した場合は必ず
pod update
しなければならず、設定変更の度にフルビルドが走る状況になっており、開発効率に少なからず影響を与えるようになってきました。そこで、現在別な仕組みで代替しようという試みが進められています。↩