-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathabout.html
executable file
·266 lines (215 loc) · 12 KB
/
about.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
<!doctype html>
<!--[if lt IE 9]><html class="ie"><![endif]-->
<!--[if gte IE 9]><!--><html><!--<![endif]-->
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>About StringTemplate</title>
<!--[if lt IE 9]><script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<link rel="stylesheet" href="css/fontface/Droid-Sans/stylesheet.css" type="text/css" media="screen" />
<link rel="stylesheet" href="css/fontface/Droid-Serif/stylesheet.css" type="text/css" media="screen" />
<link rel="stylesheet" href="css/fontface/DejaVu-Sans-Mono/stylesheet.css" type="text/css" media="screen" />
<link rel="stylesheet" href="css/st.css" type="text/css" media="screen" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="scripts/selectivizr-min.js"></script>
<script src="scripts/cycle.js"></script>
<script src="scripts/rounded.js"></script>
<script src="scripts/watermark.js"></script>
<script type="text/javascript" src="scripts/lib/jquery.mousewheel-3.0.6.pack.js"></script>
<script type="text/javascript" src="scripts/source/jquery.fancybox.js?v=2.0.6"></script>
<link rel="stylesheet" type="text/css" href="scripts/source/jquery.fancybox.css?v=2.0.6" media="screen" />
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-1024344-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<header>
<a id="index" href="index.html">StringTemplate</a>
<nav>
<script src="scripts/topnav.js"></script>
</nav>
</header>
<div id="wrapper">
<div id="container">
<div id="main">
<div id="content">
<h1>About StringTemplate</h1>
<P><TT>StringTemplate</TT> was born and evolved during the development of
<A HREF="http://www.jGuru.com"><B>http://www.jGuru.com</B></A>. The need for such dynamically-generated web
pages has led to the development of numerous other template engines in
an attempt to make web 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, <B>derive entirely from a single
principle</B>: separating the specification of a page's business logic
and data computations from the specification of how a page displays
such information. These template engines are in a sense are a
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.
<P>When developing StringTemplate, I recalled Frederick Brook's book,
"Mythical Man Month", where he identified <em>conceptual integrity</em> as a
crucial product ingredient. For example, in UNIX everything is a
stream. My concept, if you will, is <em>strict model-view separation</em>.
My mission statement is therefore:
<BLOCKQUOTE>
"<i>StringTemplate shall be as simple, consistent, and powerful as
possible without sacrificing strict model-view separation.</i>"</BLOCKQUOTE>
<P>I ruthlessly evaluate all potential features and functionality against
this standard. Over the years, however, I 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.
<P>I let my needs dictate the language and tool feature set. The tool
evolved as my needs evolved. I have done almost no feature
"backtracking". Further, I 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 a lot of sense even if
they are unfamiliar or strange at first glance. Everything in the
language exists to solve a very real need.
<P>After examining hundreds of template files that I created over years
of jGuru.com (and now in ANTLR v3) development, I found that I needed
only the following four basic canonical operations (with some
variations):
<UL>
<LI>attribute reference; e.g., <TT>$phoneNumber$</TT>
</LI>
<LI>template reference (like #include or macro expansion); e.g., <TT>$searchbox()$</TT>
</LI>
<LI>conditional include of subtemplate (an IF statement); e.g., <TT>$if(title)$<title>$title$</title>$endif$</TT>
</LI>
<LI>template application to list of attributes; e.g., <TT>$names:bold()$</TT>
</LI>
</UL>
<P>where template references can be recursive.
<P>Language theory supports my premise that even a minimal StringTemplate
engine with only these features is very powerful--such an engine can
generate the context-free languages (see
<A HREF="https://www.cs.usfca.edu/~parrt/papers/mvc.templates.pdf"><B> Enforcing
Strict Model-View Separation in Template Engines</B></A>); e.g., most
programming languages are context-free as are any XML pages
whose form can be expressed with a DTD.
<P>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. A quick scan of template
engines reveals an unfortunate truth--all but a 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 <B>should</B> be
built not what <B>can</B> be built.
<P>The fact that StringTemplate does not allow such things as assignments
(no side-effects) should make you suspicious of engines that do allow
it. I guarantee that the templates in ANTLR v3's code generator are
vastly more complicated than any web page, for example, created for
use with another template engine and I have yet to find a situation
where I needed assignments. If your template looks like a program, it
probably is--you have totally entangled your model and view.
<P>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
<em>recursion</em>. A template engine without recursion seems unlikely to be
capable of generating recursive output structures such as nested
tables or nested code blocks.
<P>Another distinctive <TT>StringTemplate</TT> language feature lacking in other
engines is <em>lazy-evaluation</em>. <TT>StringTemplate</TT>'s attributes are
lazily evaluated in the sense that referencing attribute "<TT>a</TT>" 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 web and code generation worlds because such order
decoupling allows code to set attributes when it is convenient or
efficient not necessarily before a template that references those
attributes is created. For example, a complicated web page may
consist of many nested templates many of which reference <TT>$userName$</TT>,
but the value of <TT>userName</TT> does not need to be set by the model until
right before the entire page is rendered to text via <TT>toString()</TT>.
You can build up the complicated page, setting attribute values in any
convenient order.
<P><TT>StringTemplate</TT> implements a "poor man's" form of lazy evaluation by
simply requiring that all attributes be computed <em>a priori</em>. That is,
all attributes must be computed and pushed into a template before it
is written to text; this is the so-called "<em>push method</em>" whereas most
template engines use the "<em>pull method</em>". The pull method appears
more conventional because programmers mistakenly regard templates as
programs, but pulling attributes introduces <em>order-of-computation
dependencies</em>. Imagine a simple web page that displays a list of
names (using some mythical template engine notation):
<pre class="block">
<html>
<body>
<ol>
$foreach n in names$
<li>$n$</li>
$end$
</ol>
There are $numberNames$ names.
</body>
</html>
</pre>
<P>Using the pull method, the reference to <TT>names</TT> invokes
<TT>model.getNames()</TT>, which presumably loads a list of names from the
database. The reference to <TT>numberNames</TT> invokes
<TT>model.getNumberNames()</TT> which necessarily uses the internal data
structure computed by <TT>getNames()</TT> to compute <TT>names.size()</TT> or
whatever. Now, suppose a designer moves the <TT>numberNames</TT> reference
to the <TT><title></TT> tag, which is <B>before</B> the reference to <TT>names</TT> in
the <TT>foreach</TT> statement. The names will not yet have been loaded,
yielding a null pointer exception at worst or a blank title at best.
You have to anticipate these dependencies and have <TT>getNumberNames()</TT>
invoke <TT>getNames()</TT> because of a change in the template. I'm stunned
that other template engine authors with whom I've spoken think this is
ok. Any time I can get the computer to do something automatically for
me that removes an entire class of programming errors, I'll take it!
Automatic garbage collection is the obvious analogy here.
<P>The pull method requires that programmers do a topological sort in
their minds anticipating any order that a programmer or designer could
induce. To ensure attribute computation safety (i.e., avoid hidden
dependency landmines), I have shown trivially in my academic paper
that <em>pull</em> reduces to <em>push</em> in the worst case. With a complicated
mesh of templates, you will miss a dependency, thus, creating a really
nasty, difficult-to-find bug.
<P>Just so you know, I've never been a big fan of functional languages
and I laughed really hard when I realized (while writing the academic
paper) that I had implemented a functional language. The nature of
the problem simply dictated a particular solution. We are generating
sentences in an output language so we should use something akin to a
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 I have shown. So, the very nature
of the language generation problem dictates the solution: a template
engine that is restricted to support a mutually-recursive set of
templates with side-effect-free and order-independent attribute
references.
</div><!--/content-->
<div id="sidebar">
<script src="scripts/leftnav.js"></script>
</div><!--/sidebar-->
</div><!--/main-->
</div><!--/container-->
<div class="clear"><!--necessary nudge--></div>
</div><!--/wrapper-->
<footer>
<script src="scripts/bottomnav.js"></script>
</footer>
<script src="scripts/functions.js"></script>
</body>
</html>