Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

如何に “データが壊れない” 管理画面を作るか - 管理画面開発の裏側

2,688 views

Published on

JJUG CCC 2018 Spring
http://www.java-users.jp/ccc2018spring/#/session/d0f5a2c8-0186-4bf2-a0fd-f6e4ec1fa9a2

#jjug_ccc #ccc_a5

Published in: Engineering
  • Be the first to comment

如何に “データが壊れない” 管理画面を作るか - 管理画面開発の裏側

  1. 1. 如何に“データが壊れ ない” 管理画面を作る か kjim @ JJUG CCC 2018 Spring 2018/05/26
  2. 2. Who I am: ● 村石 恵示 (Keiji Muraishi / @kjim) ● Software Engineer, Ads ● 2014/09 SmartNews 入社 ● 変遷 ○ SIer 1.5 years ○ TowersQuest 2.0 years ○ Freelance 3.5 years ○ IIJ 2.0 years ○ SmartNews 3.8 years (now!)
  3. 3. http://about.smartnews.com/ja/2018/05/10/20180510/
  4. 4. Agenda: ● SmartNews Ads の紹介 ● SmartNews Ads システム外観 ● Ad Frontend ● データにまつわる話 ● Productivity を保つ実装への落とし方
  5. 5. Agenda: ● SmartNews Ads の紹介 ● SmartNews Ads システム外観 ● Ad Frontend ● データにまつわる話 ● Productivity を保つ実装への落とし方
  6. 6. Sma w A s from 2014/12
  7. 7. Sma w A s http://static.smartnews.com/smartnews-ads/key_mediaguide_smartnews.pdf
  8. 8. SmartNews Ads テクノロジーの力で「Ads as Content」の実現を 目指す広告プラットフォーム
  9. 9. Sma w A s こんなことができます: ● SmartNews アプリへの広告配信 ○ 運用型 / 純広型 ● ターゲティング ○ ユーザー属性によって広告配信先をコントロールする ● 入札価格の自動調整 - oCPC ○ ユーザに合わせてアルゴリズムが入札価格を自動的に最適化し、効果的 に広告を配信 (https://markezine.jp/article/detail/26204)
  10. 10. Sy em O v e Agenda: ● SmartNews Ads の紹介 ● SmartNews Ads システム外観 ● Ad Frontend ● データにまつわる話 ● Productivity を保つ実装への落とし方
  11. 11. Sy em O v e 端折って単純化したりしてますが、大体こんな感じです Ad Server Ad DMP Ad Frontend
  12. 12. 今日、お話すること
  13. 13. Ad Frontend SmartNews Ads の機能にアクセスするための広 告管理コンソール
  14. 14. Add full width photo/video here! Cover up this placeholder with an image that touches the right/left sides and colored top bar Ad F o t いい感じのスクショを貼る Ad Frontend - 広告管理コンソール
  15. 15. といっても、 今日は画面の話というより もデータに着目した話をし ます。
  16. 16. Ad F o t Ad Frontend: ● 広告の出稿にまつわるあらゆる機能にアクセ スするための広告管理コンソール ● 画面だけでなく、広告代理店向けの API も 持っている ● SmartNews Ads システムの Hub 役 ○ ユーザーとシステムの Hub として ○ コンポーネント間の Hub として
  17. 17. Ad F o t 汚すのは一点: ● 広告配信プラットフォームは多様なコンポーネ ントで構成されている ○ AdServer, DMP, Tracking, AdFrontend, etc… ● 必然的にコンポーネント間の接続点が発生す る ○ どのコンポーネントがどこに接続するべきかという問題が生じる ● SmartNews Ads では、汚れ役を立ててそれ以 外を clean に保つという設計をしている 汚れ役としての Ad Frontend
  18. 18. Ad F o t 汚れ役としての二つの役割: ● サブコンポーンエント間の接続点の仲介 ○ 管理画面は多様なコンポーネントの機能を利用して「統合されたコ ントローラ」として機能する ○ 管理画面はそもそも多くのコンポーネントに接続する必要がある ● データを利用しやすい形で正確に保つ ○ データの入力側で正確なデータが担保されていれば、そのデータ の利用側は不必要な例外条件を考えなくて良くなる ○ データの利用側は、ある機能が “機能する” ための最低限の validation だけを意識すれば良い
  19. 19. Ad F o t 1. コンポーネント間の仲介: ● 接続点が増えるとメンテコストはどうしても上が る ○ システム全体としての変更耐性が下がる ○ 変更耐性が下がるとプロダクトの productivity に影響する ○ 接続点には必ず制約(仕様)が存在し、その一つの制約を複数のコンポー ネントが把握するというのはコストが高い作業である ● SmartNews Ads では、基本、直接の依存コン ポーネントを極力減らすという判断で作ってる
  20. 20. Ad F o t Mesh or Line? Mesh Line Ad Server Ad Frontend DMP Ad Server Ad Frontend DMP ● Ad Server と DMP は直 接の依存関係を作らない ● 両者の制約を吸収すること によって互いの進化のス ピードを落とさない ● Hub があることで、例え ば、機能実装の世代交代に 柔軟に対応できる
  21. 21. Agenda: ● SmartNews Ads の紹介 ● SmartNews Ads システム外観 ● Ad Frontend ● データにまつわる話 ● Productivity を保つ実装への落とし方
  22. 22. The Data SmartNews Ads における データにまつわる話
  23. 23. The データは誰が決める? ● SmartNews Ads の場合、”広告配信” に最適 なデータ構造は何か? が出発点 ○ AdServer が出発点 ● 管理画面の開発は、その設計を Follow する 形で始まった ここで問題が生じる
  24. 24. The 解く問題が異なる: ● Ad Server 大量の広告リクエストを、どのようにして効果を 最大化しつつ高速に捌くか ● Ad Frontend 広告データを、どのように直感的かつ平易な UI で正しく作れるようにするか 広告出稿までの業務フローの中でシステムを どのように介在させるか
  25. 25. 解くべき問題が異なれば必要 になるデータも異なる
  26. 26. example 1 “審査ステータス” と “有効フラグ”
  27. 27. 審査ステータス: The ● 広告の審査状態を管理する ● 審査OKの広告のみ配信できる ● 審査ステータスは広告審査の業務ルールに よって状態管理される ○ 審査業務に依存するデータである ○ この業務ルールは広告主や審査オペレータのためのものであり、 配信にも影響すべきデータである ○ 業務ルールは変更されうるデータである
  28. 28. The 審査ステータス: ステータス 配信可否 未審査 × 審査待ち × 審査OK ◯ 審査NG ×
  29. 29. 審査ステータス: Ad Server The ● 広告の審査状態を管理する ● 審査OKの広告のみ配信できる ● 審査ステータスは広告審査の業務ルールに よって状態管理される ○ 審査業務に依存するデータである ○ この業務ルールは広告主や審査オペレータのためのものであり、本質的 には配信に影響するデータである ○ 業務ルールは変更されうるデータである
  30. 30. Ad Server を変更されうる データに依存させることに なる
  31. 31. The “有効フラグ” の登場: ● Ad Server からは審査のビジネスルールに依 存したデータ参照を失くしたい ○ それによって、審査業務の変更耐性を上げることができる ● 審査ステータスに従属し管理される “有効フラ グ” を作って、Ad Server はこれに依存させる ○ Ad Server は単に ON か OFF を見れば良くなり、その背後にあるビジネ スから切り離すことができる ● “審査ステータス” と “有効フラグ” のデータは Ad Frontend が責任を持つ
  32. 32. 依存性を閉じ込めて 全体としての複雑性を 下げる
  33. 33. example 2 ユーザー定義オーディエンス (aka. Custom Audience)
  34. 34. The Custom Audience とは? “広告主が有するさまざまなユーザー情報を活用 し、SmartNews Adsにおいてターゲットとする ユーザーの条件を自在に組み合わせることがで きる機能” http://about.smartnews.com/ja/2016/03/07/20160307customaudience/
  35. 35. The 例えば: ● A という商品ページを閲覧したことのあ るユーザーにだけ広告を配信したい ● B というアプリを既にダウンロードした ユーザーは除外して広告を配信したい
  36. 36. The アーキテクチャ: ● Tracker ○ 外部 Signal(Event) を集める ● Ad Frontend ○ ユーザー定義オーディエンスを定義する ● Ad DMP ○ ユーザー定義オーディエンスと Tracker の Signal か らオーディエンスの実体を計算する ● Ad Server ○ オーディエンスの実体を利用して広告を配信する
  37. 37. The データの性格に着目: ● イベントソースが多様である ○ 過去に広告配信したことのある... A の Page にアクセスしたことのある... B というアプリをインストールしたことのある... etc… ● “自在に組み合わせる” ○ オーディエンス定義に Composability が要求される ● データ仕様が拡張される RDB のテーブル定義に マッピングするのは適さない類のデータ
  38. 38. Document Format: The ● Database には Document 形式 (JSON) で持 つようにすることによって動的性と拡張性を柔 軟に担保できるようにする ● もちろん、この判断はタダではなく、データ定義 の複雑性と正確性をきちんとコントロールする 必要が生じる ● そもそも、誰がデータを定義するかという問題 もある (Database は単なる箱と化すので)
  39. 39. The Productivity を優先する: ● 僕らのようなスタートアップにとってスピードは 非常に大事 ● 完璧を求める時間は無駄であり、割り切りとい う判断が必要 ● Document 形式を定義するのは DMP ○ そのデータの本質的なユーザーである ○ Ad Frontend はそのデータを Follow する関係
  40. 40. “Done is better than Perfect”
  41. 41. The 対処すべき問題: ● 拡張性を犠牲にしない ○ 足が遅くなってしまっては、なぜこのデータ形式を選択したのか分からなく なってしまう ● データの互換性には十分気を付けなければい けない ○ 拡張性の高さによって、新たに実装される Custom Audience 定義が発 生した時に、操作できなくとも壊れない状態にする必要性がある ● データを守るのは Ad Frontend の至上命題
  42. 42. Ad Frontend The 実装戦略: 中間モデルを作る Business Logic Ad DMPAurora SerDeLib (partofAdDMP) Converter 1. データベースの Raw データを Ad DMP の SerDe Lib を使って変換 2. [1] の結果を Ad Frontend の SerDe 実装を使っ て都合の良い中間モデルに変換 3. 画面との API はこの中間モデルを利用する
  43. 43. The 実装戦略: ● 中間モデルとRawモデルの相互変換実装は特 にしっかりとテストを書く ● エラーハンドリング処理をこの一点に集約する ○ 仮に、Ad Frontend が未知のデータを受け取ったとしても想定内エラーと して扱うようにする ● 仮に未知のデータを受け取ったとしても、その データへの操作をできなくして、データが不正 状態で更新されることを防ぐ
  44. 44. Agenda: ● SmartNews Ads の紹介 ● SmartNews Ads システム外観 ● Ad Frontend ● データにまつわる話 ● Productivity を保つ実装への落とし方
  45. 45. 機動性と安全性を 両立する 実装への落とし方
  46. 46. 原則 低レイヤーに行く程にルールをより強く強制する ことができる “蛇口よりも元栓”
  47. 47. Lay Ar it re Frontend (client) Layers: Controller Service Repository Datastore 右に行く程にデータに対するルールの 強制力は強くなる
  48. 48. Lay Ar it re Trade off: (LEFT) Front-side Store-side (RIGHT) Pros: ● (開発初期において) Productivity を高く保つこ とができる Pros: ● あらゆるデータ処理で制約 違反しないように考慮して実 装しなければいけない ● データを保全することが本質 的に難しくなる Pros: ● 強制力の強い制約条件を課 すことができる Pros: ● 拡張性と柔軟性 (Productivity) が 犠牲になる
  49. 49. Lay Ar it re Frontend (client) Layers: Controller Service Repository Datastore この図でもう一つ 言えることがあります
  50. 50. Lay Ar it re Frontend (client) Layers: Controller Service Repository Datastore 右に行く程にパフォーマンスチューニン グの余地が拡がる
  51. 51. Lay Ar it re Frontend (client) Layers: Ad Frontend の場合 Controller Service Repository Datastore Datastore の手前にデータ制約の 最終防衛ラインを敷く Repository ↓ Resource
  52. 52. Lay Ar it re 最終防衛ライン: ● Productivity を保ちつつ ● おかしなデータが渡された場合 ○ 更新せずに無視する ○ 例外状態にする といった挙動を実装することによって、デー タが保全されるようにコントロールすること ができる
  53. 53. Lay Ar it re 最終防衛ライン: ● Datastore に近い場所に防衛ラインを引くこと で、より Primitive なデータ管理が可能になる ● 一度に多くのことを考える必要がなくなる 制約ロジックの実装がシンプルになる
  54. 54. Lay Ar it re データ操作の3要素: ● Model ○ データモデル ● Resource ○ データモデルを Datastore に対して操作 するための API を提供 ● Query ○ データ操作の実装を提供
  55. 55. Resource Layer QueryQuery Lay Ar it re Resource Layer: ResourceService Query SQL ORM API Call Datastore (Database) External Component
  56. 56. Resource Layer データ操作の抽象度を保ちつつ、 そうしたくなったら 低レベルな実装にもすることができる
  57. 57. Lay Ar it re Resource ONLY: trait FooResource { def get(id: ID): Seq[Foo] def update(id: ID, foo: Foo): Int } ● Resource の api call のタイミングが操作の 実行タイミングと同期されてしまう ● 仮に update に特別なモードで処理させたい 場合、引数を追加するか、新たにメソッドを生 やすしかない
  58. 58. Resource だけでは 柔軟な API を表現 できない
  59. 59. Query データの集合を表すインタフェース表現で クエリの実行結果を抽象化して遅延実行や その他の表現力と拡張性を追加する
  60. 60. Lay Ar it re 二つの Query 定義: // for refer trait Query[T] extends Iterable[T] { def iterator(): Iterator[T] } // for update trait UpdateQuery[T] { def apply(): Query[T] }
  61. 61. Resource + Query
  62. 62. Lay Ar it re Resource meets Query: trait FooResource { def get(id: ID): Query[Foo] } ● Resource の api call のタイミングとクエリ実 行は切り離される
  63. 63. Lay Ar it re Resource meets Query: trait ExUpdateFooQuery extends UpdateQuery[ID] { def withSpecialSomething(): ExUpdateQuery } trait FooResource { def update(id: ID, foo: Foo): ExUpdateFooQuery } ● UpdateQuery で不十分なら互換性を保ちつ つ追加の API を生やす表現力が加わる
  64. 64. Lay Ar it re Resource + Query: ● 実体が欲しい時にはいつでも要求できる ● Query 取得後、実体が必要なければ余計なク エリ実行のコストを省くこともできる ● Query の結果を memory 上に cache した Query を返すこともできる ○ そして Interface は何も変わらないので同じように扱うことができる ● Query 自体を拡張した独自の Query を定義 すれば独自の API を生やすこともできる
  65. 65. Lay Ar it re Resource meets Query: trait FooQuery extends Query[Foo] { def partialize(): FooQuery } trait FooResource { def get(id: ID): FooQuery } // usage resource.get(“3838”).partialize()
  66. 66. Query データの集合を表すインタフェース表現で クエリの実行結果を抽象化して遅延実行や その他の表現力と拡張性を追加する API 表現に柔軟性と拡張性を持たせつつ、 統一的なインタフェースを提供する
  67. 67. Conclusion Con s o ● SmartNews Ads のシステム全体と Hub としての Ad Frontend ● データを利用するコンポーネントの依存関係を 適切にコントロールし、不用意に依存関係を増 やさない ● 機動性と安全性を両立する実装としての Resource + Query
  68. 68. Thank you! https://bit.ly/sn-eng-jobs

×