Sponsored Link •
Elliotte Rusty Harold talks with Bill Venners about the API design principles that guided the design of the XOM (XML Object Model) API.
Elliotte Rusty Harold is a prolific author of numerous books about Java and XML, and creator of the popular Java website Cafe au Lait and XML website Cafe con Leche. He contributed to the development of JDOM, a popular XML processing API for Java. His most recent book, Processing XML with Java, shows how to parse, manipulate, and generate XML from Java applications using several XML APIs, including SAX, DOM, and JDOM.
At a meeting of the New York XML SIG in September, 2002, Harold unveiled an XML processing API of his own design: the XOM (XML Object Model) API. On Cafe au Lait and Cafe con Leche, Harold described XOM like this:
Like DOM, JDOM, dom4j, and ElectricXML, XOM is a read/write API that represents XML documents as trees of nodes. Where XOM diverges from these models is that it strives for absolute correctness and maximum simplicity. XOM is based on more than two years' experience with JDOM development, as well as the last year's effort writing Processing XML with Java. While documenting the various APIs I found lots of things to like and not like about all the APIs, and XOM is my effort to synthesize the best features of the existing APIs while eliminating the worst.
In this interview, which is being published in multiple installments, Elliotte Rusty Harold discusses the strengths and weaknesses of the various XML processing APIs for Java, the design problems with existing APIs, and the design philosophy behind XOM.
Bill Venners: What motivated you to create XOM? What were your personal and business motivations?
Elliotte Rusty Harold: I have no business model for XOM. I don't expect to make any money out of this, certainly not directly, probably not indirectly. More than anything else, at this time I had just finished writing a thousand-plus page book called Processing XML with Java, in which I exhaustively went through SAX, DOM, JDOM, TrAX, Jaxen, and a little bit into some other APIs. Along the way as I was doing this, I just noticed lots and lots of things. I'd say, "This could be better. That doesn't make any sense. That's really silly." And I thought, maybe the time was right for something better.
Most immediately, the specific motivation was that Walter Perry of the New York XML Users Group wrote to me and said, "Hey, do you want to come present to us this September?" I said, "Sure." And I sent him about three possible topics. One topic was, "What's Wrong with XML APIs and How to Fix Them." Walter said, "That sounds like the most interesting one. Why don't we do that?" So I said, "OK, now I've got to actually figure out how to fix them." So I spent a couple of months, part time, developing XOM in preparation for that presentation.
Bill Venners: Did you start from scratch, or did you refactor the JDOM codebase?
Elliotte Rusty Harold: I originally planned to fork JDOM. When I actually
looked at it, however, it rapidly became apparent that it would be easier to start from a
blank page. Currently, there's only one non-public class in XOM that is taken
from JDOM, the
Verifier class. Not coincidentally, that is the
class in JDOM with which I've had the most personal involvement. I wrote the
original version of
Verifier, and various other people have contributed to
it since then. Other than that, there is no JDOM code in XOM.
Bill Venners: What were your design goals when you started XOM?
Elliotte Rusty Harold: More than anything else, I was looking for an XML API that novices—people who were not XML experts—could learn to use quickly, effectively, and correctly. I wanted an API that would not allow them to make mistakes, that would point them in the right direction. I wanted to make the right thing very easy to do, and the wrong thing difficult or impossible to do.
Bill Venners: What design principles did you want to keep in mind?
Elliotte Rusty Harold: The main design principle, I think, was simplicity.
I wanted maximum
simplicity consistent with correctness, to make the API as easy to
learn and use as it could possibly be. Keeping with that, one very important
thing is the principle of least surprise. It should always be very obvious what a
method does. And in reverse, you should be able to immediately guess what
the method is. If you need to create an element, the most obvious thing is, "Hey,
Element constructor. You pass in a
String that contains the name of the element."
At the same time, you don't want to eliminate the truly surprising parts of XML. You don't want to make the API simpler than XML itself is, which is a flaw I've seen in other APIs that have not achieved broad adoption.
Bill Venners: Such as, ElectricXML?
Elliotte Rusty Harold: ElectricXML is the big candidate. They have a reputation for being very easy to use, but I think that's because they have modeled something that is actually simpler than XML really is. They have smoothed over and cut away a lot of the rough spots of XML.
Also in keeping with the principle of least surprise, I intended to use Java idioms where they seemed appropriate, but not where they didn't. I learned from JDOM that you can go a little too far in that direction. Also, I was very unhappy with the large number of convenience methods in JDOM. That led me to decide I was not going to have convenience methods that made the overall design less convenient, less simple, less clear. I was going to make sure you could do anything you needed to do reasonably simply, but I wasn't going to give you three different ways to do the same thing.
I also thought it was important to start as small as I could, to model just XML and not try to do everything, at least not in version 1.0.
Bill Venners: Define everything.
Elliotte Rusty Harold: The minimal thing to do is XML plus namespaces. Everything would include XPath, XSLT, Catalogs, XInclude, XQuery, etc., a lot of additional work in the XML space that's not part of XML. To be honest, I haven't really satisfied that one. Several of those things have made it into XOM in recent months. They weren't there in the first version I announced to the XML Users Group, but a few of them are there now. To some extent I deliberately segregated them off into separate packages, so if you don't need XInclude, just ignore the XInclude package. And the dependencies between packages are one way. The XInclude package depends on the core package, but the core package doesn't depend on XInclude. Same story for the XSLT package.
Bill Venners: You listed some principles of API design in your talk. I'd like to walk through them and get your comments. You said, "APIs are designed by experts for non-experts."
Elliotte Rusty Harold: Yes. When you use an API, you are relying on the API to be correct. You assume that the developers who wrote that API knew what they were doing. For example, when you use a socket API—whether it is Winsock, the sockets API in UNIX, or java.net—you assume that the people who designed it knew what the IP header format was, knew what the difference between TCP and IP was, knew how to route packets, knew how to talk DNS, etc., so you don't have to. You are relying on their abilities. That means they better have had some pretty strong abilities. And for networking APIs, they had better be experts in networking.
For an XML API, they had better be experts in XML. I've seen a few too many programmers decide they are going to learn XML by writing an XML API. They tend to end up making novice mistakes, and then propagating those to others. XML is imperfect. XML is confusing. It is understandable that mistakes will be made, but they are still mistakes. For example, one common mistake is confusing the XML declaration with a processing instruction. I've seen that happen at least twice in two different APIs. I made that mistake in my first book on XML. It is a very common mistake to make, but if you're at the level where you're making that mistake, you shouldn't be designing an API for other people to use.
Bill Venners: But there are two sides to that. If you are an expert at something, and you're designing an API, I think the other side is: Don't assume that the user is an expert.
Elliotte Rusty Harold: Right. You do not want to require the user to know as much about XML as you do. They should be able to accomplish what they need to be able to accomplish through your API. They should not, for example, have to specially escape characters like the ampersand and the less than sign when they use them in a text node. They should just pass in a string. Your API should handle the escaping for them.
Bill Venners: So designing an API is one way to capture and provide expertise to people.
Elliotte Rusty Harold: Right. That's really the purpose of any class library. You see it in any other environment too. For example, nowadays very few people with high performance needs would use their own numerical algorithms. They would use libraries written by real professionals in the field. These are not just professional programmers, but experts in numerical algorithms, people who have carefully analyzed the edge cases, thought about issues of precision and robustness, and designed the algorithms to perform very well despite all that. The experts can simply do a much better job than the average programmer can. In any area, that's true. None of us are experts at everything. You have to specialize and say, "This is the area where I can contribute. When I move out of my field, I'm going to rely on the work of others."
Come back Monday, August 4 for the next installment of this conversation with Elliotte Rusty Harold. If you'd like to receive a brief weekly email announcing new articles at Artima.com, please subscribe to the Artima Newsletter.
Elliotte Rusty Harold is author of Processing XML with Java: A Guide
to SAX, DOM, JDOM, JAXP, and TrAX, which is available on Amazon.com at:
XOM, Elliotte Rusty Harold's XML Object Model API:
Cafe au Lait: Elliotte Rusty Harold's site of Java News and Resources:
Cafe con Leche: Elliotte Rusty Harold's site of XML News and Resources:
SAX, the Simple API for XML Processing:
DOM, the W3C's Document Object Model API:
Common API for XML Pull Parsing:
Xerces Native Interface (XNI):
TrAX (Tranformation API for XML):
Jaxen (a Java XPath engine):