Slide 1

Slide 1 text

アンケート集計システム をつくった Jumpei Takiyasu @juntaki M3, Inc. 2018-12-06 M3 Tech Meetup #5

Slide 2

Slide 2 text

name <- "Jumpei Takiyasu" company <- "M3, Inc." web <- "https://juntaki.com" Me

Slide 3

Slide 3 text

今日話すこと 1. エムスリーのアンケートシステム 2. 集計システムのデータ構造 3. 集計システムの要件 4. Go/GAEのアーキテクチャ 5. 要素技術

Slide 4

Slide 4 text

エムスリーの アンケートシステム

Slide 5

Slide 5 text

Webリサーチのビジネス オーダーメイドのアンケートでは、作成・集計ともに個別対応が必要

Slide 6

Slide 6 text

アンケート作成システム アンケートを「作る」プロセスは、柔軟性が高く効率的

Slide 7

Slide 7 text

集計システム   2018年10月リリース  

Slide 8

Slide 8 text

データ構造の整理

Slide 9

Slide 9 text

アンケート設問の種類 # 種類 アンケート用語でいうと 1 プルダウン SA (Single Answer) 2 ラジオ SA (Single Answer) 3 チェックボックス MA (Multiple Answer) 4 数値入力 数値回答 (FAの一種) 5 テキスト入力 FA (Free Answer) # 形式 1 単一設問 2 マトリクス設問 5 × 2 = 10通りのパターンがある! こんなかんじ

Slide 10

Slide 10 text

設問の種類…多すぎ…? Booleanマトリクスと、数値マトリクスだけと考えることができる # 種類 整理すると・・ 1 プルダウン Booleanの配列 2 ラジオ 3 チェックボックス 4 数値入力 数値の配列 5 テキスト入力 集計対象外(生データには必要) # 形式 1 単一設問 要素数1のマトリクス設問 2 マトリクス設問 ←

Slide 11

Slide 11 text

整理されたアンケートの生データ構造 深い階層構造になる アンケート 設問 マトリクス行 選択肢 回答 最終出力時以外いらない 回答数に比例して大きくなる 全部マトリクスにしたので、 階層の深さは一致する Q1 Q1__1_1 Q1__1 設問定義 回答 アンケート

Slide 12

Slide 12 text

整理された最終出力の集計データ構造 いくつかの集計表のカタマリが出力 全設問の集計表一覧 設問ごとの集計表群 集計表(合計、回答者数、割合・・) 集計軸ごとの集計値 集計対象の選択肢

Slide 13

Slide 13 text

集計ツールのInput/Output 集計 ツール アンケート 設問A マトリクス行 選択肢 回答 設問B マトリクス行 マトリクス行 選択肢 選択肢 選択肢 選択肢 選択肢 回答 回答 回答 回答 回答 回答 医師ごとの回答 回答 回答 回答 回答 回答 回答 回答 医師ごとの回答 回答 回答 回答 回答 回答 回答 回答 医師ごとの回答 true/false/数値 回答 回答 回答 回答 回答 回答 回答 医師ごとの回答 回答 回答 回答 回答 回答 回答 回答 医師ごとの回答 回答 回答 回答 回答 回答 回答 回答 医師ごとの回答 true/false/数値 Q1集計表(SA) Q2集計表(マトリクスSA) アンケートABC (集計軸:Q10, Q11, Q12) Q3 ….

Slide 14

Slide 14 text

要件の洗い出し

Slide 15

Slide 15 text

分析の作業は2フェーズに分割できる 加工:「設問 × 回答者のデータ」を編集する 集計:「集計値のデータ」を集計条件設定により計算する

Slide 16

Slide 16 text

「加工」で主にやりたいこと 新しい設問を計算によって作り出す アンケート 設問A マトリクス行 選択肢 回答 設問B マトリクス行 マトリクス行 選択肢 選択肢 選択肢 選択肢 選択肢 回答 回答 回答 回答 回答 回答 医師ごとの回答 回答 回答 回答 回答 回答 回答 回答 医師ごとの回答 回答 回答 回答 回答 回答 回答 回答 医師ごとの回答 true/false/数値 回答 回答 回答 回答 回答 回答 回答 医師ごとの回答 回答 回答 回答 回答 回答 回答 回答 医師ごとの回答 回答 回答 回答 回答 回答 回答 回答 医師ごとの回答 true/false/数値 設問Aと設問Bの合成 (単一設問として) Aの選択肢1を選んだ かつ Bの選択肢1を選んだ Aの選択肢2を選んだ かつ Bの選択肢3を選んだ 医師ごとの回答は ←から計算できる 医師ごとの回答は ←から計算できる 例: ● 男性かつ30代 ● 関東(東京、埼玉…) ● 患者数n人以上

Slide 17

Slide 17 text

「加工」の実現方針 ● 基本操作を網羅し、組み合わせによって複雑な操作を可能にする ● 頻出操作を関数化する(+ その基盤づくり) 論理演算 四則演算 MA選択数カウント SAの数値マッピング カテゴリ化 Boolean 数値

Slide 18

Slide 18 text

「集計」でやりたいこと 基本的には、クロス集計ができればOK 軸0個(=単純集計) 〜 軸3個の三重クロス集計まで対応 軸となる設問B 集計対象 の設問A 選択肢3 選択肢2 集計値 B-3を選んだ人の、A-2 の… ● 回答の合計値 ● 回答の平均 ● 回答者数 …などなど

Slide 19

Slide 19 text

「集計」のケースごとの要件と実現方法 設問の形式・内容によって、整理したい観点が異なる。たとえば・・ シェア計算をしたい   回答が、とある数を母数としたときに何%にあたるか   例:薬品の処方数/患者数、回答結果/回答者数 TOP-nを出したい   例:「そう思う」、「ややそう思う」の合計を知りたい → 集計表全体の設定と、表ごとの設定として整理

Slide 20

Slide 20 text

アーキテクチャ

Slide 21

Slide 21 text

システム構成 エムスリー初の Goプロダクト! (GAEも初) フロントエンドまで 型がある

Slide 22

Slide 22 text

データの流れ 加工 集計 アンケート 定義 計算式を追加 除外IDを設定 集計軸を設定 集計対象を設定 加工設定 集計設定 #2 集計設定 #1 アンケート システム アンケート 回答 アンケート 回答 計算結果 納品用集計表 Readonlyなので 元データは壊れない

Slide 23

Slide 23 text

Go API Architecture クリーンアーキテクチャ的な考え方で依存方向を厳密に決めた 実装変更の影響範囲が明確になる:  途中で、MySQL→Datastoreに移行した  →インターン生の課題として数日で実装完了 パッケージの循環参照はおきない 詳しくは、”Layered architecture Go API implementation”参照 http://s.juntaki.com/WtS

Slide 24

Slide 24 text

要素技術

Slide 25

Slide 25 text

「加工」はこんな感じになった 1つの選択肢を1変数として、DSLで数式をかけるようにした ※これはWebアプリの画面です

Slide 26

Slide 26 text

計算結果を透過的に変数として扱う 再帰的に値を取得して計算(循環参照は回数制限で回避) 設問定義 RawData RawDataへの参照 DSL 式 変数名からデータ構 造のひきあて 再帰的に値を取得し てDSLを計算

Slide 27

Slide 27 text

DSLの実装 - Knetic/govaluate 当初、文字列をGoとしてtypes.Eval()する方法を検討した →ファイルに書き出さずにメモリ上で関数の定義をするのは難しそう 独自でパーサまで実装しているKnetic/govaluateを利用 ● 四則演算、論理演算、関数定義はOK ● 変数もfloat64, boolがつかえる 関数は可変長のinterface{}しか受け取れない制限がある →Goで同等の関数を書いて、ラップする(型チェックは自前) バリデーションは ホワイトリスト的に やってます

Slide 28

Slide 28 text

「集計」はこんなかんじ Webでサクッとプレビューできて、Excelファイルとしてダウンロード

Slide 29

Slide 29 text

「集計」はこんなかんじ 表ごとの設定は個別入力できる

Slide 30

Slide 30 text

Excelの出力 - 360EntSecGroup-Skylar/excelize 薄くラップしてエムスリー仕様を実現: ● 色、幅、フォント、数字の書式など細かい指定がある(納品物なので) ● 内部むけのIDなどは、納品に入れたくないが、確認用に出したい、など

Slide 31

Slide 31 text

Golden file testing + データ自動生成 juntaki/fix https://github.com/juntaki/fix 前と変わってない、ということだけを確認するテスト。初回確認は画面でやる

Slide 32

Slide 32 text

Golden file testingを使ったテストの雰囲気 アンケートシステム バックエンドAPI go-vcr テスト対象: Application層 のハンドラ インテグレーションテ スト RequestのObjectは人手で作る 外部APIの Response YAMLファイル juntaki/fix.Fix() 集計システムAPI のResponse バイナリ/JSON ハンドラへのインプットを作るだけでテストが量産できます リグレッションテストとしてはコスパ高い! ※網羅性などをきちんと考えた、他のユニットテストとの併用がおすすめ

Slide 33

Slide 33 text

まとめ 設計・開発期間: 2018/4月 - 10月 GAEでインフラ構築はかんたん、序盤からデモしやすい TypeScript + protobuf + Goで一貫した型がある おすすめ構成です

Slide 34

Slide 34 text

Thank you! Jumpei Takiyasu @juntaki M3, Inc. https://juntaki.com