cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stefano Mazzocchi <stef...@apache.org>
Subject [RT] the quest for the perfect template language
Date Wed, 02 Apr 2003 18:25:49 GMT
The more I use the flow inside cocoon, the more I think there is no way 
back. Not only it enforces SoC, it also removes over-SoC, which happens 
where you have your information scattered around the entire place (as 
for PHP stuff, for example).

But if the sitemap is the ultimate pipeline engine and the flow is the 
ultimate (and transparently statefull!) controller engine, what is the 
*ultimate* view, the best template system?

There are a bunch of paradigms on the table but they can be separated in 
two big groups.

  1) generation based
  2) transformation based

both can be divided further into

  a) compilation based
  b) interpretation based

so, the chart is

                  +----------------------+--------------------------+
                  |                      |                          |
                  |     compilation      |      interpretation      |
                  |                      |                          |
+----------------+----------------------+--------------------------+
|                |                      |                          |
|   generation   |       XSP,JSP        |     Velocity,X:Forge     |
|                |                      |                          |
+----------------+----------------------+--------------------------+ 

|                |                      |                          |
| transformation |        XSLTC         |  JXPath,Jexl,XSLT,DVSL   |
|                |                      |                          |
+----------------+----------------------+--------------------------+


The chart should be four-dimensional as we could add another two axis 
based on the fact that we can further divide them into

  i) event stream based
  ii) octet stream based

and

  I) markup-based syntax
  II) text-based syntax

so, the final synopsis is

  XSP      -> generation      compilation     event  xml
  JSP      -> generation      compilation     octet  xml(1)
  Velocity -> generation      interpretation  octet  text
  X:Forge  -> generation      interpretation  event  xml
  XSLTC    -> trasnformation  compilation     event  xml
  XSLT     -> transformation  interpretation  event  xml
  JXPath   -> transformation  interpretation  event  xml
  Jexl     -> transformation  interpretation  event  xml
  DVSL     -> transformation  interpretation  octet  text

Most notably, it can be seen how XSLT/JXPath/Jexl cover the same exact 
space.

This leads me to believe that XSLT (if properly instrumented) could 
remove the need for the other two. Moreover, if this instrumentation is 
compatible with the XSLTC operation, it would be possible to further 
enhance the performance by pre-optimizing the stylesheet during 
pre-compilation.

Now, first of all, with modern JVMs, it's not to know when compiled code 
is more performant than interpreted code.

Under all circumstances, a java virtual machine runs on at least two 
layers of emulation:

  1) java bytecode -> native bytecode
  2) native bytecode -> internal CPU microcode

with technologies like Transmeta CodeMorphing or even Intel/AMD 
CISC->RISC internal out-of-order instruction execution, the second layer 
is still significant. For RISC-oriented architectures like PowerPC or 
Sparc, the second layer is smaller, but still very important due to the 
internal superscalar nature of modern CPUs.

Optimize code that will run on so many different execution environments 
is very hard, if not impossible.

The only interesting approach, IMO, is the one taken by XSLTC: compiling 
the stylesheet doesn't necessarely mean to *inline* the execution of 
methods by unrolling loops (like it is done in XSP, for example), but to 
remove those checks that are not necessary because the stylesheet has 
been analyzed previously.

This is nothing different from what hotspot does, only that it does it 
with run-time collected information.

So, the point is: compilation is useful only if its used to remove 
operations that are not going to be needed.

                                  - o -

Here are my thoughts:

1) I've come to the conclusion that we need both generation-based and 
transformation-based approaches.

Why?

well, the first is useful when you have non-xml data fed into the view, 
the second is useful when you have xml data fed into the view.

With the ability of cocoon pipelines, it's going to be harder and harder 
to choose which approach is best as I find myself using *both* at the 
same time in different situations.

2) stream based solutions are better than non-stream based one because 
they *always* remove the parsing stage.

3) all template languages will need

  a) variable expansion
  b) conditionals
  c) iterations

and nothing more!

4) verbosity of the syntax must be balanced: too few verbosity is 
efficient but grows into obscurity (ie Perl), too much verbosity is 
harmful because signal/noise ratio is reduced.

5) control should be inverted: the template must be a view, it should be 
'pushed' the data in, it should not contain any data-pulling logic other 
than the one used to pull data from the dataset passed on by the 
underlying controlling stage.

                                  - o -

IMHO, the template language which is closer to the optimum is XSLT but 
only with one change:

  FORGET THE XML SYNTAX!

I'm entering wild mode now, so bear with me. Suppose you had:

  1) a syntax that is simple and efficient to describe a stylesheet
  2) a defined object model accessible thru regular xpath queries
  3) no ability to call extensions


Let me give you an example of what I mean. First of all, let us assume 
that the template engine assumes an xml-izable representation of all the 
data it has access to.

So, for example:

input:
<list name="whatever" xmlns:ns="http://whatever/">
  <item xml:lang="en">blah</item>
  <item xml:lang="it">blah</item>
  <item>
   <ns:subitem>blah</ns:subitem>
   <ns:subitem>blah</ns:subitem>
  </item>
</list>

request:
...

session:
...

deli:
...

flow:
...

then we can have the following templatesheet:

namespace ("ns") {
  "http://whatever"
}

template ("/") {
  <html>
   <head>
    <title>{list/@name}</title>
   </head>
   <body>
    <form action="{flow::continuation/id}">
     <table>
      attribute ("width") {
        if ({deli:screen-width}) {
	{deli:screen-width}
        } else {
         "100%"
        }
      }
      apply-templates
     </table>
    </form>
   </body>
  </html>
}

template ("item") {
  <tr>
   <td>
    if ({ns:subitem}) {
      if ({count(ns:subitem}) > 1) {
        for-each ({ns:subitem}) {
          <span style="color:green">{.}</span>
        }
      } else {
        <span style="color:red">{.}</span>
      }
    } else if ({request::lang} == {@lang}
            || {request:://cookie/lang} == {@lang}) {
      {.}
    } else {
      "unknown language \"" {@lang} "\""
    }
   </td>
  </tr>
}

the above should be parsed, transformed into a regular xslt stylesheet 
and fed into a normal XSLT processor with extensions.

The above will then be:

  1) useful for both generation and transformation (the input object 
will be empty and the / template would be called)

  2) compilable

  3) stream based

  4) reduced verbosity yet terse

  5) access to all cocoon object model and extensible

  6) namespace-capable

  7) declarative

What do you think?

P.S. the above syntax is rough and I think it's not that perfect, but a 
terse yet powerful syntax is achievable.

Stefano.




Mime
View raw message