Brian Silverman | 70325d6 | 2015-09-20 17:00:43 -0400 | [diff] [blame] | 1 | |
| 2 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
| 3 | <html> |
| 4 | <head> |
| 5 | <title>Tips and Guidelines for Using the Ctemplate System</title> |
| 6 | |
| 7 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
| 8 | <link href="designstyle.css" type="text/css" rel="stylesheet"> |
| 9 | <style type="text/css"> |
| 10 | ol.bluelist li { |
| 11 | color: #3366ff; |
| 12 | font-family: sans-serif; |
| 13 | } |
| 14 | ol.bluelist li p { |
| 15 | color: #000; |
| 16 | font-family: "Times Roman", times, serif; |
| 17 | } |
| 18 | ul.blacklist li { |
| 19 | color: #000; |
| 20 | font-family: "Times Roman", times, serif; |
| 21 | } |
| 22 | </style> |
| 23 | </head> |
| 24 | |
| 25 | <body> |
| 26 | |
| 27 | <h1>Tips and Guidelines for Using the Ctemplate System</h1> |
| 28 | <small>(as of 10 March 2010)</small> |
| 29 | |
| 30 | <br> |
| 31 | |
| 32 | <p>The <A HREF="guide.html">basic rules</A> of the template system are |
| 33 | enough to use it, but over time, we at Google have developed some |
| 34 | tips, guidelines, and best practices that make it easier to use |
| 35 | templates effectively, and to avoid common template errors.</p> |
| 36 | |
| 37 | |
| 38 | <h2> Program Design Considerations </h2> |
| 39 | |
| 40 | <h3> <a name=versioning>Template naming and versioning</a> </h3> |
| 41 | |
| 42 | <p> Early in Google's use of templates, we noticed a problem: if a |
| 43 | binary that uses a template and its corresponding template were both |
| 44 | modified, particularly if the change were such that the old binary |
| 45 | could not work with the new template or the new binary could not work |
| 46 | with the old template, then somehow they both had to be deployed at |
| 47 | the same instant to not present errors to our users. This was hard to |
| 48 | do. The solution was to adopt a template naming and versioning |
| 49 | convention. The procedure to use it follows:</p> |
| 50 | |
| 51 | <ul> |
| 52 | <li> Each template name ends with <code>_postYYYYMMDD.tpl</code>, |
| 53 | where YYYMMDD is the date of this version's initial |
| 54 | creation. </li> |
| 55 | |
| 56 | <li> Before making (non-backward-compatible) modifications to a |
| 57 | template, copy the template to a new name, incorporating a |
| 58 | later date than the original one being copied. </li> |
| 59 | |
| 60 | <li> Edit the new file, and push it to the production server. </li> |
| 61 | |
| 62 | <li> Finally, update the code to refer to the new template-name |
| 63 | (ideally, using the <A |
| 64 | HREF="guide.html#register"><code>RegisterTemplateFilename</code> |
| 65 | idiom</A>), and push the new executable to the production |
| 66 | server. </li> |
| 67 | </ul> |
| 68 | |
| 69 | <p>When this convention is followed, the new template file does not |
| 70 | overwrite the old one when it is deployed, because it is a new file |
| 71 | with a new name. The old template file is still there to be used as |
| 72 | long as the old binary is still in production and the new template |
| 73 | file just sits there being ignored. Then when the new binary finally |
| 74 | gets deployed, it immediately starts using the new template file, |
| 75 | because it is coded (in <code>RegisterTemplateFilename</code>) to do |
| 76 | so. After that, it is the old template file that continues to sit |
| 77 | there ignored.</p> |
| 78 | |
| 79 | <p>The <A |
| 80 | HREF="reference.html#make_tpl_varnames_h"><code>make_tpl_varnames_h</code> |
| 81 | utility</A> knows about the "_postYYYYMMDD" naming convention, so it |
| 82 | is important that you use that convention exactly if you use the |
| 83 | <code>make_tpl_varnames_h</code>.</p> |
| 84 | |
| 85 | |
| 86 | <h3> Processing Phases </h3> |
| 87 | |
| 88 | <p>Typically a program using the Ctemplate System will |
| 89 | perform the following phases, usually in this order:</p> |
| 90 | |
| 91 | <ol> |
| 92 | <li> Retrieve and prepare the data used to fill a dictionary. </li> |
| 93 | |
| 94 | <li> Build the data dictionary, including all its |
| 95 | sub-dictionaries, that will supply the values to the |
| 96 | designated template object, its sections, and its |
| 97 | included templates. </li> |
| 98 | |
| 99 | <li> Retrieve the top-level template object required to |
| 100 | format the data. (This may or may |
| 101 | not involve reading and parsing a template file, |
| 102 | depending on whether the requested file has already |
| 103 | been read and parsed by the running program or |
| 104 | whether that file has been marked "reload if changed" |
| 105 | and was in fact changed.) </li> |
| 106 | |
| 107 | <li> Expand the template object into an output buffer |
| 108 | using the completed data dictionary. </li> |
| 109 | |
| 110 | <li> Output the buffer. </li> |
| 111 | |
| 112 | <li> Clean up: Destroy the top-level data dictionary |
| 113 | whenever it is no longer needed. </li> |
| 114 | |
| 115 | <li> Optionally, clear the cache at the end of program |
| 116 | execution. </li> |
| 117 | </ol> |
| 118 | |
| 119 | |
| 120 | <h3> <A NAME="oneone">One template / One procedure call</A> </h3> |
| 121 | |
| 122 | <p> Most of the code of the program will be in Phases 1 and |
| 123 | 2. Clearly, Phase 1 is outside the scope of the template system. But |
| 124 | in designing the code for Phase 2 (building the data dictionary), it |
| 125 | is wise to have the structure of the program reflect the structure of |
| 126 | the templates being used. Specifically, there should be a single |
| 127 | procedure call to build the dictionary for a single template. That |
| 128 | procedure call should take parameters that include all the data |
| 129 | required to populate the data dictionary for that template and all the |
| 130 | templates it includes. Following this "one template/one procedure |
| 131 | call" guideline further, for each included template, another procedure |
| 132 | should be called to populate the (or <i>each</i>) data dictionary for |
| 133 | that included template. This maintains the "one template/one procedure |
| 134 | call" principle in a nested fashion that reflects the nesting of the |
| 135 | templates.</p> |
| 136 | |
| 137 | <p> This is not to imply that the "one procedure call" for a template |
| 138 | should not be modularized into sub-procedures for readability and |
| 139 | maintainability, or that it should not call other auxilliary |
| 140 | procedures for such things as formatting the data and converting it to |
| 141 | the appropriate strings, etc. But it does mean that there should be |
| 142 | one entry point for building the dictionary tree for one template and |
| 143 | that entry point should show the data dependencies of that template |
| 144 | through its parameter list. This code for populating the data |
| 145 | dictionary should <i>NOT</i> be intermingled with data gathering code |
| 146 | that should have been done in Phase 1.</p> |
| 147 | |
| 148 | <p>(Inside Google, the convention has been used to name the dictionary |
| 149 | building procedure using the pattern <code>fill_..._dictionary</code> |
| 150 | where the dots are related to the name of the template the data is |
| 151 | being prepared for. For instance, the data for the template named |
| 152 | one_search_result.tpl might be placed in a dictionary via a function |
| 153 | named <code>fill_one_search_result_dictionary</code>.) |
| 154 | |
| 155 | |
| 156 | <h2> <A name=tips>Tips, Idioms, and Conventions</a> </h2> |
| 157 | |
| 158 | <ol class=bluelist> |
| 159 | |
| 160 | <li> Choose template names to create unique constant prefixes. |
| 161 | |
| 162 | <p>Template names should contain <em>at least two words</em> |
| 163 | to avoid constant prefix clashes (e.g. <code>kxy_</code> |
| 164 | instead of <code>kx_</code> ) The name of a new template |
| 165 | should be checked against the existing names before |
| 166 | proceeding. If your new template name produces a prefix that |
| 167 | conflicts with an already existing template, you should change |
| 168 | the name of your new template, even though it may be the only |
| 169 | perfect name you can come up with. You'll have to use a less |
| 170 | than perfect name in that case. (See "Template Syntax Checker |
| 171 | and Header File Generator" below for more explanation about |
| 172 | constant prefixes.)</p> </li> |
| 173 | |
| 174 | <li> <a name="tip_setformattedvalue"></a>Use SetFormattedValue |
| 175 | discriminately. |
| 176 | |
| 177 | <p> This method should never be used to sneak HTML into the |
| 178 | executable as in</p> |
| 179 | |
| 180 | <pre> |
| 181 | dictionary->SetFormattedValue(kxy_VAR, |
| 182 | "<b>%s</b>", |
| 183 | some_const_char_string); |
| 184 | </pre> |
| 185 | |
| 186 | <p>In that case, the <code><b></code> and |
| 187 | <code></b></code> should be moved into the template.</p> |
| 188 | |
| 189 | <li> Never have a section encompass an entire template. |
| 190 | |
| 191 | <p>If the first line of a template is a start section marker |
| 192 | and the last line is its matching end section marker, then |
| 193 | those markers are unnecessary in almost all cases. They are |
| 194 | usually put there to allow the entire template to be hidden or |
| 195 | iterated, but since it encompasses the entire file, the |
| 196 | section may be hidden by not expanding the file (or by hiding |
| 197 | the template-include section that includes the file) and it |
| 198 | may be iterated by iterating the template-include marker of |
| 199 | the including template. (The only exception might be if the |
| 200 | entire page is to be iterated, but this seems a bit of a |
| 201 | stretch.)</p> </li> |
| 202 | |
| 203 | <li> An included template is just a section whose contents are |
| 204 | located in a separate file. You may iterate over it just |
| 205 | like you do sections. |
| 206 | |
| 207 | <p>For example, if your template has the following |
| 208 | template-include marker:</p> |
| 209 | <pre> |
| 210 | {{>MY_INCLUDED_TEMPLATE}} |
| 211 | </pre> |
| 212 | <p>you may call</p> |
| 213 | <pre> |
| 214 | ctemplate::TemplateDictionary *child_dict = |
| 215 | dictionary->AddIncludeDictionary(kxy_MY_INCLUDED_TEMPLATE); |
| 216 | </pre> |
| 217 | <p>to iterate that section. (Note: Make sure you call |
| 218 | <code>child_dict->SetFilename()</code>! If your included |
| 219 | template is not showing in the output, this is the first thing |
| 220 | you should check.)</p> </li> |
| 221 | |
| 222 | <li> The recommended idiom to fill an include-template dictionary is |
| 223 | like this: |
| 224 | <pre> |
| 225 | fill_include_template_dictionary(dict->AddIncludeDictionary(name), ...); |
| 226 | </pre> |
| 227 | |
| 228 | <p>But what do you do if you decide, in |
| 229 | <code>fill_include_template_dictionary</code>, that you don't |
| 230 | want to display anything for this include-template after all? It |
| 231 | seems like it's too late: you've already created the |
| 232 | sub-dictionary. The solution is simple: just be sure that |
| 233 | <code>fill_include_template_dictionary()</code> doesn't call |
| 234 | <code>SetFilename()</code> in that case.</p> |
| 235 | |
| 236 | <li> Never have a section which only contains another section. |
| 237 | <p>For example, don't do this:</p> |
| 238 | <pre> |
| 239 | {{#OUTER_SECTION}} |
| 240 | {{#INNER_SECTION}} |
| 241 | section contents here |
| 242 | {{/INNER_SECTION}} |
| 243 | {{/OUTER_SECTION}} |
| 244 | </pre> |
| 245 | <p>or this equivalent template code (see the previous item):</p> |
| 246 | <pre> |
| 247 | {{#OUTER_SECTION}} |
| 248 | {{>INCLUDED_SECTION}} |
| 249 | {{/OUTER_SECTION}} |
| 250 | </pre> |
| 251 | |
| 252 | <p>This is usually done because the developer thinks the outer |
| 253 | section must be used to hide the section when the inner |
| 254 | section, intended for iteration, has no iterations. In both |
| 255 | cases, you should only have one section (either |
| 256 | <code>INNER_SECTION</code> or <code>INCLUDED_SECTION</code> in |
| 257 | the examples) and iterate that section either 0 times or more |
| 258 | than 0 times. It's the wonder of the dual use of sections, |
| 259 | i.e. that they may be conditional or iterative or, in this case, |
| 260 | both.</p> |
| 261 | |
| 262 | <p>A related suggestion: Do not have a section whose entire |
| 263 | contents is one variable marker with nothing else, unless you |
| 264 | need to iterate over that section with multiple values of that |
| 265 | variable. You don't need the surrounding section just to hide |
| 266 | the marker. A variable marker that is not set, does not |
| 267 | produce output. By convention, we set such variables to the |
| 268 | empty string. But in neither case do you need to hide it by |
| 269 | hiding a surrounding section that contains nothing else.</p> |
| 270 | |
| 271 | <li> Use this hide/show idiom for <code>if-else</code> blocks. |
| 272 | |
| 273 | <p>Since sections are hidden by default, you can use represent |
| 274 | if-else logic in your code via <code>ShowSection</code>. For |
| 275 | example:</p> |
| 276 | |
| 277 | <pre> |
| 278 | if ( my_test ) { |
| 279 | dict->ShowSection(kxyz_TRUE_BLOCK); |
| 280 | [ more code to fill the values for that section] |
| 281 | } else { |
| 282 | dict->ShowSection(kxyz_FALSE_BLOCK); |
| 283 | [ more code to fill the values for that section] |
| 284 | } |
| 285 | </pre> |
| 286 | |
| 287 | <li> <code>Write...</code> vs. <code>Fill...Dictionary</code> methods |
| 288 | - Observe the proper division of labor, don't mix them. |
| 289 | |
| 290 | <p>The output (or write) function should create the top level |
| 291 | template dictionary, call one or more fill-dictionary routines |
| 292 | with it, then get the template and expand it. It should not call |
| 293 | dictionary modifying methods, like <code>ShowSection</code> |
| 294 | and <code>SetValue</code>. By keeping these separated into |
| 295 | their own fill-dictionary routine, the code is more modular and |
| 296 | lends itself to template re-use. If you maintain the proper |
| 297 | division of labor, the template you are filling and outputting |
| 298 | may be filled and included in a larger template by someone |
| 299 | else.</p> </li> |
| 300 | |
| 301 | <li> Use <code>AddSectionDictionary</code> only when you want to |
| 302 | iterate over a section or, secondarily, if you need to avoid name |
| 303 | conflicts. |
| 304 | |
| 305 | <p>Sometimes developers get the idea that every section requires |
| 306 | its own child dictionary created by an |
| 307 | <code>AddSectionDictionary</code> call. Because of variable |
| 308 | inheritence, this isn't usually so. The intended purpose of |
| 309 | <code>AddSectionDictionary</code> is to enable iteration over a |
| 310 | section. Secondarily, if the section contains generic names that |
| 311 | may conflict with the same name in other parts of the template, |
| 312 | it may be safer to call <code>AddSectionDictionary</code> to |
| 313 | create a separate namespace. In any case, do not assume you must |
| 314 | call <code>AddSectionDictionary</code> just because you are |
| 315 | working within a section. The main dictionary can be used for all |
| 316 | levels of conditional sections as long as you avoid name |
| 317 | conflicts by keeping the marker names unique.</p> </li> |
| 318 | |
| 319 | <li> Do not place <code>RegisterTemplateFilename</code> |
| 320 | statements in header (<code>.h</code>) files. |
| 321 | |
| 322 | <p><code>RegisterTemplateFilename</code> is a macro that |
| 323 | instantiates a <code>TemplateNamelist</code> object. If you place |
| 324 | it in a header file, a different object will get created each time |
| 325 | it is included in another <code>.cc</code> file. |
| 326 | |
| 327 | <p>The <code>RegisterTemplateFilename</code> statement and its |
| 328 | associated <code>#include</code> of the <code>varnames.h</code> |
| 329 | file should occur only in the <code>.cc</code> file that |
| 330 | implements the fill-dictionary routine for that template. You |
| 331 | should never have more than one |
| 332 | <code>RegisterTemplateFilename</code> for a single template and |
| 333 | you should try hard not to copy the <code>#include</code> file to |
| 334 | other files as well. The template versioning makes this more |
| 335 | important because a developer may not know that the template name |
| 336 | with included version number needs to be updated in more than one |
| 337 | file when versioning occurs. [Also see above for more information |
| 338 | about what routine uses the filename declared by the |
| 339 | <code>RegisterTemplateFilename</code> statement.]</p> </li> |
| 340 | |
| 341 | <li> Never reference more than one template in a |
| 342 | fill...dictionary method. |
| 343 | |
| 344 | <p>Each template should have its own fill-dictionary |
| 345 | routine. That routine should only reference marker names defined |
| 346 | in that template. If this convention is followed, then all the |
| 347 | prefixes in a fill-dictionary routine will be the same. [Note |
| 348 | that an implication of this convention is that if the template |
| 349 | includes another template, via a template-include marker, then |
| 350 | containing template's fill-dictionary routine should call the |
| 351 | included template's fill-dictionary routine (being careful to |
| 352 | observe the convention described above). But |
| 353 | then, this is merely a restatement of <A HREF="#oneone">"One |
| 354 | template / One procedure call"</A>.]</p> </li> |
| 355 | |
| 356 | <li> Have fill...dictionary call <code>SetFilename</code> even if the |
| 357 | dictionary is never used for a template-include. |
| 358 | |
| 359 | <p>SetFilename() is required when a dictionary is created via |
| 360 | <code>AddIncludeDictionary()</code>. However, it's safe to set |
| 361 | all the time. By setting it always, you make the code work |
| 362 | properly if this dictionary ever changes to be template-included |
| 363 | after all. Even if not, by saying what template file the |
| 364 | dictionary is intended to go with, you are self-documenting your |
| 365 | code.</p> </li> |
| 366 | |
| 367 | <li> Do not call <code>c_str()</code> on strings to pass them to |
| 368 | <code>TemplateDictionary</code> methods. |
| 369 | |
| 370 | <p>Note that all the TemplateDictionary methods are defined to |
| 371 | take <code>TemplateString</code> objects. These are created |
| 372 | automatically from both strings and char*'s (and can be created |
| 373 | manually if you have a char* and a length). So if you have a |
| 374 | string, it's safe and efficient to just pass it in directly; you |
| 375 | do not need to extract the const char * from your string object |
| 376 | to pass it to these methods. For some reason, this is a common |
| 377 | error of novice template coders.</p> |
| 378 | |
| 379 | <p>The one exception to this rule is when using the method |
| 380 | <code>SetFormattedValue</code>. When calling that |
| 381 | method, you must call <code>c_str()</code> on strings that are to |
| 382 | be inserted |
| 383 | into the format string, just as you would when providing data for |
| 384 | any other printf format string.</p> </li> |
| 385 | |
| 386 | <li> Do not use <code>SetGlobalValue</code> when you could use |
| 387 | <code>SetValue</code> or <code>SetTemplateGlobalValue</code>. |
| 388 | |
| 389 | <p><code>SetGlobalValue</code> should be used quite rarely, for |
| 390 | constants that really are consistent across all your templates. |
| 391 | It's slower to look up a value in the global dictionary than it |
| 392 | is in the template-specific dictionary.</p> </li> |
| 393 | |
| 394 | <li> Do not use <code>StringToTemplateCache</code> unless you have |
| 395 | a specific need for its non-file-based attributes. |
| 396 | |
| 397 | <p><code>ctemplate::StringToTemplateCache</code> was created for |
| 398 | use in highly constrained cases where file I/O may be impaired or |
| 399 | undesirable, for instance to produce a server error message |
| 400 | where there may be disk problems or to produce formatted |
| 401 | output where there are processes that do not have a facility |
| 402 | for updating data files dynamically. It is not recommended for |
| 403 | ordinary use since it cannot be updated dynamically via a |
| 404 | data-push; changes always require a binary push.</p> |
| 405 | </ul> |
| 406 | </li> |
| 407 | |
| 408 | <li> Use <A HREF="auto_escape.html">auto-escaping</A> to prevent |
| 409 | Cross-Site-Scripting security vulnerabilities. |
| 410 | |
| 411 | <p>Use <code>{{%AUTOESCAPE}}</code> consistently. Use the |
| 412 | <code>:none</code> modifier to override autoesacping only in |
| 413 | those (usually rare) cases where there is a specific reason the |
| 414 | template variable should not be escaped, for example: |
| 415 | <ul class=blacklist> |
| 416 | <li>The template variable contains HTML markup that should be |
| 417 | interpreted by the browser. In this case you must be very careful to |
| 418 | ensure that the variable can in no case contain "harmful" HTML. Also, |
| 419 | keep in mind the <a href="#tip_setformattedvalue">above |
| 420 | recommendation</a> on the use of <code>SetFormattedValue</code> and |
| 421 | consider moving the HTML markup into the template.</li> |
| 422 | |
| 423 | <li>The variable is known to be already escaped at the point it |
| 424 | is inserted into the template (for example, the value might be |
| 425 | kept in escaped form in a storage backend). Here, escaping again |
| 426 | via a variable-modifier would result in "double escaping". You |
| 427 | must ensure that the variable comes escaped in the appropriate |
| 428 | context (that is, if you're inserting the variable into an html |
| 429 | document, it's html-escaped and not java-escaped).</li> |
| 430 | </ul> |
| 431 | </li> |
| 432 | |
| 433 | <li> Do not leave an extra space when using <code>{{BI_SPACE}}</code> |
| 434 | |
| 435 | <p>The built-in template variable <code>BI_SPACE</code> is itself |
| 436 | replaced by a single space. It is used where you need to make |
| 437 | sure a space is preserved at the end of a line. It is a common |
| 438 | mistake to leave an extra space before this marker, which results |
| 439 | in not one, but two, spaces created in the document.</p> |
| 440 | |
| 441 | <p>Incorrect:</p><pre> |
| 442 | <table border=0 {{BI_SPACE}} |
| 443 | align=center></pre> |
| 444 | |
| 445 | <p>Correct:</p><pre> |
| 446 | <table border=0{{BI_SPACE}} |
| 447 | align=center></pre> |
| 448 | |
| 449 | </li> |
| 450 | |
| 451 | </ol> |
| 452 | |
| 453 | <hr> |
| 454 | <ul> |
| 455 | <li> <A HREF="guide.html">User's Guide</A> </li> |
| 456 | <li> <A HREF="reference.html">Reference Manual</A> </li> |
| 457 | <li> <A HREF="auto_escape.html">Auto Escape</A> </li> |
| 458 | <!-- |
| 459 | <li> <A HREF="tips.html">Tips</A> </li> |
| 460 | --> |
| 461 | <li> <A HREF="example.html">Example</A> </li> |
| 462 | </ul> |
| 463 | |
| 464 | <hr> |
| 465 | <address> |
| 466 | Craig Silverstein<br> |
| 467 | <script type=text/javascript> |
| 468 | var lm = new Date(document.lastModified); |
| 469 | document.write(lm.toDateString()); |
| 470 | </script> |
| 471 | </address> |
| 472 | |
| 473 | </body> |
| 474 | </html> |