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.

Wednesday, September 16, 2009

Listening to HTML Events from BHO

Creating a plug-in for Internet Explorer was an interesting proposition. After years of .NET development, the first point I investigated was how to write my add-in using C#. I was surprised to find no official support from Microsoft for .NET development of IE add-ins. Thanks to COM Interop, however, it's still possible. More so, information and sample code abound for making it happen.

A number of Code Project articles have been written about how to setup your add-in project using COM Interop. But I wanted to get straight to writing C# code and seeing its effects within IE. In other words, I wanted an existing library that did the COM Interop stuff for me, and which I could simply reference from my project. Two such solutions exist: one commercial and one open source. The commercial one is Add-in Express for IE. I was always suspicious of their tool since a free trial isn't available, so I never shelled out the $149 (USD). The free open-source alternative known as SpicIE, however, is good enough.

My plug-in needs to be kept in sync with whatever text is currently selected within the browser window. Listening to HTML events raised on the browser's current page is necessary in order to do this. The SpicIE Contrib companion website includes a bare bones sample showing how to do this. This sample, however, hooks up the event handlers only after the entire page has loaded. I was looking for something a bit more interactive than that. In other words, I want to hook up the event handlers ideally as soon as the user is able to interact with page elements. This turned out to be a non-trivial task.

In response to the above problem, I developed a reusable class called HtmlPageEventManager whose purpose is to subscribe to a given list of HTML events for each new webpage that's opened. A goal is to attach handlers as soon as the user can begin interacting with page elements, even before the page load is complete. Using this class is simple -- just call the constructor:
var evts = new List<HtmlEvent>() {
HtmlEvent.onclick, HtmlEvent.ondblclick, HtmlEvent.onkeydown,
HtmlEvent.onselectstart, HtmlEvent.onselectionchange,
HtmlEvent.onfocusin
};
new HtmlPageEventManager( this, evts, this.HtmlEventHandler );
You can download my solution here to try it out. And feel free to use it in your own projects if you find it useful.

I encountered some issues while creating HtmlPageEventManager.
  • As mentioned above, I want to add the HTML event handlers as soon as possible, i.e. even before the page load is complete. Doing so in the NavigateComplete handler seemed to work great, until I tested opening a hyperlink in a new tab or window. The new tab or window often times didn't have the HTML event handlers functioning correctly. I could see from debugging that IHTMLDocument3.attachEvent was indeed called on the correct document or element instance and returned 'true' indicating handlers were attached, but the handlers were thereafter never invoked. It seemed that the document/element wasn't "ready" to have events attached, although that didn't concur with the 'true' return value.
    Via the debugger, I discovered that from within OnNavigateComplete, I can detect the problem situation by looking at the IWebBrowser2.Busy property, and adjust my strategy concerning when to add the handlers. So now the registrations occur in OnNavigateComplete only when browser.Busy is true. And if they haven't been registered by the time OnDocumentComplete is reached, then they get registered there instead.

  • When you "Refresh" a webpage, the event registrations were always being lost. That is, they weren't being reconnected on the new page elements. I found out that the NavigateComplete and DocumentComplete handles aren’t called on a "Refresh". When I tested it earlier, it seemed like they were called. But what I observed must have been those two handlers called for frames within the main document – not the main document itself. I overcame this issue by subscribing to the BHO's DownloadComplete event, where I again call my "RegisterEventHandlers" helper method that attaches the HTML event handlers. I incorporated the idea from this code of a "normalPageLoad" member variable to conditionally call RegisterEventHandlers.

Wednesday, July 1, 2009

DragDropManager for WPF TreeViews and ListViews

Update: Please note that the download for this project has been moved here.

My new drag-and-drop manager for WPF, which handles both TreeViews and ListViews, is ready for download. Here's a list of features it includes:
  • Supports drag-drop operations among any number of TreeViews and/or ListViews.
  • Shows drag adorner while dragging among different TreeViews/ListViews.
  • Explicitly supports two types of drop events: ProcessMove for moving an item, and ProcessLink for linking one (see demo).
  • User controls where, relative to the item under the drag cursor, the item will be dropped: above, below, or (for TreeViews) within.
  • Spiffy animations for grabs, drops, and cancelled operations.
  • Auto-expand item if hovering over it during drag operation.
  • Auto-scroll TreeView or ListView if near top or bottom edge.
  • Works on the standard TreeView and ListView controls. No third-party TreeView or ListView control is required.
  • Not dependent upon a particular presentation-model (aka ViewModel) implementation. The pattern isn't even necessary in order to use the DragDropManager.

Demonstration Application

The demo consists of a TreeView that holds categories, and a ListView populated with the selected category's items. These two controls together have a total of three types of drag-drop operations setup on them.
  1. Move a category within the TreeView
  2. Move an item within the ListView
  3. Link an item with another category
The demo is available for download here. The drag-and-drop setup code in the demo looks like this:

dragMgr.AddControl<Category>( categoriesTreeView );
dragMgr.AddControl<Item>( itemsListView );
dragMgr.AddHandler<Category>( categoriesTreeView, dragMgr_ProcessMove );
dragMgr.AddHandler<Item>( itemsListView, dragMgr_ProcessMove );
dragMgr.AddHandler<Item, Category>( categoriesTreeView, dragMgr_ProcessLink );
dragMgr.GetLinkEffect += dragMgr_GetLinkEffect;

The first two lines indicate which controls will have their dragging managed. The following three lines add the event handlers whose job is to actually move or link the domain-model objects. The last line adds the custom link animations you will see in the demo.

The body of your ProcessMove and ProcessLink event handlers will depend on how you've architected your presentation-model. The demo app doesn't even use one, so the event handlers simply look like this:

void dragMgr_ProcessMove( object sender, MoveArgs<Category> moveArgs )
{
 moveArgs.oldPosition.parent.SubCategories.Remove( moveArgs.itemToMove );
 moveArgs.newPosition.parent.SubCategories.Insert(
  moveArgs.newPosition.childIndex, moveArgs.itemToMove );
}

void dragMgr_ProcessMove( object sender, FlatMoveArgs<Item> moveArgs )
{
 var category = (Category)categoriesTreeView.SelectedItem;
 category.Items.RemoveAt( moveArgs.oldIndex );
 category.Items.Insert( moveArgs.newIndex, moveArgs.itemToMove );
}

void dragMgr_ProcessLink( object sender, LinkArgs<Item, Category> e )
{
 e.TargetLoc.Items.Add( e.ItemToLink );
}

Obfuscation for .NET

Update (1 November 2012):
I recently tried upgrading to the latest Smart Assembly version (now owned by Red Gate) while in the process of upgrading my project to .NET Framework 4.5. The latest Smart Assembly version seemed to work okay at first, but then I discovered a bug that caused it to crash. I sent a bug report to Red Gate, along with a repro, then waited and bugged them until I finally received a reply that said: "I'm hopeful that a release may be available with a couple of weeks, however there's no full time development team currently working on Smartassembly; the majority are deployed on other tools." This was especially infuriating since I had purchased "1 year Support & Upgrades". What kind of support is this? None at all, I think. My conclusion is that development on Smart Assembly is stagnant. Therefore, it's best to consider the product dead.

Original Post:
I recently had to fulfill my need for an obfuscation utility for .NET. More specifically, I needed a solution that works with WPF. I learned that WPF poses a particular challenge concerning obfuscation, since the BAML format has not been made public by Microsoft.

My first attempt was using Dotfuscator Community Edition which comes bundled with Visual Studio. After spending a significant amount of time picking certain properties and methods to exclude, I still couldn't get the obfuscated version of my app to run. So I finally gave up and instead turned to Google to help me find an alternative tool.

The only tool I found, with specific mention of WPF support, was {smartassembly}. As long as I exclude those types and (attached) properties used in XAML, this tool works like a charm.

{smartassembly} projects are stored in an XML format, so you can edit them using either your favorite text editor or {smartassembly}'s designated user-interface. The UI follows a rather interesting concept. It's a gigantic vertically scrollable area, consisting of a collapsible pane for each settings group. It reminds me a lot of a word-processor. This may seem strange at first, but after a couple hours of usage, you'll likely see the design concept's merit points.

{smartassembly} has security and optimization features in addition to simple obfuscation. One of particular interest is error reporting. When your program crashes, error reports can be collected by a server and made available for your viewing. That feature, however, is only available in the Professional and Enterprise editions. The Standard edition will run you 500 USD, and the other editions move up from there. For more information, see the {smartassembly} website.

Wednesday, April 22, 2009

Non-Intrusive Tree & Graph Types

I just submitted a second article to Code Project. This one is called Non-Intrusive Tree & Graph Types. It's an original subject for me, totally different from my first CP article, so I don't know what to expect. I'm looking forward to see what feedback I'll be getting.

Saturday, January 31, 2009

Drag-and-Drop in a WPF TreeView


Update: Get the latest version of my DragDropManger by clicking here.

When it came to adding drag-and-drop support to my application, the unfortunate dearth of an easy-to-use solution for WPF TreeViews became apparent. The closest thing available was drag-and-drop support for ListViews provided by our beloved WPF guru, Josh Smith. So, with Josh's blessing, I set out to adapt his ListViewDragDropManager into a TreeViewDragDropManager. It was a lengthy learning process, but I'm happy to say that the port is complete and a robust solution for TreeView DnD is now available. To demonstrate this functionality, the download contains a modified version of "Demo 2" from my Code Project article.

Although many of the private helpers and event handlers in my port differ significantly from the original, the public interface remains nearly identical. So you can read Josh's article, the "Using the code" section in particular, to get started. But do note the differences. First, my class takes two type parameters (instead of one), which you can best understand in the context of my Code Project article. Second, whereas Josh's ProcessDrop event is optional, my class requires you to subscribe in order to actually move a dropped item.

The drag-and-drop setup code in the demo look like this:
var m = new TreeViewDragDropManager<SampleTreeNode, SampleTreeNodeView>( sampleTreeView );
m.ProcessDrop += delegate( object sender, ProcessDropEventArgs<SampleTreeNode> e ) {
e.DroppedItem.ParentNode = null; //move the selected item
e.NewParent.SubNodes.Insert( e.NewIndex, e.DroppedItem );
};

Thursday, September 18, 2008

Visa run by bicycle

A fact of life for many foreigners staying long term in Thailand, and in other countries probably, is the visa run. My visa is valid for one year, but I'm only allow to stay continuously for a maximum of ninety days. Before exceeding that limit I must leave Thailand, even if for just five minutes before returning again.

So today it was visa run time again! Well, my ninety days wasn't up until Monday, but I decide to get it over with a few days early. I arrived yesterday in this town on the Burmese border, called Mae Sot. I came from Lampang where I was visiting some American friends. I didn't depart there until 1pm, however, so I arrived in Mae Sot at 5pm. I headed straight to the border. When I got there at 5:11pm I found out the Burmese side closes at 5pm. Oops.

I headed into town where I eventually found the decent and affordable Green Guest House. It's located on a side-street behind the police station, just past the holding facility (just a big cage really) for illegal Burmese immigrants. After checking in, I went to eat dinner at the restaurant Krua Canadian (Canadian Kitchen) which (surprise!) is owned and operated by a Canadian guy with a Thai wife. It was good tasting Mexican food, better than what I had in Chiang Mai. I assume the Canadian owner spent some time living in Mexico before coming to Thailand.

This morning I rented one of the guest house's bicycles, then rode the five kilometers or so to the border. I took a bunch of photos, with the idea in mind to write this blog entry tonight. So here the photos are below.

The day's mode of transporation, in front of the guest house


The road ahead


The road ahead becomes a four-lane highway


Border checkpoint in sight


For some, this is the way home


Crossing the bridge into Burma


Some Burmese don't need a bridge, or travel documents, to get into Thailand


The Burmese end of the bridge is in sight


I spent a couple minutes walking down the street


Then into some market... (then I headed back to Thailand)