I’ve decided not to repost much of the code because of the amount, but I made
some pretty significant changes. In line with Scott Bellware’s suggestions,
I’ve added more granularity to the View interface so that the view never
actually holds a reference to the business object. The control’s to display
information are exposed as properties (actually, the textbox.Text property is
exposed as a property of the interface), so the presenter can actually change UI
elements through the inderection these properties provide. I defined two events
on the interface as well to denote when the LookUp event first and Persist. My
Presenter doesn’t care about a button click, so when the View experiences a
button click that actually means “LookUp”, it fires the LookUp event, which the
Presenter is listening for.
I will include one bit of code, and that is the IView interface
implementation in my WinForms code-behind class:
The above is a snippet from the form code. Notice how the interface
properties are mapped to the appropriate text box, and the button click handlers
just invoke the events defined by the interface. Now it would be very trivial
to snap a different UI on to the same Presenter.
I used NUnit to hook up unit tests to the entire thing to prove that this
layout was fully testable. Each component at every layer has been tested in
isolation. The interfaces make it easy to make stubs, but interfaces were
mainly used for loose-coupling. I’m tightly coupled where concrete classes are
referenced, but that’s fine. I think that loose-coupling should server a
purpose, so it may not be appropriate everywhere. For instance, my Presenter is
tightly coupled with the Repository object. I can still test my Presenter is
isolation because I have a property in my Presenter to hold a reference to the
Repository. In my test, I inherit from the Repository, override the members,
and set the Presenter’s property to my stub object. This isolates Presenter.
I was a bit surprised at how simple my tests ended up being because each
class served a specific purpose, so it was easy to test for that purpose. As
long as my Presenter could call the Repository, it was working. As long as the
Repository could get a Contact back from the ContactData object, it was
working. Only my unit test for MyContactData actually tested that the data was
correct because the object was being created at this point.
Another point of interest is the amount of private methods in my solution.
My two event handlers in the Presenter are private, and that is it. Everything
else is a publicly exposed piece of a concrete class that serves a distinct
Download my code and give it a look. I’m open for criticism. Maybe with a
little collaboration, we can, as a community, make architecture recommendations
and provide a community-supported prototype of a single feature demonstrates the
use of good practices. The more feedback the better.