SlideShare une entreprise Scribd logo
1  sur  39
Télécharger pour lire hors ligne
RefinementsとExtendsを活用した
Explore構築
~JOINを跨いだフィールドを
 すっきり実装しよう〜
2021. 12. 09
Mirrativ, Inc. 
Chikako Hirayama
© 2021 Mirrativ, Inc. 1
今日のアジェンダ
1. ミラティブ・スピーカーの紹介
2. Lookerを導入した経緯
3. ExtendsとRefinementsの活用事例
▲ミラティブの公式マスコット・
 ミラビット
2
3
「採用候補者さまへの手紙
」より
4
「採用候補者さまへの手紙
」より
5
「採用候補者さまへの手紙
」より
6
「採用候補者さまへの手紙
」より
7
「採用候補者さまへの手紙
」より
スピーカーの紹介
❏ 分析部所属のデータアナリスト
❏ 経歴
❏ 2018年3月 東京大学経済学研究科
マネジメント専攻修士課程修了
❏ Consumer Generated Mediaの定量分析
❏ 2018年4月 株式会社コロプラ入社
❏ バーチャルYouTuberやそのイベントの運営
❏ 2020年1月 株式会社ミラティブ入社
❏ データアナリスト
❖ 平山 智香子 Chikako Hirayama
▲ミラティブでまいにち配信して
います。ギフトを贈ったり贈られ
たりして集めたエモモ(アバター)
8
ミラティブの分析組織
❖ プロジェクトごとにアナリストがアサインされている
エモモ
(アバター)
PdM
エンジニア デザイナー アナリスト
プラットフォーム改
善
PdM
エンジニア デザイナー アナリスト
BizDev
PdM
エンジニア デザイナー アナリスト
PdMと二人三脚です!
▲対談記事
9
Lookerを導入した経緯
❏ 以前はRedashでクエリを管理
❖ KPIの定義など、データガバナンスを強化するため
クエリごとにKPIの定義がバラバラ
❏ NUUの定義方法
❏ 顧客に報告するKPI
クエリのアップデートをファイルの
フォークで管理
❏ 誤って以前のバージョンを使うなどのミ
スも
作ったクエリが散逸する
❏ 管理方法が検索のみ
❏ 検索性能も微妙
KPIの定義をLookMLで統一
GitHubでバージョン管理
Look・Dashboardはフォルダで管理
(検索性能も高い)
基本的なデータ抽出はPdMが自力でできるように
→アナリストがより高度な分析に特化
副産物
10
Looker導入のスケジュール
❖ 顧客(ゲーム会社さま)用レポートの運用から開始、
徐々にエクスプローラを構築
Rapid Deployment
Redashからの
移行期間
完全移行
PoC ・・・
・Redashで使用している機 能
が同様に使えるかを確認 
・Slack連携
 ・アラート
・顧客用レポートのために 必
要なExploreから実装
・サポートを受け易いうち
 に難しめの技術にトライ
 ・LookerAPI
 ・Lookerbot
・各チームで業務に使用
 するダッシュボードを
 移行
・PMにヒアリング
 Exploreも構築
・各プロジェクト毎に
 必要時に追加開発
ベーシックなダッシュボード移行から始める会社さんが多いと思いますが、
導入目的として優先順位の高かった 顧客用レポートの運用から進めました
2021/1 2021/3 2021/6
2020/2
11
Looker導入のスケジュール
❖ 平山が業務に必要な最低限を構築、他メンバーに伝達
Rapid Deployment
Redashからの
移行期間
完全移行
PoC
2021/1 2021/3 2021/6
2020/2
業務時間比率(Looker:他)
7:3 10:0 8:2 3:7
他 0:10 0:10 7:3 2:8
先に学習
○: 一人で設計を決めたので設計思想が統一できた
PRレビューは
平山
PRレビュー
相互に
×: 他のアナリストメンバーが本格的に触り始めたのがRapid Deploymentの終了後だった
 →他メンバーとLookerスキルレベルを揃えるのが大変だった……
 →フルリモートでは埒が明かなかったので、出社合宿を2〜3回やって解決
・・・
12
ミラティブのLooker環境の構成
❖ BigQueryの構成と対応するようにフォルダで管理
Project α
Dataset 1
Table A
Table B
Dataset 2
Table C
Project α
explores
Dataset 1.explore
views
Dataset 1
Table A.view
Dataset 2.explore
Table B.view
Dataset 2
Table C.view
13
プロジェクトにつき
10数個
データセットにつき
数10〜数100個
普段使うのは1個
ミラティブのLooker環境の構成
❖ 派生テーブルは元Viewと同じフォルダ下に
Project α
explores
views
Dataset 1
Table A.view
Table B.view
Dataset 2
Table A
Table A derived.view
14
本題です
みなさん、
こんな経験ありませんか?
15
Extendsを使いたい場面の前提
view: orders {
dimension: id {
type: number
sql: ${TABLE}.id;;
}
dimension: item_id {
type: number
sql: ${TABLE}.item_id;;
}
dimension: coins {
type: number
sql: ${TABLE}.coins;;
}
}
explore: orders {
label: "注文履歴"
}
❖ あるECサイトで商品の注文履歴のテーブルordersがあるとします
16
id item_id coins
1 101 100
2 102 200
3 101 500
4 103 1,000
orders
Extendsを使いたい場面の前提
view: orders {
#中略
dimension: sum_coins {
type: number
sql: ${TABLE}.coins;;
}
measure: coins {
type: sum
sql: ${coins};;
}
}
explore: orders {
label: "注文履歴"
}
❖ 売上の合計は、coinsのsumのメジャーで取得できます
17
orders
sum_coins
1,800
id item_id coins
1 101 100
2 102 200
3 101 500
4 103 1,000
Extendsを使いたい場面の前提
❖ 商品マスタitemsをJOINして、カテゴリー1の売上(1,600)を求めたいです
18
orders
id item_id coins
1 101 100
2 102 200
3 101 500
4 103 1,000
id category
101 1
102 2
103 1
items
id item_id coins category
1 101 100 1
2 102 200 2
3 101 500 1
4 103 1,000 1
JOIN
Extendsを使いたい場面〜JOINを跨いだフィールド〜
view: orders {
#中略
dimension: coins {
type: number
sql: ${TABLE}.coins;;
}
measure: sum_cat1_coins {
label: "カテゴリー1の総売上"
type: sum
sql: ${coins} ;;
filters: [items.category: "1"]
}
}
explore: orders {
label: "注文履歴"
join: items {
type: left_outer
relationship: many_to_one
sql_on: ${orders.item_id} = ${items.id};;
}
}
❖ ordersに「カテゴリー1の総売上」を追加する場合、
下記のようにitemsのcategoryを参照するのが簡単です
参照
orders
sum_cat1_coins
items
JOIN
19
しかし!
この作り方には
問題が!!!
JOINを跨いだフィールドの問題点
❖ ordersを他のExplore(ユーザー情報)にJOINするとエラーになります
explore: users {
label: "ユーザー"
join: orders {
type: left_outer
relationship: one_to_many
sql_on: ${users.id} = ${orders.user_id};;
}
}
Inaccessible view "items" referenced in
"orders.sum_cat1_coins". "items" is not accessible in
explore "users". Check for missing joins in explore
"users".
orders
sum_cat1_coins
items
users items?
JOIN
JOIN orders
sum_cat1_coins
20
▲usersにJOINしているordersで、itemsを参照したディメ
ンションがあるのに、usersにはitemsがJOINされていな
いので、迷子になっています
JOINを跨いだフィールドの解決策①
❖ usersにもitemsをJOINする
explore: users {
label: "ユーザー"
join: orders {
type: left_outer
relationship: one_to_many
sql_on: ${users.id} = ${orders.user_id};;
}
 join: items {
type: left_outer
relationship: many_to_one
sql_on: ${orders.item_id} = ${items.id};;
}
}
}
orders
sum_cat1_coins
items
users
JOIN
JOIN
orders
sum_cat1_coins
21
items
JOIN
items
あった!
×: usersではsum_cat1_coinsを使わない場合、
 不要なJOINを増やすことになる
○: sum_cat1_coinsが迷子にならない
JOINを跨いだフィールドの解決策②
❖ sum_cat1_coins用の派生テーブルを作る
view: orders_der_items {
derived_table: {
explore_source: orders {
column: id {}
column: coins {}
column: category
{field: items.category}
}
}
#中略
measure: sum_cat1_coins {
label: "カテゴリー1の総売上"
type: sum
sql: ${coins} ;;
filters: [category: "1"]
}
}
orders
sum_cat1_coins
items
users
JOIN
orders
22
JOIN
orders_der_items
sum_cat1_coins
JOIN
explore: users {
label: "ユーザー"
join: orders {
type: left_outer
relationship:
one_to_many
sql_on:
   ${users.id} =
${orders.user_id};;
}
}
×: 派生テーブルがどんどん増える
○: usersに必要最低限のJOINのみで済む
Lookerのサポートチャットで質問してみました
23
コードやファイルを必要以上に増やさずに
JOINを跨いだフィールドを
すっきり実装できる方法はありませんか?
Extendsを調べてみてください
view: orders {
#中略
dimension: sum_coins {
type: number
sql: ${TABLE}.coins;;
}
measure: coins {
type: sum
sql: ${coins};;
}
}
view: orders_extended {
extends: [orders]
measure: sum_cat1_coins {
label: "カテゴリー1の総売上"
type: sum
sql: ${coins} ;;
filters: [items.category: "1"]
}
}
JOINを跨いだフィールドの解決策③ Extendsでの問題解決
❖ Extendsは既存のViewを残したまま新規に複製が作れる機能
orders orders_
extended
24
explore: orders {
label: "注文履歴1"
}
explore: orders_extended {
label: "注文履歴2"
join: items {
type: left_outer
relationship: many_to_one
sql_on:
${orders_extended.item_id}
   = ${items.id};;
}
}
Extends
Explore
注文履歴1
 id
 item_id
 coins
 sum_coins
 
Explore
注文履歴2
 id
 item_id
 coins
 sum_coins
 sum_cat1_coins
Extendsでの問題解決
❖ 他のExploreにJOINする方には、Extendsの内容は反映されない
view: orders_extended {
extends: [orders]
measure: sum_cat1_coins {
label: "カテゴリー1の総売上"
type: sum
sql: ${coins} ;;
filters: [items.category: "1"]
}
}
explore: orders_extended {
label: "注文履歴"
join: items {
type: left_outer
relationship: many_to_one
sql_on: ${orders_extended.item_id} = ${items.id};;
}
}
explore: users {
label: "ユーザー"
join: orders {
type: left_outer
relationship: one_to_many
sql_on: ${users.id} = ${orders.user_id};;
}
}
orders
Extends
orders_extended
sum_cat1_coins
items
JOIN
users JOIN orders
itemsを参照するsum_cat1_coinsがない
→エラーが発生しない!
25
Extendsでの問題解決
❖ fromを使ってExplore名は元のままとする
view: orders_extended {
extends: [orders]
measure: sum_cat1_coins {
label: "カテゴリー1の総売上"
type: sum
sql: ${coins} ;;
filters: [items.category: "1"]
}
}
explore: orders {
from: orders_extended
label: "注文履歴"
join: items {
type: left_outer
relationship: many_to_one
sql_on: ${orders_extended.item_id} = ${items.id};;
}
}
explore: users {
label: "ユーザー"
join: orders {
type: left_outer
relationship: one_to_many
sql_on: ${users.id} = ${orders.user_id};;
}
}
orders
Extends
orders_extended
orders
sum_cat1_coins
items
JOIN
users JOIN orders
orders_extendedのままだとordersで
作成した可視化が全て壊れるので注意!
26
※fromではなくview_nameでの管理もOK!
27
ViewやExploreを拡張する方法には、
Extendsの他に
Refinementsというのもあるらしい。
何が違うんだろう……?
ExtendsとRefinementsの違い
❖ Refinementsは既存のViewにそのまま付け足す
orders orders_
extended
sum_cat1_coins
28
explore: orders {
label: "注文履歴1"
}
explore: orders_extended {
label: "注文履歴2"
join: items {
type: left_outer
relationship: many_to_one
sql_on:
${orders_extended.item_id}
   = ${items.id};;
}
}
Extends
Explore
注文履歴1
 id
 item_id
 coins
 sum_coins
 sum_100_over_coins
Explore
注文履歴2
 id
 item_id
 coins
 sum_coins
 sum_100_over_coins
 sum_cat1_coins
view: orders {
#中略
dimension: coins {
type: number
sql: ${TABLE}.coins;;
}
}
view: +orders {
measure: sum_100_over_coins {
label: "100円以上の注文の総売上"
type: sum
sql: ${coins};;
filters: [coins: ">=100"]
}
}
view: orders_extended {
extends: [orders]
measure: sum_cat1_coins {
label: "カテゴリー1の総売上"
type: sum
sql: ${coins} ;;
filters: [items.category: "1"]
}
}
sum_100_over_coins
sum_100_over_coins
ExtendsとRefinementsの違い
❖ 他のExploreにJOINする方にも、Refinementsの内容は反映される
view: orders {
#中略
dimension: coins {
type: number
sql: ${TABLE}.coins;;
}
}
view: +orders {
measure: sum_100_over_coins {
label: "100円以上の注文の総売上"
type: sum
sql: ${coins};;
filters: [coins: ">=100"]
}
}
view: orders_extended {
extends: [orders]
measure: sum_cat1_coins {
label: "カテゴリー1の総売上"
type: sum
sql: ${coins} ;;
filters: [items.category: "1"]
}
}
explore: orders {
from: orders_extended
label: "注文履歴"
join: items {
type: left_outer
relationship: many_to_one
sql_on: ${orders_extended.item_id} =${items.id};;
}
}
explore: users {
label: "ユーザー"
join: orders {
type: left_outer
relationship: one_to_many
sql_on: ${users.id} = ${orders.user_id};;
}
}
orders
Extends
orders_extended
orders
sum_100_over_coins
sum_cat1_coins
items
JOIN
users JOIN orders
sum_100_over_coins
sum_100_over_coinsは
他のExploreにJOINするordersにも
29
ミラティブでのRefinementsの使用例
❖ ユーザーの行動ログのビューが長くなりそうで管理に困っていた
30
id action user_id t
1 launch 10001 2021-01-01 00:00:00 UTC
2 view 10002 2021-01-01 00:00:10 UTC
3 broadcast 10003 2021-01-01 00:01:00 UTC
4 view 10001 2021-01-01 01:00:00 UTC
ユーザーの行動ログの BigQueryテーブル
ユーザーの行動を表す actionが数千種類ある
→元のテーブルが同じだからと言って、
 全て同じファイルに書き続けると lkmlが長大になる
ミラティブでのRefinementsの使用例
❖ 長いviewをユーザーの行動の種類ごとにファイルに分割
view: actions {
# BigQueryからロードしたディメンション
dimension: t {}
dimension: action {}
}
# actions_ref_view.view
include: "../actions.view.lkml"
view: +actions {
# 視聴
measure: count_view {
type: count
filters: [is_view: "yes"]
}
dimension: is_view {
type: yesno
sql: ${action} = "view";;
}
}
# actions_ref_broadcast.view
include: "../actions.view.lkml"
view: +actions {
# 配信
dimension: is_broadcast {
type: yesno
sql: ${action} = "broadcast";;
}
}
Dataset 1
actions.view
another.view
actions
actions_ref_view.view
actions_ref_broadacst.view
元のviewと別ファイルにする場合はincludeが必要
actions_ref
31
Lookerのフォルダ構成の提案
❖ 元テーブル毎にExtends・Refinementsを管理
Dataset 1
actions.view
actions
actions_ref_view.view
actions_ref_broadacst.view
actions_ref
actions_der
actions_extended.view
actions_der_by_user_id.view
BigQueryのテーブルまま
Exploreのactions専門のフィールド
派生テーブル
拡張したフィールドを種類毎に
32
まとめ
■ JOINを超えたフィールドはExtendsで実装しよう
■ 長いViewはRefinementsで分割しよう
→すっきりしたファイル・Explore構成に!
33
Meety募集中です & データアナリスト募集中です
❖ Lookerの情報交換、弊社に興味をお持ちの方、歓迎です!
https://meety.net/matches/syufQOiyqKPw
34
ご清聴ありがとう
ございました
35
36
発表での質疑などを
踏まえた補足
たくさんのフィードバックありがとうございました!
ユーザーコミュニティに参加した意義を痛感しました……!
view: orders {
#中略
measure: sum_cat1_coins {
label: "カテゴリー1の総売上"
type: sum
sql: ${coins} ;;
filters: [items.category: "1"]
}
 set: detail {
fields: [id, item_id, coins,
sum_cat1_coins]
 }
}
JOINを跨いだフィールドの解決策④
❖ フィールドは元Viewに作り、
他のExploreにJOINする時にフィールドを絞る
orders
sum_cat1_coins
items
users
JOIN
orders
37
JOIN
×: フィールドを増やすたびに
 setをメンテナンスする必要がある
○: ファイルを増やさなくて済む
explore: users {
label: "ユーザー"
join: orders {
type: left_outer
relationship: one_to_many
sql_on:
   ${users.id}
   = ${orders.user_id};;
fields: [details*]
}
}
}
orders内で完結する
フィールドのみ
# orders.view
view: orders {
#中略
}
# orders_ref.view
include: "orders.view.lkml"
view: +orders {
measure: sum_cat1_coins {
label: "カテゴリー1の総売上"
type: sum
sql: ${coins} ;;
filters: [items.category: "1"]
}
}
JOINを跨いだフィールドの解決策⑤
❖ フィールドはRefinementsに作り、
ExploreにRefinementsをincludeするしないで選ぶ
orders
sum_cat1_coins
items
users
JOIN
orders
38
JOIN
# orders.explore
include: "orders.view.lkml"
include: "orders_ref.view.lkml"
include: "items.view.lkml"
explore: orders {
join: items {
type: left_outer
relationship: many_to_one
sql_on:
${orders_extended.item_id}
   =${items.id};;
}
}
# users.explore
include: "users.view.lkml"
include: "orders.view.lkml"
explore: users {
join: orders {
type: left_outer
relationship: one_to_many
sql_on:
   ${users.id}
   = ${orders.user_id};;
}
}
×: Exploreごとにファイルを作り、includeをメンテナンスする必要がある
○: Viewの管理をRefinementsで統一できる
JOINを跨いだフィールドの解決策の長所と短所まとめ
39
内容 ○長所 ×短所
① 全てJOIN わかりやすい JOINが増える
② 派生テーブル JOINの数は減る 派生テーブルが増える
③ Extends ファイルとコードが少なく済む Extendsファイルが増える
④ JOINするフィールドを絞る ファイルを増やさなくて済む setのメンテナンスが必要
⑤ Refinementsのinclude Refinementsで全て管理できる includeのメンテナンスが必要
それぞれの解決策に一長一短があるので、
みなさんの環境に合わせて追加開発コストが少なく
済みそうなものを試してみるのがよさそうです!

Contenu connexe

Tendances

マッチングサービスにおけるKPIの話
マッチングサービスにおけるKPIの話マッチングサービスにおけるKPIの話
マッチングサービスにおけるKPIの話cyberagent
 
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)Yoshitaka Kawashima
 
ビジネスパーソンのためのDX入門講座エッセンス版
ビジネスパーソンのためのDX入門講座エッセンス版ビジネスパーソンのためのDX入門講座エッセンス版
ビジネスパーソンのためのDX入門講座エッセンス版Tokoroten Nakayama
 
Gunosyにおけるパーソナライズシステム
GunosyにおけるパーソナライズシステムGunosyにおけるパーソナライズシステム
GunosyにおけるパーソナライズシステムShunsuke Kozawa
 
エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織Takafumi ONAKA
 
「顧客の声を聞かない」とはどういうことか
「顧客の声を聞かない」とはどういうことか「顧客の声を聞かない」とはどういうことか
「顧客の声を聞かない」とはどういうことかYoshiki Hayama
 
JMDC / Looker User Meetup in Tokyo #4
JMDC / Looker User Meetup in Tokyo #4JMDC / Looker User Meetup in Tokyo #4
JMDC / Looker User Meetup in Tokyo #4ssuser91ce63
 
チャットコミュニケーションの問題と心理的安全性の課題 #EOF2019
チャットコミュニケーションの問題と心理的安全性の課題 #EOF2019チャットコミュニケーションの問題と心理的安全性の課題 #EOF2019
チャットコミュニケーションの問題と心理的安全性の課題 #EOF2019Tokoroten Nakayama
 
45分間で「ユーザー中心のものづくり」ができるまで詰め込む
45分間で「ユーザー中心のものづくり」ができるまで詰め込む45分間で「ユーザー中心のものづくり」ができるまで詰め込む
45分間で「ユーザー中心のものづくり」ができるまで詰め込むYoshiki Hayama
 
Unityでオニオンアーキテクチャ
UnityでオニオンアーキテクチャUnityでオニオンアーキテクチャ
Unityでオニオンアーキテクチャtorisoup
 
プロダクトの強い軸を作るプロダクトマネジメントフレームワーク
プロダクトの強い軸を作るプロダクトマネジメントフレームワークプロダクトの強い軸を作るプロダクトマネジメントフレームワーク
プロダクトの強い軸を作るプロダクトマネジメントフレームワークkumiko koshiro
 
5分でわかった気になるインセプションデッキ
5分でわかった気になるインセプションデッキ5分でわかった気になるインセプションデッキ
5分でわかった気になるインセプションデッキTakao Oyobe
 
プログラマが欲しい仕様書とは
プログラマが欲しい仕様書とはプログラマが欲しい仕様書とは
プログラマが欲しい仕様書とはKatsutoshi Makino
 
ゲームエンジニアのためのデータベース設計
ゲームエンジニアのためのデータベース設計ゲームエンジニアのためのデータベース設計
ゲームエンジニアのためのデータベース設計sairoutine
 
「速」を落とさないコードレビュー
「速」を落とさないコードレビュー「速」を落とさないコードレビュー
「速」を落とさないコードレビューTakafumi ONAKA
 
ゲームの仕様書を書こうまとめ
ゲームの仕様書を書こうまとめゲームの仕様書を書こうまとめ
ゲームの仕様書を書こうまとめSugimoto Chizuru
 
ユーザーストーリー駆動開発で行こう。
ユーザーストーリー駆動開発で行こう。ユーザーストーリー駆動開発で行こう。
ユーザーストーリー駆動開発で行こう。toshihiro ichitani
 
.NET Core時代のCI/CD
.NET Core時代のCI/CD.NET Core時代のCI/CD
.NET Core時代のCI/CDYuta Matsumura
 

Tendances (20)

マッチングサービスにおけるKPIの話
マッチングサービスにおけるKPIの話マッチングサービスにおけるKPIの話
マッチングサービスにおけるKPIの話
 
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)
 
ビジネスパーソンのためのDX入門講座エッセンス版
ビジネスパーソンのためのDX入門講座エッセンス版ビジネスパーソンのためのDX入門講座エッセンス版
ビジネスパーソンのためのDX入門講座エッセンス版
 
Gunosyにおけるパーソナライズシステム
GunosyにおけるパーソナライズシステムGunosyにおけるパーソナライズシステム
Gunosyにおけるパーソナライズシステム
 
はじめてのPRD
はじめてのPRDはじめてのPRD
はじめてのPRD
 
エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織
 
「顧客の声を聞かない」とはどういうことか
「顧客の声を聞かない」とはどういうことか「顧客の声を聞かない」とはどういうことか
「顧客の声を聞かない」とはどういうことか
 
JMDC / Looker User Meetup in Tokyo #4
JMDC / Looker User Meetup in Tokyo #4JMDC / Looker User Meetup in Tokyo #4
JMDC / Looker User Meetup in Tokyo #4
 
チャットコミュニケーションの問題と心理的安全性の課題 #EOF2019
チャットコミュニケーションの問題と心理的安全性の課題 #EOF2019チャットコミュニケーションの問題と心理的安全性の課題 #EOF2019
チャットコミュニケーションの問題と心理的安全性の課題 #EOF2019
 
45分間で「ユーザー中心のものづくり」ができるまで詰め込む
45分間で「ユーザー中心のものづくり」ができるまで詰め込む45分間で「ユーザー中心のものづくり」ができるまで詰め込む
45分間で「ユーザー中心のものづくり」ができるまで詰め込む
 
Unityでオニオンアーキテクチャ
UnityでオニオンアーキテクチャUnityでオニオンアーキテクチャ
Unityでオニオンアーキテクチャ
 
プロダクトの強い軸を作るプロダクトマネジメントフレームワーク
プロダクトの強い軸を作るプロダクトマネジメントフレームワークプロダクトの強い軸を作るプロダクトマネジメントフレームワーク
プロダクトの強い軸を作るプロダクトマネジメントフレームワーク
 
5分でわかった気になるインセプションデッキ
5分でわかった気になるインセプションデッキ5分でわかった気になるインセプションデッキ
5分でわかった気になるインセプションデッキ
 
プログラマが欲しい仕様書とは
プログラマが欲しい仕様書とはプログラマが欲しい仕様書とは
プログラマが欲しい仕様書とは
 
WayOfNoTrouble.pptx
WayOfNoTrouble.pptxWayOfNoTrouble.pptx
WayOfNoTrouble.pptx
 
ゲームエンジニアのためのデータベース設計
ゲームエンジニアのためのデータベース設計ゲームエンジニアのためのデータベース設計
ゲームエンジニアのためのデータベース設計
 
「速」を落とさないコードレビュー
「速」を落とさないコードレビュー「速」を落とさないコードレビュー
「速」を落とさないコードレビュー
 
ゲームの仕様書を書こうまとめ
ゲームの仕様書を書こうまとめゲームの仕様書を書こうまとめ
ゲームの仕様書を書こうまとめ
 
ユーザーストーリー駆動開発で行こう。
ユーザーストーリー駆動開発で行こう。ユーザーストーリー駆動開発で行こう。
ユーザーストーリー駆動開発で行こう。
 
.NET Core時代のCI/CD
.NET Core時代のCI/CD.NET Core時代のCI/CD
.NET Core時代のCI/CD
 

Lookerユーザー会#7 RefinementsとExtendsを活用したExplore構築 ~JOINを跨いだフィールドをすっきり実装しよう〜 / Looker User Meetup 7