<!DOCTYPE html>
<!-- ========================================== kroc camen of camen design ============================================= -->
<title>code · ASP Templating</title>
<link rel="stylesheet" type="text/css" href="/design/design.css" />
<meta name="viewport" content="width=device-width, maximum-scale=1.0, user-scalable=no" />
<link rel="alternate" type="application/rss+xml" href="/code/rss" title="Just code" />
<link rel="canonical" href="/code/asp-templating" />
<!-- =================================================================================================================== -->
	<h1><a href="/" rel="index">
		Camen Design
		<li><a href="/">all</a></li>
		<li><a href="/projects">projects</a></li>
		<li><a href="http://forum.camendesign.com">forum</a></li>
		<li><a href="/quote/">quote</a></li>
		<li><a href="/writing/">writing</a></li>
		<li><a href="/blog/">blog</a></li>
		<li><a href="/photo/">photo</a></li>
		<li><a href="/code/" rel="tag">code</a></li>
		<li><a href="/art/">art</a></li>
		<li><a href="/link/">link</a></li>
		<li><a href="/poem/">poem</a></li>
		<li><a href="/audio/">audio</a></li>
		<li><a href="/web-dev/">web-dev</a></li>
		<li><a href="/annoyances/">annoyances</a></li>
		<li><a href="/eve/">eve</a></li>
		<li><a href="/code-is-art/">code-is-art</a></li>
		<li><a href="/inspiration/">inspiration</a></li>
		<li><a href="/windows/">windows</a></li>
		<li><a href="/gift/">gift</a></li>
		<li><a href="/gaming/">gaming</a></li>
		<li><a href="/mac/">mac</a></li>
		<li><a href="/osnews/">osnews</a></li>
		<li><a href="/c64/">c64</a></li>
		<li><a href="/linux/">linux</a></li>
	</ul><a rel="next" href="/code/cleanly-grouping-by">
		← newer article
<!-- =================================================================================================================== -->
	<!-- date published or updated -->
	<time pubdate datetime="2007-07-27T19:49:00+01:00">
		<sup>7:49<abbr>pm</abbr> • 2007</sup>
		<abbr title="July">Jul</abbr> 27
	<!-- categories -->
		<li><a href="/code/asp-templating" rel="bookmark tag">code</a></li>
		<li><a href="/code-is-art/asp-templating">code-is-art</a></li>
		<li><a href="/web-dev/asp-templating">web-dev</a></li>
		<li><a href="/windows/asp-templating">windows</a></li>
	<!-- licence -->
		<a rel="license" href="http://creativecommons.org/licenses/by/3.0/deed.en_GB">c</a>
		share + remix
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<h1>ASP Templating</h1>

'//Allows replacing of tags in a text file with other content
Class clsTemplate
	Public Content  '//The text of the template
	Private Sub Class_Initialize
		Content = ""
	End Sub
	'//Substitute a tag marker "&amp;{TAGNAME}" with given content
	Public Sub ReplaceTag (ByVal strTag, ByVal strContent)
		'//Whilst tags and constants are functionally the same, they allow you to markup your templates
		'//in a way where it is clear that tags represent large substitutions and dynamic content, and
		'//constants represent highly common, short one-line strings, such as HTML IDs, URLs and the like
		Content = Replace (Content, "&amp;{" &amp; strTag &amp; "}", strContent)
	End Sub
	'//Substitute a constant marker "&amp;__TAGNAME__" with given content
	Public Sub ReplaceConst (ByVal strConst, ByVal strContent)
		Content = Replace (Content, "&amp;__" &amp; strConst &amp; "__", strContent)
	End Sub
End Class

'//Retrieve a template file and then provide direct access to it
Public Function LoadTemplate (ByVal strTemplateName)
	Set LoadTemplate = New clsTemplate
	LoadTemplate.Content = App.Disk.LoadText (TemplateDir &amp; strTemplateName)
End Function

	<strong>This took over 100 hours to create.</strong><br />
	No, seriously, it did.
	I’ve been going over a website I designed and created a while ago with a fine tooth comb, rectifying some of the
	ancient and frankly awful code. One of the biggest problems outright was that of 12’500 lines of code in the site,
	the HTML code was totally intermixed with the server side code. Updating anything was a total pain, and the logic
	code was so spread out it was proving a nightmare to re factor it.
	The solution to this would be to template the HTML content and simply swap out some tags in the template with the
	dynamic parts of the content. The real challenge in doing this was being able to deal with a website with pages
	containing very intermixed dynamic, and non dynamic content, plus lots of common HTML used between all the pages.
	I needed a way to recursively handle templating, being able to swap out one template tag with the content of another
	template, and then deal with the dynamic parts of that sub template, ad-infinitum. This posed a real head-racking
	problem trying to piece together the concepts in my mind, with such a limited programming language, and still trying
	to maintain some elegance. It’s like trying to solve algebra. You have <var>x</var> and <var>y</var>, but
	neither are concrete known numbers yet, but you still have to do multiplication with them. Needless to say I paced
	around a <em>lot</em>, went through a lot of cups of tea.
	Before I started, I had googled quickly to see what else people were doing regards templating in ASP. I looked at a
	class called “ASPTemplate” which included the basic concept of swapping out markers in a template file with
	defined “tags”, allowing you to put a <q><code>{TAGNAME}</code></q> marker in the template, and then replacing
	it with your dynamically generated content before going to the presses.<br />
	<br />
	It was over engineered though.<br />
	Look at my solution, then check out the 530-line
	<a href="http://asptemplate.svn.sourceforge.net/viewvc/asptemplate/trunk/asptemplate/asptemplate.asp?view=markup" rel="external">ASPTemplate</a>

<hr />

	<strong>There is an art</strong> to classes and that is do one thing, and do it well. ASPTemplate was using regular
	expressions to find each tag in the template, and then substituting the defined tag content if present. The problem
	with this is that it was looking at all tags on the page, and trying to find content for each, meaning that there
	was added complexity dealing with tag markers which then had no content given to the class by the caller. This is
	just bad design.
	With each template marker tag, you’re making a statement that this will have some content. There isn’t anything
	fuzzy about this. Being able to ignore tag markers would lead to severely lazy templating, potentially causing very
	hard to trace bugs when you start get into recursive templating with dynamic and non dynamic content replacement.
	ASPTemplate had the problem of trying to cater to everybody, including lazy programmers with bad code. In order to
	be elegant I needed to be able to define one clear way of templating that made precise design statements about how
	template files should be written. This is what I struggled with a lot, trying to hone the code down to a single
	precise <em>statement</em>.
	About half way through development I had produced a class that created two arrays <code>Tags</code> and
	<code>Constants</code>, that the caller added content to with the relevant tag name. Then an <code>Evaluate</code>
	function would be called that then looped through each tag replacing the content and returning the resultant string.
	This way only the tags the caller added would be parsed, meaning that any tags that were not defined by the caller,
	but were present in the template file would be clearly visible on the output.
	Whilst I had something that worked like ASPTemplate, it still wasn’t elegant. The <code>Evaluate</code> function
	was side-effecting by acting upon the <code>.Content</code> property, but also then returning the property as well.
	Also I was having difficulty pinning down who would handle the recursion. Would this be handled in-class by allowing
	special tags that would auto load and replace template files? The problem was that I was still trying to do too
	much. I had seen ASPTemplate, and thought it the style to follow.
	Firstly, if I was only storing the replacement content, only to evaluate it all in one go, it seemed pointless
	considering that no other interaction was needed with the <code>.Content</code> until actual evaluation. Ergo, I
	switched to replacing the Tags and Constants straight away, instead of storing them and evaluating in a batch. This
	removed the side effects of the <code>.Evaluate</code> function and helped solve the real main problem - recursion.
	I realised that if one tag in a template was replaced immediately with the content of another template, I would need
	to evaluate the newly present tags too. I was trying to handle this with function calls either inside or out. It
	would have created a never ending tree of functions, each not doing a lot, with a difficult path to follow on
	screen, especially if some of those functions were then on shared code-pages. It would be impossible to follow the
	recursion as it happened.
	Instead I only needed to continue using the replace tag function knowing that as each tag was replaced, the new tags
	were immediately present and ready to be substituted. It also allowed for tags to be shared across all levels of
	templates by replacing them last. This had removed a huge amount of caller complexity by reducing everything down to
	just one level and allowing you to template with great complexity in a clean run. It also meant that my class
	didn’t need to have more bells and whistles to handle a million use cases. I didn’t need more and more tag types
	to deal with exception cases in the design.

<hr />

	<strong>The last part</strong> of the design was to make the caller code elegant to look at and as streamlined as
	possible to avoid having to create and destroy hundreds of variables / class instances and have massive indentations
	just to do the templating process as this would mix with the logic badly and make things just as hard to follow as
	By creating a function to both create a new template class, preload the content and then return a self instance
	allowed me to get a loaded template in one line, without having to <code>Dim</code> any variables! This made the
	whole thing very self contained and very elegant for ASP.

<pre><code>With LoadTemplate ("EMail/Contact")
	.ReplaceTag "MESSAGE", strMessage
	Site.SendEMail strName, strEMail, strSubject, .Content
End With</code></pre>

	I think I managed to achieve the simplicity I desired, at any recursion level, and with the ability to mix dynamic
	and static content very easily.
	In the end I had to ditch any idea of following everybody else’s way of doing things, and the expected norms of
	programming and start really listening to just myself to hone this code down from a homogeneous blob of confused
	design and functionality that was trying to cater to too many scenarios instead of defining a solid single scenario
	to always follow in the first place. Ergo I ended up with a piece of code that would only take a few minutes to
	write, but took 4 solid days with little sleep, revising and thinking hard to come up with something to suit the
	12’500 line project I had to apply it too.
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
	<nav><a href="http://forum.camendesign.com">‹ Discuss this in the Forum ›</a></nav>
	<a href="mailto:kroc@camendesign.com">kroc@camendesign.com</a>
		<a href="/code/asp-templating.rem">Rem</a> •
		<a href="/code/asp-templating.html">HTML</a> •
		<a href="/design/">CSS</a> •
		<a href="/.system/">PHP</a> •
		<a href="/.htaccess">.htaccess</a>
	<form method="get" action="https://duckduckgo.com">
		<input type="hidden" name="sites" value="camendesign.com" />
		<input type="search" name="q" placeholder="search…" />
		<input type="submit" value="Go" />
<!-- =================================================================================================== code is art === -->