Thursday, April 09, 2009
Convenience vs. Correctness
I'm not sure how I feel about this.
I've been wanting to update my website for some time now, but the latest version of
xsltproc
hates me. Or rather, it hates the XSL files that worked fine
under an earlier version of the code.
It took a few hours of debugging (XSL makes COBOL look terse) but I figured out the issues, and most of them relate to attributes. Or rather, the lack of attributes when testing them.
I had a bit of code:
<xsl:if test="count($objects[@listindex != 'no'])"> ... </xsl:if>
I was passing in a bunch of entities (think DOM objects, or if that's too obscure, things similar to HTML tags):
<section id="News" directory="news/"> ... </section> <section id="People" directory="people/"> ... </section> <section id="Software" directory="software/" pubdate="yes"> ... </section> <section id="Projects" directory="projects/"> ... </section> <section id="Merchandise" location=" ... "> ... </section> <section id="Reference" directory="refs/"> ... </section> <section listindex="no" id="Errors" directory="errors/"> .. </section>
(the neat thing about XML—you get to create your own tags) and as you
can see, there are several sections, with one I don't really care to list,
thus the listindex
attribute. It avoids creating links to
those sections I don't care about.
The old version of xsltproc
would attempt to compare the
attribute listindex
index against the value “no”, and if the
attribute was missing, then it just assumed the attribute was there, but the
value was something other than “no”. The function count()
counts the number of nodes that match, and would return “6”, because there
were six entities where the attribute listindex
was not equal
to “no” (despite the fact that the attribute listindex
didn't
exist in most cases).
The newer version would only check those entities that had the
listindex
attribute, and here, the function
count()
returned “0”, because of all the entities that
had the listindex
attribute, none had a value other
than “no”.
And that's why I'm conflicted on this.
The earlier interpretation makes things convenient. I want to ignore
entities that have listindex='no'
and include everything else.
The number of entities that I want to ignore is small, so it is easier to just
add this when I want to ignore something than to add
listindex='yes'
to everything.
On the other hand, I prefer strict type checking and having everything
explicitly spelled out. Nothing hidden, no surprises. So I can see that
I'm asking for all entities that have the listindex
attribute,
and only those entities that have the listindex
attribute.
And on the gripping hand, having to check the existence of an attribute before checking it's value every single time is making a verbose language even more verbose and seriously changes the logic in the code (and I'm only half done, sigh).