AML Reusability Guide
AML provides several features to reuse code and logic across different objects, improving maintainability and efficiency in analytics development. Almost anything created in AML can be defined once and reused by any other AML object.
For example:
- Create a chart once and use it in multiple dashboards
- Create part of a dashboard and use it in multiple dashboards
- Define dimensions, metrics, calculations and re-use in multiple models
- etc.
By reusing logic, you can avoid duplication, reduce errors, and make your code more modular and scalable. This page acts as a guide to provide an overview of the general steps needed to reuse logic in AML.
The Reusability Process
- Step 1: Identify the logic to be reused and the resulting object that will reuse said logic.
- Step 2: Extract reused logic to const or Partial for later reference.
- Step 3: Refer to the reused logic in the resulting object.
- Step 4 (optional): Extend the reused object to further customize it. This is useful when you want to mostly reuse the whole object, but with some additional small modifications.
- Step 5 (optional): Parameterize logic with Func: for cases when you need to customize the reused logic with different parameters.
Step 1: Identify the logic to be reused
In order to reuse logic in AML, you should first identify the logic to be reused, and the resulting object that reuse said logic. Examples of reused logic include:
- SQL and AQL code snippets, reused in metrics and dimensions' definitions
- Dataset's metrics, reused in other datasets
- Model's dimensions, reused in other models
- Dashboard's blocks and themes, reused in other dashboards
- etc.
Step 2: Extract the reused logic to const or Partial
Top level objects in AML with explicit types (e.g. DataModel, Dataset, Dashboard, etc.) are already AML constants and ready to be reused, thus no further extraction is needed. An object's properties (Dashboard's blocks, Model's dimensions, etc.) are also ready to be reused individually (see step 3 for details).
There are 3 cases when extracting reused logic is necessary:
- For reusing primitive values such as numbers, strings, etc.
- For reusing non-top level objects in AML such as
VizBlock
, you can extract them to a const object. - For reusing parts of an object, you can extract them to a Partial object.
Primitive values can be extracted to const objects. For example:
const my_const = 123
const my_string = "Hello, World!"
Non-top level objects are sub-objects that are part of another object, such as a VizBlock
or PageTheme
in a Dashboard
. Non-top level objects with explicit types can be extracted to a const object.
// Equivalent: const my_block = VizBlock {...}
VizBlock my_block {
// details omitted...
}
Multiple properties of objects (such as dataset's metrics, data model's fields) can be extracted together, at once, to a Partial object. Note that any subset of an object's properties can be put in a partial.
PartialDataset my_dataset {
description: "This is a dataset that contains metrics a and b"
metric a {
// details omitted...
}
metric b {
// details omitted...
}
}
PartialModel my_model {
dimension a {
// details omitted...
}
dimension b {
// details omitted...
}
}
To reuse Partial
objects, you can use extend
function. Please refer to step 4 for details.
Extracted objects can quickly clutter your project files, making it difficult to navigate your work. To improve organization, consider grouping extracted AML objects and functions into an AML module. An AML module is essentially a directory that serves as a container for these related items, helping you maintain a cleaner and more structured project.
Step 3: Refer to the reused object or its properties
For primitive values, you can refer to them directly by their name, or use string interpolation feature.
const my_const = 123
const color_blue = "#0000FF"
PageTheme my_theme {
background_color: color_blue
}
const today = @sql current_date() ;;
Model today_sales {
description: "Sales data for today"
query: @sql select * from sales where date = ${today} ;;
// other details omitted...
}
For full object with explicit names, you can refer to them directly just with the name itself.
For individual properties of objects, you can refer to them by using the object's name followed by a dot and the property name. For examples:
Model original_model {
dimension my_dimension {
// details omitted...
}
}
Model another_model {
dimension another_dimension: original_model.dimension.my_dimension
}
Dataset original_dataset {
metric a {
// details omitted...
}
}
Dataset another_dataset {
metric b: original_dataset.metric.a
}
Dashboard original_dashboard {
block my_block {
// details omitted...
}
}
Dashboard another_dashboard {
block another_block: original_dashboard.block.my_block
}
Step 4 (optional): Extend an existing object
Refering to the reused object directly is useful when you want to reuse the whole object. In order to reuse an existing object with some additional modifications, you can use the extend
function. This function can be applied on an analytics object to produce a new object that takes on the original properties, while merging in the additional properties.
Model base_model {
dimension a {
// details omitted...
}
}
Model another_model = base_model.extend({
dimension b {
// details omitted...
}
})
Another use case is to reuse a Partial
object. You can use extend
function to combine the Partial
object with another object.
PartialModel my_partial_model {
dimension a {
// details omitted...
}
}
Model base_model {
// details omitted...
}
Model another_model = base_model.extend(my_partial_model)
More details about extend
function can be found in the AML Extend page.
Step 5 (optional): Parameterize logic with Func
When you need to customize the reused logic with different parameters, you can use Func
to parameterize the logic. Func
is a reusable block of code designed to perform a specific task. It can take parameters and return a value.
Func sum(x: Number, y: Number) {
x + y
}
Func double(x: Number) {
const multiple = 2
x * multiple
}
Func myvizBlockWithDataset(dataset: String) { // auto infer return type = VizBlock
VizBlock {
label: 'A pie chart'
viz: PieChart {
dataset: dataset // use the dataset parameter here instead of hard-coding
legend: ref('public_users', 'role')
series {
field {
ref: ref('public_users', 'id')
aggregation: 'sum'
}
}
}
}
}
Dashboard my_dashboard {
// details omitted...
block my_block: myvizBlockWithDataset('ecommerce')
}
More details about Func
can be found in the AML Func page.
Conclusion
By following the steps above, you can effectively reuse logic in AML, making your analytics development process more efficient and maintainable. For more details on AML's reusability features, please refer to the AML Reusability Overview.