Presentation Model: "Screen" Store Example

“It is better to trust in the LORD Than to put confidence in man.” —
Psalm
118: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
).  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
    .  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
).  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
).

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. 
:D

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.

 

 

 

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

8 Responses to Presentation Model: "Screen" Store Example

  1. Joey you rock. I’m downloading the code now and I’ll post my flames in a bit :) j/k

    FYI: Googlecode’s svn link says http://joeydotnet.googlecode.com/svn/trunk but there is no “trunk” folder. I removed this and it worked.

  2. Oops, It must be case sensitive or something I don’t know. Browsing the repository in googlecode shows it just fine.

    For your readers, if you want to check out the code in SVN, here’s the command:

    svn checkout http://joeydotnet.googlecode.com/svn/joeyDotNet/samples/Screen.Specific.DTOs/

  3. joeyDotNet says:

    Doh! Sorry about that. Thanks for setting me straight Ben.

  4. Count me in. I’m downloading now. Very cool post. Good idea to keep us active. Google Code rules!

  5. BB says:

    Great post, and code example. I’m fairly new to mocking and therefore wondered what are the benefits of using mocking for creating the monitor objects in the test fixture? Wouldn’t it be simpler (and more readable) to just create the monitors using the domain class?

  6. joeyDotNet says:

    @BB,
    I have a post kinda in the works that explains some of the benefits of explicitly creating interfaces, even for domain objects (like the Monitor in the example).

    The quick answer is that when possible, I like to encapsulate as much behavior and object interactions within the domain objects themselves. So if I’m writing a test for a service that has to perform some actions on a domain object, I don’t necessarily care *how* the domain object does what it does. I only care that the service is making the calls to the domain object.

    The way all this relates is that if I was working with a concrete domain object, in which the behaviors might be complex (i.e. involving other objects, etc…), I may have to go through a possibly complex “set up” process to get the domain object in the needed state before it can be used in the service test. Patterns like ObjectMother and Builders can help with this and it is something I’m looking into.

    But, in my service test, if I can just set up a couple expectations on my domain object’s interface, it removes the need for the service test to know *how* the domain object does anything and/or interacts with other domain objects.

    Hope that somewhat answers your question for now. :)

  7. BB says:

    Thanks for the clear answer! It helped me understand the reasoning behind the mocking of the domain objects. Looking forward to mentioned post!

  8. Colin Jack says:

    Ta for the example, someone really needs to write a codebase to make object to object mapping like this easy. I’m all for using TDD to develop the interfaces of the presentation DTOs but have Having to write the code/tests for the mapping by hand each time seems very painful. Did you ever look at using Spring, we’ve thought about it but we aren’t using presentation DTOs yet so there hasn’t been a big need:

    http://forum.springframework.net/showthread.php?t=822

    > the benefits of explicitly creating interfaces, even for domain objects

    I find this thread useful when considering mocking the domain:

    http://tech.groups.yahoo.com/group/domaindrivendesign/message/5683

    Personally I don’t think I like mocking domain classes, especially not when it affects the design (e.g. requiring every class to support an interface or virtual members). Part of the problem, for me at least, is that if you scale this up any important abstractions are going to get lost in all the IFoo interfaces you include for mapping. Mind you when I do need a little mocking I turn to TypeMock anyway (guilty pleasure :) ).