- General guidelines
- LookML file management
- Admin
- Version control
- Credits and references
- Other
- Ideas for later iterations
Your LookML code should:
- Be reusable and maintainable
- Provide end users with superior UI/UX
- Facilitate onboarding of new developers
- Aim for clarity and brevity
- Optimize query performance
Inspried by LookML development experience, Looker training on SkillJar, Looker Docs, and various other LookML development articles and blog posts.
It's more readable, easier to keep consistent, and avoids having to quote identifiers due to capitalization, spaces, or other special characters. Also, keep in mind that LookML is case sensitive.
For example 'Gross Revenue', instead of 'Gross revenue'. This is to match the default settings in Looker, which will add field labels based on the specified field name using title case.
Expected exceptions include cases where a field, explore, or model contains an abbreviation (e.g. ‘KPI’).
Abbreviations can and should be used when the definitions are well-known and agreed upon across the organization. Optimize the stakeholder experience for accuracy, clarity, and brevity.
When abbreviations are used in labels or titles, add the full detail to the field description. This can provide context on the intended field usage for stakeholders who may not interact with the data as frequently (e.g. new to Looker or to the organization).
For readability, an overarching pattern is:
- If there's only one item, put it on the same line as the parameter.
- If there are multiple items, put each one on its own line (including the first one). Then, indent one level more than the parameter.
# Bad
explore: cohorts {
label: "Cohort Data Tool"
fields: [users.id, users.name, users.first_name, users.last_name, users.email, users.age, users.created_date, users.gender, users.traffic_source, users.count]
# Good
explore: cohorts {
label: "Cohort Data Tool"
fields: [
users.id
, users.name
, users.first_name
, users.last_name
, users.email
, users.age
, users.created_date
, users.gender
, users.traffic_source
, users.count
]
If code containing commas needs to be split across multiple lines, put the commas at the beginning of the subsequent lines, followed by a space.
- This makes it easier to spot missing commas.
- Version control diffs will be cleaner when adding to the end of a list because you don't have to add a trailing comma to the preceding line.
- The comma is only there for / because of what follows it. If nothing followed the comma it wouldn't be needed, so putting the comma on the same line as what follows it makes it clearer why it's there.
# Bad
explore: orders {
always_filter: {
filters: [dim_products.is_in_stock: "yes", fact_customers.is_sale_customer: "yes", fact_orders.is_delivered: "yes"]
}
# Good
explore: orders {
always_filter: {
filters: [
dim_products.is_in_stock: "yes"
, fact_customers.is_sale_customer: "yes"
, fact_orders.is_delivered: "yes"
]
}
One exception: trailing commas auto-generated by Looker. For example, when using the Create View From Table
feature, fields like timestamps (e.g., order_completed_at
) result in dimension groups that include a list of timeframes, each one on its own line separated by a trailing comma. The effort required to update these auto-generated lines of code is greater than the value created.
Use a single #
followed by a single space to begin a comment. When commenting on a field in a view file include it before the field.
Note that this is a departure from Brooklyn Data Co.'s preferred comment syntax for SQL (/* */
) because LookML does not recognize this syntax as a comment.
# Bad
dimension: month_formatted {
type: date
sql: ${TABLE}."MONTH" ;;
}
# Date formatted dimension is required to join on other tables
# Good
# Date formatted dimension is required to join on other tables
dimension: month_formatted {
type: date
sql: ${TABLE}."MONTH" ;;
}
If you find yourself requiring the same table calculation in more than one Look or Dashboard tile, move the logic upstream to a view file. This will make future maintenance easier and enable developers and/or users to more easily leverage the calculation in other reports.
Use folders to keep LookML files organized. Most projects will need a folder for dashboards
, models
, and views
. You may find additional folders useful depending on the specific project (e.g., a beta
folder for productionalized work that is released to a test group of users).
Optimize for clarity and brevity. Where applicable, keep naming consistent with the underlying data model (e.g., dbt data model).
- Do not indent structural parameters such as
include:
,test:
, andview:
- Use two-space indent for each level of nested parameters below these structural parameters
- Leave an empty line of code before each major section header (see Section headers below)
- Do not leave empty lines of code in between fields within the same section header
# Bad
## Primary key
dimension: id {
primary_key: yes
type: number
sql: ${TABLE}."ID" ;;
}
## Foreign keys and IDs
dimension: order_id {
type: number
sql: ${TABLE}."ORDER_ID" ;;
}
dimension: product_id {
type: number
sql: ${TABLE}."PRODUCT_ID" ;;
}
# Good
## Primary key
dimension: id {
primary_key: yes
type: number
sql: ${TABLE}."ID" ;;
}
## Foreign keys and IDs
dimension: order_id {
type: number
sql: ${TABLE}."ORDER_ID" ;;
}
dimension: product_id {
type: number
sql: ${TABLE}."PRODUCT_ID" ;;
}
- Start View files with the LookML parameters that define the file such as:
include:
view:
sql_table_name:
extends:
drill_fields:
(for Views)
- Within each section header list dimensions and dimension groups before measures
- Use in-line comments as section headers to keep fields organized. The approach recommended here is designed to:
- help developers navigate lengthy view files
- faciliate a better user experience in the Explore by aligning / organizing fields according to the view labels under which they will be nested. Because this style guide also recommends explicitly calling fields in Explores and in joined views, this approach is especially helpful if you are building Explores that use multiple joins: having fields classified under section headers helps developers choose the fields to surface in the Explore.
- The following list includes common section headers and the preferred order to include them (when applicable).
## Primary Key
- Whenever possible define the primary key## Parameters
- These fields will appear to the user under the ‘Filter-Only Fields’ section of the field picker## Filters
- These fields will appear to the user under the ‘Filter-Only Fields’ section of the field picker.## Foreign keys and IDs
- Hide keys and IDs that you expect users will not interact with (e.g.,product_id
ordistribution_center_id
)## Timestamps
## Duration
## Flags
- Yes/No fields. These are typically modeled asis_[characteristic]
orhas_[characteristic]
## Properties
- List descriptive characteristics here such assize
,color
,operating_system
, andevent_type
## Statuses
## Revenue
## Costs
## SLAs
- These fields contain Service Level Agreements## Ratios and Percents
## Sets
The list above is meant to serve as a guide only. You should adapt the number of sections in your list to the complexity of the modeling work and according to your use case.
- Use a single indentation to align section headers with the beginning of field declarations
- Begin headers with two hashes (##) and a space
- Group hidden fields in each section into a sub-section named
### Hidden
. This streamlines interacting with and reviewing what can be added to Explores the view file. - Within each section header do list:
- visible (i.e. not hidden) fields first
- dimensions and dimension groups before measures
- alphabetically to make it easier to find fields when scrolling through view files
- Your View file should look something like this sample view file
- Productivity tip: You can fold LookML to see a condensed view of the file. See Shortcuts in the LookML development environment for details.
- When naming
yesno
fields (e.g.,## Flags
), use an interrogative structure (e.g., “Is Returned” instead of “Returned”). This more naturally lends itself to the ‘yes’ or ‘no’ that appears in the column. - Do not include “Yes/No” in the label of a
yesno
(boolean) field. Looker includes this by default.
# Bad
dimension: returned {
type: yesno
sql: ${returned_raw} IS NOT NULL ;;
label: "Is Returned Item (Yes/No)"
}
# Good
dimension: is_returned {
type: yesno
sql: ${returned_raw} IS NOT NULL ;;
label: "Is Returned Item"
}
- Avoid the words
at
,date
ortime
at the end of a dimension group field name. Looker appends each timeframe to the end of the dimension name:created_date
becomescreated_date_date
,created_date_month
, etc.- Instead use
created
which becomescreated_date
,created_month
, etc.
- Instead use
# Bad
dimension_group: created_at {
type: time
timeframes: [
time,
date,
week,
month,
raw
]
sql: ${TABLE}.created_at ;;
}
# Good
dimension_group: created {
type: time
timeframes: [
time,
date,
week,
month,
raw
]
sql: ${TABLE}.created_at ;;
}
- Whenever possible measures should reference LookML dimensions rather than the source table.
# Bad
measure: total_transaction_amount {
type: sum
sql: ${TABLE}."TRANSACTION.AMOUNT"
value_format_name: usd
}
# Good
measure: total_transaction_amount {
type: sum
sql: ${transaction_amount}
value_format_name: usd
}
- If a measure and a dimension reference the same ${TABLE}.”field_name”, prefix the dimension with an underscore to differentiate between the two.
# Bad
dimension: order_subtotal_usd {
type: sum
sql: ${TABLE}."ORDER_SUBTOTAL_USD" ;;
}
measure: order_subtotal_usd_measure {
label: "Order Subtotal USD"
type: sum
sql: ${TABLE}."ORDER_SUBTOTAL_USD" ;;
}
# Good
dimension: _order_subtotal_usd {
label: "Order Subtotal USD"
type: sum
sql: ${TABLE}."ORDER_SUBTOTAL_USD" ;;
}
measure: order_subtotal_usd {
type: sum
sql: ${_order_subtotal_usd} ;;
}
- Use a common term to name aggregate measures. For example:
- Sum:
total_[FIELD_NAME]
- Count:
count_[FIELD_NAME]
- Average:
avg_[FIELD_NAME]
- Max:
max_[FIELD_NAME]
- Min:
min_[FIELD_NAME]
- Median:
median_[FIELD_NAME]
- Sum:
# Bad
measure: sale_price {
type: sum
.
.
.
}
# Good
measure: total_sale_price {
type: sum
.
.
.
}
- Give ratios concise but descriptive field names
# Bad
measure: customer_repeat_rate {
description: "The percentage of customers who purchase again within 30 days"
.
.
.
}
# Good
measure: 30_day_repeat_purchase_rate {
description: "The percentage of customers who purchase again within 30 days"
.
.
.
}
- Use accurate, concise descriptions in all fields to help non-technical users navigate Looker with little or no help
# Bad
dimension: first_to_last_order_days {
description: "Number of days as customer"
.
.
.
}
measure: brand_share_of_wallet_within_company {
description: "This particular brand's sales in dollars (all transactions in foreign currencies are translated to USD) divided by the total sales across our entire website, including full-price and sale items"
.
.
.
}
# Good
dimension: first_to_last_order_days {
description: "Days between first and latest order"
.
.
.
}
measure: brand_share_of_wallet_within_company {
description: "This brand's sales divided by all sales"
.
.
.
}
- By default cast currency values with no cents (e.g.,
value_format_name: usd_0
) - Display cents (e.g.,
value_format_name: usd
) if they provide analytical value or are required
- By default cast numeric values with no decimals (e.g.,
value_format_name: decimal_0
) - Display decimals (e.g.,
value_format_name: decimal_1
,value_format_name: decimal_2
) if they provide analytical value or are required. The preference is to display the fewest number of decimals as needed to meet the business stakeholders' requirements.
- By default cast percents with no decimals (e.g.,
value_format_name: percent_0
) - Display decimals (e.g.,
value_format_name: percent_1
,value_format_name: percent_2
) if they provide analytical value or are required. The preference is to display the fewest number of decimals as needed to meet the business stakeholders' requirements.
Check out Looker’s documentation on value_format if you need to customize formatting.
You can sort results of a dimension, dimension group, or measure using the order_by_field parameter in LookML. This can be particularly useful in some situations. For example, you can overwrite Looker’s default behavior to order delivery_status
alphabetically and order results in based on business logic, instead.
Sort alphabetically | Sort according to business logic |
---|---|
(default behavior) | (applying order_by_field) |
Cancelled | Pending |
Delivered | Ordered |
Ordered | Shipped |
Pending | Delivered |
Shipped | Cancelled |
There are dozens of parameters you can add to your dimension and measure definitions. We’ve highlighted commonly used parameters and recommend listing them in the following order (note: not all fields are required and in many cases shouldn’t be used together):
# Dimensions
dimension: {
primary_key:
hidden:
view_label:
label:
group_label:
group_item_label:
description:
type:
sql: ;;
value_format_name:
drill_fields: []
}
# Measures
measure: {
hidden:
view_label:
label:
group_label:
group_item_label:
description:
type:
sql: ;;
value_format_name:
drill_fields: []
}
Brooklyn Data Co.'s preference is to build Looker projects on top of a robust data warehouse using dbt for data transformations. While there are occasional exceptions to the rule, move derived tables to the underlying data model and adding dimensions and measures as needed to your LookML views whenever possible.
- If you need to use a derived table, model them in a separate view file.
Remember that you can keep your LookML code DRY (Don't Repeat Yourself) by referencing a derived table in another view using
.SQL_TABLE_NAME
. See the documentation for more details.
- Use new lines to separate Liquid tags and SQL/Looker fields
- Use two spaces to indent each condition from the LookML parameter and four spaces to indent each output item.
# Bad
dimension: customer_lifetime_orders {
type: number
sql: ${TABLE}."CUSTOMER_LIFETIME_ORDERS" ;;
html:
{% if value > 10 %} <font color="darkgreen">{{ rendered_value }}</font>
{% else %} <font color="darkred">{{ rendered_value }}</font>
{% endif %} ;;
}
# Good
dimension: customer_lifetime_orders {
type: number
sql: ${TABLE}."CUSTOMER_LIFETIME_ORDERS" ;;
html:
{% if value > 10 %}
<font color="darkgreen">{{ rendered_value }}</font>
{% else %}
<font color="darkred">{{ rendered_value }}</font>
{% endif %} ;;
}
- Use in-line comments as section headers. Common section headers and their order include:
- ## Model configuration
- ## Explores
- Use the order of the following parameters (where applicable) to define your LookML Model
- Include an empty line of code after each one of these parameters
label:
connection:
datagroup:
access_grant:
include:
explore:
join:
join:
- Use label (for models) to define a custom label if the model’s name isn’t concise or descriptive enough for the Explore menu
- Include all views from the
views
folder in the project ("/views/*.view.lkml"
) unless there is a reason not to - Similarly, include all dashboards from the
dashboards folder
in the project ("/dashboard/*.dashboard.lkml"
) unless there is a reason not to
- Use the order of the following applicable parameters to define your explores
explore:
hidden:
label:
group_label:
description:
extension:
extends:
required_access_grants:
access_filter:
always_filter:
sql_always_where:
view_name:
query:
fields:
always_join:
join: {
from:
required_access_grants:
view_label:
fields:
relationship:
type:
sql_on:
sql_where:
}
- Avoid developing a single ‘one-stop’ Explore
- Optimize the data consumer’s (i.e. non-technical user’s) experience by creating one Explore for each set of related business questions
- For example, business users at an e-commerce company analyzing orders might be overwhelmed by all the possible details related to a customer sale included in a single Explore. Developers should create multiple Explores to help users have a more a focused experience (e.g., Explores for Customers, Orders, Products, Shipping, etc.)
- Use the fields (for Explores) parameter to explicitly select all the fields or sets to be included in the Explore.
- LookML developers will easily be able to identify which fields are included in the Explore without having to reference the view file or loading the Explore. This is especially helpful when the Explore includes multiple joins and a subset of fields from each joined model.
- Include only the joins you need to satisfy reporting requirements. Additional joins can negatively impact query performance and introduces additional code maintenance complexity
- When possible be explicit with LookML in your joins. This will make your intentions clearer for other developers -- especially less experienced developers on your team -- when reading, maintaining, or updating the Explore. Specific examples include:
- Do join views using
sql_on
instead offoreign_key
- Do use
relationship: many_to_one
andtype: left_outer
(where applicable) even though these are Looker’s default relationship and join type - Do use fully scoped fields with the fields (for Explores) parameter to explicitly identify what users will see in the Explore's field picker
- Do join views using
- Although LookML uses symmetric aggregates by default to protect against fanout, use ‘many-to-one’ whenever possible. Some reasons for this extra caution include:
- Not all SQL dialects support symmetric aggregates (see the list of dialects that support symmetric aggregates)
- It is possible to disable symmetric aggregates, in which case you'll need properly defined joins to avoid fanout
- Protect developers (including yourself!) who may use the Looker generated SQL to debug or run an ad-hoc report (e.g., in SQL Runner, in an IDE)
- Read more about this topic in this Looker blog post and Looker Community post
- For more detail check out Looker's documentaiton on Working with joins in LookML
- Your model file should look something like this sample model file:
- Not all parameters are required and in some cases shouldn’t be used together
- Use view labels to help data consumers quickly navigate the Explore Field Picker
- It’s preferable to define with view labels at the field level to ensure a consistent UX across various Explores
- For fields that roll up to different view labels -- depending on the Explore -- consider using view label for Views, for Joins, for Explores
- Standard view labels for common Explores may include:
Explore | Orders, Order Items, Products, and similar… | Web Event Data, Web Session Data, and similar… |
---|---|---|
View labels | *_IDs | *_IDs |
Customers | Funnel Metrics | |
Orders | Products | |
Products | Session Bounce Page | |
Shipping | Session Landing Page | |
Timestamps | Sessions | |
Users | Users | |
Visitors | ||
Timestamps |
LookML dashboards are stored as version-controlled files associated with the project in a Git repository. They also provide LookML developers with a way to update or modify a dashboard in bulk.
User-defined dashboards (UDDs) are great for putting together mock-ups / proof of concepts / MVPs of dashboards. They’re also a great way to give non-technical and non-developers a way to build and collect relevant visualizations together in one place.
- Typically you should start dashboard development with UDDs (which can easily be converted to LookML dashboards).
- Only convert to a LookML dashboard when necessary (e.g., when you need to bulk edit tiles) as this adds additional code to the model which needs to be maintained and peer reviewed when introducing changes.
LookML Dashboard files can easily become long and challenging to read through. Use the following to facilitate your development work, peer review, and future code maintenance.
- Create a separate
.dashboard
file for each LookML dashboard - Use in line comments to create sections of code within the file
- Begin headers with two hashes (
##
) and a space
- Begin headers with two hashes (
- Do not indent major headers and include a blank line before each major header
- Examples include
## Configuration
,## Filters
,## Elements
- Examples include
## Configuration
- dashboard: overall_sales
title: Overall sales
layout: grid
.
.
.
## Filters
filters:
- name: date
title: 'Date Range'
type: date_filter
.
.
.
## Embedded dashboard
embed_style:
background_color:
show_title:
.
.
.
## Elements
- Use major section headers as guide posts to divide your elements up into meaningful blocks. These might correspond to the rendered layout of the dashboard or use some other logic.
-
Example 1
## Company-wide performance ## Regional performance ## State performance ## Website performance
-
Example 2
## Single value visualizations ## Graphical visualizations ## Tabular visualizations
-
Example 3
## Row 1 ## Row 2 ## Row 3 ## Row 4
-
- Ultimately, the goal here is to keep you more organized in the development process and to help your peers when they’re reviewing unfamiliar Dashboard LookML code
## Section 1
## Basic parameters
- name: [element_1]
.
.
.
## Basic parameters
- name: [element_2]
.
.
.
## Section 2
- Use in line comments to break up each group of element-defining parameters
- Indent one level more than the section headers.
- Examples include
## Basic parameters
,## Layout
,## Tool tip
,## Measure and dimensions
,## Filters
, and## Axes, legends, series attributes, and sorts
## Section 1
## Basic parameters
## Layout
## Tool tip
## Measures and dimensions
## Filters
## Axes, legend, series attributes, and sorts
## Section 2
## Basic parameters
.
.
.
- Start off with basic parameters like
name:
,title:
, andtype:
.
- Define the position of the dashboard element (where applicable)
- Include tool tips (where applicable) here (e.g. a note on a pie chart)
- List the parameters that define the measures and dimensions
- Leave a blank row only between table calculations
- List the parameters that will change what data is surfaced in the visualizations
- List the parameters that will change how the the visualization looks
The layout of your Dashboard LookML file should look something like this sample LookML Dashboard file:
- Include only the parameters that impact how the dashboard’s visualizations look
- For example, when using
Get LookML
from an Explore query, Looker will (by default) include some parameters that are set to their defaults or are null even though they don’t change how visualizations are rendered. - Keeping these parameters makes dashboard LookML files unnecessarily longer and can make code maintenance more time consuming.
- For example, when using
# Bad (37 lines of code)
- name: add_a_unique_name_1613506330
title: Untitled Visualization
model: thelook
explore: order_items
type: looker_column
fields: [distribution_centers.name, order_items.order_count]
sorts: [order_items.order_count desc]
limit: 500
x_axis_gridlines: false
y_axis_gridlines: true
show_view_names: false
show_y_axis_labels: true
show_y_axis_ticks: true
y_axis_tick_density: default
y_axis_tick_density_custom: 5
show_x_axis_label: true
show_x_axis_ticks: true
y_axis_scale_mode: linear
x_axis_reversed: false
y_axis_reversed: false
plot_size_by_field: false
trellis: ''
stacking: ''
limit_displayed_rows: false
legend_position: center
point_style: none
show_value_labels: false
label_density: 25
x_axis_scale: auto
y_axis_combined: true
ordering: none
show_null_labels: false
show_totals_labels: false
show_silhouette: false
totals_color: "#808080"
series_types: {}
defaults_version: 1
# Good (10 lines of code)
- name: distribution_center_orders
title: Order count by distribution center
model: thelook
explore: order_items
type: looker_column
fields: [
distribution_centers.name
, order_items.order_count
]
sorts: [order_items.order_count desc]
The following guidelines apply to LookML and user-defined dashboards.
- Truncate the displayed values to contextually meaningful values.
# Scenario
Executive dashboard summarizing quarterly sales performance where
reported values are in the magnitude of thousands and millions of dollars.
# Bad
Report whole dollar amounts such as $55,237.06 and $45,811,972.24.
# Good
Report truncated dollar amounts such as $55.0K and $45.8M.
- Don’t include a y-axis title for charts with a single y-axis and the measure is included in the chart title.
# Scenario
A chart titled "Customer orders per day"
# Bad
Label the y-axis as "Order count"
# Good
Leave the y-axis unlabeled
- Don’t include an x-axis title for charts that include the dimension in the chart title
# Scenario
A chart titled "Daily web event sessions" or "Orders by status"
# Bad
Label the x-axis as "Date" or "Status", respectively
# Good
Leave the x-axis unlabeled
- Use uniform date formatting throughout the dashboard. See looker documentation for description and date expressions
# Scenario
Two looks in same dashboard:
1. Monthly order count
2. Monthly revenue
# Bad
1. Monthly order count with x-axis labeled ‘March-2020’
2. Monthly revenue with x-axis labeled ‘2020-03’
# Good
1. Monthly order count with x-axis labeled ‘2020-03’
2. Monthly revenue with x-axis labeled ‘2020-03’
OR
1. Monthly order count with x-axis labeled ‘March-2020’
2. Monthly revenue with x-axis labeled ‘March-2020’.
- Keep your code DRY (Don't Repeat Yourself) and use an overall filter for all fields that have the same definition and the same taxonomy
- For example: if the customer and vendor location are entered using the same taxonomy (e.g US-NY), then you can use one overall dashboard filter for both location fields
Develop visualizations that are inclusive to a wide audience of users. Avoid obscure abbreviations and terminology, be mindful about the size of text and images, and consider users with visual deficiencies.
Tools like Google Chrome’s DevTools allow you to emulate vision deficiencies in the development process before pushing work to production. Also, Looker’s Color Collection Pallets includes the Dalton color collection which accommodates various forms of color vision deficiency.
Where appropriate, conditionally format with html or within the UI. You can define font color or even include a visual cue (e.g., unicode characters) to help communicate an attribute of the data. For example, a table that includes the YoY % change in sales might be displayed in green font and with an “▲” to indicate positive change or red font with a “▼“ to indicate negative change.
- Configure the Database Time Zone and Query Time Zone (where applicable) settings to the reporting timezone. Otherwise some users might assume
current_timestamp
, timestamp columns, etc. are in UTC and can apply incorrect offsets.
- You can decide who has access to view or edit dashboards and Looks in your folder by using the Manage Access feature. This is helpful when you want to limit access to your reports to specific users. For example, you might be building a dashboard that’s still a WIP (Work In Progress) and you’re not ready for others to use the unvalidated reports, yet.
- When searching for a Look or dashboard, it can be frustrating having to go through multiple results to find what you're looking for. Consider trashing unused content (e.g, content not viewed in the last 90 days). If there's demand for it, ask the requestor questions to be sure it's really important and verify whether there's an alternative report available before taking it out of trash.
Prefix branch names with the purpose of the development work followed by a brief description of the work. Separate these details with a /
and use -
between words.
Common prefixes include feature/
, fix/
, and update/
.
# Bad
incl_new_report_for_stakeholders
important_updates_requested_by_stakeholders
sprint-4-development-work-include-a-new-feature-for-the-sales-team
# Good
feature/sales-dashboard
fix/marketing-dashboard-table-calcs
update/dashboard-color-palettes
Create a new branch in Looker for each task. Typically, each developer task is related to a single issue or user story which helps signal when a new branch is needed and when that branch can be deleted (e.g., when the issue is closed, the feature has been deployed).
If you’re using a version control integration (e.g., GitHub) remember to delete the branch there and in your Looker instance.
- Before you begin development work, ensure the branch you are using is up to date with master branch
- Commit changes in logical chucks
- Avoid committing multiple unrelated tasks in the same commit
- Resolve all LookML warnings and errors before committing.
- Toggle the Admin feature Code Quality. Specifically, “Require fixing errors and warnings before committing,” to enforce code quality before committing.
- QA between production and development mode
- Are there any key Looks or dashboards affected? (Consider using the Content Validator)
- Are the figures affected negatively by joins and other code changes?
- Document your reasoning
- Consider using a PR template (see below)
PR reviews should be a part of the Looker development workflow. Use a PR template to standardize what gets documented in the PR. The template also serves as a reminder to developers about what they need do before merging changes into production (see ## Checklist
below).
Here’s a Brooklyn Data Co.'s Looker PR template:
## Overview
_Summarize the goal of your work and what motivated it._
## Key changes
- _Describe major updates._
## Other notes
- _List open questions and other things your reviewer should know._
## Related links
- _List links to related ticket(s)._
- _(optional) Link to other files and resources, such as specific related reports in Looker._
## QA
- _List links to related QA or describe QA work and findings._
## Checklist
- [ ] New code follows [Looker style guide](insert link when published).
- [ ] Communicating with users:
- [ ] This PR will not impact / break existing stakeholder workflow(s).
- [ ] This PR will impact / break existing stakeholder workflow(s) and there is a plan in place to communicate them.
- [ ] Model(s) connection(s) were reverted to production
## Screenshots
_(optional) Include screenshots that demonstrate the new feature(s)._
- https://github.com/brooklyn-data/co/blob/master/sql_style_guide.md
- https://github.com/brooklyn-data/co/blob/master/dbt_coding_conventions.md
- https://das42.com/insights/the-ultimate-lookml-style-guide/
- https://docs.looker.com/?version=7.14
- https://discourse.looker.com/t/lookml-best-practices/1636
- SkillJar - Looker Training - SQL Tutorial for Business Analytics
- Internal Brooklyn Data Co. wiki pages
- https://looker-open-source.github.io/look-at-me-sideways/rules.html
- https://help.looker.com/hc/en-us/articles/360001784747-Best-Practice-LookML-Dos-and-Don-ts
- https://help.looker.com/hc/en-us/articles/360001784587-Best-Practice-Writing-Sustainable-Maintainable-LookML
- https://help.looker.com/hc/en-us/articles/360001766908-Best-Practice-Create-a-Positive-Experience-for-Looker-Users
- https://discourse.looker.com/t/example-lookml-development-guidelines/5979
- https://www.agileconnection.com/article/picking-right-branch-merge-strategy
We've outlined topics planned for future iterations of this style guide. Your suggestions and contributions to any published content (above) or planned topics (below) are welcome!
- dbt vs LookML
- DRY (Don't Repeat Yourself)
- Group and group item labels
- Views
- When not to use Liquid
- Clearer guidance on using section headers
- Models
- Datagroups
- Persist with
- Access grants
- Explores
- Opinions about:
- How many Explores to include per model?
- How many view labels to include in each Explore?
- How many fields to include in each Explore?
- Should we use just one
fields:
parameter with fully scoped fields, or multiplefields:
parameters (one for each view)?
- Opinions about:
- Dashboards
- User-defined dashboard (UDD)
- General guidelines
- When to use UDDs vs LookML dashboards
- List preferred chart types for common data questions / visualizations
- Take a stance on how to displaydates (e.g, YYYY-MM, or Month 'YY, or Mon 'YY, or Mon-YY, etc.)
- Guidance on working with
drill_field:
- Include screenshots to visually comminicate guidelines / recommendations
- User-defined dashboard (UDD)
- Version control
- Commit messages
- Commit frequency
- Access Control
- Using permission sets and roles
- Admin
- Guidance on configuring the Looker project