Thursday, October 9, 2008

Xml Design Patterns

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/xml_design_patterns.htm]

Xml is the defacto way to store data in files - whether it's build instructions as an MSBuild script, a Domain Specific Language based on code-generating from an xml filea config file, or something else.

 

So, your xml files are storing lots of mission-critical information. They're getting huge, being modified by tons of developers, and getting hard to maintain. It's time to refactor them. Here are several ideas to refactor your xml files (much of this is demonstrated in MSBuild):

  • Create a variables section. For example, MSBuild has a  section, where each inner node can define a new variable. You can then reference those variables elsewhere throughout your script like so: $(myVar).

  • Allow importing of files. Often you'll want to either split a big file into smaller ones, or reuse a single file many times (for example, put all your global variables into a separate file, and then re-import it everywhere).

  • Related to this, allow chunks of xml to be automatically included in other chunks with some sort of "include" syntax. In other words, ensure that the xml file itself is refactored. MSBuild allows you to call other targets with a task. Or, say you have a test script that's generated from xml, and every test needs to repeat your "login routine". Define the login routine in one xml snippet, and allow it to be re-included in all the other snippets.

  • Have the xml structured to automatically determine relationships. For example, if you have a parent-child relationship of data (here is the menu, here are all the pages accessible from that one menu), then consider using Xml's natural hierarchy (a

    node with a bunch of child nodes). You could also use the natural order of the xml nodes to determine the natural sequence that the data appears (like the order of the pages).

  • Provide some way of an extension method or hook. In MSBuild, you can define your own custom tasks and dynamically load them.

  • Create special syntax for domain-specific concepts. For example, the MassDataHandler takes xml snippets, and converts them to SQL insert statements to assist with database unit testing. A common problem for inserting SQL statements is handling the identity columns. In this case, if you prefix the value with an '@', the MassDataHandler automatically knows to go lookup its identity value.

  • Create templates for default values, which other xml nodes can override. For example, the MassDataHandler allows you to run SQL inserts, one xml node per database row. But say five rows all have the same values for something (like they're all children of the same parent), then it provides the ability to have a "default row" which defines the default values. Other xml nodes can then override these default values.

I guess you could say there are design patterns for good xml. As Xml becomes more and more prevalent, I expect that "Xml Design Patterns" to become more prevalent too.

No comments:

Post a Comment