チュートリアル実装の『そこどうしてる?』 Poiboyではこうしてる!

チュートリアル実装の『そこどうしてる?』 Poiboyではこうしてる!

2018年9月28日に株式会社Diverseにて行われた「マッチングサービス開発の裏側Night」での登壇資料になります。
https://diverse.connpass.com/event/100488/

1a74617b91d2757b839b9cf3614648ce?s=128

Tomohiro Imaizumi

September 28, 2018
Tweet

Transcript

  1. チュートリアル実装の 『そこどうしてる?』 Poiboyではこうしてる! マッチングの裏側Night #1 2018/09/28 @imaizume

  2. <2 INDEX • 自己紹介 • Poiboyについて • Poiboyのチュートリアルと実装解説 1.男女で画面のViewController分けるか問題 2.実装をライブラリでやるか自前でやるか問題

    3.デバッグどう/どこまでやるか問題
  3. <3 INDEX • 自己紹介 • Poiboyについて • Poiboyのチュートリアルと実装解説 1.男女で画面のViewController分けるか問題 2.実装をライブラリでやるか自前でやるか問題

    3.デバッグどう/どこまでやるか問題
  4. ‣ 今泉 智博 @imaizume ‣ 2017年株式会社ミクシィ新卒入社 ‣ 現在株式会社 所属 ‣

    iOS利用経験0から iOS版開発担当に ‣ (ほぼ)毎日健康COMP生活はもうすぐ1周年
  5. <5 INDEX • 自己紹介 • Poiboyについて • Poiboyのチュートリアルと実装解説 1.男女で画面のViewController分けるか問題 2.実装をライブラリでやるか自前でやるか問題

    3.デバッグどう/どこまでやるか問題
  6. とは❓

  7. Diverseが運営する カジュアルマッチングアプリ❤

  8. 最⼤の特徴 = ⼥性主導 女性からの「いいね = ポイ」でマッチング成立 男性はポイされた後に初めて返信できる ねらい マッチングアプリを初めて使う女性にも 安心して使ってほしい

    ポイ メッセージ
  9. 今⽇の内容: Poiboyチュートリアルの実装⽅針 実装で直面する疑問・課題とPoiboyでの実装例を紹介 3つのテーマで実装の「そこどうしてるの?」を解説 ウォークスルー 登録前/登録後 チュートリアル プロフィール 登録 今日話すところ

    Poiboyのチュートリアル構成 SNS認証 登録前チュートリアル プロフィール登録 登録後チュートリアル ウォークスルー 本使用
  10. <10 INDEX • 自己紹介 • Poiboyについて • Poiboyのチュートリアルと実装解説 1.男女で画面のViewController分けるか問題 2.実装をライブラリでやるか自前でやるか問題

    3.デバッグどう/どこまでやるか問題
  11. テーマ1: チュートリアルの画⾯ (ViewController)を男⼥で分けるか問題

  12. 男⼥の画⾯どうやって分けてる?? • 男女でUI/ロジックが似ている画面をどうするか問題 • 男女ではなく登録経路で分かれることも… • プラットフォームで仕様が異なるケース(今回は割愛) ⽅針: A.共通化 /

    B.分離 Facebook (左) と Twitter (右) 男性 (左) と ⼥性 (右)
  13. A. なるべく共通化する • 男女/登録経路で共通のVCを使用 • 内部Viewの表示切替え • 共通化が有効そうな場所 • ログイン画面

    • プロフィール登録画面 • 見た目が似ているUI // 画像切り替え self.banner.image = isMale ? maleBannerImg : femaleBannerImg self.user.image = isMale ? maleUserImg : femaleUserImg self.example.image = isMale ? maleExampleImg : femaleExampleImg // 制約切り替え self.maleContraint.priority = isMale ? .defaultHigh : .defaultLow self.femaleContraint.priority = !isMale ? .defaultHigh : .defaultLow 男⼥共通のVC
  14. B. なるべく分離する // MARK: ViewController出し分け if isMale { // 男性

    let vc = MaleRegisterViewController() self.present(vc, animated: true) } else { // 女性 let vc = FemaleRegisterViewController() self.present(vc, animated: true) } • 男女/登録経路毎のVCを定義 • VC自体を表示制御 • 完全分離が有効そうな場所 • 性別に固有の体験 • Viewや状態数が多い • UIや仕様変更が見込まれる 男性VC ⼥性VC
  15. 共通化 VS 分離メリデメ A. 共通化 B. 分離 ✂ メリット •

    DRYな実装がしやすい • Viewの構築時間を短縮可 • ロジックの可読性が向上 • 画面単位の仕様変更に強い デメリット • VC内のロジックが複雑化 • コードでの状態変更 • UIのバグ発見・再現が困難 • WETな実装になることがある • ファイル数が増える • 同一変更でも複数箇所修正 場面毎に考えて方針を選んでも良いが 原則の方針は決めておきたい
  16. Poiboyではこうしている! VC内ロジックの簡素化を重視 (以前は共通化したVCで条件分岐が増え 男女間の表示バグが多発していた) VC単位で分離するケースが増加 self.view1.hidden = false if isMale

    { // 男性 self.view2.hidden = false self.view.text = " " } else { // 女性 self.view2.hidden = true self.view.text = " " if isOk { self.view3.height = 80 } } 男⼥共通VC self.view1.hidden = false self.view2.hidden = false self.view.text = " " 男性⽤VC self.view1.hidden = false self.view2.hidden = true self.view.text = " " if isOk { self.view3.height = 80 } ⼥性⽤VC
  17. UI上のバグの発⾒/再現性 片方に実装を忘れる → バグの発見・再現が容易 コードでの状態変更 → バグの発見・再現が困難 現在の課題: VCの名前に統一性がないため、新メンバーが把握に時間がかかる 画⾯遷移テストの書きやすさ

    /// 性別選択で女性を選択後に女性用ウォークスルー画面が表示される func testNavigationToFemaleWalkThrough() { let navigator = NavigatorMock() let isBetaUser = false let vc = GenderRegisterViewController( navigator: navigator, genderStore: GenderStoreStub(isFemale: true) ) ) vc.tapFemaleViewAction() XCTAssertTrue(navigator.viewControllerStack.first is FemaleWalkThroughViewController) }
  18. 具体例 (プロフィール登録画⾯) 男女共通に見えるが実は完全に別のVC • 画面上部のバナーパターンが増えても大丈夫だった • 前後のVCを増減しても影響が少なかった 男性登録画⾯ ⼥性登録画⾯ バナーが増えて

    もバグは出ない 女性側よりも 遅れて実装 制約の付け替え が不要に 細かい文言等の 違いも一目瞭然
  19. <19 INDEX • 自己紹介 • Poiboyについて • Poiboyのチュートリアルと実装解説 1.男女で画面のViewController分けるか問題 2.実装をライブラリでやるか自前でやるか問題

    3.デバッグどう/どこまでやるか問題
  20. テーマ2: チュートリアルの実装 ライブラリを使うか⾃前で頑張るか問題

  21. チュートリアル画⾯をどう作るか ?? • 登録後ユーザーが必ず表示する画面 • Poiboyではウォークスルーとコーチングの組合せ • 特にコーチングは自前実装そこそこ面倒 ウォークスルー コーチング

    ⽅針: A. ライブラリ / B. ⾃前
  22. チュートリアル⽤ライブラリ • ライブラリもかなり充実 (調べて初めて知った) • 複雑なウォークスルーはRazzleDazzleがよさそう • UIがテンプレベースのため既視感が強い • 比較/詳解はtakatattaさんのスライドもご参考に

    • ephread/Instructions • aleksandrshoshiashvili/ AwesomeSpotlightView • ruipfcosta/SwiftyWalkthrough • teodorpatras/EasyTipView • ariok/BWWalkthrough • hyperoslo/Presentation • ealeksandrov/EAIntroView • MatthewYork/MYBlurIntroductionView • IFTTT/RazzleDazzle ウォークスルー コーチマーク
  23. ライブラリ VS ⾃前メリデメ ライブラリへ完全依存したくないが完全自前も厳しい… A. ライブラリ B. 自前 メリット •

    導入・メンテの工数少ない • OS/端末ごとの動作保証あり • 複雑な仕様やUIにも対応可 • アクション制御も自在 デメリット • アプリへの最適化に限度 • テンプレ的なUI/UX • デザイン次第で工数大 • メンテコストも大
  24. Poiboyではこうしている! ライブラリ:自前 = 2:8 くらいのハイブリッド • ウォークスルー: 完全自前実装 • 仕様変更が多い

    • ボタン配置やUIも最適化したい • チュートリアル: 自前 + 一部吹出しにCMPopTipView • 指定の矩形をくり抜くカスタムViewで実装 • CMPopTipViewの吹出しを加えてコーチング • CMPopTipViewは画像等を含むことができない CMPopTipViewの吹き出し 画像の吹き出し
  25. 単純なコーチングの実装例 • コーチマークVCを定義、各ステップでpresent • UIBezierPathでマスクを切り抜き ベースのVC コーチングのVC チュートリアル var rects:

    [CGRect] = [self.rect1, self.rect2, self.rect3] self.setupMaskView(rects: &rects, isCircle: true) // 複数矩形の切り抜きにも対応できるよう配列で定義 let paths: [UIBezierPath] = rects.map { Helper.rectToSquarePath($0) } let maskLayer: CALayer = self.maskView.generateLayer(paths) self.maskView.layer.addSublayer(maskLayer) CGRect ↓ UIBezierPath この3つの合計で スコアが変動するよ タップして次へ self.present
  26. 複雑なコーチング (連続した動作制御) ステップ数少 →UIView.animateまたは Promiseをチェーン ステップ数多 →closureのスタックを用意 stack.popで実行する

  27. 複雑なコーチング (カードフリック) • チュートリアル用のViewにカードを重ねる • DataSourceから上2枚分のカードをコピーしDI • カードUIはカスタムView実装 • 動きも忠実で実際のデータなので使用感が出る

    DataSource CardView x2 CardContainerView view.animate self.showPopTip 上に重ねる アニメーション
  28. 本当はもっとこうしたい • VCの名称に一貫性がない(新人が覚えるの大変) • メンテ大変なので実装やステップを簡略化したい • 男女やプラットフォーム間の差をなくしたい • アニメーションを滑らかに (lottieの活用とか)

    • 現在CMPopTipViewはノーメンテ→EasyTipViewを推奨
  29. <29 INDEX • 自己紹介 • Poiboyについて • Poiboyのチュートリアルと実装解説 1.男女で画面のViewController分けるか問題 2.実装をライブラリでやるか自前でやるか問題

    3.デバッグどう/どこまでやるか問題
  30. テーマ3: デバッグどう/どこまでやるか問題

  31. チュートリアルのデバッグ⼤変問題 • 初日体験は大切なので重点的にデバッグしたい • でも全ての動作/表示のチェックは大変 • 特に登録条件(状態)が多いと大変 • (Poiboyは男女 x

    登録導線で4パターン) ⽅針: A.⾃動(UI/Unitテスト) VS B. ⼿動(Beta)
  32. Poiboyではこうしている! • XCUITestで登録完了までの一連スクショを自動撮影 • Firebase AuthのSMS認証にデバッグアカウントを作成 手動デバッグ中心だが作業負荷の軽減にチャレンジ中

  33. XCUITestでの起動から登録までのスクショ撮影 XCUITestのスクショ自動撮影を利用 • エンジニアが全ケースを網羅できず • QAまで表示崩れを把握不可 これまで 改善後 XCUITestでの Facebookログイン

    • 正常系の表示確認を簡略化 • 対象端末を絞り手動確認も継続
  34. Firebase Auth でSMS認証にデバッグ⽤ FacebookやTwitter認証はログインが面倒 • PoiboyではSMS認証に Firebase Authを使用 • 任意の電話/PIN番号を

    登録可能 • 最大10件まで登録可能 • なので番号を専有して も大丈夫 • 入力がかなり楽になる
  35. (おまけ) 電話番号の⾖知識 実在しないけど入力が簡単な電話番号は? 携帯電話番号の規格では “0X0-0000-XXXX”等の形式なら任意の番号で実在しない❗ 番号を追加する際はご注意を http://www.soumu.go.jp/main_sosiki/joho_tsusin/top/tel_number/number_shitei.html

  36. 本当はこうしたい • XCUITestが認証でコケる問題 • 他の正常系でのスクショ撮影 • XCUITestよりもFastlane? • レポートの定期的な書き出し •

    iOSSnapshotTestCaseで画像比較 できたらなお良し 性別選択で落ちた 認証が問題だった
  37. まとめ: Poiboyではこうしてる! テーマ1: チュートリアルの画面分け なるべくVC単位で分離しバグを減らしている! テーマ2: チュートリアルの実装どうやるか 自前実装メインで最適なUIを実装している! テーマ3: デバッグどう/どこまでやるか問題

    手動デバッグの負荷軽減にチャレンジ中!
  38. 参考資料 Poiboy iOS https://itunes.apple.com/jp/app/poiboy-ポイボーイ/id1028982003 導入画面を実装したよ @takattata https://speakerdeck.com/takattata/dao-ru-hua-mian-woshi-zhuang-sitayo 総務省|電気通信番号の利用・指定|電気通信番号指定状況 http://www.soumu.go.jp/main_sosiki/joho_tsusin/top/tel_number/ number_shitei.html