Presentation Model: “Screen” Store Example


“It is better to trust in the LORD Than to put confidence in man.” —

[Psalm

118:8](http://www.blueletterbible.org/cgi-bin/tools/printer-friendly.pl?book=Psa&chapter=118&version=NKJV#8)

Ok folks.  First, a couple disclaimers:

  • I first heard of this kind of approach from JP back during his Richmond boot-camp

    tour.  🙂  Having said that, I’m fully expecting folks (including JP) to shoot

    holes in the implementation of this example.  I’m merely providing it to better

    explain the pieces involved.

  • A lot of the patterns and layering you will see in the

    example are intentionally overdone for the purposes of showing

    the mechanics.

Now that we have that little tidbit out of the way.  This post is intended to

be read in 2 parts. 

First, get the code man…

You can grab the entire source code (either from my google code repository or

in [this

convenient little zip file](http://joeydotnet.googlecode.com/files/ScreenStoreExample.zip)).  Feel free to browse the code for a bit, but

come back to this post so I can show an example of adding a

new, simple feature using this code base.

Some quick notes regarding the solution:

  • If you open a console to the root directory of the solution you can run

    “build test” to run all the unit tests and see them succeed (hopefully, :P)

  • I was lazy in this example and didn’t include my usual “build run” target

    which will automatically compile, test and fire open a browser to run the

    application [without

    opening VS](http://www.jpboodhoo.com/blog/DirectoryStructureForProjects.aspx).  So you’ll have to open up VS and do the old skool Ctrl+F5

    (sorry).

Second, let’s add a quick little feature

Right now the monitor search results show brand, size and model.  Let’s say

the customer would like to also see whether or not the monitor is in stock from

the search results.  Let’s see what that would take.

First off, you may have noticed that I’m using the very handy SmartGridComponent from

Ayende (now included in the [Castle Contrib

project](http://using.castleproject.org/display/Contrib/Home)).  Here’s how it’s used in this example: 

<% 
component smartGrid, { @source:searchResults, @displayId:false } :

section more:
%>
<td>${Html.LinkTo("Details", "monitor", "view", item.Id)}</td>
<%
end
end
%>

As you can see, I don’t actually have to specify which columns should be

shown in the grid, since it’s “smart” enough to figure it out from the object it

is bound with.  This means we don’t even have to modify our view to add this

feature!

(To learn more about using this component, check out the new [Castle

project wiki page on it](http://using.castleproject.org/display/Contrib/Smart+Grid+Component)).

So we know that the object that is used to display our search results is

MonitorSearchResultDTO.  Instead of just adding an IsInStock

property to it now, let’s drive it out via TDD like good little boys and girls. 

😀

If we glance at our Monitor domain object, we see that a

Monitor already has the ability to check if its in stock or not

(whether it should or not is a whole ‘nother discussion which is not

the point of this post).  Well, sounds like all we have to change is our mapper

implementation.  Let’s open up our

MonitorToMonitorSearchResultDTOMapperTest fixture.

Mapper tests are, for the most part, not all that exciting.  A lot of value

matching and that’s about it.  So let’s set up our 2 stubbed monitors to return

values for their IsInStock() methods.

// ...
SetupResult.For(mockDell24InchUltraSharp.IsInStock()).Return(true);

// ...
SetupResult.For(mockApple30InchCinemaDisplay.IsInStock()).Return(false);

 

Now let’s add our asserts to make sure the mapper is doing its job of setting

the appropriate values on the DTO.  (Yes, I realize relying upon indexers in

this case is just plain ugly, but you’ll forgive me this time, won’t ya?  🙂

// ...
Assert.IsTrue(listOfSearchResults[0].IsInStock);

// ...
Assert.IsFalse(listOfSearchResults[1].IsInStock);

 

You’ll probably notice we don’t have an IsInStock property

on our MonitorSearchResultDTO yet.  Simply use ReSharper to add

it now. 

(You’ll probably want to update the constructor for this DTO in order to

keep it immutable, since there really isn’t a reason it should ever need

to change once created.)

Now if your run our test suite using “build test” from the console, you’ll

probably get a compilation error.  That’s because we need to actually make the

necessary changes to get our test to pass.  So we just need to update our mapper

to use the modified constructor on our DTO.

return new MonitorSearchResultDTO(monitor.Id, monitor.Brand, monitor.Model, monitor.Size, monitor.IsInStock());

 

So, re-run the tests using “build test” and we should be green.  Now just build the app and refresh

the browser.  You should see that a new column appears in the search results

named “Is In Stock”. 

(Note: This feature actually only takes about 30 seconds to add.  Needless to

say it took much longer to actually write about it and explain it here.)

One last problem though.  It’s using “true/false” as the values which makes

for a pretty terrible user experience. 

Need Something To Do?

So, dear reader.  Here’s a petty little task for you if you’re interested. 

**How would you change the search results “Is In Stock” column to show

“Y/N” instead of “true/false”? ** (Bonus points for leveraging built-in

MonoRail features in the solution)

In Conclusion

Let the flaming begin.  🙂  Seriously though, I hope this example at least

has some value and maybe gives a small glimpse into one way to use a

presentation model to maintain a nice separation between your presentation and

domain.  I’d really like to see other folks post some examples as well.

 

 

 

Anyone played with Enso?