|
Making Macros more Component-like in Helma 2.0 Problem Description and AnalysisWith the current way of building Helma applications, there is often a conflict between Actions and Macros regarding which one should control aspects of rendering particular parts of a dynamically rendered page. Actions are the entry points for requests issued via the Web. They generally know what is meant to happen when a request comes in, but they don't know what exactly it should look like. The actual look of a page is delegated to the appication's Skins, which, through Macro tags, accesses the application's data and casts it into a final form.Currently, the distribution of control is often an either-or decision: Either an Action determines what is to displayed and simply pushes the data through a "dumb" skin, or the Action is agnostic and the parts to be displayed are pulled out of the app's data by "smart" Macros. Both approaches have their shortcomings. Problems with the "Push" approachThe "Push" approach, where the Action acts as controller and pushes data through a predetermined set of Skins, has the obvious shortcoming of lacking flexibility. In contrast to Skins, Actions are usually hardcoded and can't be customized, so it's not easily possible to enhance or modify a page generated with the "Push" approach.This is a good thing in situations where there is an actual Action to perform that shoudn't be messed with. However, in cases where what we want is customizability, this apporach does not work well. Problems with the "Pull" approachThe "Pull" approach, where the application offers a set of Macros to pull data out of the application, is the response to the shortcomings of the "Push" approach described in the previous paragraph. It obviously solves the problem custimizability, letting the Skin designer choose which pieces to use and display and which not.However, there is a (less obvious) problems with this approach. "Pull" style macros tend to be written as self sufficient entities, doing everything from access control to accessing persistent application data. Hence, Macros often end up being more complex, powerful and specific than they should be. This is a bad thing for several reasons. First, it makes it hard to impossible to separate different aspects of an application, e.g. access control and rendering some piece of HTML. Second, it forces developers to make Macros very specific and thus greatly hinders reusability. Finally, some tasks may be performed again for each Macro instead of performing it once by the Action and sharing its results. Problem AnalysisThe main reason why most application designs fall either in the Push or in the Pull category is that Helma 1.2/1.3 lacks a convenient way of sharing per-request metadata between Actions and Macros. Currently, the only way to achieve this is to use one of the req.data, res.data or session.data objects. However, these data objects are already used for other purposes such as delivering form data or pieces of rendered HTML. Helma 2.0 should offer dedicated information path in order to ensure Helma developers and facilitate better application design practice.Proposed ImplementationThis RFC proposes two partial and complementary solutions, one to provide a container for per-request metadata shared between the Action and all Macros, and one to allow per-Macro binding of parameters. The first is a slight improvement over the Helma 1.2/1.3 status quo, while the latter is a more significant leap that may well influence the basic design of future applications.Shared per-Response MetadataThis part of the proposal describes a per-response container for metadata. Metadata here means data that is not directly used for rendering purposes, but as control data to influence the further flow of execution. The metadata container works analogical to the res.data object and is called res.meta. It will relieve the res.data object from the burden of carrying all per-response data and allow it to serve as a more dedicated container for response part data.This may be a general approach in Helma 2.0 to separate some of the common data structure, such as replacing req.data with singular req.form, req.headers and req.cookies containers. This will be subject to a different RFC, though. Per-Macro Parameter BindingThis part of the proposal describes a way of directing data towards a target Macro without knowing if or where the Macro is invoked and without doing any of the Macro's job. This solution works by binding data to a specific ID in the controlling code, and by using this ID inside a Skin's Macro tag to get to this data.The controlling code uses a new function res.bind() to obtain an object that is bound to a specific ID. This object is then populated with data to be passed to the Macro.
Macro tags inside Skins could than simply use an id attribute to "dial up" the bound object.
<% html.table id="mainlist" %>The simplest way to pass the bound object to the Macro would be to pass it to the Macro function as first parameter. In-place attributes in the Macro tag would then override the bound values. For example, the following Macro tag would get the object bound to "mainlist", but override the background value in the original object: <% html.table id="mainlist" background="#aadd00" %>This approach is both simple and "conceptually backwards compatible". An alternative approach would be to pass the bound object to the Macro function separately from the attributes defined in the Macro tag. In both cases, the important fact is that the bound object is "pushed" to the Macro function. The Macro code does not have to do anything in order to gain access to the data.
... comment
|
navigation
Download
Community
Weblog
Mailing Lists
IRC Channel
Documentation
Introductions
Tools
Reference
Project
Roadmap
Bug Reporting
Source
Wiki
Tags
Updates
Related Projects
search
|
||||