Skip to main content

Taglibs: Designing Web APIs for the Non-Programmer

{cs.r.title}






As the number of web pages and web applications that need to be
written rises, more and more non-coders will need to write them. There
simply isn't the budget or time for professional programmers and graphic
designers to write them all. But this can only happen if we have a
development platform that is reliable, concise, and easy to use. JSPs
and taglibs have the potential to be this platform, but only if the tags
are written well. This article will discuss the usability of taglibs and
demonstrate the lessons learned from three redesign case studies.

Taglibs: Visual Basic for the Web

Just as Visual Basic brought simple desktop programming to the
masses, web programming will increasingly be done by non-professionals.
As we approach the day where every group of any kind has a web page,
there simply won't be enough time and budget for professionals to write
all of them. More web software will be written by people who don't have
the time to learn full structured programming. They will make brochures,
mailing lists, calendars, and online polls. There will be a lot of
commonly requested features that simply need to be customized. These
customers will need a Visual Basic of the web.

As components of the J2EE system, JSP scriptlets and taglibs have the
potential to be such a development system. J2EE is robust and reliable,
with the ability to isolate applications from each other and from
general concerns like load balancing and logging. J2EE makes a
multi-customer hosting business practical.

For those of you not familiar with them, taglibs are Java classes
that convert an HTML element (tag) into new output before the page is
sent to the user. It could be as simple as having <util:date> become
January 1st, 2004, or as complicated as generating inline charts
and reports. The important thing is that you, as the programmer, can use
Java to write an encapsulated extension to HTML. To the web page writer,
it looks like the extension is simply a magic tag; it's as if the
browser itself now supports a new HTML element that does neat things.

Taglibs are particularly good for non-professional developers. They
integrate well with visual editors and provide a comfortable interface
for people only familiar with the declarative programming of HTML.
When properly designed, taglibs are easy to use, powerful, and can scale
without any work from the end user.

Usability

Like all software, taglibs have their own unique usability problems.
The user interface (UI) of a taglib isn't buttons and menus, but tags
and attributes. With a graphical UI, there is a cognitive cost to adding
features. The features still display, even if the user never
uses them. Witness the many unused buttons in the typical
Microsoft Office application. Each extra piece of functionality costs
the user a tiny bit of their concentration and memory, of their cognitive
load. With a tag-based UI, however, the user has to know about a feature
in order to use it, so unused functionality is hidden. A user can use
two tags of a tagset and never know about the other fifty. This is the
sign of a scalable UI. The cognitive load scales directly with the
complexity of the task. Easy tasks require little knowledge; hard tasks
require more knowledge.

We have to be careful, though. In some sense, the UI for a taglib is
really the documentation. If the manual is long or hard to read, then the
application will be hard to use. Some taglibs have complex features that
need lots of documentation. In these cases, we must make sure that the
simple basic features can be used with very little reading; say, a single
paragraph. Then, extra documentation can be read to learn how to do more
complicated tasks.

Defining our Audience

A common technique for designing usable software is to create a
synthetic user: an imaginary person who embodies the type of user for which we are
writing. This user will have a name, job, and background. By
personifying the user, we can get a better mental grasp of the problems
this user will have, and how they will react under different
circumstance.

For this article we will create Bob, a veterinarian. As a new vet,
he is a very busy man. He wants to create a web site for his struggling
practice with updated news, a calendar, and simple navigation from page
to page. His practice is too small to afford a professional designer, so
he'll have to do it himself. He could learn to program JSPs with
scriptlets, but he would rather spend his time helping animals. He can
use a visual editor and knows enough about HTML to fix broken links. Bob
is our target user.

Bob's constraints tell us that our programming solution needs to be
easy to use, quick to learn, and very reliable. It must have low load on
the sysadmin, because Bob can't pay for much support. In short, Bob needs
very good but very targeted software. This is why we want clean taglibs
for Bob. Now let's redesign three tags for him to use.

An RSS Tag

<rss:contentfeed
        href="http://coolnews.org/feed.xml"
        id="coolnews">
    <rss:for-each id="coolnews" item="item">

     <b><%=item.getTitle()%></b><br>

     <%=item.getContent()%><br>

     <hr>
</rss:feed>

This is an RSS tag. It reads from an RSS feed and prints each item.
It uses ids to mark the feeds and requires a for loop with scriptlet
syntax. Our goal is to rewrite this tag to make it do as little as
possible and let Bob use as much standard HTML as possible. The more
attributes and tags that are required, the more Bob will have to learn before
getting things to work. We want our users up and running with the simplest
possible usage of a tag, and then we'll build upon that.

So what does an RSS tag do? It reads from an RSS feed and prints
each item. At a minimum, we need the URL of the RSS feed. While our users
may not understand what an RSS feed is (an XML document returned over
HTTP) they will probably understand that if you stick in a special URL
from your news service, say The New York Times, then the headlines
should come out. Now what should we call the attribute? RSS, LINK, FEED?
While all of these may make sense in our domain, we need to consider our
audience. What would Bob think? Well, Bob is familiar with web pages and
he understands that the image tag puts an image in his web page. It
would be a logical next step that an RSS tag puts an RSS feed in his web
page. So we will follow the HTML lead and use src for the URL.

Next we need to print out the title and content of each item. We can
do this with title and body tags. The names are simple and unambiguous.
Presto -- with a four-line example, Bob can now embed an RSS feed in his web
page. The most common case is now the simplest to access.

<rss:feed href="http://myblog.org/feed.xml">
     <b><rss:title/></b><br>
     <rss:content/><br>
     <hr>
</rss:feed>

This will produce output that looks like Figure 1:

Figure 1
Figure 1. Output of the RSS tag

Documenting the RSS Tag

How can we document this? I once heard of a TV that required 15
minutes of setup screens and reading the manuals to install. Until the setup was
finished, the TV could not be used for watching TV shows. When it takes
fifteen minutes to make a device perform its primary purpose, then
something is wrong. Any piece of software should perform its most
primary function immediately. iTunes, for example, plays music and it
does it very, very well. It does lots of other things, too, but you can
make it play music after looking at it for about five seconds.
Everything else is secondary. If you can't explain how to use the
software in a single printed page (or on a single web page, "above the
fold") then it's too complicated. Either the program or its
documentation needs to change.

The best way to document the RSS tag is with an example. Show that
the software turns "this" (the three tags) into "that" (sample output). This
is a very direct way of explaining what the software does and how it
does it. The primary purpose is clear, and Bob can immediately use the
software without reading one word further. All other features can come
after further reading, but the basic feature is right there. Score one
for usability! Our documentation is shown in Figure 2.

Figure 2
Figure 2. Documentation of the RSS tag

A Tree Menu

Our next case study is slightly more complex: a tree menu. I adapted
this from some open source code I found on the Internet. It did its task well, generating cross-browser tree menus, but it wasn't simple to use. It
did, however, have the advantage of not needing external JavaScript
files, which made it a good base from which to start. Now let's look at how it works and
then discuss how we can make it better.

<treetag:tree level="1" label="Menu 1"
    browser="<%=getHeader('user-agent')"
    image="folder" type="mac"/>
<treetag:tree level="2" label="Sub Menu 1"
    image="document" type="mac"
    href="foo.html"/>
<treetag:tree level="1" label="Menu 2"
    image="folder" type="mac"/>
<treetag:tree level="2" label="Sub Menu 2"
    image="document" type="mac"
    href="bar.html" />

This will create a tree menu that looks like a file browser mixed with
Windows help. It has a folder, book, or document image next to each item.
It works well and isn't too complicated, but it could be a lot better.
The tree it produces looks like Figure 3:

Figure 3

Figure 3. Sample tree output

First, why do we have to specify the depth level of each node? If
the tags were nested, then the level could be figured out at runtime.
There is no reason to have the user specify the depth level. This is something well
written software should do for the user, so let's get rid of that
attribute. We also see that the user has to specify the browser type
with a Java scriptlet. This could also be easily done inside of the tag
code without user intervention, so let's pull that out, as well.

Finally there is a pair of attributes to specify the icon. One is
the platform type and the other is a keyword specified that maps to a set
of images using a config file. To add any new images, the user would have
to modify the config file and put the images in a special directory,
probably controlled by the sysadmin. This system is also pretty specific
to file browsers and doesn't lend itself to other uses of a tree menu,
such as for navigation. It would be better if the user could just
specify the images directly. This would keep them from bugging the
sysadmin and allow for non-local images via external URLs. Again we will
use a derivation of src, since most people are familiar with that naming
convention.

Here is our redesigned tree menu:

<tree:tree>
  <tree:node label="Menu 1" opensrc="folder.open.gif"
      closesrc="folder.close.gif">
    <tree:node label="Sub Menu 1" src="doc.gif"
        href="foo.html"/>
  </tree:node>
  <tree:node label="Menu 2" opensrc="folder.open.gif"
      closesrc="folder.close.gif">
    <tree:node label="Sub Menu 2" src="doc.gif"
        href="bar.html"/>
  </tree:node>
</tree:tree>

We've also expanded this from one tag to two by having a separate
tree tag that wraps the nested node tags. This delineates the tree as a
whole from its parts, as well as from the rest of the page, which will
be important as we add new features, such as styling.

Styling the Tree

The code above will create a tree, but it won't look like anything
more than a list of links with some indentation. We have to specify
styling. Styling is tricky because there are a million different ways to
style a menu. One solution is to create a set of attributes on each tag
for the font, dimensions, color, and border, but that would result in
many, many attributes and might still not cover every possible usage.
Another solution is to require the use of CSS, but of course the user
would have to understand CSS, yet another thing to learn. What does
Bob want? He probably understands colors and fonts and would only learn
CSS by small examples. The best solution is to do both: have a limited
set of attributes for the most common settings (colors and borders) and
to require the use of CSS for anything more complicated. Now the tag
code will look like this:

<tree:tree border="1" bgcolor="#ff0000"
    color="#ffffff">
    <tree:node label="Menu 1">
        <tree:node label="Sub Menu 1"
        bgcolor="#0000ff"/>
    </tree:node>
    <tree:node label="Menu 2">
        <tree:node label="Sub Menu 2"
        bgcolor="#0000ff"/>
    </tree:node>
</tree:tree>

We've added the border, bgcolor, and color attributes to the tree tag
at the top. This sets those values for the whole tree. Bob can override
the colors for each node as desired. This scheme handles quite a lot of
cases while still being simple and easy to describe.

For CSS styling, Bob will need to know what HTML is actually
generated by the tags. We could document this or tell him to do a
view source from the browser, but if we have nested tables, it could
still be complicated. Instead, we provide named classes to access the
different parts of the tree. Here is the final version:

<style>
  .tree { width: 200; background-color: #ffff00;
          border: 1px solid black; }
  .top-node { font: 14pt bold sans-serif; }
  .node { background-color:#0000ff;
          font: 10pt sans-serif; }
</style>

With this design, Bob only learns enough to do the task at hand, but he is
prepared for learning more complicated features. The styling and the API
both scale with the complexity of the task.

As a final addition we can add auto-opening. Since HTML trees are
usually used for navigation, it would be nice if the branch that
contains the current page was always open. This could be implemented by
putting an open tag on each page to force the proper menu to be open.
However, our code knows the href of each node and the URL of the current
page, so we can figure it out auto-magically most of the time. 99% of
the time, this is exactly what the user wants, so let's make this the
default and let the user turn it off in cases where it's not
appropriate. I call this a passive feature, since it requires no
intervention or even knowledge by the user to function. As our lives
become more complex, I think we are going to see more and more of these
kinds of features.

An HTML Calendar

Our final example is an HTML calendar. I've come across this one several
times with small organizations that want a web-based calendar just to
show when their next meeting or class is. They want it to look pretty
but simple. It's not collaborative or dynamic. It's a small piece of
software that should be simple to use, but as I found how out, dealing
with dates can be very tricky.

Let's start with the basics:

<calendar:calendar/>

This produces the calendar seen in Figure 4.

Figure 4
Figure 4. Basic calendar tag output

Now that's a simple API. It prints a calendar for the current month
with arrows to go forward and backward through time. As with the tree,
styling is handled mostly through CSS. It's pretty simple to just
display the calendar. Events, however, are another matter.

Specifying events through structured notation is difficult, as the
designers of virtually any calendaring software can attest. The basic
idea is to have the user specify as much detail as needed and all other
variables will be looped. It's not going to be perfect, but it should be
enough to cover most tasks. Here's an example:

<calendar:event day="31" month="12" year="1999" description="New Years Eve"/>
<calendar:event day="31" month="10" description="Halloween"/>
<calendar:event day="5" description="Rent due!"/>
<calendar:event day="Tuesday" description="Dance class"/>
<calendar:event day="Monday" week="1" description="Neighborhood Meeting"/>

This produces the calendar seen in Figure 5:

Figure 5
Figure 5. Calendar with event tags

The first event is New Year's Eve, 1999; a one-time
event. The second is on the 31st day of every 10th month, or
every Halloween. The third is on the fifth of every month, and the fourth is every Tuesday. Finally, the fifth is every
Monday in the first week of a month, or the first Monday of each month. These five
examples cover almost every possible event someone could want, in a clear
syntax. There are only four attributes to learn and they directly relate
to the Bob's likely mental model.

To make this truly easy to use we would want to handle alternate
forms of each value, most of which we can do with help from
java.util.Calendar. We can ignore capitalization, support localized
spellings of the weekdays, and allow the use of month names instead of
numbers. Any strange form of data entry should be supported, if at all
possible. The more mental work we can remove from Bob's web coding, the
better he can perform his real job.

Leaving Out Features

I should note that some features were specifically left out.
There is no way to specify a time of day or use advanced selectors, such as
"do this every business day." These features are common in personal
planners, but aren't actually relevant to our users. Setting the time of
the event doesn't matter because this calendar isn't used as an alarm.
It's a calendar on a web page, not a PDA or Outlook. The time can be
included in the description, but our software doesn't need to do anything
special with it. The second feature, specifying more than one day a week,
is a timesaver but doesn't add anything new. Bob could just make five
of the same event. This is a good tradeoff, because setting up a
calendar is an uncommon task. Bob will probably do a single setup and
update it maybe once a month. The savings in learning time more than
makes up for the time spent copying and pasting the event. As a
compromise, though, we could accept comma-separated weekdays; a
transparent addition to most users.

Packaging and Documentation

Now we have designed three JSP taglibs to handle relatively
complicated tasks with a simple API. Before I finish, I'd like to talk a
little bit about packaging. We want to make the software as easy to
install as possible, since a failed install = failed software, and that
doesn't help anyone.

First we should package up all code as a .war file. Any support
files, config files, etc. should be packaged up in the .war as well. Even the
.tld can go in there. To help with the job of packaging, I recommend Ant
tasks. In addition to the usual .jar and .war tasks, there are a few that
auto-generate the documentation from the .tld file. This output should
be used as a base but not a replacement for prose with examples. After
all, you wouldn't want to learn MS Word by reading the function
reference. (Actually, that might be kinda cool :) )

There should be two separate sets of documentation, one for the
installer and one for the user. This is because the user documentation
will likely be forwarded by your customer, the admin, to his
users
, the people actually using your software. It's also a good
idea to write all documentation as HTML with CSS stylesheets so that the
admin can rebrand it if necessary.

The installer's set should discuss what the software does, what
resources it requires, and how to configure it. The taglib should, if at
all possible, run with zero configuration: just a single entry in the
web.xml file. Sensible defaults and auto-detection really help out here. The
second set of documentation is for the user. It only covers what the
software does and how to use it. It should start with simple examples
using the primary function of the taglib, then build upon that.
That way, the users can start at the beginning and only read enough to do
what they want.

Source Code

The three tags I've described here are released as open source and
are available as taglibtools.zip. I
developed them specifically for non-technical users. The RSS feed was for my
sister, who is an actress with a weblog. The calendar was for the
president of my neighborhood association. The tree was for the redesigned
neighborhood web site that my girlfriend, a print designer, has created.
All three are smart but non-technical people with better things to do
than learn my APIs. The tags had to be reliable, so that I didn't have to fix
them, and simple, so that I didn't have to answer lots of questions.

Conclusion

In this article, I have covered the basics of usability for software
and then shown how that is applied to the UI of taglibs. We've learned
the golden rules of UI design:

  1. Know your audience. Just like art, code needs an audience to be relevant, and different audiences need different programs.

  2. Reuse your user's brain. Use well previously known metaphors and notations wherever possible.

  3. Minimize configuration. Use auto-detection and reasonable defaults.

  4. Make your UI scale. Complexity of the UI should grow linearly with the complexity of the task.

  5. Make your documentation scale. The user should have to read enough to get the job done and no more.

  6. Handle malformed and unusual input wherever as possible.

    And most importantly ...

  7. Don't waste your user's brain. This means his or her time and cognitive abilities. Your user is using your software to save time. Successful (and popular) software won't waste it.

I hope I have also demonstrated how important taglibs will be to the
future of the Web. If they are to be heavily used, and I hope they
will, then ease of use will be the primary factor in their design.

Related Topics >> JSP   |