-
Notifications
You must be signed in to change notification settings - Fork 1
/
rules.yaml
361 lines (350 loc) · 11.4 KB
/
rules.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
rules:
- title: Dimension name not in snake case
code: D101
rationale: Dimension names should match the conventional format, which is snake
case—words in lowercase, separated by underscores. For example, `order_id` instead
of `orderId` or `OrderID`.
select:
- dimension
- dimension_group
regex: ^[_a-z0-9]+$
negative: false
type: PatternMatchRule
- title: Measure name not in snake case
code: M103
rationale: Measure names should match the conventional format, which is snake case—words
in lowercase, separated by underscores. For example, `count_orders` instead of
`OrderCount`.
select:
- measure
regex: ^[_a-z0-9]+$
negative: false
type: PatternMatchRule
- title: View name not in snake case
code: V100
rationale: View names should match the conventional format, which is snake case—words
in lowercase, separated by underscores. For example, `all_orders` instead of `allOrders`
or `AllOrders`.
select:
- view
regex: ^\+?[_a-z0-9]+$
negative: false
type: PatternMatchRule
- title: Name of count measure doesn't start with 'count_'
code: M100
rationale: You should explicitly state the aggregation type in the dimension name
because it makes it easier for other developers and Explore users to understand
how the measure is calculated.
select:
- measure
filter:
- type: ParameterFilter
parameter_name: type
value: count
- operator: OR
type: ParameterFilter
parameter_name: type
value: count_distinct
regex: ^count_
negative: false
type: PatternMatchRule
- title: Name of sum measure doesn't start with 'total_' or 'sum_'
code: M101
rationale: You should explicitly state the aggregation type in the dimension name
because it makes it easier for other developers and Explore users to understand
how the measure is calculated.
select:
- measure
filter:
- type: ParameterFilter
parameter_name: type
value: sum
- operator: OR
type: ParameterFilter
parameter_name: type
value: sum_distinct
regex: ^(?:total|sum)_
negative: false
type: PatternMatchRule
- title: Name of average measure doesn't start with 'avg_' or 'average_'
code: M102
rationale: You should explicitly state the aggregation type in the dimension name
because it makes it easier for other developers and Explore users to understand
how the measure is calculated.
select:
- measure
filter:
- type: ParameterFilter
parameter_name: type
value: average
- operator: OR
type: ParameterFilter
parameter_name: type
value: average_distinct
regex: ^(?:avg|average)_
negative: false
type: PatternMatchRule
- title: Yesno dimension doesn't start with 'is_' or 'has_'
code: D100
rationale: Wording the name of a `yesno` dimension as a question makes it clear
to the user what a yes or no value represents.
select:
- dimension
filter:
- type: ParameterFilter
parameter_name: type
value: yesno
regex: ^(?:is|has)_
negative: false
type: PatternMatchRule
- title: Measure references table column directly
code: M110
rationale: Measures should not directly reference table columns, but should instead
reference dimensions that reference table columns. This way, the dimension can
be a layer of abstraction and single source of truth for **all** measures that
reference it.
select:
- measure.sql
regex: \$\{TABLE\}
negative: true
type: PatternMatchRule
- title: Dimension group name ends with redundant word
code: D200
rationale: "When Looker creates the underlying dimensions, Looker appends the name\
\ of the timeframe to the dimension group name. For example, for a dimension group\
\ called `order_date`, Looker will create dimensions with redundant names: `order_date_date`,\
\ `order_date_month`, `order_date_year`, etc. \n\nInstead, use `order` as the\
\ dimension group name, which becomes `order_date`, `order_month`, etc."
select:
- dimension_group
regex: _(?:at|date|time)$
negative: true
type: PatternMatchRule
- title: Explore doesn't declare fields
code: E100
rationale: 'When fields are explicitly defined, LookML developers can easily identify
the fields included in the Explore without having to reference the view file or
loading the Explore page.
This is especially helpful when the Explore includes multiple joins and a subset
of fields from each joined model.'
select:
- explore
criteria:
- type: ParameterFilter
parameter_name: fields
negative: false
type: ParameterRule
- title: Explore missing label
code: E111
rationale: 'Explores should define a label to provide a user-friendly name for the
Explore in menus. Looker generates title-cased names for Explores based on the
name in LookML, but these names aren''t always useful for users. For example,
an auto-generated Explore name **Prod Sessions L3d** (generated from explore:
`prod_sessions_l3d`) is not as succinct or informational as **Web Sessions**.'
select:
- explore
criteria:
- type: ParameterFilter
parameter_name: label
negative: false
type: ParameterRule
- title: Visible dimension missing description
code: D301
rationale: Dimensions that are visible in the Explore page should have a description
so users understand how and why to use them, along with any caveats.
select:
- dimension
- dimension_group
filter:
- operator: NOT
type: ParameterFilter
parameter_name: hidden
value: 'yes'
criteria:
- type: ParameterFilter
parameter_name: description
negative: false
type: ParameterRule
- title: Visible measure missing description
code: M112
rationale: Measures that are visible in the Explore page should have a description
so users understand how and why to use them, along with any caveats.
select:
- measure
filter:
- operator: NOT
type: ParameterFilter
parameter_name: hidden
value: 'yes'
criteria:
- type: ParameterFilter
parameter_name: description
negative: false
type: ParameterRule
- title: View must define at least one primary key dimension
code: V110
rationale: Views must define a primary key so that any Explores that reference them
can take advantage of symmetric aggregates and join them properly to views. This
rule only applies to views that have defined a `sql_table_name` or `derived_table`
parameter.
select:
- view
filter:
- type: ParameterFilter
parameter_name: derived_table
- operator: OR
type: ParameterFilter
parameter_name: sql_table_name
- operator: NOT
type: ParameterFilter
parameter_name: extends
criteria:
- type: ParameterFilter
parameter_name: primary_key
value: 'yes'
criteria_on: dimension
negative: false
type: ParameterRule
- title: View missing label
code: V111
rationale: 'Views should define a label to provide a user-friendly name for the
view in Explores. Looker generates title-cased names for views based on the view
name in LookML, but these names aren''t always useful for users in Explores. For
example, an auto-generated view name **Prod Sessions L3d** (generated from view:
`prod_sessions_l3d`) is not as succinct or informational as **Web Sessions**.'
select:
- view
criteria:
- type: ParameterFilter
parameter_name: label
negative: false
type: ParameterRule
- title: Primary key dimension not hidden
code: D302
rationale: Primary keys are not typically used directly in Explores because users
are more interested in aggregates like measures, which reduce the grain beyond
the grain of the primary key. Thus, these dimensions should be hidden.
select:
- dimension
filter:
- type: ParameterFilter
parameter_name: primary_key
value: 'yes'
criteria:
- type: ParameterFilter
parameter_name: hidden
value: 'yes'
negative: false
type: ParameterRule
- title: Dimension not in alphabetical order
code: D106
rationale: 'Sort dimensions alphabetically to make it easier to find a dimension
while scrolling through a view file.
A dimension or dimension group violates this rule if it is not alphabetically
sorted with respect to the previous dimension or dimension group.
Primary keys are excluded from the set of dimensions used to determine alphabetical
order.'
select:
- dimension
- dimension_group
filter:
- operator: NOT
type: ParameterFilter
parameter_name: primary_key
alphabetical: true
is_first: false
use_key: true
type: OrderRule
- title: Measure not in alphabetical order
code: M106
rationale: 'Sort measures alphabetically to make it easier to find a measure while
scrolling through a view file.
A measure violates this rule if it is not alphabetically sorted with respect to
the previous measure.'
select:
- measure
alphabetical: true
is_first: false
use_key: true
type: OrderRule
- title: Primary key dimension not the first dimension in this view
code: D107
rationale: The primary key should be listed first in a view so developers quickly
understand the grain of the view and what a single record represents.
select:
- dimension
filter:
- type: ParameterFilter
parameter_name: primary_key
value: 'yes'
alphabetical: false
is_first: true
use_key: true
type: OrderRule
- title: Dimension label includes redundant "Yes/No"
code: D303
rationale: For `yesno` dimensions, Looker adds "Yes/No" to the end of the dimension's
label by default, so there's no need to include it in the label.
select:
- dimension.label
regex: (?i)Yes/No
negative: true
type: PatternMatchRule
- title: View uses the same table as another view
code: V112
rationale: Views should not have the same `sql_table_name` because two views with
the same table name are effectively the same view. Instead, consolidate these
views into a single view.
select:
- view
type: DuplicateViewRule
- title: Name of persistent derived table view doesn't start with 'pdt_'
code: V113
rationale: Views that define persistent derived tables should be prefixed to make
it easy to identify views based on PDTs.
select:
- view
filter:
- type: ParameterFilter
parameter_name: datagroup_trigger
- operator: OR
type: ParameterFilter
parameter_name: sql_trigger_value
- operator: OR
type: ParameterFilter
parameter_name: interval_trigger
- operator: OR
type: ParameterFilter
parameter_name: persist_for
- operator: OR
type: ParameterFilter
parameter_name: materialized_view
value: 'yes'
filter_on: derived_table
regex: ^pdt_
negative: false
type: PatternMatchRule
- title: Include uses a wildcard
code: I100
rationale: Including all views using a wildcard (e.g. `*.view`) slows down LookML
compilation and validation. Instead, explicitly include the specific views that
you need.
select:
- include
regex: \*\.view
negative: true
type: PatternMatchRule
- title: Join doesn't define its relationship explicitly
code: J100
rationale: 'If the `relationship` parameter for a join is omitted, Looker will use
a default relationship of `many_to_one`. However, it''s better to define the relationship
explicitly so that developers scanning the code can quickly understand the join.
Explicitly defining the relationship can also help prevent errors caused by mistyping
or using the wrong columns in the join condition. '
select:
- join
criteria:
- type: ParameterFilter
parameter_name: relationship
negative: false
type: ParameterRule