Sony Arouje

a programmer's log

Decouple Data interchange format from Domain Model

with one comment

I was doing a client app to display some data, the client receive data in xml format. One design constrain for me was, consumer’s domain model should have less impact even if the interchange format changes. So once the domain is loosely coupled, it can work on any type of data. The data can be in XML, JSON, or what ever it is.  This post explains how I achieved it, it’s a very simple approach based on Strategy and Iterator Pattern.

For simplicity, I read the xml data from a file. Below is the xml

<Library>
  <Books>
    <Book Name="CLR via C#" Price="30"></Book>
    <Book Name="Algorithm Design Manual" Price="40"></Book>
  </Books>
</Library>

Parsers

I created a parser class to parse the xml files. Below is the contract and the parser.

public interface IBookDetailsParser:System.Collections.IEnumerator
{
    string getName();
    double getPrice();
}
public class BookDetailsXMLParser:IBookDetailsParser
{
    private int _nodeCount;
    private int _position;
    private XmlDocument _bookDetails;
    public BookDetailsXMLParser(XmlDocument bookDetails)
    {
        this._bookDetails = bookDetails;
        this._position = -1;
        this._nodeCount = _bookDetails.SelectNodes("/Library/Books/Book").Count;
    }
    public string getName()
    {
        return this.getValue("Name");
    }

    public double getPrice()
    {
        return Convert.ToDouble(this.getValue("Price"));
    }

    private string getValue(string attributeName)
    {
        var node = _bookDetails.SelectSingleNode("/Library/Books/Book[" + (_position + 1).ToString() + "]/@" + attributeName);
        if (node == null)
            return string.Empty;

        return node.Value;
    }
    public object Current
    {
        get { return _bookDetails.SelectSingleNode("/Library/Books/Book[" + (_position + 1).ToString() + "]"); }
    }

    public bool MoveNext()
    {
        _position++;
        return (_position < _nodeCount);
    }

    public void Reset()
    {
        _position = -1;
    }
}

As you can see the parser is based on the enumerator pattern.

Domain Model

public class Book
{
    public Book(string name,double price)
    {
        this.Name = name;
        this.Price = price;
    }

    public string Name { get; private set; }
    public double Price { get; private set; }
}
public class BookList
{
    private IBookDetailsParser _bookDetailParser;
    public BookList(IBookDetailsParser bookDetailParser)
    {
        this._bookDetailParser = bookDetailParser;
    }

    public IList<Book> GetBooks()
    {
        IList<Book> books = new List<Book>();
        while (_bookDetailParser.MoveNext())
        {
            Book book = new Book(_bookDetailParser.getName(), _bookDetailParser.getPrice());
            books.Add(book);
        }

        return books;
    }
}

BookList is not aware of what kind of data format it operates on. In case of XML data we can inject the xml parser provided above. Later if we want to change to JSON format then write a json parser implemented by IBookDetailsParser and pass the new json parser to BookList. In this approach any change in data interchange format wont make any impact to our model.

BookService combine all these things together.

public class BookService
{
    public IList<Book> GetAllBooks()
    {
        ServerDataReader dataReader=new ServerDataReader();
        System.Xml.XmlDocument booksXML = dataReader.GetBooks();

        BookList bookList = new BookList(new BookDetailsXMLParser(booksXML));
        return bookList.GetBooks();
    }
}

Any change in the interchange format will affect the BookService. We can make it loosely coupled here as well but that’s not the intention of this post, here I just want to show a loosely coupled domain model from data format.

Advertisements

Written by Sony Arouje

November 16, 2011 at 5:01 pm

One Response

Subscribe to comments with RSS.

  1. Could you write about Phsycis so I can pass Science class?

    Mande

    November 23, 2011 at 5:29 am


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: