1

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?

5
  • Are you talking about serializing and deserializing objects? It helps to provide a specific programming language because XML serialization for a given language is pretty easy to find using Google.
    – S.Lott
    Commented Oct 5, 2011 at 19:01
  • No, this is about a data-driven program. In my case the XML is defining game rules.
    – Michael K
    Commented Oct 5, 2011 at 19:19
  • 3
    "the XML is defining game rules" isn't helpful at all. XML can be used to encode "game rules" an indefinite number of different ways. If you're not using well-defined object serialization, you're going to have to provide a lot more details to get any useful comments on "good design" or "better way to do it". Since you've provided no code, no examples and only a vague definition of what's going on. "sees a tag inside the main structure" sounds like a SAX parser. Is that what you're talking about?
    – S.Lott
    Commented Oct 5, 2011 at 19:27
  • You're right, there wasn't enough detail. I've updated the question - please let me know if you need more.
    – Michael K
    Commented Oct 5, 2011 at 19:50
  • Beware of the inner platform effect. I don't see how the rather verbose XML config and all the code that goes with it makes anything easier. You're creating a DSL, that will definitely be less powerful and probably even more bloated than corresponding Java code would be.
    – back2dos
    Commented Oct 6, 2011 at 3:37

3 Answers 3

1

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.

1

Nearly every common language has a standard library for handling this sort of thing.

In Java there is the "Properties" library which automatically loads an XML into a hash map. Other languages have similar libraries for handling simple XML config files.

If your config file is more than a simple Key/Value pairs, then, you may as well use Xereces of some similar full blown XML parser and use Xquery to get the data you require.

But remember "Jim's Law" -- "If you have a Turing Complete configuration file, then you are just programming in crappy langauge"

0

So the Pieces tag causes a Pieces object to be created and setAttributes() is called with the tag's attributes.

That's object serialization in XML. You're de-serializing an object of the given class with the given values.

Don't write this yourself. It's a waste of time. Just download one that works with your target language.

When we check for a win, evaluate() is called with the current state of the game.

Right. You've deserialized an object. Now you evaluate a method. The method then evaluates the various clauses and conditions to determine and overall value.

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

Not really. Use a readily available XML serialization and you can avoid writing too much code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.