グローバルで戦う為にAndroid版Pairsをフルスクラッチで開発した話

はじめまして。Pairs Global事業部の@yuyakaidoです。
今年はAdvent Calendarをエウレカ内外で合計6つ書くことになっており、最近はブログばかり書く毎日を過ごしています。


さて、Eureka Native Advent Calendar 2日目はAndroidネタです。私は現在Pairs Global事業部でAndroidアプリの開発をしており、ここ1年でPairsをグローバル版としてフルスクラッチで開発してきました。そこで、今回はそのフルスクラッチ開発の概要を解説します。

Pairs Japan/Pairs Globalの関係性

まず、本題に入る前に弊社が提供するPairs Japan/Pairs Globalの関係性を説明します。Pairs Japanはその名の通り日本で展開しているサービスであり、Pairs GlobalはPairs Japanから派生して台湾・韓国にて展開しているサービスを指します。技術的な関係性としては、Pairs Japan/Globalは元々同じコードベースで開発されており、Product FlavorでJapan/Globalの分岐を行っていました。


しかし、本格的にグローバル展開していくにあたって、グローバル版独自の機能が増えてきて日本版と同じコードベースでは都合が悪い場面が増えたこともあり、現在はPairs Japan/Globalはそれぞれ独立したリポジトリとして管理されています。また、グローバル展開にあたり、仕様やデザインの全面見直しがあったのもリポジトリ分割を決定した理由の1つです。

フルスクラッチ開発の目的

グローバル展開するにあたり、仕様やデザインの全面見直しを行っていく中でPairs Japanとはまったく別といっていいほどの仕様やデザインになりそうな見込みとなったため、Pairs Japanを修正する形で実装するよりも、今後のグローバル展開を見据えた構成に変更しながら実装すべきではないかと考え、仕様・デザイン変更と同時にフルスクラッチで開発することを決めました。まとめると、Pairs Globalをフルスクラッチ開発する目的は以下の2つです。

  1. マッチングサービスにおけるグローバルスタンダードな仕様・デザインにすること
  2. グローバル展開後もスケールできるコードベースにすること

フルスクラッチで開発するにあたって意識したこと

上記で述べたフルスクラッチ開発の目的のうち、2つ目が主にエンジニアサイド主導で考える部分になり、ここをもう少し掘り下げてみます。

  • 言語/画像のローカライズ基盤
  • サービス特性に適したアーキテクチャ・テスト

言語/画像のローカライズ基盤

Pairs Globalは現在台湾・韓国でサービス展開しており、複数の国に対してアプリケーションは1つという構成になっています。したがって、単一アプリで複数の国/言語に対応する必要があります。幸いAndroidはグローバル展開前提で設計されているため、基本的にはOS標準のローカライズ手法に則った形で実装すればOKです。具体的には以下の方針で実装しています。

  • 言語
    • res/valuesを言語毎に作成
    • 台湾語をPrimary Language(values)として設定
    • 韓国語をSecondary Language(values-ko)として設定
  • 画像
    • 文字入りの画像を使わずに全てvalusだけで実装(アプリ側で翻訳済みの文言を合成)
    • 今後のグローバル展開を見据えてデザイン作成のコストを削減する狙い
    • 副次的な効果として、アプリサイズを削減可能

サービス特性に適したアーキテクチャ・テスト

Android界隈では様々なアーキテクチャについて議論されていますが、前提として全てのアプリに最適なアーキテクチャは存在しない、というのが私の考えです。その前提を踏まえた上で、Pairsにはどんなアーキテクチャが適しているのかを改めて考えてみます。

  1. 会員ステータスの変更により、アプリ全体の挙動が変わること
    • 例えば、無料会員と有料会員でトーク画面の切り替えが発生
    • これを解決するためには「ステータス変更通知とそれによる挙動変更」をうまくハンドリングする必要があります
  2. 会員ステータスの数が多く、それによる分岐が多いこと
    • 具体的には、無料会員、有料会員、プレミアム会員、いいね残高、ポイント残高などにより分岐が発生
    • これをうまく解決するためにはステータス分岐を宣言的に定義し、テストコードを書くと良さそうです

ステータス変更通知とそれによる挙動変更

1つ目の課題を解決する手段としてPairs Global AndroidではFluxを採用し、全体としては以下のようなアーキテクチャを採用しています。FluxはFacebookが公開している単方向データフロー型のアーキテクチャで、Storeが状態保持と変更通知を担当しており、View側でこの変更通知を購読しておくことで、変更検知とそれによる挙動変更を実現することができます。





例えば、自分のいいね!残高を表示する画面を実装する場合を考えてみます。
まず、自分のいいね!残高を保持するdata classを以下のように定義します。
また、残高表示画面はいいね!残高が変更されると即座に更新されることを要件とします。

1
data class Me(val likeBalance: Int)



この場合、Meの状態保持と変更通知を担当するMeStoreを実装し、MeStoreはObservableとして変更を通知します。そして、残高表示画面は変更通知を受け取ってそれを描画することだけに集中すればOKです。


Fluxのより詳細な解説は次回の記事を予定しております。

ステータス分岐とテストコード

2つ目の課題を解決する手段として、ステータス分岐やユーザーアクションによって起きる挙動をenumとして定義し、その分岐ロジックに対してテストコードを書く、という方針を取っています。例えば、Pairs Globalにおいて、いいね!ボタンを押した際の挙動は以下の4パターンがあります。(詳しい仕様は省略しており、4パターンの挙動があるということだけご理解いただければ大丈夫です。)

  1. いいね!購入ダイアログが表示される
  2. ポイント交換ダイアログが表示される
  3. キャンペーン中であれば無料でいいね!が送信される
  4. いいね!が送信される

これをenumで表現すると以下のようになり、アプリ内にいくつも存在するいいね!ボタンを押した際は全て以下のenumを使って判定を行います。そして、getメソッドに対するテストコードを記述することでいいね!ボタンを押した際の挙動をテストすることが可能です。

1
2
3
4
5
6
7
8
9
10
11
12
enum class LikeApproachBehavior {
    ShowPurchasePointDialog,
    ShowExchangePointDialog,
    SendFreeLike,
    SendLike;
 
    companion object {
        fun get(...): LikeApproachBehavior {
            // 省略
        }
    }
}

まとめ

今回はPairs Global Androidのフルスクラッチ開発の概要をお伝えしました。

  • フルスクラッチ開発の目的
    • マッチングサービスにおけるグローバルスタンダードな仕様・デザインにすること
    • グローバル展開後もスケールできるコードベースにすること
  • フルスクラッチ開発で意識したこと
    • 言語/画像のローカライズ基盤
    • サービス特性に適したアーキテクチャ・テスト

アーキテクチャに関しては内容が多いわりに詳しくは触れることができなかったため、次回の記事でもう少し詳細に解説予定です。もしご興味あればご覧ください。


エウレカでは、一緒に働いていただける方を絶賛募集中です。募集中の職種はこちらからご確認ください!皆様のエントリーをお待ちしております!

Recommend

PairsのBlue-Green-Deployment事情とゴールデンイメージの生成高速化(失敗)について

【出張レポート】IAC XCO Security meeting@Dallas に参加してきました