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.

条件式評価器の実装による管理ツールの抽象化

3,384 views

Published on

Go Conference 2017 Spring で発表したスライドです。

Published in: Technology
  • Be the first to comment

条件式評価器の実装による管理ツールの抽象化

  1. 1. 条件式評価器の実装による 管理ツールの抽象化 2017/03/25(土) @Go Conference 2017 Spring The Go gopher was designed by Renee French. The gopher stickers was made by Takuya Ueda. Licensed under the Creative Commons 3.0 Attributions license.
  2. 2. 自己紹介 メルカリ/ソウゾウ 上田拓也 twitter: @tenntenn ■ コミュニティ活動 Google Cloud Platform User Group (GCPUG) Tokyo Goビギナーズ golang.tokyo Go Conference ■ 業務 GAE/Goでメルカリアッテを作ってます GoやGCPコミュニティを盛り上げる仕事 Gopherを描く仕事(LINEスタンプ) 2
  3. 3. アッテ開発の技術 : Golang と Google App Engine
  4. 4. アジェンダ ■ 管理ツールの抽象化 ● 管理ツールとは? ● 管理ツールを抽象化するとは? ● バナーツールにおける抽象化 ● デモ ■ 抽象化の実現 ● 条件式評価器 ● UIの自動生成 ■ まとめ 4
  5. 5. 管理ツールの抽象化 5
  6. 6. 管理ツール 6 ■ 各社呼び名が違う ● CSツール/バナーツール ● CS/オペツール ● CMS ● OPEツール ● 管理画面 ■ 要するに何をするツールか? ● サービスのコンテンツなどを管理 ● ユーザデータなどを閲覧
  7. 7. 管理ツールを抽象化するとは? ■ 「抽象化」 = 汎用的に使えるようにする ● 複数のプロジェクトで使える ● 複数の用途で使える ■ 抽象化することのメリットは? ● 開発/運用の工数が少なくて済む ● 使い方を覚える必要がない ■ 抽象化は難易度が高い ● 何を汎用的にすればいいのか? ● 使いづらいツールにならないか? ● 設計ミスで余計に工数がかかる 7
  8. 8. 具体例から抽象化を考える −バナーツール ■ バナーツール ● モバイルアプリにバナーを配信する ● バナーの管理や配信条件を設定する 8
  9. 9. デモ 9 YouTubeで見る
  10. 10. 抽象化できるポイント1 ■ コアな機能を抽象化(汎用化)する ● 配信条件を式で書けるようにする ○ String(os) == "ios" など ● 設定できるレスポンスを自由にする 10 アプリ バナーツール バナー取得 OS, APIバージョン などの変数 条件に当てはまるバナー 画像URL, 遷移先URL 条件式とレスポンス を設定する
  11. 11. 抽象化できるポイント2 ■ UIを抽象化する ● データからUIを自動生成する ○ 条件式を構築するUIを保存された条件から作る ○ レスポンスの設定を行うUIを対象サービス(アプリ) ごとにスキーマを設定し、自動生成する 11 String(os) == Enum(__os, "0,1", "iOS,Android") os: iOS ▼ Android UIを生成する部分リクエストから もらう部分 条件式から作る例 String(os) == "1" UIで選んだ値で展開※一部簡略化している
  12. 12. 抽象化の実現 12
  13. 13. 条件式評価器の実装 13 ■ goパッケージを用いて式の評価器を作る ● go/parserパッケージで式のASTを取得 ● ASTを再帰的に評価していく ■ 定数評価器をうまく使う ● go/constantパッケージを使う ● constant.Valueに変換する == "A" "B" BinaryExpr BasicLit "A" == "B" false パース 定数評価 参考:goパッケージで簡単に静的解析して世界を広げよう
  14. 14. 定数評価器の利用 ■ go/constantパッケージ ● 定数同士の演算ができる 14 func BinaryOp(x Value,op token.Token,y Value) Value 例:二項演算 constant.Valueに変換できれば、 簡単に演算をやってくれる
  15. 15. 型付き変数の実装 ■ 式の中で型を表す ● 関数呼び出しを変数として扱う ● 大文字で始まる関数呼び出しのみ ● 引数は識別子のみでそれを変数名とする ■ 変数を評価する ● 式の評価時には値が決まっている ● 評価器から見ると名前付きの定数に近い ● constant.Valueにして評価 15 Int(n) == 10 型 変数名
  16. 16. 関数の実現 ■ 関数を使えるようにする ● 小文字から始まる関数呼び出しを対象 ● 引数は任意の式 ● オリジナルの組込み関数のみ使用できる ○ cond, until, hours, days,... ■ 関数呼び出しを評価する ● const.Valueを引数と戻り値に取る関数 ● reflect.MakeFuncの思想と似ている ● 関数呼び出しごとにスコープを作る ○ 別の式を呼び出すcond関数のため 16
  17. 17. 関数の例 ■ 引数と戻り値をconstant.Valueにする 17 func add(args []constant.Value) []constant.Value { x, _ := strconv.ParseInt(args[0].String(),10,64) y, _ := strconv.ParseInt(args[1].String(),10,64) return []constant.Value{ constant.MakeInt64(x + y), } } ※スペースの都合上、エラー処理は省いてある type Func interface { Do(args []constant.Value) []constant.Value } 例:足し算
  18. 18. 条件式を保存して呼び出す ■ cond関数 ● よく使う式をDBに保存しておける ● cond関数を使って呼び出せる ● 呼び出し時に変数に値を束縛できる 18 String(os) == Enum(__os, "0,1", "iOS,Android") 保存された式 (id:1) cond(1,"__os=1") 呼び出す式 列挙型の変数 変数の値 呼び出す式のID String(os) == "1" 展開した式
  19. 19. JSON SchemaとUIの自動生成 ■ JSON Editor ● JSON SchemaからWeb UIを作る ● 保存されたデータからJSON Schemaを自動 生成してやればよい 19 ※画像はJSON Editorのリポジトリより
  20. 20. 条件式からUIを自動生成する ■ 保存された式を組み合わせる ● __で始まる変数をUIで設定する ● UIで設定した変数を束縛する形でcond関数 を用い、バナーの条件式とする 20 String(os) == Enum(__os, "0,1", "iOS,Android") os: iOS ▼ Android 保存された式 (id:1) cond(1,"__os=1")JSON Schema バナーに設定される式 作業者は保存された条件を ANDやORで組み合わせるだけで済む UIが生成される 選んだ値を設定する
  21. 21. その他の機能 ■ バリデーション ● 型情報を用いたバリデーション ○ 型情報からJSON Schemaが作れる ● ゼロ値を用いたバリデーション ○ 式が真偽値になるかどうか判定できる ■ あいまい検索 ● 変数を一部だけ与えて式を評価できる ● condをすべて展開し、使われていない変数 を含むASTのノードを枝刈りしていく 21
  22. 22. 抽象化した恩恵 ■ バナー以外の管理でも使える ● 期間/優先度/条件を持つ情報を管理でき る ● ゲームのマスタ管理 ○ イベント、ショップ など ● 運営からのお知らせ 22 1プロジェクトで4箇所くらい 使おうとしている例も!
  23. 23. まとめ ■ 管理ツールの抽象化 ● コア機能を汎用的に作る ● UIを自動生成する ● 特定のサービスに依存するものはデータとし て持つ ■ 抽象化の実現 ● goパッケージを使う ● JSON Schemaを使ってUIを自動生成 23
  24. 24. golang.tokyo ☓ GCPUG 24 4月27日(木)開催予定@メルカリ LT発表者募集中! https://golangtokyo.connpass.com/event/53209/
  25. 25. Thank you! twitter: @tenntenn Qiita: tenntenn connpass: tenntenn 25
  26. 26. 26 補足
  27. 27. 型をバリデーションに利用する ■ バリデーションを行う ● JSON Schemaを使えばJSONがスキーマを 満たしているかチェックできる ● 変数に型を導入することで、型情報を基にス キーマを定義できる ● 型に沿ったバリデーションができる ■ オリジナル型を作る ● 組込み型としてオリジナルの型を作れる ○ URL, IntRange など ● バリデーションも行える 27
  28. 28. ゼロ値をバリデーションに利用する ■ 式を評価すると真偽値になるか判定する ● 条件式中に変数があると評価できない ● 変数にはゼロ値がある ● 変数にゼロ値を設定してみて評価する ○ 評価結果が真偽値になればOK 28 Int(n) == 10 0 == 10 false Int(n) + 10 0 + 10 10 例1 例2
  29. 29. ASTの操作とあいまい検索 ■ 条件式を検索する ● 変数の一部を与えて検索する ● condを展開する必要がある ● 与えられなかった変数を使っている部分を無 視して評価する 29 && == == v1 1 v22 v1が与えられた場合 && == true v1 1 &&か||がくるまで 上にのぼる &&ならtrue ||ならfalseに置き換える
  30. 30. テスト配信条件に条件式を応用する ■ 汎用的に作って再利用する ● QA用に特定のユーザにだけ配信したい ● アプリ毎に条件が違う ○ ユーザID、IP など ● テスト配信にも条件式評価器がそのままつ かえる ● UIもスキーマから生成できる 30 テスト配信状態になっていて、 テスト配信条件に当てはまる リクエストのみテスト用バナーが配信される
  31. 31. 抽象化できるポイント3 ■ マルチテナント型にする ● UIはデータから自動生成される ○ サービスごとに適したUIが作られる ● データベースをサービスごとに分ける ● エントリポイントによってデータベースを切り 替える 31 簡単に複数サービス(アプリ) に対応できる!
  32. 32. マルチテナント型にする ■ 1ソースで複数のアプリに提供する ● Google App Engine のNamesace APIを使 う ● DBの名前空間をアプリごとに分ける ● ホスト名ごとに名前空間を作る 32 詳しくは 「Namespace API を用いたマルチテナント型 Web アプリの実践」 という資料で!

×