Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Render library specification: Difference between revisions

From MoodleDocs
(Replaced content with "{{Infobox Project |name = Renderer consistency |state = Specification |tracker = https://tracker.moodle.org/browse/MDL-45770 |discussion = https://moodle.org/mod/forum/dis...")
 
(99 intermediate revisions by 5 users not shown)
Line 1: Line 1:
{{Infobox Project
{{Infobox Project
|name = Renderer consistency
|name = Renderer consistency
|state = Specification
|state = Specification
|tracker = -
|tracker = https://tracker.moodle.org/browse/MDL-45770
|discussion = -
|discussion = https://moodle.org/mod/forum/discuss.php?d=261202
|assignee = Damyon, Sam
|assignee = Damyon, Sam
}}
}}
{{obsolete}}


== Project goals ==
The text on this page has been remove because it is out of date and inaccurate. Check the history to see the old text.
* Make it easier to create user interfaces.
* Make it easier to style the user interface.
* Make it easier for themers to customise the user interface.
* Better faciliate frontend frameworks in Themes.
* Give Moodle a more consistent look and feel.
* Improve site performance by reducing the CSS footprint.
 
{{Work in progress}}
 
==Understanding renderers in Moodle==
 
Renderers have been around since Moodle 2.0 and are now the requirement when writing any code that produces output.
Renderers come in many shapes and forms depending upon the developers take on how output should be produced.
They are typically given a range of arguments all of which fall into the space created by three concepts:
# Simple arguments - scalars, booleans the like; either being content or an option.
# Multi-purpose objects - objects that serve both to provide data for output and as a functional, interactional object. If you are familiar with the MVC architecture pattern then this is the model. It may relate directory to what is being output (it may be a forum post object when printing a forum post) but more likely its relation is to that of the component or a subsystem there of (giving a forum object to method producing a output for a forum discussion).
# Single-purpose object - here we have an object that is built to solely supplement the output process. Its properties are usables and its methods relate purely to the state of the object in relation to its display. It is to say just a container of useful information and devoid of logic.
 
Because there is no mandated organisation, nor has there ever being there is immense variation in the what constitutes content to a renderer. There is no way to predict what is provided, not that there should necessarily be of course.
 
One of the upsides to our current render system is that you are not limited to having a single renderer for a component, you can make use of language capabilities and the output framework and create layers of renderers to cut back code duplication and to aid in preparing a base for consistent structuring and output.
 
Into the equation we add targets and subtypes. Targets all us to create both standard renderers and renderers specific to the needs of the output method. Standard being HTML, without output methods including CLI and AJAX.
Subtypes allow for compartmentalisation to occur in component architecture allowing for greater granularity and organisation when writing a render and design its use within the component.
 
People have never being constrained as to how they implement a renderer, we've being happy enough to simply guide them towards using renderers because of the benefits they provide and the benefits are numerous but there are really two primary benefits:
 
1. A change in thinking: It required developers to think about their code organisation. They were introduced in a time before Object Orientation was used in design, a time when logic and output were tightly intermingled in most code.
 
2. An extensible approach to output: The render system allowed for the overriding renderers to occur. Renderers were supplied in a chained stack. This benefiting both theme designers and developers.
Theme designers got the final say - when they overrode a renderer they determined what would occur. When the renderer was used if they hadn't overridden the method being called it would fall back to the next renderer in the stack.
It also benefited developers, when you wrote a renderer for a component you were working on you a) knew that your output could be customised by themers and b) you could rely on the stack to re-use existing render methods published on the core_renderer. Another words if you need to create a notification you could ask your renderer to produce it and as you'd not defined in your renderer it'd fall to the responsibility of the next renderer in the chain.
This allowed you to produce "widgets" within your output that were more consistent across components.
Of course subjectively you could override those core methods to alter how a "widget" was rendered throughout your entire component.
It is highly flexible.
 
==Understanding themes==
 
Themers are without a doubt the most widely customised plugin provided by Moodle. But there are some gotchas to how we've created themes in Moodle, especially as we currently stand.
For a start there is a lose relation between the renderers and the output in that the HTML is created by the render in relation to the component whereas the CSS is in many cases added to the theme in order to style the HTML without relation to the component.
This leads to the renderer being dependent on the theme to do the right thing.
This is true for core by the way. Plugins can have styles.css files and as such can lay groundwork CSS without the need to inject it into a theme.
For core we work around this by having a "base" theme(s). The base theme is responsible primarily for laying the ground work for core and for applying some minimal default styling.
However the issue is still there, the relation betweem HTML and CSS in Moodle is largely indirect.
 
Next up lets consider frontend frameworks. Moodle has a chosen frontend framework at present, however rather than being located in core it is located within a theme.
This has implications on its use throughout Moodle in that it cannot directly be used within renderers as other themes may not be running the framework, or may be running a different framework.
While there is definitely some cross over there is much of the chosen framework that is simply out of reach short of overriding renderers and going to town to create a "secondary" display of Moodle.
 
==So what is the problem==
 
There are several. Lets be blunt about this. This specification is not a single task. It is about improving the state of output in Moodle and there are going to be several steps in achieving this. On a positive note these steps can in many cases be broken down into granular tasks that can be worked on asynchronously.
First lets understand some of the major problems:
* We've not established best practices, nor even documentation on what constitutes a good renderer, or considerations that should be paid mind in planning and designing of code.
* We've not got an established style guide/pattern library/element library, nor anything that could be referenced when someone starts tossing around those buzz words.
* Backend congestion. Through flexibility and a lack of the above documentation and guides we've got substantial fragmentation of our design. Spread across all layers of code and deep into the crevasses within our code. Design and output is duplicated in numerous places, and consequently ends up further fragmenting as further work forgets to update all places (or simply cannot update all places).
* Developers are encouraged to push functionality boundaries in order to take it places observed in other projects or to challenge oneself. While consistency is often talked about it is rarely observed when designing output. We end up with numerous "similar" looking widgets all functioning slightly differently and consequently there is a feeling that this is the way to achieve a new fresh look. One widget at a time.
* Existing renderer implementations vary widely and in many cases contain logic they should not. Access chcecks, database queries, object manipulations. All of which should not be present as it introduces muddling of concepts and logic that must be duplicated and then maintained for anyone overriding renderers.
* Themers have a mammoth task at present in applying a consistent style to Moodle, or in choosing to implement a new frontend framework (bootstrap, foundation, pureio etc). Our lack of an organisation in the output leaves a lot to be desired. Having the theme responsible for choosing a frontend framework is the right way to handle this, however backend Moodle doesn't support themeing as well as it should be/could be.
* Ontop of the above it introduces a need to override several renderers should you want to create a consistent style and because of inconsistent renderer implementaions this can easily lead to a maintenance nightmare. All for the sake of restyling how a users picture is presented through Moodle for instance.
* JavaScript introduces problems of its own. We are doing more and more with JavaScript these days. However there is a heavy dependence on the output that gets produced and the JavaScript enhancing it. In a lot of cases the relationship is ill defined and due to the complexity and structure of the JavaScript overriding the output structure of the rendered component is completely impossible for all but the most experienced developers.
* Inline with the above there we lack a best practice and documentation on how to delivery output templates as well as the creation, and manipulation of output structure.
 
== Identified issues==
There is a general trend in the problems noted, when looking at output we lack organisation, documentation, and consistentency across the board. However the actual issues we are focusing on in this spec can be identified as below:
 
* Lack of a style guide / element library / pattern library.
** Leading to inconsistent output and style.
** Increased workload due to usability and accessibility thinking and testing needing to occur repetitvely.
** Increased workload due to multilang (rtl) support usually coming after the deisng of new output.
* Inconsistent renderer implementations.
** Lack of best practices.
** Lacking plus outdated documentation.
** Logic-full renderers greatly hinder theming.
** An unnecessarily increased requirement to understand both PHP and Moodle code as each renderer differs and are usually poorly documented.
* No abstraction from CSS framework.
** Without organised structure classes are applied in a chaotic fashion leading to the requirement to duplicate core styles.
** As there is no core styles newly created output widgets need to be styled in all base themes leaving chance of design regressions occuring in predimonantly major upgrades but occasionally minor releases as well.
** Inconsistent output structure ensures CSS quickly balloons as styles need to be both created and copied to several areas.
* Poor linking between UI components and the JavaScript.
** Ill-defined link between output and the JavaScript enhancing it.
** No common technique to template UIs generated by javascript
 
==Manageable Tasks==
The following are the major tasks we have identified so far. These tasks can be though of as Epic's, or taks for which we will create subtasks (if this output specification itself becomes and Epic).
Within this section will include notes and implementation ideas on the major tasks we've identified.
 
* Chose an output methodology and begin defining core elements.
* Create an element library and accompanying style guide.
* Create a style guide document.
* Define and document renderer best practices.
* Define and update the JS documentation.
* Update renderer documentation.
* Update theme documentation and theme tutorials.
* Progressively convert renderers.
 
<b>Damyons original list left here for reference.</b>
* Rewrite the docs for renderers
** Read and rate each of the existing docs pages (see related links below)
** Write new complete docs for everyone (at [[Output API]])
** Cross link old docs to the new ones
* Add an admin tool that can show a categorised list of renderable objects for each plugin/and core - filled with test data. The goal of this tool is to
** validate that the renderer/renderable follows best practice (no DB queries, complex types, complex logic)
** provide a page for themers to check that their new theme correctly displays all the renderables
** provide a page for developers to see all the reusable renderables (in a well defined structure) they can use when building their own pages
* Define a comprehensive list of low level widgets we can add to core as renderables. This is a library of components that should be used by other renderers (by compositing them). E.g. list, table, warning, grid. These renderables should be structured into layers, starting from renderables that cannot be broken into smaller parts, up to widgets made of smaller renderables, up to layouts (and possibly up to entire pages).  Sources for this list should come from:
** Existing CSS Frameworks (bootstrap, pureio) (but must be framework agnostic)
** Existing renderables in Moodle that we see as “perfect” already (maybe there are some)
** Existing patterns in Moodle that we do over and over but don’t have a renderable for yet
* Build this list of widgets as core renderables with a generator so they are listed in the admin tool
* Use compositions of these new core renderables for all new code (policy decision)
* Discuss and agree on a best practice for writing JS that depends on HTML structures in the DOM (e.g. progressive enhancement - or just ids for action listeners) (perhaps a specific renderable for a JS region)
* Slowly convert the old renderers to compositions of the new ones with minimal logic etc (no eta)
 
===Define the elements that make up Moodle===
There are several tasks that will go into this, but the first and most important will be deciding upon an organisational methodology. Some way to compartmentalise the Moodle output.
At present a reducing granularity system is looking the most appealing. If you have a read of the [http://bradfrostweb.com/blog/post/atomic-web-design/ Atomic Design] written by Brad Frost you'll get the drift of the sort of compartmentalisation we are looking at.
 
Once a system has being chosen the following tasks can be tackled:
* Identify the layers we require.
* Define the boundaries and responsibilities of those layers.
* Identify the initial set of elements, likely the finest granularity first as I imagine starting at the bottom and working up will be the best way to proceed.
 
Further elements (those relating to Moodle will be defined as part of the element library work).
 
===Element library and style guide===
Add an admin tool that can show a categorised list of renderable objects for each plugin/and core - filled with test data. The goal of this tool is to:
 
* Provide a page for themers to check that their new theme correctly displays all the renderables
* Provide a page for developers to see all the reusable renderables (in a well defined structure) they can use when building their own pages
 
The tasks here will be:
* Spec the element library tool with regard to our chosen element methodology.
* Create the element library tool.
* Establish a definition method of elements, and compositions of elements as renderables.
* Define the core elements from the task above in code somehow and verify the element library tool reveals them.
* Finally define a comprehensive list of low level widgets we can add to core as renderables. This is a library of components that should be used by other renderers (by compositing them). E.g. list, table, warning, grid. These renderables should be structured into layers, starting from renderables that cannot be broken into smaller parts, up to widgets made of smaller renderables, up to layouts (and possibly up to entire pages).  Sources for this list should come from:
** Existing CSS Frameworks (bootstrap, pureio) (but must be framework agnostic)
** Existing renderables in Moodle that we see as “perfect” already (maybe there are some)
** Existing patterns in Moodle that we do over and over but don’t have a renderable for yet
 
Ontop of this there is functionality that would be great to add to it:
 
* Validate that the renderer/renderable follows best practice (no DB queries, complex types, complex logic)
* Provide responsible testing immediately within the tool. Adjusting the viewing area on queue to allow both developers and designers to experience how the individual renderables respond in varying presentation medias.
* Provide language direction testing immediately within the tool. Like the above allow designers and developers to quickly experience a renderable in a different language directions.
* Renderable linear reporting. So that you can see which other renderables make use of this renderable and which renderables get used by this renderable. This will be hugely helpful in judging impact when themeing.
 
====Thoughts on naming====
We will need to define useful names for the different categories of renderables so that we can effectively organise them and provide guidelines for writing each type - the names are a small part of this solution but will possibly be a point for contention. Different frameworks have different names for these things and people will prefer something that sounds like something they are already using.
 
(draft!) Categories for renderables
 
* Elements
* Components (built of smaller elements)
* Layouts (structured arrangements of smaller components/elements/layouts)
 
Refs for categorizing patterns
* http://bradfrostweb.com/blog/post/atomic-web-design/
* http://oocss.org/
* http://alistapart.com/blog/post/getting-started-with-pattern-libraries
* http://style.codeforamerica.org/
 
===Style guide===
This has two real advantages.
 
# First assumably this will be developed initially while defining the elements that will make up Moodle output and will aid us in verifying what we are doing. If it can be easily documented then we are on the right track. If we start encountering to many conditions and or too much variation then we are drifting off track.
# When defining new elements we are able to use our style guide to do so and it'll provide us measure of how Moodle output evolves.
 
The big disadvantage to this will be that this will be a dry document to create.
 
===Define and document renderer best practices===
 
This will be tricky and no doubt how we decide to define a best practice will have to have regard for the output methodology we choose.
 
===Define and update the JS documentation===
 
Discuss and agree on a best practice for writing JS that depends on HTML structures in the DOM (e.g. progressive enhancement - or just ids for action listeners) (perhaps a specific renderable for a JS region)
 
===Update renderer documentation====
This will of course need to be done after the element library and renderer best practices but should be pretty simple at that point.
* Read and rate each of the existing docs pages (see related links below)
* Write new complete docs for everyone (at [[Output API]])
* Cross link old docs to the new ones
 
===Update theme documentation and theme tutorials===
There are likely the most well documented plugin type within Moodle. There are good specification docs, good 2.0 conversion docs and good tutorials on many aspects of theming.
Many of these pages will need to be updated to reflect best practices and such after we start ticking off some of the other tasks.
 
===Progressively convert renderers===
This is the very last task really, and is pretty much just an ongoing job that may not even require a specific MDL issue.
It is not essential but in the interests of not letting core code fall behind core concepts it should be worked on.
 
== Notes on renderers / renderables ==
Proposed improvements to the docs on renderers / renderables.
First - the docs need an overhaul to more clearly explain how renderers / renderables work for core devs, plugin devs and themers. There needs to be clearer guidelines for the things that can be done in a renderable, and in a renderer.
 
A "good renderer" is:
* Receives some “data” through a renderable
* Produces some “output”
* Where “output” is some HTML and any javascript init calls
* Can use basic PHP functions/loops, like for(), foreach(), count()
 
A "good renderer" is not:
* nasty php logic (or even non-nasty php logic)
* access checks
* non-trivial function calls
* using any Moodle functions not related to output
* calling the database
* unshaven
* a bad renderer
 
A “renderable” is:
* All the data required to generate the output.
* Properties should be simple data types only, or renderables, or array of those
 
== Related links ==
* [[Output API]]
* [[Migrating your code to the 2.0 rendering API#Outputting HTML specific to your module]]
* [[Output_renderers]]
* [[Overriding_a_renderer]]
* [http://moodle.org/mod/forum/discuss.php?d=177535 Forum discussion on renderers]
* [[Renderer]]

Latest revision as of 03:42, 12 December 2016

Renderer consistency
Project state Specification
Tracker issue https://tracker.moodle.org/browse/MDL-45770
Discussion https://moodle.org/mod/forum/discuss.php?d=261202
Assignee Damyon, Sam


Warning: This page is no longer in use. The information contained on the page should NOT be seen as relevant or reliable.


The text on this page has been remove because it is out of date and inaccurate. Check the history to see the old text.