Object-oriented – Designing an easily extensible XML driven OOP system

object-orientedxml

I've been working on a project that is very data-driven (a checkers board game with customizable rules; I'm using XML for the data storage). I need a design that is easy to extend as we add new features to the project via new XML tags.

My XML schema looks like this for a win condition (checkers):

<game>
   <winconditions>
      <condition winner="Black">
         <Pieces color="Red" number="0" />
      </condition>
      <condition winner="Red">
         <Pieces color="Black" number="0" />
      </condition>
   </winconditions>
</game>

<game> is the root element. There are other major sections such as <board> which defines the size and shape of the board and placement of the pieces, and <moves> which defines how pieces move. The idea is to have several "options" that combine to form a "condition" – if all "options" are true, the "condition"'s evaluation returns a winner.

Right now, the best strategy I have come up with is to create a package for the tag processing classes:

processors
   pieces

And an interface to a win condition option:

public interface WinConditionOption {
   void setParameters(HashMap<String, String> args);
   boolean evaluate(GameState state);
}

The file processor, when it sees a tag inside the <winconditions> tag, uses reflection to look up the corresponding class and calls it using the interface. So the Pieces tag causes a Pieces object to be created and setAttributes() is called with the tag's attributes. When we check for a win, evaluate() is called with the current state of the game. Pieces would evaluate whether the number of pieces belonging to that player was a certain number, 0 in this case (no pieces left).

Is this a good design? Is there a better way to do it and still be able to write minimal new code to add a new win option?

Best Answer

The design you indicated is missing an important feature - flexible XML formatting of new conditions. Based on your post, this wouldn't be possible:

<condition ...>
    <pieceCombos>
        <combo>...</combo>
        <combo>...</combo>
    </pieceCombos>
</condition>

An better way would be to have each of these classes know how to read (and write) their own information from the appropriate xml element. So something like this could be cleaner and more flexible:

// This abstracts away specific methods of reading from xml.
public class YourXmlHandler
{
    ...
    GetChildElement(int index);
    GetAttribute(int index);
    ...
}

public interface IXmlReadable
{
    void LoadFromXml(YourXmlHandler reader);
}

public interface IWinOption
{
    bool Evaluate();
}

This allows you to reuse the IXmlReadable interface for anything affected by the XML content. It leaves the win option separate for the items that must be Wins.

You may end up with a WinConditions class that knows to read multiple WinCondition entries from the XML and a Pieces class that knows how to read its data. The WinCondition class knows exactly what it wants from the XML and just gets it or throws a meaningful exception.

Related Topic