Pre-Processing and Reusability
When you decide to change your web page header, or your corporate color, or your phone number... do you really want to edit each and every web page on your site one at a time? Your phone number should be defined once, then used automatically on each page that needs it.
As you browse around the CleanCode website (or most any website for that matter)you'll notice that the header, footer, left and/or right navigation bars tend to remain constant from page to page. There are different ways to do accomplish this, some are clean techniques, some are not.
But first let's discuss the two basic page types:
The key to duplicating portions of your web page is... not duplicating. That is, you should use reusable components. Say, for example, you have several hundred static web pages, each of which has the same footer, and in particular, the same dated copyright notice. Now it's New Year's. So you'll have to edit each of your several hundred web pages and update the copyright date. Or let's say you want to change your header a little bit. Again, go edit all the files...
So that's the wrong way to do it with static pages. Let's explore a better way. But first, I'll just mention dynamic pages, which do it the "right" way almost automatically. Again, a dynamic web page is generated by an application program. Typically, such a program will use a template to fill in a skeleton page, or pull together different blocks of HTML code, or generate HTML code internally. Any way you slice it, the application will have the copyright date in just one place, so updating it requires updating it only once.
Now static pages, on the other hand, are commonly done in two ways. The first we've seen--each page includes the copyright date so updating it is laborious. The second method eliminates the multiple copies of the copyright notice, and hence the maintenance problem, but introduces a usability issue. This method is done with frames. With frames, you load the constant piece of code in one frame, typically the navigation bar, and the changing portion in another frame. Frames are handy for very specific uses, but officially they are to be shunned, because of accessibility issues. Another reason to shun is that you can't bookmark a specific frame content, only the original default frame contents. I will profess that frames do still have their place, however, and they are used on the CleanCode site in two places--for the Java library documentation and for the Perl library documentation.
So how can you take the benefit of frames (no multiple copies) with the benefit of non-frames (no accessibility or bookmark issues) and still use static pages? With a utility called a preprocessor.
A preprocessor is simply a tool that converts one format to another format. In the case we've been pursuing, this would involve converting from a main page content to a full HTML page. The conversion process will add the appropriate header, footer, sidebar, ... whatever we choose that we wish to have on every page. An astute web search will reveal many preprocessor utilities. One that is particularly useful is ppWizard. Another of this ilk I've seen, but not looked at extensively, is htmlPX. I'll also mention a handy tool for quick prototyping, including things like finding the correct DOCTYPE string to use a particular standard, this page builder is convenient.
If you're still not sure what a preprocessor is, the ppWizard web site provides excellent tutorials and documentation. It aptly describes a preprocessor as similar to server-side includes and active server pages, if you're familiar with how those work. It further provides a comparison of SSI, ASP and ppWizard, indicating the advantages and disadvantages of each, and that you might want to use them in concert. (See Apache for information on server-side includes, and W3Schools for information on active server pages.)
The preprocessors like ppWizard above are standalone tools. The other type of preprocessor to consider, depending upon your needs, is the library component. That is, for CGI or other dynamic web page generation, a preprocessor is also a handy tool to use.
It is a particularly bad idea to include statements
in your program such as
output = "<tr><td>Name</td>" + "<td>Value</td><tr>";
, because it is so easy to create non-well-formed code. Also, that intimately mixes layout with function, which is a poor design practice.
At the least, you should use an HTML generation toolkit, such as included in the standard Perl CGI module.
CleanCode also provides an HTML generation toolkit (HTML::Generator and HTML::XGenerator) which is a more specific tool than CGI in one sense, focusing only one output generation, and a more generic generator in another, in that the
methods are not named for HTML elements.
But back to preprocessors. A great preprocessor in the Perl arena is the HTML::Template module, available from CPAN. This uses templates which are just HTML files with some added elements, variables, and conditionals, providing control over the final page generation. This is a library module that you can access from your own server application program to create dynamic web pages. (It is used to generate the CleanCode Perl documentation set, which is then stored as a set of static web pages for users to access. See the CleanCode utility pod2htmltree.)
Finally, the best for last. You are probably familiar with XML. With XML comes XSL, a powerful, flexible preprocessing tool. Any XSL processor is, by its very nature, an HTML preprocessor. You can find several off-the-shelf XSL processors, which take an XML data file and an XSLT template file as input, producing whatever you've specified as output. That may be HTML, but it may also be a differently structured XML, or even just plain text, if you wish. (Other than the Java documentation and Perl documentation sets on CleanCode, most of the web pages are static, but were created as XML and run through an XSL processor to get the final HTML. This was done, of course, through another CleanCode utility (XmlTransform) which takes a whole directory tree and transforms it per your directions.)
XSL has another advantage--it is usable as either a standalone utility (such as xsltproc) or as a library component (available in Java, Perl, JavaScript, and probably other languages). The CleanCode utility XmlTransform mentioned earlier uses Java library modules for XSL processing, essentially putting a wrapper around the core XSL processor to handle multiple directories, with optional validations of input and output files. Note that I mentioned JavaScript as an available language (through ActiveX objects). This allows you to dispense with storing HTML pages at all! Use pure XML pages on your website, each of which specifies an XSLT translation file, so the "preprocessing" is done entirely within the client browser, converting it only at the last instant to HTML. (See the CleanCode utility list for a real product use of this, rather than an academic example. The list utility may also be interesting to readers of this article, since it uses both HTML::Template (for single directory lists) and XSL (for tree lists), but they both essentially generate the same type of output.)