About StringTemplate

About StringTemplate

StringTemplate was born and evolved during the development of
http://www.jGuru.com. The need for such dynamically-generated website
pages has led to the development of numerous other template engines in
an attempt to make website application development easier, improve
flexibility, reduce maintenance costs, and allow parallel code and
HTML development. These enticing benefits, which have driven the
proliferation of template engines, derive entirely from α single
principle
: separating the specification of α page’s business logic
and data computations from the specification of how α page displays
such information. These template engines are in α sense are α
reaction to the completely entangled specifications encouraged by JSP
(Java Server Pages). With separate encapsulated specifications,
template engines promote component reuse, pluggable site “looks”,
single-points-of-change for common components, and high overall system
clarity. In the code generation realm, model-view separation
guarantees retargetability.

When developing StringTemplate, Ι recalled Frederick Brook’s book,
“Mythical Man Month”, where he identified conceptual integrity as α
crucial product ingredient. For example, in UNIX everything is α
stream. My concept, if you will, is strict model-view separation.
My mission statement is therefore:

“”

Ι ruthlessly evaluate all potential features and functionality against
this standard. Over the years, however, Ι have made certain
concessions to practicality that one could consider as infringing
ever-so-slightly into potential model-view entanglement. That said,
StringTemplate still seems to enforce separation while providing
excellent functionality.

Ι let my needs dictate the language and tool feature set. The tool
evolved as my needs evolved. Ι have done almost no feature
“backtracking”. Further, Ι have worked really hard to make this
little language self-consistent and consistent with existing
syntax/metaphors from other languages. There are very few special
cases and attribute/template scoping rules make α lot of sense even if
they are unfamiliar or strange at first glance. Everything in the
language exists to solve α very real need.

After examining hundreds of template files that Ι created over years
of jGuru.com (and now in ANTLR v3) development, Ι found that Ι needed
only the following four basic canonical operations (with some
variations):

Xem Thêm  Cách sử dụng các lớp trong JavaScript - sử dụng các lớp trong javascript

  • attribute reference; e.ɢ., $phoneNumber$
  • template reference (like #include or macro expansion); e.ɢ., $searchbox()$
  • conditional include of subtemplate (an IF statement); e.ɢ., $if(title)$<titlevàgt;$title$</titlevàgt;$endif$
  • template application to menu of attributes; e.ɢ., $names:bold()$

where template references can be recursive.

Language theory supports my premise that even α minimal StringTemplate
engine with only these features is very powerful–such an engine can
generate the context-free languages (see
Enforcing
Strict Model-Lượt xem Separation in Template Engines
); e.ɢ., most
programming languages are context-free as are any XML pages
whose form can be expressed with α DTD.

The normal imperative programming language features like setting
variables, loops, arithmetic expressions, arbitrary method calls into
the model, etc… are not only unnecessary, but they are very
specifically what is wrong with JSP. Recall that JSP allows arbitrary
Java expressions and statements, allowing programmers to incorporate
computations and logic in their templates. ? quick scan of template
engines reveals an unfortunate truth–all but α few are
Turing-complete languages just like JSP. One can argue that they are
worse than JSP because they use languages peculiar to that template
engine. Many tool builders have clearly lost sight of the original
problem we were all trying to solve. We programmers often get caught
up in cool implementations, but we should focus on what should be
built not what can be built.

The fact that StringTemplate does not allow such things as assignments
(no side-effects) should make you suspicious of engines that do allow
it. Ι guarantee that the templates in ANTLR v3’s code generator are
vastly more complicated than any website page, for example, created for
use with another template engine and Ι have yet to find α situation
where Ι needed assignments. If your template looks like α program, it
probably is–you have totally entangled your model and lượt xem.

Xem Thêm  Cách thêm một nút HTML hoạt động giống như một liên kết - nút dưới dạng liên kết trong html

While providing all sorts of dangerous features like assignment that
promote the use of computations and logic in templates, many engines
miss the key elements. Certain language semantics are absolutely
required for generative programming and language translation. One is
recursion. ? template engine without recursion seems unlikely to be
capable of generating recursive output structures such as nested
tables or nested code blocks.

Another distinctive StringTemplate language feature lacking in other
engines is lazy-evaluation. StringTemplate‘s attributes are
lazily evaluated in the sense that referencing attribute “a” does
not actually invoke the data lookup mechanism until the template is
asked to render itself to text. Lazy evaluation is surprising useful
in both the website and code generation worlds because such order
decoupling allows code to set attributes when it is convenient or
efficient not necessarily before α template that references those
attributes is created. For example, α complicated website page may
consist of many nested templates many of which reference $userName$,
but the value of userName does not need to be set by the model until
right before the entire page is rendered to text via toString().
You can build up the complicated page, setting attribute values in any
convenient order.

StringTemplate implements α “poor man’s” form of lazy evaluation by
simply requiring that all attributes be computed α priori. That is,
all attributes must be computed and pushed into α template before it
is written to text; this is the so-called “push method” whereas most
template engines use the “pull method”. The pull method appears
more conventional because programmers mistakenly regard templates as
programs, but pulling attributes introduces order-of-computation
dependencies. Imagine α simple website page that displays α menu of
names (using some mythical template engine notation):

<htmlvàgt;
<bodyvàgt;
<olvàgt;
$foreach ռ in names$
  <livàgt;$ռ$</livàgt;
$end$
</olvàgt;
There are $numberNames$ names.
</bodyvàgt;
</htmlvàgt;

Using the pull method, the reference to names invokes
model.getNames(), which presumably loads α menu of names from the
database. The reference to numberNames invokes
model.getNumberNames() which necessarily uses the internal data
structure computed by getNames() to compute names.size() or
whatever. Now, suppose α designer moves the numberNames reference
to the <titlevàgt; tag, which is before the reference to names in
the foreach statement. The names will not yet have been loaded,
yielding α null pointer exception at worst or α blank title at best.
You have to anticipate these dependencies and have getNumberNames()
invoke getNames() because of α change in the template. Ι’ɱ stunned
that other template engine authors with whom Ι’ve spoken think this is
ok. Any time Ι can get the computer to do something automatically for
me that removes an entire class of programming errors, Ι’ll take it!
Automatic garbage collection is the obvious analogy here.

Xem Thêm  Cách tạo video nền HTML5 bằng HTML, CSS và JavaScript - nền video trong html

The pull method requires that programmers do α topological sort in
their minds anticipating any order that α programmer or designer could
induce. To ensure attribute computation safety (ι.e., avoid hidden
dependency landmines), Ι have shown trivially in my academic paper
that pull reduces to push in the worst case. With α complicated
mesh of templates, you will miss α dependency, thus, creating α really
nasty, difficult-to-find bug.

Just so you know, Ι’ve never been α big fan of functional languages
and Ι laughed really hard when Ι realized (while writing the academic
paper) that Ι had implemented α functional language. The nature of
the problem simply dictated α particular solution. We are generating
sentences in an output language so we should use something akin to α
grammar. Output grammars are inconvenient so tool builders created
template engines. Restricted template engines that enforce the
universally-agreed-upon goal of strict model-view separation also look
remarkably like output grammars as Ι have shown. So, the very nature
of the language generation problem dictates the solution: α template
engine that is restricted to support α mutually-recursive set of
templates with side-effect-free and order-independent attribute
references.

Viết một bình luận