As threatened, I’ve extracted an HtmlWriter class. And certainly the code is an improvement, though there’s one thing about it I don’t like.

The class has a couple of core responsibilities: it knows how to close the currently open tag, and it knows how to indent. (One could argue that it’s a bit pointless to indent output intended for machines, of course.) So you can do something like this:

writer.open("body");
writer.open("p");
// Stick in more output.
writer.close();
writer.close();

and you’ll get output that looks like this:

<body>
  <p>
    // More output.
  </p>
</body>

Not rocket science, and it doesn’t even save you typing. But it does save you from counting spaces, and it clearly expresses what you’re doing.

This is fine for tags that live on a single line. But sometimes I don’t want to do that: e.g. I might want to create a line like this:

    <h1>Header</h1>

My first attempt at the corresponding code was as follows:

writer.indent();
writer.openInline("h1");
writer.print("Header");
writer.close();
writer.newline();

Which expresses what’s going on, I suppose, but it’s a lot of typing. And the first and last pairs of lines show up every time you wanted to generate output like this.

This might suggest creating a method on HtmlWriter as follows:

void printInlineElement(String element, String text) {
  indent();
  openInline(element);
  print(text);
  close();
  newline();
}

That works for the example above, but what if the text itself contains tags, as in this example:

    <h1><cite>Title</cite></h1>

We’d like all HTML tags to be generated by HtmlWriter, so we don’t want to pass in the literal string <cite>Title</cite> to printInline. But what are our other options?

One is to replace the second argument to printInline by some sort of class which has a method that to generate the text. (And that method can take the HtmlWriter as an argument.) Which is a pretty natural solution; in this instance, though, it’s really clunky to create a class on the fly when all you want to do is insert a relatively small amount of text. (Java’s anonymous classes help a bit, but not enough.) In a language with lambda, I might go this way, but not in Java.

What I ended up doing is leave printInline like above, but in addition to add static members to HtmlWriter to generate text with inline tags surrounding it. I picked this option because it was probably the simplest choice given the existing uses of HtmlWriter, but it sucks: in some places, HtmlWriter exists to accumulate HTML that you’re generating, while in other places it’s just some static functions to spit out HTML. One or the other is acceptable (though the former is preferable); both at the same time is wrong. (Not just aesthetically: it limits future possibilities, making it impossible to, say, have HtmlWriter automatically turn relative links into absolute ones, or do line wrapping, or anything else requiring state.)

If I were programming in C++, though, there would be a third, quite attractive solution. The methods open and close, or openInline and close, or indent and newline, are always designed to be called in pairs. So our C++ reflexes say: create classes whose constructor calls the first member of the pair, and whose destructor calls the second member of the pair. Which would leave us with code like this:

Line(writer);
InlineElement(writer, "h1");
// Code to generate whatever HTML we want; that code can generate text directly
// or call further methods on writer.

That’s much nicer; three lines of code instead of five, no loss of expressiveness, and it’s as flexible as you’d want. (I would probably further refactor those first two lines into a single line, but never mind that.)

But I am programming in Java instead of C++. Too bad. I do think that proponents of general garbage collection sometimes underestimate what they’re giving up (phrasing the discussion solely in terms of performance issues). If we accept that a language should provide (possibly optional) reference-counted garbage collection, then the question is whether it’s more useful to augment that with general garbage collection, or with destructors. Much of the time, I prefer the latter. And I look forward to future programming languages where I don’t have to make that choice.

(I was going to end the post there, but then I had more thoughts while walking the dogs. We already have a bigger picture available: it’s all about the ease of constructing function-like objects in various circumstances. You can even analyze the C++ case that way: the function-like object in question is the rest of the current block. So maybe you can do destructor-style programming pretty easily in languages without destructors but with lambda; and maybe in this situation, I should let people pass an appropriate function class to various methods, and also (for ease of use, so people aren’t creating anonymous classes all the time) provide some concrete classes for people to use, classes that do things like insert a bit of text or create an entity surrounding the output of a further functor class. Hmm. I guess I’ll try that and see how it works; should be fun, at least. But I should probably not let myself do that until I’ve implemented more functionality, to prevent myself from spending too much time refactoring.)

Post Revisions:

There are no revisions for this post.