CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff

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.



Comments

Dave said:

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.

# June 6, 2007 1:32 AM

Alex Scordellis said:

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.

# June 6, 2007 9:03 AM

Paul Rayner said:

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.

# June 6, 2007 11:21 AM

joeyDotNet said:

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.

# June 7, 2007 8:53 AM

Ralf Kretzschmar said:

Hi Jeremy,

did you now about this: atomicobject.com/.../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.

# June 7, 2007 1:17 PM

Jeremy D. Miller said:

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.

# June 7, 2007 1:32 PM

Jeremy D. Miller -- The Shade Tree Developer said:

I've long, long since left the rails of "Build your own CAB" topics and wandered off into

# June 26, 2007 9:58 PM

Jeremy D. Miller -- The Shade Tree Developer said:

I will finish "Build your own CAB" at least before Acropolis hits and makes it all obsolete

# June 29, 2007 11:12 AM

Jeremy D. Miller -- The Shade Tree Developer said:

Just to continue the world's longest run on sentence. Before I start, here's the table of contents

# July 6, 2007 12:40 PM

HMK's Spurious Thoughts said:

Even if you are not into .NET, WinForms etc. this series by Jeremy D. Miller is a great one to follow. Posts so far: Preamble The Humble Dialog Box Supervising Controller Passive View Presentation Model View to Presenter Communication Answering...

# July 13, 2007 1:05 PM

Jeremy D. Miller -- The Shade Tree Developer said:

The title is a mouthful and accurately implies an alarmingly high jargon to code ration, but I just didn't

# July 24, 2007 5:18 AM

Jeremy D. Miller -- The Shade Tree Developer said:

Yes, this is overdue. Here is an introduction and table of contents to my "Build Your Own CAB"

# July 25, 2007 9:21 PM

Jeremy D. Miller -- The Shade Tree Developer said:

The title is a mouthful and accurately implies an alarmingly high jargon to code ration, but I just didn't

# July 26, 2007 10:57 AM

Jeremy D. Miller -- The Shade Tree Developer said:

To everybody that attended one of my talks at DevTeach this week. All of the materials are now online

# November 29, 2007 12:03 PM

Vidar’s Musings » Blog Archive » DataSets - thanks, but no thanks said:

Pingback from  Vidar’s Musings  » Blog Archive   » DataSets - thanks, but no thanks

# May 25, 2008 4:51 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Jeremy D. Miller

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 previously worked as a systems architect building mission critical supply chain software for a Fortune 100 company and learned agile development practices as a .Net consultant at ThoughtWorks, one of the pioneers of agile development. Jeremy is the author of the open source StructureMap (http://structuremap.sourceforge.net) tool for Dependency Injection with .Net and the forthcoming StoryTeller (http://storyteller.tigris.org) tool for supercharged FIT testing in .Net. Jeremy's thoughts on just about everything software related can be found on his weblog "The Shade Tree Developer" at http://codebetter.com/blogs/jeremy.miller, part of the popular CodeBetter site. Jeremy is a Microsoft MVP for C#. Check out Devlicio.us!

This Blog

Syndication

News

All opinions expressed here constitute my (Jeremy D. Miller's) personal opinion, and do not necessarily represent the opinion of any other organization or person, including (but not limited to) my fellow employees, my employer, its clients or their agents.

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP