XML Schema Doesn’t Need Inheritance

Got a chance to talk to Dare today about the XML vs. Objects stuff we’ve been blogging on. We started by talking about the convergence of objects, databases and XML. He mentioned a chapter of Tim Neward’s Effective Enterprise Java book where Ted recommends designing the data first. Ted started Effective Enterprise Java 2 days before Patrick was born so I haven’t been reading it. The issue with designing the data first is that typically, a developer is predisposed towards one of the three poles of data design (XML, objects or relational DB) that will color that design unintentionally.

I realized I still lean towards OO when Dare pointed out the fact that XML (actually, I should say XSD) doesn’t really need derivation. Because of my OO background, it took me a while to digest that concept. But since XML is just data without behavior, it doesn’t need polymorphism the way that objects do. Consider the following schema:

<xs:complexType name="ctAddress">
  <xs:sequence>
    <xs:element name="Street" type="xs:string" maxOccurs="1" minOccurs="1" />
    <xs:element name="City" type="xs:string" maxOccurs="1" minOccurs="1" />
    <xs:element name="State" type="xs:string" maxOccurs="1" minOccurs="1" />
    <xs:element name="ZipCode" type="xs:string" maxOccurs="1" minOccurs="1" />
    <xs:any namespace="##targetNamespace" />
  </xs:sequence>
</xs:complexType>

This is version one of the address complex type schema for some arbitrary web service. Over time, we realize that we want to be more global in our addressing schema, so we want to add a country element. Since not all of the other services we interact with will be updating to the new schema, we need to make country an option element (i.e. minOccurs=”0″). While we could use schema inheritance to do this, we could also just duplicate the existing elements and add a country element:

<xs:complexType name="ctAddress">
  <xs:sequence>
    <xs:element name="Street" type="xs:string" maxOccurs="1" minOccurs="1" />
    <xs:element name="City" type="xs:string" maxOccurs="1" minOccurs="1" />
    <xs:element name="State" type="xs:string" maxOccurs="1" minOccurs="1" />
    <xs:element name="ZipCode" type="xs:string" maxOccurs="1" minOccurs="1" />
    <xs:element name="Country" type="xs:string" maxOccurs="1" minOccurs="0" />
    <xs:any namespace="##targetNamespace" />
  </xs:sequence>
</xs:complexType>

What’s interesting is that even though these two schema types are not related by inheritance, I can still validate XML addresses against either schemas. In fact, XML addresses with and without addresses validate against both schemas! That’s difficult to model in a typing system where objects have a bound to a single specific type. Other types of changes can be introduced so that break validation to one of the schema but not the other. For example, if we changed the minOccurs of ZipCode to zero, all messages that validate to the first schema would also validate to the second, but the reverse would not always be true. This is like a IsA relationship in OO, but in the wrong direction (a base message “is a” derived message, but a derived message is not always a base message).

The upshot of all this is that I think my argument against XML Serialization as a general concept is strengthened. While it does work in many scenarios, I can easily build XML messages and XSD schemas that don’t cleanly conform to an OO typing system. Since the flexibility in XML is critical (that’s what I’m using for loosely coupled public interop interfaces), I know I don’t want my schema design to be constrained to the limited set of scenarios that are supported by XML Serialization.

YAPnPP

Even though I said I’d try and lay off the Patterns and Practices blog entries for a while, I had a customer email me his thanks for posting these links. So I decided to update my site a little to add links to practices and application blocks that I think are a must read. They’re now listed down the left hand side along with .NET links, .NET tools and the DevHawk Navigation menu. As new practices and application blocks are published, I’ll be adding to this list as appropriate.

Another Hit in the Pattern & Practice Parade

I didn’t notice right away, but there’s a new version of the Operating .NET Applications book. The original version was missing the chapter on Instrumenting .NET applications since the Enterprise Instrumentation Framework (EIF) hadn’t shipped yet. EIF is downloadable from MSDN Subscriber Downloads for all Enterprise and Universal subscribers. The new version of the book also contains information on Sizing and Capacity Planning.

Yet Another New Pattern and Practice

This time it’s the Web Service Facade for Legacy Applications. Unlike many of the other patterns and practices, this is very lightweight – a scant 20 pages after you take out the coverage of the included sample application. However, a bigger issue that the lack of content is the definition of “legacy application”. This guide discusses three possible legacy apps – those that expose a COM interface, those that expose a DLL and those in a standalone EXE. However, when my customers talk about legacy apps, they’re usually referring to apps running on the mainframe. A more relevant guide in this vein would talk about using Host Integration Server to provide Web Service Facades for mainframe transaction programs.

WSS RSS v0.4

It’s taken long enough, but I’m finally getting WSS RSS v0.4 out the door. Primary new feature is support for customizing the RSS feed on a list type basis. I had made a slight unreleased change to expose pubDate as well as dc:date. Now, that stuff is all in the wssrss.config file so it’s easy to add support for whatever item elements you want. There is also support for expiring items in the feed based on age or on value match (for example, exclude tasks that are marked completed), again configured via the wssrss.config file. In even bigger news, I didn’t change the installer process this time.

It’s going to be a while before I do a v0.5 release. I want to enable configuration of the RSS feed on a per-list basis, instead of just on a per-list-template basis. Plus I’ve got a few bugs and I want to figure out how to expose a UI link to the OPML and RSS feeds on a WSS website. But I think I want to wait until a later build of WSS is available. I’ve gotten email from a WSS early adopter program members who is having issues with WSSRSS and a later build of WSS (sorry, v0.4 will have the same issue). I’m hoping to get access to a later build, but obviously, I’m not going to publicly post a new version of WSSRSS if the corresponding build of WSS isn’t generally available. Also, while there has been some strong interest in WSSRSS, it started life as a demo to help me learn how to program WSS. I’ve got other things I want to try with WSS that have sat on the back burner while I worked on WSSRSS. I promise to post code when I get something working.