Sponsored Link •
Another basic difference between the object and document approach is the nature of the contract between the client and server. For network-mobile documents, the protocol (including the data models of any documents) forms the contract between the client and server. For network mobile objects, the object's interface forms the contract. One important advantage of objects is that it is easier to evolve the object's contract over time compared to the document's or the protocol's contract.
Coming up with a good design, whether you are designing an API or a DTD, is difficult. Figuring out, agreeing upon, and communicating the design requirements can often be a significant challenge. Another challenge is actually figuring out how best to model the functionality (in the API case) or the information (in the DTD case) that the requirements demand. On top of all that sits another challenge, perhaps the most difficult of all: predicting the future.
Requirements evolve over time. As a result, a design's ability to gracefully accommodate future changes is usually an important quality. But how do you achieve such a design when you don't know what those changes will be? Mark Johnson, JavaWorld's XML columnist, discussed the difficulty of anticipating future evolution in XML DTD designs:
It's difficult to get a DTD right because it's difficult to get a data model right, and a DTD is a data model. The hardest thing about getting a data model right is that data models evolve. There's "right" for today, and "right" for tomorrow. But you don't know what's "right" for tomorrow up front, so you have to guess. Data modeling is, in part, the art of including enough generality to anticipate future schema changes without kicking the model up to such a high level of abstraction that it's inefficient or incomprehensible.
Fortunately for API designers, Java pays close attention to the need to evolve contracts. The little read "Chapter 13: Binary Compatibility" of the Java Language Specification describes all the ways a Java class or interface can change without breaking binary compatibility with client code that was compiled with an earlier version. Similarly, the Java Object Serialization specification provides mechanisms that enable serialized objects to be exchanged between parties that know about different versions of the object's class. Java's support for versioning of classes, interfaces, and objects helps make it easier to evolve requirements over time. XML, by contrast, does not offer much help in the face of evolving requirements. On the topic of evolving DTDs, Rusty Harold, author of XML: Extensible Markup Language (IDG Books, 1998) and creator of the XML developer Website "Cafe con Leche," (Resources) said this:
XML does not provide any explicit versioning support. You have to do it all yourself. However, [if you write a DTD in 2000 that validates year 2000 tax return XML documents] it is fairly easy to write a new DTD in 2001 that will validate both 2000 tax returns and 2001 tax returns. Writing that DTD in 2000 or 1999 is a little harder.
Typically, designers of data models leave room for future change by specifying in the initial data model some abstraction that can be ignored if not recognized. For example, the Java class file format (a data model for defining Java types) includes a data entity called an attribute. Each attribute in a class file has a name that indicates the attribute's structure and semantics. The original Java virtual machine specification defined the structure and meaning of several named attributes, and identified the attributes that Java virtual machines are required to recognize and use. The specification also stated that:
The attribute abstraction of the Java class file format enables the class file data model to evolve such that class files that contain new attributes remain backwards compatible with old virtual machine implementations that don't recognize the new attributes. Designers of an XML DTD or any other data model can incorporate an abstraction similar to the class file's attribute to make their data models more accommodating to future changes in requirements.
Although dealing with evolving requirements can be a challenge when you are working on a monolithic application, it is far more difficult when you are working on a distributed system. In a monolithic application, you can adopt a new contract that is incompatible with the old and update all parties to the old contract to understand the new one. For example, in a monolithic Java application, you could break an interface's contract by changing the name of a method in that interface. If you recompile the entire application, however, the compiler will find all the code that was broken by your change. If you fix all those areas of the code so that they use the new method name, your application will once again compile.
In a distributed system, on the other hand, you often don't have the option of updating code that is broken by a change to a contract. In a public system, such as Moreover.com's news feed, you don't control all of the system's pieces. In fact, you don't necessarily know who controls all the pieces. But even if you controlled all of the distributed system, it may be physically impossible to update all pieces quickly enough to satisfy the users.
Generally, in distributed systems, once you have a contract between a client and server, you can't break it. But you usually still need to evolve it. This is why Java's support for versioning of classes and serialized objects is so important: Java's versioning support lets you evolve an API that forms a client-server contract without breaking parties familiar only with the contract's previous version. Therefore, this versioning support is one of the prime benefits of mobile objects over mobile documents.