Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Build your own CAB Part #7 – What’s the Model?

First, go catch up on what’s come before:

  1. Preamble
  2. The Humble Dialog Box
  3. Supervising Controller
  4. Passive View
  5. Presentation Model
  6. View to Presenter Communication
  7. Answering some questions

What’s the Model? 

I’ve spent most of the series talking about the View or the Presenter, but the Model piece of the triumvirate has a role to play as well. 

A couple years ago I participated in a session on design patterns for fat clients that Martin Fowler was running to collect data for his forthcoming sequel to the PEAA book.  One of the topics that came up in conversations afterward was whether or not it was desirable to put the real Domain Model on the client or use a mirror version of the Domain Model that you allow to have some user interface specific functionality.  In other words, is the Domain Model pattern applied to the user interface a completely different animal with different rules than the traditional POCO Domain Model in the server?  We didn’t come up with any kind of a consensus then, and I’ve never made up my mind since. 

As I see it, you have four choices for your Model:

  1. Domain Model Class – Just consume the real application classes.  Many times it’s the simplest path to take, and leaves you with the fewest moving parts.  My current and previous projects both used this approach with a fair amount of success.  In my current project our Domain Model classes implement quite a few business rules that come into play during screen interactions.  The downsides to consuming the real Domain Model in the View are that you’re binding the View more tightly to the rest of the application than may be desirable and the possibility of polluting the Domain Model with cruft to support INotifyPropertyChanged interfaces and other User Interface needs.  Part of the reason I’m perfectly happy to consume Domain Model objects directly on my project is that our screen design doesn’t require any special UI support for our custom data binding solution.
  2. Presentation Model – Even if you’re largely following a Model View Presenter architecture, the Presentation Model is still useful.  Think of this realistic screen scenario:  the real domain objects are an aggregate structure and your View definitely needs some INotifyPropertyChanged-type goo.  In this particular case a Presentation Model that wraps and hides the real domain objects from the View is desirable.  The Presentation Model probably provides a flattened view of the domain aggregate to make data binding smoother while implementing much of the UI infrastructure code, allowing the domain classes to take the shape that is most appropriate for the business logic and behavior and keeping them from being polluted with UI code.  I should not that using a Presentation Model will potentially add extra work to synchronize the data with the underlying domain objects.
  3. Data Transfer Object – Forget about behavior and just use a lump of data.  This is often a result of hooking the user interface directly to the return values of a web service.  In my previous application we wrote an absurd amount of mapping code to map data transfer objects to domain objects and vice versa and I think we all felt like it ended up being a huge waste (we *really* needed to isolate our client from the backend, so it was mostly justified).  This time around I’m honestly quite content just to bind some of the user interface directly to the Data Transfer Objects returned from our Java web services.  I feel a little bit dirty about this, but this approach is dirt simple.  It does couple us a bit more to the server than I would normally like, but I’m hoping to compensate with a fairly elaborate Continuous Integration scheme that does a fully integrated build with end to end StoryTeller/Fit tests anytime either codebase changes to detect breaking changes.
  4. DataSet/DataTable/DataView – See below:

Somebody has to ask, what about DataSet’s?  I despise DataSet’s in general, but there’s no denying that sometimes the easiest way to solve a problem is to revert back to Stone Age techniques and use them.  There’s a memorable scene from the first Lord of the Rings movie when Gandalf is speaking to Frodo very dramatically of the One Ring – “It wants to be found.”  It’s the same way in WinForms.  The user interface widgets often want to consume a DataSet.  The entire WinForms UI toolkit was originally wrapped around a very datacentric view of the world and sometimes you just go along with it. 

Alright, it’s not that bad.  I will happily use a DataSet/DataTable/DataView in my user interface as the ostensible Model any time it’s the easiest way to use a UI widget or when I want to take advantage of the sorting and filtering capabilities of a DataTable (I think that equation changes when Linq to Objects hits).  The Data* classes aren’t my real domain though, I generally convert my real classes to a DataTable just in time for display.  And no, a DataSet-centric approach doesn’t buy me much because as I’ll show in the next section the Model has real responsibilities beyond just being a dumb bag of data.  Plus the little issue that DataSet’s are not interoperable and we’re using web services written with Java for our backend services. 

While a DataSet makes the data binding generally very simple, you’re left with the usual drawbacks to a DataSet.  You can’t embed any real logic into the DataSet, so you have to be careful with duplication of logic.  If you insist on a DataSet approach, I’d recommend giving the Table Module approach some thought as a way to centralize the related business logic for a particular set of data to avoid duplication.  Personally, I think DataSet’s are clumsy to use inside of automated tests in terms of test setup.  A strongly-typed DataSet helps to at least get some Intellisense, but they annoy me as well.  Plus you’ll often find yourself building data that’s meaningless to the test just to satisfy the referential integrity rules of a DataSet.  That’s wasted effort.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in Build your own CAB, Design Patterns. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    Ralf,

    I’ve most certainly read their paper. It’s all the same stuff I’ve been talking about though. They’re taking a Passive View approach with specific adapters between the Presenter and View for screen synchronization (which I would whole heartedly recommend if you go down the Passive View approach). The communication is through events instead of direct calls to the Presenter the way I prefer.

  • http://rkse.blogspot.com/ Ralf Kretzschmar

    Hi Jeremy,
    did you now about this: http://atomicobject.com/pages/Presenter+First
    There are also two interviews with the guys behind Presenter First on channel nine / AR Cast.
    Don’t get me wrong, I really appreciate the things you have brought to us in the last couple of weeks, but I really think Presenter First is the best idea I came accros in years.

  • http://joeydotnet.com/blog joeyDotNet

    One of the techniques I’ve used lately and have been successful with is creating screen-specific DTOs. This is a tip I picked up from JP when he did his Nothin’ But .NET class down here in VA.

    Now I’ve only done this on a couple web projects (both using MonoRail of course… :), but I’ve found it great in these scenarios, especially if you can leverage a UI framework that will automatically 2-way databind your DTOs and views, like MonoRail.

  • http://virtualgenius.spaces.live.com/ Paul Rayner

    Another issue related to the use of a Dataset/Datatable that recently has come up for me is the handling of null date values. If you want to leave a date value blank in your form then when you copy the null value into the DataTable it will (by default) throw an exception. I found a way around this, but it was extra head-scratching that I would rather have not had to do.

    In other words, while this can sometimes be a worthwhile approach, there may extra baggage with using a DataTable that must also be considered.

  • Alex Scordellis

    In the past I’ve created strongly-typed DataSets to represent my domain model and used .NET 2.0’s partial classes to add functionality to them. This allows me to take advantage of the easy binding, navigation etc. of DataSets and still have an OO domain model where the behaviour lives in the same class as the data. Of course this stops you from using inheritance and other OO features in your model, and you still have the problems related to satisfying referential integrity etc, but for the small project I was working on it was a neat solution.

  • http://laribee.com/blog/ Dave

    Some consider “Services” (the most overloaded term in software development, ever) to be part of the model, at least as far as the MVP triad is concerned. By Service I mean mainly behavioral classes. Like the canonical ISmsService, web service proxies, etc.

    Also – minor point – 1, 2, and 3 work very well together in a stack when you have a hard need to remote over http, web services, etc. Semi-tangential to your posts but I think 3 might be the last bastion for (reflective over the DTO) code generation.