Wednesday, April 13, 2011

Reusable Tree Operations for the .NET Framework

An earlier article of mine describes how a common ITreeNode<T> interface can facilitate reusable tree operations thanks to the introduction of extension methods. That article discusses reusable tree operations with respect to domain-models. Trees, however, are a ubiquitous data structure and also occur throughout the .NET Framework, as discussed in [Eberhardt 2010]. Ideally, the .NET Framework would include an ITreeNode<T> interface that's consistently implemented within the Framework, but this is not so. [Eberhardt 2010] describes a way to provide tree operations to those Framework types by means of the adapter pattern and code generation. His approach, however, has drawbacks. Wrapping a node instance every time it is navigated is likely to impact performance, and relying on code generation complicates maintenance. Upon looking into the matter for myself, I came up with an approach that suffers neither of these drawbacks.

Before continuing onto my solution, I want to note what tree operations, specifically, should be available. Leveraging the functionality already provided by LINQ to Objects reduces this list considerably. For example, instead of numerous methods that deal with ancestors, such as IsAncestorOf and FindAncestorOfType<T>, a single Ancestors method can be provided with LINQ to Objects taking care of the rest.
//item.IsAncestorOf( newParent )
newParent.Ancestors().Contains( item )

//tvi = this.FindAncestorOfType<TreeViewItem>();
tvi = this.Ancestors().OfType<TreeViewItem>().First();
LINQ to XML sets a good example by borrowing its "axis methods" — that query ancestors, siblings, descendants — from XPath. [Eberhardt 2010] does an excellent job of describing these.

Now I will show my solution for adapting .NET Framework tree types in order to make common tree operations available on them. The code that I will be discussing is available as part of Qnomad's CoreHelpers library. To create my solution, I applied a variation of the adapter pattern. Instead of instantiating a wrapper for every tree node, there's just one wrapper per adapted tree type, e.g. DependencyObject. The library also includes a singleton of this sort for the ITreeNode<T> type discussed in my earlier article. The tree operations, then, use the singletons to navigate the hierarchy. The various pieces of this puzzle are outlined below.
  • internal static class TreeOperations: Contains an implementation for each tree operation. Each method signature is of the form:
    internal static IEnumerable<T> Operation<T>( T startNode, ITreeNodeAdapter<T> adapter )
  • internal interface ITreeNodeAdapter<T>
    {
    bool HasSubItems( T treeNode );
    IEnumerable<T> GetSubItems( T treeNode );
    T GetParent( T treeNode );
    }
  • Next come the implementations of ITreeNodeAdapter<T>. The library contains these two:
    • internal class WpfTreeNodeAdapter : ITreeNodeAdapter<DependencyObject>
    • internal class ITreeNodeAdapterImpl<T> : ITreeNodeAdapter<ITreeNode<T>>
You've undoubtedly noticed that everything so far has been declared as internal. The public methods are all on the corresponding "Extensions" classes. The library's WpfExtentions class, for example, contains this method:
  public static IEnumerable<DependencyObject> Ancestors( this DependencyObject startNode )
{
return TreeOperations.Ancestors( startNode, WpfTreeNodeAdapter.Instance );
}
Well, that pretty much wraps it up. So now you see a better way for exposing common tree operations on .NET Framework tree types.

Monday, March 21, 2011

Advantages of the Domain Model

Prior to arriving at my previous consulting assignment, the company had already completed their first WPF project. The architecture they used on that earlier project included a rather unusual, in my opinion, hybrid object/relational in-memory representation of business objects. Some of the business objects were wrapped in View Models, while the View was directly referencing ADO.NET data rows of other business objects. I initially kept an open mind, programming their new app to that earlier architecture. But I eventually realized that it provided me no way to abstract away from the underlying relational structures. I then spent the weekend refactoring the new app, and building its Data Access layer. Having broken away from the status quo established by their first WPF project, however, my efforts were not greeted warmly. I had to spend a subsequent weekend producing the below “Advantages of the Domain Model”, as well as the Microsoft Embraces the Domain Model article I posted earlier, for convincing them to go with a purely object-oriented in-memory representation of business objects.

Advantages of the Domain Model


Confining object/relational mapping logic to a clearly demarcated data access layer (DAL) within your application, facilitates the creation of a single, coherent, object-oriented Domain Model to represent your application’s business objects. Adherence to this practice leads to more robust, scalable, and maintainable software.

Separation of concerns


View
View Model
Domain Model
Data Access
Data Services
Separation of concerns is a fundamental principle within computer science. As applied to an application’s overall architecture, it provides for organizing a complex software system into separate, but interdependent, parts. The new app’s codebase is easier to understand and maintain than the old app, thanks to the separated Data Access, Domain Model, and View Model layers. The responsibilities of all three layers are lumped into one layer within the old app.
  • Conceptual model. The Domain Model provides a concise representation of the domain of interest. This can aid in communication with experts in the problem domain who are not necessarily developers.

  • Division of labor and organization of code. Need to retrieve or persist data? Then call into the DataAccess singleton. Need to execute some business logic when a condition’s selected field changes? Then go to the Domain Model and put the logic into the Condition.SelectedField setter. Need to tell the View how to display itself differently? Then go to the View Model.

  • Code Reuse. Both the old and new apps contain object-relational mapping logic. The difference is that the new app’s Data Access layer, by way of generalized functions, eliminates the needless repetition found within the old app’s numerous Load and Save methods.

  • Consistent interface to in-memory data. Hiding the relational model specifics, as is accomplished by the new app’s Data Access layer, provides a consistent representation of business objects. The View layer in the old app, on the other hand, contains bindings that reference both .NET properties as well as database fields.

  • Maintainability. Because of the separation of responsibility, the new app can be modified more easily when business needs change. Changing a database field’s name, for example, requires a limited maintenance effort in the new app. Since data access is coded concisely in the Data Access layer, it involves altering just one string.

Increased Productivity


Coding directly to ADO.NET objects, as the old app does, means that you cannot easily navigate the relationships between business objects. The new app’s Data Access layer, on the other hand, shields upper layers from database specifics. This allows for more natural modeling of data, and simpler handling of complex relationships between entities.
  • The business objects are strongly typed, so we benefit from compile-time type-checking.

  • Business objects’ members expose themselves through Intellisense, eliminating typos and problems with remembering property names.

  • We can navigate the object-oriented Domain Model by using the OO-dot syntax, such as condition.SelectedField.Type.AvailableOperators. That is, we just choose an object instance to be our point-of-entry, then navigate from there. The ADO.NET objects in the old app, on the other hand, don’t allow you to easily navigate the data model.

Thursday, January 20, 2011

WPF Dialog Service via Binding

View Model logic sometimes involves showing a modal dialog box. The dilemma has always been: how do you show the dialog while abiding by the rule that the View Model not reference the View? A common solution has become to create a dialog service class, then extract its interface for the View Model to consume. In my opinion, using the interface is only slightly better than using the actual class. It still looks to me like the View Model is referencing the View. Why attempt such a charade when the View Model's primary means of communication with the View is perfectly adequate?

Although the View Model must not reference View classes, the View Model can still talk to the View. If there wasn't such a capability, then displaying the View Model's properties to the user would be impossible. The communication method I am referring to, of course, is data binding. Data binding is already the primary means of communication between the View and the View Model. We can use it for showing a dialog box as well.

Showing a dialog box using the solution I have created involves two easy steps:
  1. Add the MessageBoxHelper.Message attached property into the View.
  2. Within the View Model, set the property specified in the first step when you want the dialog box to be shown.
The View Model's property mentioned in these steps is of type DialogPM. This class contains no View-specific logic. It's purpose, rather, is to transport parameters for the MessageBox.Show(... method call from the View Model to the View and, if that method's result is important, back from the View to the View Model.

Download the Qnomad CoreHelpers library to see the complete example.

Sunday, January 2, 2011

Microsoft Embraces the Domain Model

Soon after I introduced a Domain Model into the application I was creating for my employer, I found myself at a team meeting trying to explain to fellow programmers, and my manager at the time in particular, why such a change is beneficial. I started by describing how, by the nature of data flowing from the relational database to the object-oriented runtime environment and back, we have an inherent need to translate between two different data models. The manager stopped me in my tracks when she said that I sounded “too academic”. Although left speechless at the moment, in retrospect (and at the risk of sounding like a smart ass) I should have responded, “the law of gravity may sound academic when described by a physicist, but that alters neither its truth nor practical consequence.” Just as the laws of physics describe our physical world, the world our applications live in can be described in terms of data models. The problem stemming from the presence of two data models, instead of just one, is called the Object-Relational Impedance Mismatch.

The Object-Relational Impedance Mismatch is an “academic” (to quote my former manager) sounding term for a practical problem facing software application development.
…work directly against the relational structure of database tables.

This is all well and good for simple databases and simple applications. However, as a database gets richer and an application more sophisticated, we see increasing divergence between the way an application needs to look at the data—its “conceptual” or “object” model—and the way information is structured in the database—the “storage” or “relational” model.” A manufacturer's ordering system, for example, may store its order information in multiple related tables, yet the application programmer really wants to work with a single, conceptual “order” entity without having to do a complex JOIN in every order-related query. (This is a case of what’s called the “object-relational impedance mismatch,” if you’ve heard that term.)
The above quote is taken from an article in the MSDN Library titled Microsoft Data Development Technologies: Past, Present, and Future by Kraig Brockschmidt and Lorenz Prem, Program Managers at Microsoft.

Microsoft released the ADO.NET Entity Framework in August 2008 as part of the .NET Framework version 3.5 SP1, and then an improved version in the .NET Framework 4 released in April 2010. What is the ADO.NET Entity Framework? From its overview:
The ADO.NET Entity Framework enables developers to create data access applications by programming against a conceptual application model instead of programming directly against a relational storage schema. The goal is to decrease the amount of code and maintenance required for data-oriented applications.
The “conceptual application model” is commonly known as the Domain Model.

With the Entity Framework finally here, it is clear that Microsoft has at long last embraced the Domain Model pattern. This is significant given that, in the 12 year hiatus since Microsoft's last data-access paradigm shift when it released ADO in October 1996, they’ve been careful to find the new emblem of application architecture for years to come. In general, Microsoft is the most immune to “fads”. They tend to do things their own way, and avoid industry standards up until the standards become so engrained that the obvious choice becomes to embrace them or get left behind. Microsoft’s embrace of the Domain Model is evidence, in my eyes, that this has become an engrained industry standard.

For those of us using the .NET Framework to build applications, Microsoft’s commitment to the Domain Model goes beyond confirming an industry standard. Having Visual Studio 2010 installed on our machines, while relying on it so much for development, we also have access to the extensive tooling support Microsoft has built around the pattern. From the MSDN library: “conceptual and relational representations can be easily created using designers in Visual Studio, and the Entity Framework designer in Visual Studio will create a default mapping without any effort on your part.” It’s a safe bet that this tooling support will be continually improved with future Visual Studio releases.