$30 off During Our Annual Pro Sale. View Details »

Firebase Remote Configの運用で知ったこと・知っておくと良いこと / Things I Learned from Operation of Firebase Remote Config

Firebase Remote Configの運用で知ったこと・知っておくと良いこと / Things I Learned from Operation of Firebase Remote Config

2019年6月18日に合同会社DMMで行われたpotatotips #62で発表した資料です。
Firebase Remote Configを実装・運用した時に気づいたTIPSについて解説しました。

Poiboy(ポイボーイ) 出会い探しマッチングアプリ
https://poiboy.jp/

Firebase Remote Config (公式)
https://firebase.google.com/docs/remote-config?hl=ja

Firebase Remote Config を使ってA/Bテストをやってみよう - PSYENCE:MEDIA
https://tech.recruit-mp.co.jp/mobile/post-14940/

sgr-ksmt/Lobster - 🦐 Type-safe Firebase-RemoteConfig helper library 🦐
https://github.com/sgr-ksmt/Lobster

jmatsu/remocon - a CLI for managing Firebase Remote Config based on YAML files.
https://github.com/jmatsu/remocon

iOSアプリのテストを書きたいのに書けないあなたへ
https://speakerdeck.com/imaizume/how-you-should-start-to-write-your-first-unit-test-for-ios

環境ごとにFirebaseプロジェクトを使い分ける方法 (@giiiita)
https://qiita.com/giiiita/items/be71c14a59f596bc4001

Tomohiro Imaizumi

June 18, 2019
Tweet

More Decks by Tomohiro Imaizumi

Other Decks in Programming

Transcript

  1. Firebase Remote Configの運⽤で
    知ったこと・知っておくと良いこと
    potatotips #62 @合同会社DMM

    View Slide

  2. 今泉 智博 (@imaizume)
    Androidユーザー歴8年のiOS開発者
    株式会社Diverse : Poiboy iOS開発
    株式会社UZUMAKI : 開発/SNS運⽤
    ⾃⼰紹介

    View Slide

  3. Firebase Remote Config概要
    • アプリ内ロジックを遠隔で切り替える
    • 対象はOSバージョンやパーセンテージ等で指定
    • Poiboyでは主にA/Bテスト時の振り分けに使⽤
    • 導⼊から半年で10回以上A/Bテストを実⾏

    View Slide

  4. 参考: Remote Configの導⼊⽅法 (Swift 4)
    * application(didFinishLaunchingWithOptions)内に以下を追加
    pod 'Firebase/Analytics'
    pod 'Firebase/RemoteConfig'
    Podfile
    FirebaseApp.configure()
    AppDelegate内
    * Podfileに追加
    * 取得したいフラグにデフォルト値を設定してから値を取得
    let remoteConfig = RemoteConfig.remoteConfig()
    let parameter = “sample_beta_feature"
    /// デフォルト値は取得不能時等に使われる
    remoteConfig.setDefaults([parameter: false as NSObject])
    /// 必要な型にキャストする
    let isBeta = remoteConfig[parameter].boolValue
    if isBeta { /* betaユーザーに対する処理 */ }
    使いたい場所

    View Slide

  5. 今⽇のTopics
    • enumでのパラメータ管理
    • パラメータのスタブ化
    • その他運⽤⾯の話など
    Remote Configを実装・運⽤した時に気づいたTIPS

    View Slide

  6. enumでのパラメータ管理

    View Slide

  7. 背景: パラメータを管理したい
    • パラメータはどんどん増える
    • A/Bテストなどの施策がたくさん⾛る
    • パラメータ管理はStringだときついのでenumに
    • デフォルトで利⽤可能なパラメータ型
    • String / NSNumber / Data / Bool

    View Slide

  8. パラメータを表すenumを定義
    enum BoolParameter {
    case beta_feature_A
    case beta_feature_B

    var defaultValue: Bool {
    switch self {
    case .beta_feature_A:
    return false

    }
    }
    }
    enum StringParameter { … }
    enum NumberParameter { … }
    パラメータ型ごとのenum
    型の種類に応じて
    定義が必要
    パラメータ名とデフォルト値を定義

    View Slide

  9. パラメータ値の取得処理
    FirebaseStore {
    func boolValue(for key: BoolParameter) -> Bool {
    let remoteConfig = RemoteConfig.remoteConfig()
    remoteConfig.setDefaults(key.defaultValue)
    return remoteConfig[key.rawValue].boolValue
    }
    func stringValue(for key: StringParameter) -> String? {
    let remoteConfig = RemoteConfig.remoteConfig()
    remoteConfig.setDefaults(key.defaultValue)
    return remoteConfig[key.rawValue].stringValue
    }
    }
    let store = FirebaseStore()
    let boolValue: Bool = store.boolValue(for: .beta_test_A)
    let stringValue: String? = store.stringValue(for: .beta_test_B)
    パラメータ値の取得処理
    補完やfind usageの機能も利⽤可能に
    取得⽤メソッドも
    型ごとに⽤意

    View Slide

  10. (アプリ側)パラメータ管理⽤OSS: Lobster
    • 管理周りの⾃前実装が不要に
    • 扱えるデータ型が拡張される
    (CollectionなどもOK!)
    https://github.com/sgr-ksmt/Lobster
    extension ConfigKeys {
    static let text
    = ConfigKey("text")
    }
    let text: String = Lobster.shared[.text]
    Lobsterでの実装
    使った⼈いたらぜひ話を聞きたいです❗

    View Slide

  11. (コンソール)パラメータ管理⽤OSS: remocon
    • YAMLにパラメータを定義
    • コマンドで更新
    • コンソールを触らないので
    安全に管理できそう
    • エンジニアだけが触る前提
    じゃないと難しい?
    https://github.com/jmatsu/remocon
    こちらも使った⼈いたら話を聞きたいです❗

    View Slide

  12. パラメータのスタブ化

    View Slide

  13. 背景: 依存注⼊したい
    • テスト等でA/Bを任意の値に指定したい
    • そこでパラメータをスタブできるようにしておく
    • リポジトリパターンと抽象への依存を活⽤
    (詳しくは過去に発表した資料もご覧ください)
    https://speakerdeck.com/imaizume/how-you-should-start-to-write-your-first-unit-test-for-ios

    View Slide

  14. 補⾜: 環境ごとに設定を分ける⽅法
    let options = FirebaseOptions(
    contentsOfFile: FirebaseConfig.resourceFilePath())!
    FirebaseApp.configure(options: options)
    AppDelegate内
    struct FirebaseConfig {
    static func resourceFilePath() -> String {
    #if DEBUG
    return Bundle.main.path(forResource:
    "GoogleService-development-Info", ofType: ".plist")!
    #else
    return Bundle.main.path(forResource:
    "GoogleService-Info", ofType: ".plist")!
    #endif
    }
    }
    Config
    参考: https://qiita.com/giiiita/items/be71c14a59f596bc4001
    QAやデバッグ⽤のパラメータを設定可能なので便利

    View Slide

  15. 抽象への依存を可能にするprotocolを定義
    /// Bool型のパラメータを返すStoreに要求されるインターフェイス
    protocol BoolStoreProtocol {
    func boolValue(for key: BoolParameter) -> Bool
    }
    /// String?型のパラメータを返すStoreに要求されるインターフェイス
    protocol StringStoreProtocol {
    func stringValue(for key: StringParameter) -> String?
    }
    StoreProtocol.swift
    Presenter StoreProtocol
    Store
    Stub
    Firebaseから
    取得した値
    任意の指定値
    true
    protocolで抽象化

    View Slide

  16. Remote Configの値を返すStore
    class FirebaseStore {}
    extension FirebaseStore: BoolStoreProtocol {
    func value(for key: BoolParameter) -> Bool {
    let remoteConfig = RemoteConfig.remoteConfig()
    remoteConfig.setDefaults(key.defaultValue)
    return remoteConfig[key.name].boolValue
    }
    }
    extension FirebaseStore: StringStoreProtocol {
    func value(for key: StringParameter) -> String? {
    let remoteConfig = RemoteConfig.remoteConfig()
    remoteConfig.setDefaults(key.defaultValue)
    return remoteConfig[key.name].stringValue
    }
    }
    FirebaseStore.swift
    Storeは型:class = n:1で定義

    View Slide

  17. 任意の値を返すStub
    // 任意のパラメータで任意の値を返すことも可能
    /// 常にfalseを返すスタブ
    class BoolStoreStub: BoolStoreProtocol {
    func boolValue(for key: BoolParameter) -> Bool {
    return false
    }
    }
    /// 常に"You are a beta user!"を返すスタブ
    class StringStoreStub: StringStoreProtocol {
    func stringValue(for key: StringParameter) -> String {
    return "You are a beta user!"
    }
    }
    StoreStub.swift
    Stubは型:class = 1:1で定義

    View Slide

  18. 呼び出し側
    let boolStore: BoolStoreProtocol = FirebaseStore()
    let realBoolValue = boolStore.value(for: .beta_test_A) // true or false
    let boolStub: BoolStoreProtocol = BoolStoreStub()
    let stubBoolValue = boolStub.value(for: .beta_test_A) // always true
    class SomePresenter {
    private let firebase: BoolStoreProtocol
    init(_ firebase: BoolStoreProtocol = FirebaseStore()) {
    self.firebase = firebase
    }

    }
    let realPresenter: SomePresenter = .init()
    let stubPresenter: SomePresenter = .init(boolStub)
    FirebaseRemoteConfigParameter.swift
    抽象への依存でStubとStoreを区別なく使⽤可能に

    View Slide

  19. その他運⽤⾯の話など

    View Slide

  20. QAの⽅のための実装
    • QA時にRemote Configの状態が知りたくなる
    • デバッグメニューに現在の値を表⽰してあげる
    QA担当者が分かりやすい表記で書こう✌

    View Slide

  21. A/Bテストのやり⽅
    • Poiboyでは…
    • ロジック切り替え: Firebase Remote Config
    • ログ送信: Treasure Data / Repro 等
    • Firebase A/B Testing
    • 2019年6⽉現在beta版
    • ⚠予めユーザープロパティを送る必要あり
    TreasureData.sendEvent(
    eventType: .someEvent,

    isBetaUser: firebase.value(forKey: .beta_user_A)
    )
    TreasureDataへのイベント送信
    ロジック切り替えとイベント収集は別ツールでもOK✂

    View Slide

  22. 運⽤ルールの明⽂化 / ワークフローへの組み込み
    ルール・ワークフローの例
    • パラメータ作成時
    • 対応が分かるようフラグ名と条件名は同じに
    • 説明欄に意図や施策を⼈間の⾔葉で書く
    • A/Bテスト終わってもパラメータが放置される問題
    • 毎スプリントで不要パラメータ消去タスクを積む
    • 事故防⽌のためQA項⽬に追加
    • AndroidとiOSでパラメータ分ける時
    • Androidは”a_”プレフィックスをつける
    他社さんの運⽤周りのノウハウもぜひ知りたいです

    View Slide

  23. まとめ
    ✓ パラメータはenumで管理
    ✓ 複雑な管理はライブラリを使おう
    ✓ 開発⽤と本番⽤でプロジェクトを分けよう
    ✓ スタブ化するとテスト時に便利
    ✓ 現在のパラメータをどこかに表⽰しよう
    ✓ フラグ管理とログ集計のツールは別でもOK
    ✓ 運⽤フローは早めに明⽂化
    懇親会でもぜひ話しましょう

    View Slide

  24. 参考リンク
    • Poiboy(ポイボーイ) 出会い探しマッチングアプリ
    https://poiboy.jp/
    • Firebase Remote Config (公式)
    https://firebase.google.com/docs/remote-config?hl=ja
    • Firebase Remote Config を使ってA/Bテストをやってみよう - PSYENCE:MEDIA
    https://tech.recruit-mp.co.jp/mobile/post-14940/
    • sgr-ksmt/Lobster - Type-safe Firebase-RemoteConfig helper library
    https://github.com/sgr-ksmt/Lobster
    • jmatsu/remocon - a CLI for managing Firebase Remote Config based on YAML files.
    https://github.com/jmatsu/remocon
    • iOSアプリのテストを書きたいのに書けないあなたへ
    https://speakerdeck.com/imaizume/how-you-should-start-to-write-your-first-unit-
    test-for-ios
    • 環境ごとにFirebaseプロジェクトを使い分ける⽅法 (@giiiita)
    https://qiita.com/giiiita/items/be71c14a59f596bc4001

    View Slide