Reed Robison wrote a blog entry about State Aware Objects in the Mobile LOB Accelerator. I thought I would talk about how this part of LOB developed.
While building LOB we set some design principals. These are some of the key tenets in order of priority:
- It should have great performance.
- It should be simple and accessible to developers.
- Architecture should respect set boundaries i.e. System.Data should not show up in the UI.
- The application should run on CF 3.5 to show case new technologies.
As you can see performance and simplicity trumped everything else and thank god. I would be killed if the original design had gone forward. Why because while it solved the problem and with more functionality it was not simple or accessible.
The first version looked something like this
while dbRead.Next() {
myObject = new SomeClass(dbReader.GetValues);
myCollection.Add(myObject);
}
What this did was allow for an ability to track state and perform undo and redo. It also allowed for one of the fastest way to retrieve data using an array of objects. The problem with this approach broke down to
- the code was really nasty for extracting out the values for the property getters
- the object was totally dependent on the order of data
- due to the order dependency you could only find out at runtime if you wrote the right code
- the approach violated the simple and accessible principal
Another track that was investigated was using attributes to decorate the properties. This would allow the data layer to manufacture the SQL based on reflecting the properties. You could do something like
[DataColumn("CustomerId")]
public int CustomerId
While this would allow the data layer the ability to figure out SQL on its own this approach had problems as well including
- violated separation of layers since now data objects had to know how they were stored
- reflection is the slowest way to do anything and performance was not great
- not really simple and accessible
- data objects were now dictating data storage design
While cool the approach did not get any benefits beyond not writing SQL. It also made implicit assumptions about how data would be stored.
As we whittled our design choices we kept coming back to the design principals. This lead to the final version where our data objects only tracked their state in a simple way. The data objects could be stored in a database, flat file, XML etc. The way they are hydrated makes changing them very easy. The objects don't care how they are persisted or hydrated they only care about what they are and can do. This gives a clear separation of concerns like separating technical details from the problem domain. It allows for multiple people working on different parts to only have to communicate in terms of contracts. If I am a UI designer I don't care about data layer details nor do I as a subject matter expert in the domain care about the UI or storage of the data.
I hope this is help in giving some background in why we did the things we did with the Mobile Line of Business Accelerator 2008.
We do something very similar. We use a class that provides access to a single record, and an aggregate class that is responsible for extracting sets of this object.
so we end up with
public class Item
{
}
public class ItemAggregate
{
public Item[] GetAll()
{
}
public int Count()
{
}
}
The magic happens with a tool we have called DataMaker that builds these classes by introspecting the tables in SQL/Oracle/ODbc/SQL Compact connection.
Very fast and very reliable.
Posted by: Richard Jones | October 18, 2008 at 02:35 PM