We use an in-house framework for building applications and the subject of how we decouple business domain classes from a particular data source recently came up. This blog post provides a quick overview of the core Torq framework classes/interfaces and how they are decoupled from particular database implementations. A business domain class that is to leverage the framework needs to implement the ITorqObject interface. The properties and methods of this interface include functionality related to a Torq specific reflection extension, authorization, property change events, list events, a parent object in the case of object composition scenarios and most importantly the concept of an object source and an object mapper. Every ITorqObject instance is associated with an ITorqObjectSource which defines where it is “stored” and an ITorqObjectMapper instance whose responsibility is to map between the in-memory object world and the object source. In addition there is an ITorqList list interface that extends the standard IList definition with Torq specific reflection knowledge.

An example of an implementation of the ITorqObjectSource and ITorqObjectMapper interfaces is where a Matisse object database is used in deployment. Fresher have their own Matisse specific API and means of generating .NET classes from an ODL definition or a running database. The problem with using that approach is that the application code is then strongly tied to that API and also the representation of list relationships in the generated code is spread across multiple methods (get, add, remove etc). The approach taken with the Torq framework is to provide an implementation of the ITorqObjectSource and ITorqObjectMapper interfaces that is Matisse specific. The diagram below indicates the main classes involved. Fortunately the Matisse API provides the MtObjectFactory class that can be overridden to provide application specific object creation during interaction with an MtDatabase instance. The MatisseObjectMapper class is-a MtObject and it will create an associated domain object (an ITorqObject instance) as needed. It then provides the data mapping functionality for the ITorqObject instance via its set of Get/Set prefixed methods for various core and parameterized types. Since Matisse is an object database, the mapping is fairly trivial when compared to the mapping needed to an RDBMS.

The ITorqObject interface is used where-ever the concept of a “torq domain object” is needed. This allows any base class to implement this interface to work with the framework. Practically all our domain classes are derived from the TorqObject class which provides a default implementation of ITorqObject. This default implementation provides a heap of protected convenience methods for interaction with the ITorqObjectMapper and ITorqObjectSource associated with the domain object.

In the domain classes, there is a small bit of coding overhead needed for every property or relationship. There is the static definition of a Torq specific reflection object. It is uninitialized in the source code, but the framework initializes these static properties automatically when a business domain assembly is loaded. A private field is then used to store the results of any Get/Set methods. The TorqObject base class then forwards Get/Set method calls onto its ITorqObjectMapper instance to get data from the object source and update the object source. The following example extract shows how this is achieved for a string property. Note that the GetProperty and SetProperty methods provide an interception point for the framework to insert functionality related to authorization, logging and persistence. Note that the Torq specific reflection information (TorqProperty in the example) provides a useful mechanism for accessing strongly typed class level information in the code. An example is in databinding, where you can use say Party.NameProperty instead of a string literal in defining what property a UI control is being bound to.

        public static TorqProperty NameProperty;
        private string name;

        public string Name
        {
            get { return GetProperty( NameProperty, ref name );}
            set { SetProperty( NameProperty, ref name, value ); }
        }

Here’s an example of the implementation of a list property on a business domain object. Note that the ITorqObjectSource will define the type of the list. Each source can provide its own ITorqList implementation to handle object source specific needs.

        public static TorqListProperty ContactMechanismsProperty;
        private ITorqList<IContactMechanism\> contactMechanisms;

        public ITorqList<IContactMechanism\> ContactMechanisms
        {
            get { return GetProperty( ContactMechanismsProperty, ref contactMechanisms ); }
        }

The Torq framework will evolve over time and it would be handy to reduce the small coding overhead associated with each class property. The use of a private field as an intermediate in memory storage could go and it would be great to be able add more of this code automatically either at run time or as a post compile step. A significant advantage of the current approach is its much easier to use a debugger and just step through the source code. Fancier approaches such as runtime code generation make it conceptually more difficult to debug at run time.

This blog post provided a quick dip into the foundation of the Torq framework we use for developing business domain products. The framework is intended purely for in-house use. I decided to put these details up to provide an overview of how you could leverage an OO database such as Matisse but not tie your application code to it. Note that I am an advocate of the Matisse database and do recommend you check it out. Regardless its also beneficial in many scenarios to not tightly couple application code to a specific data store.