deviant ART

[x]

clsTemplate.asp by ~Kroc:iconKroc:


Creative Commons License
Some rights reserved. This work is licensed under a
Creative Commons Attribution-Share Alike 3.0 License.
Details
Submitted: Jul 27, 2007
File Size: 133 KB
Image Size: 133 KB
Resolution: 1024×817
Comments: 7
Favourites & Collections: 3 [who?]

Views
Total: 665
Today: 1

Downloads
Total: 20
Today: 0

Thumb

Artist's Comments

This took over 100 hours to create. 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 one hell of a 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 x and y, but neither are concrete known numbers yet, but you still have to do multiplication with them. Needless to say I paced around a _lot_, 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 {TAGNAME} marker in the template, and then replacing it with your dynamically generated content before going to the presses.

It was over engineered though.
Look at my solution, then check out the 530-line ASPTemplate [link]

There is an art 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 statement.

About half way through development I had produced a class that created two arrays `Tags` and `Constants`, that the caller added content too with the relevant tag name. Then an `Evaluate` 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 Evaluate function was side-effecting by acting upon the `.Content`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 `.Content` 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 `.Evaluate` 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.

The last part 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 before.

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 `Dim` any variables! This made the whole thing very self contained and very elegant for ASP.


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


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.

Kroc Camen.

Devious Comments

love 0 0 joy 0 0 wow 0 0 mad 0 0 sad 0 0 fear 0 0 neutral 0 0

`electricnet:iconelectricnet: Jul 27, 2007, 1:57:08 PM
I simply admire how much you think about the details in your code. Even for an outdated language like ASP, you make the best of what you can do with that language. This code wouldn't be the same without the background story. Even though this could have taken 10 minutes to write, the fact that you think so much about the possibilites and the best way to do things is just admirable. That is the way to make perfect code.

--
:star-empty:e
deviant #320,841 | FAQ | life moves on if you want it to. <3
~jastreich:iconjastreich: Aug 3, 2007, 10:56:33 AM
Code as art I totally agree with, but asp on the other hand I find to be ... well ... not so artistic. I'm not criticizing your code so much as I am your choice in languages.

--
[link]
~Kroc:iconKroc: Aug 3, 2007, 11:59:41 AM
It's legacy code I have to support because that's what the site is written in. Plus it shouldn't matter what language it is in; this is such a simplistic class that almost any language could do this. Plus, heavy limitations in a language can either cripple you, or push you harder to be more creative. ASP is a very small language, where just about everything you have to implement yourself; therefore it's good for coming up with creative ways to make functions that are already built into other languages. As I've said, it's for a commercial project, the language is not my choice - if God hands you lemons, ...

--
¡uʍop uɐəɯ ɪ ¿dn sʇɐɥʍ
~Sixthcrusifix:iconSixthcrusifix: Aug 4, 2007, 6:06:54 PM
Code is copyrightable and therefore I define it as art.

Besides that, this is visually appealing; it's so clean and tidy!

--
Pizza Box fun, Girl you know you want some!
*Cenakuu:iconCenakuu: Feb 2, 2008, 5:29:41 PM
I have a question, what program did you do this in?

--
Awesomesauce avatar by ~zazouko. :happycry:
--
Tired of all those annoying petitions?
Click here to sign the anti petition petition!
~Kroc:iconKroc: Feb 2, 2008, 10:36:45 PM
TextMate (macromates.com) on Mac OS X. I'm on a Mac now, but still edit some Windows code on it.

--
¡uʍop uɐəɯ ɪ ¿dn sʇɐɥʍ
*Cenakuu:iconCenakuu: Feb 2, 2008, 10:38:18 PM
Ahh, thank you much.

I had been looking around for a good editor like notepad++ but for Mac and had been unsuccessful until now.

--
Awesomesauce avatar by ~zazouko. :happycry:
--
Tired of all those annoying petitions?
Click here to sign the anti petition petition!