こんにちは、株式会社AbemaTVでiOS、tvOSを開発している波戸 @dekatotoro と申します。

先日開催されたサイバーエージェントグループの技術カンファレンスCA BASE CAMP 2019にて登壇した、 継続的な開発スタイル 「AbemaTV iOSアプリを週一で リリースしている話」 について紹介させていただきます。

当日の発表では、AbemaTVのiOSチームで取り組んだ開発フローの改善について、前提となる開発体制とコードベースを交えてお話しました。本記事では、当日の発表スライドを元に紹介していきたいと思います。

発表スライドは以下になります。

Agenda

  1. 開発体制
  2. コードベース
  3. 開発フロー
  4. 今後の取り組み
  5. まとめ

1. 開発体制

現在AbemaTVの開発局は約80名程います。
Direction, Android, iOS, Web, Server, QA…といたチームに分かれており、今回はこの中のiOSチームにフォーカスした開発体制や開発フローについての紹介になります。

developer2

対応デバイス

iOSチームはiPhone, iPad, AppleTVやGoogleCast、AirPlay再生が開発デバイスの担当範囲になります。
iphone_ipad_tv

AppleTVやiPhone/iPadの画面回転、縦横レイアウトの最適化に対応していることも大きな特徴です。

iOSチーム

iOSチームはここ最近は約12~15名程で開発をしており、サイバーエージェント内のネイティブアプリ開発チームでは一番大きなチームで、日本国内で見ても有数のチームではないかと思います。

AbemaTVの2015~2016年の立ち上げ初期は4名でしたが、2017年は約8名、2018年は約12名とだんだん大きなチームになってきました。
ios_team

Micro Team

開発スピードと品質は人数の増加に比例して向上することが理想の形だと思いますが、チームの人数が増え大規模な開発になってくると、様々なコストが発生し、実際には開発スピードと品質は人数が増える毎にその速度はスローダウンしていってしまうことも多いのではないでしょうか。マイクロサービスのような綺麗な分離が難しいネイティブアプリの場合、何かしら工夫していかないと6〜7人を超えるとスローダウンが顕著になってくると経験上感じています。

理想の開発スピードと品質 現実の開発スピードと品質
スクリーンショット 2019-03-23 11.44.00 スクリーンショット 2019-03-23 11.44.20

人数が増えてくると開発スピードと品質が低下してしまう原因として、我々のチームでは以下のようなものがありました。

  • マネジメントコスト増
  • コミュニケーションコスト増
  • コンフリクトリスク
  • コード品質のばらつき
    これらを引き起こしている根本の原因には以下のようなものが上げられます。

  • 責務の集中や増加

  • ドキュメント不備 / 属人化

  • 1人の取り扱うコード範囲の広さ

  • スキルや経験に依存
    言語化してみると当たり前のことではないかと思いますが、こういった要素を極力排除して、開発効率をを高めるために、iOSチームの中でも小さなチームに分かれて開発する体制にしています。

具体的には海外対応、マネタイズ、コア、AppleTV、広告、視聴品質といったチームに分かれており、スプリントの計画や振り返り、コードレビュー、スケジューリングもチーム内で責任を持って取り組んでいます。1人のところはチームを跨いだコードレビューにはなってしまいますが、基本的にはチームで責任を持って取り組んでいます。
team

少人数のチームに分かれて開発することで、以下の効果が見込めます。

  • 責務の分散
  • マネジメントコストの削減
  • コミュニケーションコストの削減

2. コードベース

レポジトリ

iOSチームで開発しているコードベースは以下のようになっています。

  • ios ‥‥ iOSアプリ
  • tvos ‥‥ tvOSアプリ
  • api ‥‥ APIモジュール
  • protobuf-swift ‥‥ .protoを.swiftに変換したもの
  • cmdshelf-ios ‥‥ scripts
  • etc ‥‥ mock, tool, sample
    代表的なレポジトリはiostvosの2つになり、iOS/tvOS共通のapiがあります。protobuf-swiftProtocol Buffersを使用しているのですが、protoからswiftに変換したソースを置いておくレポジトリ、共通のscript郡のcmdshelf、そのほかモックやサンプル、ツールなどのレポジトリがあります。

iosで約10万行、tvosで約4万行、apiで5000行程度になっています。
repository

以下は、iosのレポジトリの1月16日 ~ 2月16日の1ヶ月のGitHubのinsightsになりますが、1ヶ月で187個のpull requestがマージされていて、営業日で1日平均すると、だいたい8~10個のpull requestがマージされていることになります。
insights

コードベースを分析してみると様々なデータが取得できますが、毎日大量のコードが変更されているということがわかると思います。

テスト

テストについて簡単に触れておくと、テストは以下の方針で極力書くようにしており、立ち上げ初期はテストコードも少ない状態でしたが、テストケースの比率は徐々に増えてきています。

  • Model層やロジックはテストを書く
  • UIはModelのテストとQAで担保(UIのテストはデザインや仕様が頻繁に変わる現状だとコストが大きいのと、ViewとModelを分離する設計にしているため)

3. 開発フロー

こういったチーム体制やコードベースに対してどのような開発フローで開発しているのか、今までの開発フロー(旧開発フロー)と新しい開発フロー(新開発フロー)について紹介したいと思います。

旧開発フロー

今までの開発フローは、2週間サイクルのスプリントで申請をしていました。開発期間が1週間、QA期間が1週間の繰り返しになります。もちろん大きめの開発はスプリントを跨ぐ開発も多々あります。

  • 2週間サイクルのスプリントで開発と申請
  • 開発期間1週間、QA期間1週間
    old_development_flow2

旧開発フロー ブランチ戦略

旧開発フローのブランチ運用は、開発用のmasterブランチとQA用のqaブランチで運用していました。各自featureブランチを開発期間中はmasterブランチから、QA期間中の不具合の修正はqaブランチから切って作業し、qaブランチでテストが完了したらリリースできる状態となります。
QA期間中全く開発が止まるわけではなく、QA期間中に次の開発や大きめのスプリントを跨ぐ開発をやっているメンバーももちろんいます。

  • 開発用のmasterブランチとQA用のqaブランチで運用
  • 各自featureブランチをmaster / qaから切って作業
  • qaブランチでテストが完了したらリリースできる状態
    old_flow_branch

旧開発フロー 課題

旧開発フローで感じていた課題がいくつかあり、以下のようなものが上げられます。

  • 各チームの取り纏めの調整コストが高い
  • リリースマネージャーの負担が大きい
  • 1つのチームの遅延でリリースが延びる
  • チーム間の案件の優先度に左右されリリースが延びる
  • 2週間に1回のリリースだと改善の速度が出ない
    1つのチームの遅延がリリーススケジュールに影響するのは多発しており、例えばこの図のように、マネタイズチームで申請予定日に間に合わなかった場合に、他のチームの案件もリリースが延びてしまうことになってしまっていました。
    old_flow_problem

新開発フロー

こういった課題を解決するために、開発フローを大きく変更しました。
旧開発フローと大きく異なる点は、1週間サイクルの開発/申請であること、開発とQAの期間は分けないことの2つが大きなポイントになります。

  • 1週間サイクルの開発と申請
  • 開発とQAの期間は分けない
    new_flow

新開発フロー ブランチ戦略

新しい開発フローのブランチ運用ですが、各自featureブランチをmasterから切って作業するのは旧開発フローと同じですが、異なる部分として、featureブランチでコードレビュー後にそのままfeatureブランチでQAを完了してからmergeするという運用が大きく違います。masterブランチはリリーステスト※をすればいつリリースしても良い状態を保つことが重要になります。

※ リリーステスト – リリース前に主要機能を一通り確認しているリグレッションテスト

  • 各自featureブランチをmasterから切って作業
  • featureブランチでQA後にmasterにmerge
  • masterはリリーステストをすれば、いつリリースしても良い状態
    new_flow_branch

「開発 no QA」はQAが不要なものですが、例えば UIのOSや端末のバリエーションテストが必要ないものや、ロジックのみの変更でUnitテストで担保できているものはコードレビューのみでQAなしでmergeしています。

「開発 / QA」はUI/UXや、テストが書けないものなどはコードレビュー、featureブランチでQA確認後masterへmergeとなります。

また、まだ大きく活用はできていませんが「開発 with Feature Flag」はFeature Flag※をAbemaTVでは導入しており、開発が完了したらQAでのみ機能をオンにしてQAを行い、問題なければFeature Flagをオンにして機能をリリースといったフローになります。

※ Feature Flag –
比率やOSのversion、UserIDなどを指定して機能のon/offを動的に行えるもの
SeeAlso – featureflags.io

新開発フロー 振り返り

新しい開発フローで実際に開発してみて、各チームの調整コストや依存、リリースマネージャーの負担が大きく減ったと感じています。旧開発フローだとちょっとした不具合でも今回入れないと2週間後になってしまうということから、適正なチケットの優先度判断ができていなかった部分が、1週間サイクルにしたことで適正にできるようになりました。また、リードタイムはソフトウェア開発において重要な指標となりますが、リリースサイクルが2週間から1週間に短くなったことは改善のトライ数も増え良かったのではないかと考えています。

  • 各チームの取り纏めの調整コストが減った
  • チーム間の依存が減った
  • リリースマネージャーの負担が減った
  • チケット優先度の判断が適正になった
  • リードタイムの削減

新開発フロー スケジュール

1週間の具体的なスケジュールは以下のようにしています。

  • 月曜日 リリース、TestFlight申請
  • 火曜日
  • 水曜日 masterブランチをビルド
  • 木曜日 リリーステスト
  • 金曜日 申請
    月曜に前週の金曜日に申請していたものをリリースしています(審査が通過していれば)。またTestFlightも審査が1日程度かかるので月曜日に申請しておきます。水曜日の19時にmasterブランチをビルドして木曜日にリリーステスト、金曜日に申請といった流れになります。金曜日申請にしている理由は、週末終盤のリリースはなるべく避けたいことと土日も審査のレビュー期間として有効に使うためになります。
    new_flow_schedule

bitriseのschedulerとfastlaneを使って、月曜日のTestFligth申請、水曜日19時のmasterビルドとTestFlight配信、金曜日19時の申請を自動化しています。
new_flow_auto

「人が機械に合わせる」というかたちでmasterブランチは常にリリースできる状態を保ち、決まったスケジュールでdeliveryは行うことで無駄なスケジュール調整などがなくなり決まったスケジュールに合わせて計画を立て開発をすることができるようになりました。
new_flow_build

4. 今後の取り組み

Trunk-Based Development

ブランチ戦略でも少し触れましたが、Feature Flagを活用したTrunk-Based開発を目指しており、柔軟な開発とスムーズなmasterブランチの進行でリードタイムを短くしていくことを目指しています。

  • Feature Flagの活用
  • masterブランチはいつでもリリースできる状態
  • QAなどに依存しないリリースサイクル
    Trunk-Based Developmentについては こちらをご参照ください。

Micro Framework化

現在Micro Framework化を進めています。static frameworkが使えるようになったことでdynamic framewokほど起動時間を気にせずframework化を検討することができるようになりました。アプリの構成要素をモジュール単位でframework化し、モジュール単位で起動やデバッグをできるようして開発速度の向上を図ることを進めています。

micro_framework

コードレイアウト

今までstoryboardやxibを使ってレイアウトを組んでいましたが、コードでUIを実装することでコンフリクトリスクの軽減やUIのコードレビューの向上、再利用性の向上も見込めると考えています。

  • storyboard / xibを使わずコードでレイアウト
  • コンフリクトリスクの軽減
  • UIコードレビューの向上
  • 再利用性の向上
    code_layout

設計の改善

AbemaTV iOSアプリは現在「MVVM + Flux」で設計していますが、設計の改善を進めています。もともとFluxで設計していましたが、グローバルで状態保持する必要がないところはFluxをやめてMVVMに変更していっておりFluxを縮小していっています。また、MVVMは実装者によって差が出やすいので、StreamのInputとOutputを明確にして一方通行フローに強制する軽量なフレームワークを作成してコードレビューや品質、開発速度の向上を図ろうと考えています。軽量なフレームワーク Unio を作成中です。
54809507-d9a1b580-4cc6-11e9-93cf-2ffd8e1e952c

 

5. まとめ

開発スピードや品質については色々な要素が関連しているかと思いますが、特にメンバーが多いチームでは開発体制や開発フローは重要な要素だと考えています。
その中で、小さなチームへの分割と開発フローや自動化・テストの充実、モジュール化、Feature Flagの活用といったことを組み合わせることによって、人数が増えても開発速度が落ちない、スケールする開発チームを目指して今後も取り組んでいきたいと思います。

 

conclusion

hato
2011年サイバーエージェント中途入社。 Ameba、AWAの開発を経て、現在はAbemaTVのiOS, tvOS開発を担当。