User:SnorlaxMonster/Template architecture

From Bulbapedia, the community-driven Pokémon encyclopedia.
Jump to navigationJump to search

One of the most important things to consider when designing a template is its API — how users interact with it when using it.

Templates that separate how they work from the inputs that they display can be easily redesigned, without requiring existing usages to be updated. While it is impossible to entirely eliminate the need to update template usages, by following certain guidelines, it is possible to reduce how often this needs to occur.

Many templates are currently designed in ways that will require updating individual usages to change their design. The goal should be to ensure that the next template migration is the last that will ever need to happen, as the new API design is versatile enough to allow the template to be entirely redesigned without having to update any usages. Or at the very least, that any template migration could be easily automated via a bot run.

Core principles

The following are the core principles to consider when designing a template:

  1. Single responsibility: Do one, and only one, thing.
  2. Separation of concerns: The inputs taken by a template should not make assumptions about how they will be used.
  3. Intuitive: Have an intuitive API for editors who never look at the template's code.
  4. Extensible: Minimize how frequently the template itself needs to be updated when predictable new information needs to be added.

When to use templates

Avoid code directly in mainspace pages

Most users will only ever interact with the mainspace. As much as possible, editors should not have to understand anything more complex than basic wiki markup and which template to use in order to edit pages.

  • MediaWiki-specific tags — such as <ref> and <gallery> — are encouraged in mainspace pages.
  • Tables are encouraged in the mainspace, as long as they are used as tables. Tables should not be used for layout purposes.
    • Nested tables should never be used.
    • Raw CSS should be avoided in the mainspace. Tables should usually be styled using CSS classes, not CSS directly on the mainspace page. Rows with uniform coloring should originate from the table's CSS class, but rows with variable coloring may need to have coloring CSS defined against individual rows.
  • <div> and <span> tags should never appear directly on mainspace pages. If a design is desired that uses these tags, that design should be created in a template.
  • <br> should be used sparingly in the mainspace. Where possible, lines should be allowed to wrap naturally (by constraining the width of the container) or handled by templates — differing screen sizes and skins will prefer line breaks in different places, so this is best handled in a centralized manner in templates, not on individual pages. If a template needs to accept a list of items as an input, this will ideally be passed to the template as a list — either with individual parameters for each item, or using bullet syntax (so that MediaWiki parses it as <ul> and <li> elements, which can be more easily styled using CSS).

API design

Avoid making assumptions about how a template displays

The data that a template takes as input should be independent of how that data is formatted in the output.

For example, consider a template that displays a list of arbitrary length in rows of 6. If this is structured as a separate template for each row, accepting 6 items as input, then this display of 6 items per row is baked into the template definition. If in the future, it is desired that the template instead display a variable number of items per row based on screen resolution, or display the data in a table with one item per row, the input structure now arbitrarily has 6 items per template call despite this not being reflected in the output. In fact, changing the template's display in this case may require updating every single usage of the template to a new syntax. Additionally, if an item is inserted earlier in the list, this will require shuffling down every subsequent item in the list into the next template call. Instead, if this template had been originally designed to have one wrapper template and one template call per list item, it could display any of these aforementioned ways without requiring any changes to the template usages.

Likewise, mixing table syntax or HTML tags (such as <div> tags) with template necessarily makes assumptions about the structure of the templates. This can be justified in the case of table header templates, where the header of a table is standardized in a template, while the rows and footer and constructed using raw table syntax. But if the header and rows are both constructed using templates, then the footer should be too (even if the template is simply outputting |}).

Avoid accepting CSS as input

A template should almost never accept raw CSS as input. Taking raw CSS requires making substantial assumptions about how a template is designed, which restricts the ability to redesign that template in the future.

The most common instance of passing CSS to a template is colors. Templates will often be colored depending on the subject they are presented data about — for example, Pokémon infoboxes are colored based on the type of that Pokémon. There are two potential approaches to passing colors to a template: specifying the names of standardized colors to use (e.g. |colorscheme=grass), and passing the colors directly (e.g. |colorscheme={{grass color}}, |colorscheme=3FA129). The first approach — specifying the name of the color instead of providing raw CSS values — is strongly preferable, as it defers the styling to the template itself, not the individual instance. For example, this allows a template to use different shades of the same color as it desires, without needing separate arguments for each different shade of that input color. This means that a template can easily be redesigned without needing to change its inputs.

Aim to be consistent with similar templates

Ideally, templates that do similar things to each other have similar APIs.

For example, most link templates on Bulbapedia accept the link as the first parameter, and display text as the second parameter. If your link template accepts these arguments in the reverse order, it will be unintuitive to most editors.

Avoid hardcording inputs into parameters

When designing a template, consider how the data might be extended in the future. Avoid putting

For example, when designing a template that displays data from multiple different games, it can be tempting to define separate parameters for each game. Consider a gallery template, that displays images from each game in a particular set of games. If the template takes the image for each game as input on a unique parameter (e.g. rby_sprite, gsc_sprite, etc.), the template will need to be updated every time a new game is released. Instead, consider defining a wrapper template, and individual item templates that take both the game and image as input. This means that the template does not require updating when a new game is released.

Prefer using named parameters for optional parameters

There are two types of template parameters: Positional parameters and named parameters. In the example {{MSP|0487|Giratina|form=O}}, the template {{MSP}} is being called with two positional parameters (0487 and Giratina) and one named parameter (form with the value O).

Due to how positional parameters are specified, it is difficult to provide later-numbered positional parameters without defining earlier parameters. As a result, template parameters should be structured so that there is never an occasion where a later positional parameter is defined when an earlier positional parameter is undefined. If both parameters are optional, it is often preferable to make one or both of those parameters a named parameter instead.

For example, consider a notice template that takes two parameters: the reason for the template's presence (which does not need to be specified), and the part of the article that the template is referring to (defaulting to the whole article). It is conceivable to have an instance of the template that specifies the reason for its presence but applies to the whole article, and it is likewise conceivable to have a notice template that applies to only a specific section without specifying a reason. As such, at least one of these parameters should be a named parameter, so that the other can be easily specified without requiring the first to be present.

Use meaningful defaults

MediaWiki does not enforce that any particular template parameter be specified. As such, the default behavior of a template should be reasonable for a null input. Parameters should usually default to displaying "Unknown" when not specified, or not display at all.

While it is often tempting to make a good example use-case your template's default display, this is usually a bad idea. Instead, create a documentation subpage, and place your example on that page.

For example, if a template is pre-populated with Pikachu as a default, this likely means that the type field is pre-populated with "Electric". As a result, some users may observe that they can simply leave the type parameter null and still get the desired display. If the template were to be redesigned in the future, this could cause such usages to break, requiring an audit of all usages of the template to ensure they are defining all input parameters as expected.

Template styling

There are many different templates on Bulbapedia, but most of them fall into only a handful of categories. Some simple templates (e.g. link templates) are unlikely to use CSS styling, so these considerations largely do not apply to them, whereas other types make extensive use of it.

Common types of styled templates include:

  • Infoboxes
  • Table templates
  • Navigation templates
  • List templates
  • Notice templates

Use common designs whenever possible

Where possible, styled templates should rely on common CSS classes for most of their styling, with the individualized templates instead focusing on how to lay out that data. In cases where common designs are not used, there should be an exceptional reason that that particular template cannot use the common design, or that template's design should be considered to be adopted as a new common design.

For example, instead of every single infobox defining its own width, padding, margins, etc., infoboxes should all be members of an infobox class defined in the site-wide CSS which handles most of these concerns. This does not necessarily need to be the same class for every single infobox — there can feasibly be a handful of standardized infobox designs. Likewise, most navboxes use one of a handful of navbox designs, so should use a common CSS class with other navboxes that use the same design.

The usage of common designs means that template styling problems can be solved across the site's thousands of templates by adjusting only a handful of common designs, instead of having to test and update every single template individually. This is especially important when there are issues with display on mobile platforms, at specific resolutions, or on specific skins.