DevoxxFR 2024 Reproducible Builds with Apache Maven
How to Make Designer-Friendly Template Engine
1. RubyKaigi 2010
How to Make Designer-Friendly
Template Engine
- Keep Template as pure HTML -
makoto kuwata
http://www.kuwata-lab.com/
copyright(c) 2010 kuwata-lab.com all rights reserved.
1
2. README.txt
Goal
✤ For template engine users: get
correct knowledge
✤ For template engine desingers: get
an ideal solution
Motiv. ✤ Want correct wrong explanations
related to template engine
✤ Want to insist that eRuby is not an
ideal solution
Target ✤ Template engine users and designers
copyright(c) 2010 kuwata-lab.com all rights reserved.
2
3. I must apologize...
✤ I would talk about...
✤ How to keep html design of template files
✤ What are performance bottole necks of engine
✤ What is wrong about existing template engines
✤ How to design engine which is designer-friendly,
very fast, and easy to implement in any languages
✤ But I only have 30 minutes
✤ I can talk about the first issue
copyright(c) 2010 kuwata-lab.com all rights reserved.
3
4. Reference
✤ Rubyist Magazine - Guide to Template System
✤ http://jp.rubyist.net/magazine/?0024-TemplateSystem
✤ http://jp.rubyist.net/magazine/?0024-TemplateSystem2
copyright(c) 2010 kuwata-lab.com all rights reserved.
4
5. Agenda
✤ Fundamental section:
✤ Business Layer and Presentation Layer
✤ Existing Issues and the Cause
✤ Think about Presentation Logic
✤ Kwartz section:
✤ Introduction to Kwartz template engine
✤ Presentation Logic Pattern
copyright(c) 2010 kuwata-lab.com all rights reserved.
5
7. Business layer and Presentation layer
✤ Business layer
✤ WHAT should be displayed?
✤ by main program
✤ Presentation layer
✤ HOW to display it?
✤ by template engine, template file
copyright(c) 2010 kuwata-lab.com all rights reserved.
7
8. Data and Logic
✤ Both layers have each data and logic
Business layer Presentation layer
(main program) (template engine)
Data Business Data Presentation Data
Logic Business Logic Presentation Logic
separated by template engine
copyright(c) 2010 kuwata-lab.com all rights reserved.
8
9. Applicaiton Example
Business logic
✤ Select top 20
✤ of book sales Business data
✤ by <table> tag Presentaion
data
✤ with toggling bgcolor
Presentation
logic
copyright(c) 2010 kuwata-lab.com all rights reserved.
9
10. Frequent Misunderstandings (1)
Mis: ✤ Template engine separates
presentation from logic.
Truth: ✤ Template engine separatin
presentation layer from business
layer.
✤ Presentation layer have own
logics.
common mistake in Japan...
copyright(c) 2010 kuwata-lab.com all rights reserved.
10
11. Frequent Misunderstandings (2)
Mis: ✤ Presentation layer shouldn't
contain any logics.
Truth: ✤ Presentation layer should contain
presentation logics.
✤ "HTML template shouldn't contain any
presentation logics" and "Layers should
be separated" are different things.
copyright(c) 2010 kuwata-lab.com all rights reserved.
11
12. Add-up
✤ Business layer
✤ WHAT should be displayed?
✤ By main program
✤ Presentation layer
✤ HOW to display it?
✤ By template engine and template file
✤ Both layers have each data and logics
copyright(c) 2010 kuwata-lab.com all rights reserved.
12
14. Templates Annoys Designers
ProjectA: Rails
<table> ProjectC: PHP
<% @arr.each { %> <table>
.... <?php foreach() { ?>
<% } %> ....
</table> <?php } ?>
</table>
ProjectB: JSP
<table>
<forEach items="">
Designer: Why I must
....
master so much langs?
</forEach>
</table>
copyright(c) 2010 kuwata-lab.com all rights reserved.
14
15. Edit & Update the same file
template file
<table>
<% @arr.each { %>
....
<% } %>
</table>
Conflict!
edit presentaion
edit HTML logic
Designer Programmer
copyright(c) 2010 kuwata-lab.com all rights reserved.
15
16. The Cause of Issues
✤ It is the cause that template file
presentation logics <table>
are embedded in <% i = 0 %>
<% @arr.eachx do |x| %>
template file
<% i += i %>
<% c = i.odd ? %>
<% 'odd':'even' %>
pure HTML is the <tr class="<%=c%>">
solution <td><%= x %></td>
</tr>
<% end %>
</table>
copyright(c) 2010 kuwata-lab.com all rights reserved.
16
17. Pure HTML Template is Great
✤ Easy to preview by browsers
Designer
for
✤ No need to learn a lot of template langs!
✤ Easy to validate by HTML validator
✤ Allow to use their favorite HTML editor
Avoid edit confliction
Programmer
for
✤
✤ Remove whitespaces to reduce traffic
✤ Transform template files for mobile phones
copyright(c) 2010 kuwata-lab.com all rights reserved.
17
18. The Question which bothered Matz
✤ So, where is presentation logics?
Matz diary (2004-08-24)
http://www.rubyist.net/ matz/20040824.html#p01
(Summary)
When view layer needs some logics,
where should I put it in?
I don't want it to be in HTML template...
copyright(c) 2010 kuwata-lab.com all rights reserved.
18
19. Add-up
✤ Presentation logics in template files
causes a lot of problems
✤ Pure HTML template is great
✤ Where is presentation logics?
copyright(c) 2010 kuwata-lab.com all rights reserved.
19
21. Where should be Presentation Logics?
A. In template file (eRuby, JSP, Kid)
Presentation Logic
Business Logic & Data
+ Presentaion Data
B. In main program (Amrita2, XMLC, HTML::Template)
Presentation Logic
Presentation Data
+Business Logic & Data
C. In independed file (Kwartz, Tapestry, Mayaa)
Presentation Logic
Business Logic & Data
Presentation Data
template file main program
copyright(c) 2010 kuwata-lab.com all rights reserved.
21
22. A. In Template File (1)
ex: eRuby (Ruby)
<table>
<% odd = false %>
<% for item in @list %>
<% odd = ! odd
<% cls = odd ? 'odd' : 'even' %>
<tr class="<%= cls %>">
<td><%=h item %></td>
</tr>
<% end %> •HTML and non-HTML
</table> are mixed
→ never pure HTML !
copyright(c) 2010 kuwata-lab.com all rights reserved.
22
23. A. In Template File (2)
ex: JSP with custom tags (Java)
<table>
<c:forEach var="item" items="${list}"
varStatus="loop">
<c:set var="klass"
value="${loop.count%2==0?'odd':'even'}" />
<tr class="${klass}">
<td><c:out value="${item}" /></td>
</tr>
</c:forEach> •Even if you use custom tags,
</table> presentation logics are mixed into
HTML (just same as eRuby).
copyright(c) 2010 kuwata-lab.com all rights reserved.
23
24. A. In Template File (3)
ex: Kid template engine (Python)
<table>
<tr py:for="i, item in enumerate(items)"
class="${i % 2 and 'even' or 'odd'}">
<td py:content="item">dummy</td>
</tr>
</table>
•Using HTML tags and attributess, Kid
aquired designer-friendly template!
•But notice that presentation logics are
still embedded into templates
copyright(c) 2010 kuwata-lab.com all rights reserved.
24
25. A. In Template File (4)
Pros.
✤ Presentation layer (= template file) is
compretely separated from business layer.
✤ Easy to uderstand, easy to implement
Hard to keep pure HTML
Cons.
✤
✤ Designer and programmer will edit the
same file at the same time, and conflicted
in the result
✤ Designer may break presentation logics in
template files accidentally
copyright(c) 2010 kuwata-lab.com all rights reserved.
25
26. Where should be Presentation Logics?
A. In template file (eRuby, JSP, Kid)
Presentation Logic
Business Logic & Data
+ Presentaion Data
B. In main program (Amrita2, XMLC, HTML::Template)
Presentation Logic
Presentation Data
+Business Logic & Data
C. In independed file (Kwartz, Tapestry, Mayaa)
Presentation Logic
Business Logic & Data
Presentation Data
template file main program
copyright(c) 2010 kuwata-lab.com all rights reserved.
26
27. B. In Main Program (1)
ex: Amrita2 temlate file (Ruby)
<table>
<tr id="list" class="odd">
<td id="item">dummy</td>
</tr>
</table>
•Just to place "mark" (= id attr in
Amrita2) into template file
•Pure HTML template (because no
presentation logics in it)
copyright(c) 2010 kuwata-lab.com all rights reserved.
27
28. B. In Main Program (2)
ex: Amrita2 main program (Ruby)
## business data to display
list = [ 'A', 'B', 'C' ] •Necessary to "process"
## presentation logic bussiness data for
list2 = []; odd = false presentation layer
for x in list
cls = (odd = !odd) ? 'odd' : 'even'
item2 = a(:class=>cls) { {:item=>x} }
list2 << item2
end
context = { :list=>list2 }
## read template and render with data
tmpl = Amrita2::TemplateFile.new('ex1.html')
tmpl.expand(html='', context)
print html
copyright(c) 2010 kuwata-lab.com all rights reserved.
28
29. B. In Main Program (3)
Pros.
✤ Just embed "mark" into template
✤ pure HTML template (in most cases)
✤ No conflicts when editing files
✤ No accidental change of logics by designer
Cons.
✤ Business layer and Presentation layer are
NOT separated! (*)
✤ Confusable usage (because logic should be
represented by data)
(*) devisable to avoid (ex. define dedicated class)
copyright(c) 2010 kuwata-lab.com all rights reserved.
29
30. Where should be Presentation Logics?
A. In template file (eRuby, JSP, Kid)
Presentation Logic
Business Logic & Data
+ Presentaion Data
B. In main program (Amrita2, XMLC, HTML::Template)
Presentation Logic
Presentation Data
+Business Logic & Data
C. In independed file (Kwartz, Tapestry, Mayaa)
Presentation Logic
Business Logic & Data
Presentation Data
template file main program
copyright(c) 2010 kuwata-lab.com all rights reserved.
30
31. C. In Independed File (1)
ex: Kwartz presentation data file (Ruby)
<table>
<tr id="mark:list" class="odd">
<td id="mark:item">dummy</td>
</tr>
</table>
•Just place "mark" (= id attr in
Kwartz) in template file
copyright(c) 2010 kuwata-lab.com all rights reserved.
31
32. C. In Independent File (2)
ex: Kwartz presentation logic file (Ruby)
#item { ## id="mark:item"
value: x; ## display value of x
}
#list { ## id="mark:list"
logic: { ## iterate over element
for x in @list
_elem
end
} •Write your presentation logics
}
just like CSS
•No presentation logics in HTML !
copyright(c) 2010 kuwata-lab.com all rights reserved.
32
33. CSS
(Visual Design)
HTML
(Document
Structure)
Kwartz JavaScript
(Presentation (Client-side
Logic) Logic)
copyright(c) 2010 kuwata-lab.com all rights reserved.
33
34. C. In Independent File (3)
Pros.
✤ Business layer and Presentation layer are
completely separated!
✤ Presentation data (=HTML) and
Presentation logic are also separated!
✤ Pure HTML template
✤ No conflicts when editiong files
✤ No accidental modification of logics
Cons.
✤ Number of files are increased
copyright(c) 2010 kuwata-lab.com all rights reserved.
34
35. Important thing, More Important thing
✤ Important thing
✤ Template format is pure HTML
✤ More important thing
✤ Presentation logic should be separated (or
independent) from others!
✤ Pure HTML template is just derivation from it
copyright(c) 2010 kuwata-lab.com all rights reserved.
35
36. Frequent Misunderstanding (1)
Mis.: ✤ My template is pure HTML, so
presentation layer is separated!
Truth: ✤ "Template is pure HTML" doesn't
mean "Presentation layer is
separated"
✤ Probably she/he misunderstands "No
logics in template" as "Presentation layer
is separated"
copyright(c) 2010 kuwata-lab.com all rights reserved.
36
37. Frequent Misunderstanding (2)
Mis.: ✤ Web designer may write buggy
logic in raw PHP, so I introduced
Smarty!
Truth: ✤ Smarty can't prevent buggy logic
nor accidental logic modification.
✤ The root cause of the problem is that
desginer can access to presention logic
✤ A radical solution is to separate
presentation logic from template file
copyright(c) 2010 kuwata-lab.com all rights reserved.
37
38. Add-up
✤ Presentation logic can be...
✤ In template file (non-html, conflictions)
✤ In main program (layers are not separated)
✤ In independent file (ideal)
✤ Pure HTML template is important
✤ Separation of presentation logic is
more important
copyright(c) 2010 kuwata-lab.com all rights reserved.
38
40. Kwartz Overview
✤ What is Kwartz?
✤ A template engine which can separate
Presentation logic from Presentation data
(=HTML)
✤ Pure HTML template
✤ Implemented in Ruby, PHP
✤ http://www.kuwata-lab.com/kwartz/
copyright(c) 2010 kuwata-lab.com all rights reserved.
40
41. Example: Presentation Data
Add "marking" (=id attr)
to where you want to
ex.html manipulate dinamically
<table>
<tr id="mark:list">
<td id="mark:item">Foo</td>
</tr>
<tr id="dummy:d1">
<td>Bar</td>
</tr>
</table> `id="dummy:xxx"' means
dummy elelment
copyright(c) 2010 kuwata-lab.com all rights reserved.
41
42. Example: Presentation Logic
ex.plogic Write presentation logic
#list { for each elements
logic: {
for x in @list
_stag ## start-tag
_cont ## content
_etag ## end-tag
end
} Repeat <tr> element
}
#item {
value: x;
Display value of x as
}
content of <td> element
copyright(c) 2010 kuwata-lab.com all rights reserved.
42
43. Example: Compilation
Compile files into a eRuby file
$ kwartz -l eruby -p ex.plogic ex.html > ex.rhtml
ex.rhtml (compiled by Kwartz)
<table>
<% for x in @list %>
<tr> •Attribute `id="mark:xxx"' is
<td><%= x %></td> removed automatically
</tr> (not removed if `id="xxx"')
<% end %>
</table> •Element which has
`id="dummy:xxx"' is also
removed
copyright(c) 2010 kuwata-lab.com all rights reserved.
43
44. Example: Main Program
Main program
## business data to be displayed
list = ['A', 'B', 'C']
context = { :list => list }
## load template and render it with data
require 'erubis'
eruby = Erubis::Eruby.load_file('ex.rhtml')
html = eruby.evaluate(context)
print html
Main program doesn't
require Kwartz
copyright(c) 2010 kuwata-lab.com all rights reserved.
44
45. Pros and Cons
✤ Pros. ✤ pure HTML template
✤ Very fast
✤ Supports eRuby, PHP, JSP, and so on
✤ Available with non-HTML text file
✤ Cons. ✤ Messy compile (should be automated)
✤ Runtime error is reported with line
number AFTER compiled code, not
original source code
copyright(c) 2010 kuwata-lab.com all rights reserved.
45
46. Practical Examples (1)
repeat over element repeat only content
#list { #list {
logic: { logic: {
for item in @list _stag
_stag # start-tag for item in @list
_cont # content _cont
_etag # end-tag end
end _etag
} }
} } Useful to repeat
<dt> and <dd>
copyright(c) 2010 kuwata-lab.com all rights reserved.
46
47. Practical Examples (2)
display only when display default value
#list { #list {
logic: { logic: {
if @list.size > 0 _stag
_stag if @name.blank?
_cont print('World')
_etag else
end _cont
} end
} _etag
}
}
copyright(c) 2010 kuwata-lab.com all rights reserved.
47
48. Practical Examples (3)
remove dummy tag remove dummy element
#list { #list {
logic: { logic: {
#_stag }
_cont }
#_etag
} replace by other
}
#list {
logic: {
_element(list2)
}
} reuse a certain
element
copyright(c) 2010 kuwata-lab.com all rights reserved.
48
49. Practical Examples (4)
より複雑なプレゼンテーションロジック
#list {
attrs: "class" cls; # attribue
logic: {
odd = false Presentation logic is
for x in @list separated from HTML file
odd = !odd
cls = odd ? 'odd' : 'even'
_elem
end No need to touch HTML at all
} even if you change presentaion
} logic dramatically
copyright(c) 2010 kuwata-lab.com all rights reserved.
49
50. Add-up
✤ Kwartz tempate engine
✤ Separates presentation logics from presentation
data (=HTML)
✤ Pure HTML Template
✤ No need to touch HTML file at all even if you
change presentation logics
copyright(c) 2010 kuwata-lab.com all rights reserved.
50
52. Overview
✤ What is Presentation Pattern?
✤ Best practices in presentation layer (data & logic)
✤ (Notice that this is my original term and not
popular at all)
✤ Very easy to understand, compared to GoF!
✤ http://www.kuwata-lab.com/kwartz/kwartz3ruby-
pattern-catalog.html
copyright(c) 2010 kuwata-lab.com all rights reserved.
52
53. List of Patterns
✤ Replacement ✤ Iteration
✤ Replace Element with ✤ Iterate Element Pattern
Value Pattern ✤
Iterate Content Pattern
✤ Replace Content with
Value Pattern ✤ Selection
✤ Default Content Pattern ✤ Select Element/Content
✤ Replace Element with Pattern
Element/Content Pattern ✤ Pick-up Element/Content
✤ Replace Content with Pattern
Element/Content Pattern ✤ Extract Element/Content
Pattern
✤ Deletion
✤ Delete Element Pattern Today's menu
✤ Delete Tag Pattern
copyright(c) 2010 kuwata-lab.com all rights reserved.
53
54. Select Element Pattern
✤ Req: Want to change data according to condition
<div id="mark:message"> #message {
<div id="error"> logic: {
ERROR! if status == 'error'
</div> _element(error)
<div id="warning"> elsif status == 'warn'
Warning: _element(warning)
</div> else
<div id="noerror"> _element(noerror)
No error. end
</dvi> } Select an elem
Add different id according to
</div> }
for each elems condition
copyright(c) 2010 kuwata-lab.com all rights reserved.
54
55. Pick-up Element Pattern
✤ Req: Want to include a lot of dummy elems (for preview)
<ol id="mark:list"> #list {
<li id="mark:item"> logic: {
Item1 _stag
</li> add id to _element(item)
<li>Item2</li>
non-dummy _etag
<li>Item3</li>
elements }
<li>Item4</li> }
Pick up only non-
<li>Item5</li> dummy elems, and
<li>Item6</li> dummy elems are
</ol>
removed in the result
copyright(c) 2010 kuwata-lab.com all rights reserved.
55
56. Extract Element Pattern
✤ Req: Want to extract a certain elem form a document
<html id="mark:whole"> #whole {
<body> logic: {
<form id="form"> _element(form)
<input ... /> }
Replace document
<input ... /> }
by a certain elem
<input ... />
</form> #DOCUMENT {
</body> logic: {
</html> Add id attr to _element(form)
document root }
elem (=<html>) Kwartz provides special
}
id name for this purpose
copyright(c) 2010 kuwata-lab.com all rights reserved.
56
57. Add-up
✤ Presentation pattern
✤ Best practices for presentation layer (data & logic)
✤ Select Element Pattern:
select only a elemement according to condition
✤ Pick-up Element Pattern:
use only necessary element, and remove others
✤ Extract Element Pattern:
replace document by a certain element
copyright(c) 2010 kuwata-lab.com all rights reserved.
57