Monday, December 29, 2008

My Add MvpView VS Template

So, I did a presentation at work on the MyDumbView (MVP Passive View / Observer pattern) blog post I made a few weeks ago. After the presentation, I heard a complaint about the amount of work required to wire up a view. While I don't think it's a very valid point (you'd write just about the same amount of code in a code-behind, it would just be untestable). It did get me to thinking... Why not make a VS template with a wizard that implements the view for you?


So I did.

Features



  • Allows you to browse an assembly, and chose view to implement
  • Supports multiple "templates" for aspx markup
  • "Wires up" all views properties and events according to template definition
  • "News up" a presenter, so views with value types will "just work" without any hand coding!
  • Generates a populated resx file for each view created

Install


To install it, just download the zip file, unzip and run the Install.bat file.  What does it do?

Creates C:\AddView and copies AddView.dll
Creates C:\AddView\Templates and copies Templates.xml
Copies MVPView.Zip to your visual studio ItemTemplates folder (it'll do both vs 2005 and 2008).
Adds AddView.dll to your GAC (this is required by VS)

Of course you can uninstall it by undoing all the steps above.



Lets Use it


If you haven't read the MyDumbView post yet, now would be a good time to, because that's the project I'm adding a new file to. Basically, this template will write all the UI code needed for an MVP view to work. You can then spend the time all the time you want prettying it up, or let a UI guy or gal do that for ya.



We're going to add a new View to the Web Project. To do so we simple right click on the web project and chose "Add New Item".

Down at the bottom under "My Templates" there will be a new item titled "MVP View". Select it. Go ahead and get rid of that Space in the file name, it's annoying. I just named my MVPView.aspx


 







A form will pop up that allows you to select the assembly that has the View you wish to implement. Select that assembly ( <SolutionDir>\References\MyDumbView.dll) and in the right hand tree browse to the View you wish to implement (MyDumbView.Presentation.Views). If the presenter is a different namespace, you can specify the presenters namespace as well (MyDumbView.Presentation.Presenters). You can also select different templates to use to generate the HTML. The Templates are located in C:\Templates\Templates.xml, and can be modified as much as you wish, or you can add templates to the file easily. Just take a look at it.

Once we've filled in everything, Select OK.



Vola! An aspx file, the codebehind and App_LocalResource\FileName.aspx.cs are generated. Yep, they "just work"!


The aspx is resource file driven, so you can change the text by just editing it, and of course you can hand edit the aspx to your hearts content.

The idea here was NOT to let a tool generate all the UI, it was simply make it easier to practice a pattern that I think is very effective. Of course this won't work for everything, but it sure saves a lotta hand coding.

As it's currently written, it will throw not implemented exceptions for Array properties (very similar to how Resharper implements interfaces), since those will typically control drop downs or repeaters and require some hand coding on your part.


FEEDBACK PLEASE!!!

Saturday, December 20, 2008

Clean Code by Robert C. Martin

A Handbook of Agile Software Craftsmanship

Book Review

So this is my first read of an "Uncle Bob" book. I'm quite impressed. I can't say that I learned anything spectacular. It was more of a book of "yeah, exactly" moments. Quite a few one liners... Some of my favorites.

First, you are a programmer. Second you want to be a better programmer. Good. We need better programmers.

Leave the campground cleaner than you found it. (The boy scout rule).

The first rule of classes is that they should be small. The second rule of classes is that they should be smaller than that.

Don't comment bad code. Rewrite it.

The proper use of comments it to compensate for our failure to express our self in code.

I think that's brilliant! If code requires comments, it's badly named or does not express itself well.

Bob isn't saying all comments are bad, he's just saying that comments shouldn't excuse bad code.  BTW, documentation is not the same as comments... Two very different things.

Comments lie, at least they're capable of it. Code isn't...

He quotes Ward Cummingham (inventor of Wiki).

You know you are working on clean code when each routine you read turns out to be pretty much what you expected. You can call it beautiful code when the code also makes it look like the language was made for the problem.

Maybe I'm too passionate about coding, but that's motivating to me. "Like the language was made for the problem"!

Code Formatting

A great nice to read... Mostly, "yeah, I know that" moments, but it's great to hear it put in Bob's matter of fact tone. He uses a newpaper article as an example. Tell the overall story (high level) first, get into details later. Your code should be easy to read. Private methods should be close to their first consumer. That way the reader doesn't have to scroll down (far) to find what exactly that method does. Hopefully it's named well enough that they really shouldn't have to go look.

Classes

The first rule of classes is that they should be small. The second rule of classes is that they should be smaller than that.

Nice!

So, I'm working on a MVP view code generator (hope to blog about it very soon). As I was reading this book. I had a class called CSharpPropertyGenerator. In the class I had 3 methods that generated getters for the property. Resharper told me they could be static... SMELL!! Pulled them into thier own class, and it was amazing how much easier the code was to read. Yeah, sure I probably would done it anyway, but I definitely felt Bob looking over my shoulder.

Arguments

The perfect number of arguments for a function is 0. One is OK. Two is questionable, Three... Time to look and see if this should be an it's own class.

 

SOLID

Yep, he's an agile guy, and re-iterates the principles of SOLID.

He's adamant about (DRY), and makes the point that most of the patters of software development are in response to DRY.

Separations of Concerns? You betcha... Once again, no huge "wow" moments, just a nice to read it all in one place. 

Smells and Heuristics

Probably my favorite chapter, in fact it's worth mentioning some of my favorite bullet points.

  • Obvious Behavior is unimplemented...
    "The Principle of Least Surprise"
  • Incorrect Behavior at Boundries.
    Don't rely on your intuition, rely on unit tests.
  • Duplication (need I say more?)
  • Base classes depending on their derivatives.
  • Feature Envy
  • Selector Arguments
    Really liked this one. He used an example function calculateWeeklyPay(bool overTime) and refactored to 3 methods. straightPay, overTimePay and overTimeBonus.
    Much easier to read, and makes much more sense!
  • Inappropriate Static.
  • Function names should say what they do
  • Polimorphism over if/else switch.
    NICE! Would everyone PLEASE jump on this bandwagon?
  • Encapsulate Conditionals
    if(ShouldBeDeleted()) instead of if(time.hasExpired() && timer.isRecurrent()).
  • Avoid Negative Conditionals
  • Functions should descend only on level of abstraction

I give this book a B... Nice easy read, that just reinforces things responsible developers probably already know. If anything in this post surprises you, then I'd STRONGLY suggest it. The only negative in this book is that all the source code is java. But I don't consider that a big deal.

Wednesday, December 10, 2008

Re-Writing Wife's Website

My wife and I own a Dance Studio. I wrote a website for her some 4 years ago, and have since given it 1 re-write. I think it's high time for another.

So, I was having a talk with Matt (dude, get a blog or something!), about namespace organization at Work. While I don't like "assembly explosion" (just made that up.. a quick google search tells me that I should copyright it). I do think that my Model belongs in it's own assembly that has absolutely no 3rd party references. I personally don't think namespace segregation will do the trick.

Here's what I'm thinking, listed in order of dependency

BDF.Model

Pretty clear what's here, right. DomainModel is more letters, so I didn't use it. But it'll just contain all my Entities. Matt wrote a great paper (kinda like a cliff notes for object types based on DDD). Gunna try to follow those patterns here. Everything will be POCO, value types as often as possible, yada, yada. No 3rd party refs here at all.

BDF.Core

Core? Business? Not sure. I think service level stuff and persistence should go here. Since Service level stuff will need to understand persistence, it should sit down here. It'll ref Model and anything I use for Persistance (NHibernate). 

BDF.Presentation

Presentation stuff here. Sticking with MVP. WILL NOT ref System.Web. 

BDF.Web

No APP_CODE for me... This will contain anything that a responsible developer might put in APP_CODE. I'm thinkin' I'll even put the webservices here... Am I being silly? Might be actually, this is one where Matt and I differ, and I'm wondering if he's right.

Second Thoughts...

Could Core and Presentation be combined??? I don't think so, but it's worth considering.

Anyway, time for Christmas party. Done blogging for now.

Tuesday, December 9, 2008

My View is dumber than yours, but it sure smells better!


Download complete solution
Run Webform implementation
Run Ajax implementation



So, I'm a big fan of the MVP passive view pattern. If you don't know the benefits of this pattern, I'm not gunna take the time in this post to explain them, you can use google.

However, I think that the most common implementation of MVP falls just a bit short. Typically, with the passive view pattern, the presenter exposes public methods that the view calls. While the methods are fully testable, I think that having the view have intimate knowledge of its presenter fails the smell test. In my mind, the dumber untestable code is, the better. A view should only know about itself and the existance of a presenter, not what the presenter does.

I think the solution to this problem is using the MVP with the Observer pattern. Marrying the two is simple enough, and there’s no excuse (IMO) not to.  So I decided to make a quick example….

For this example I made a very simple domain model, consisting of one object.

The Code?

namespace MyDumbView.DomainModel

{

    public class Person

    {

        public virtual int PersonId { get; set; }

 

        public virtual string FirstName{get;set;}

 

        public virtual string LastName{get;set;}

       

    }

}

I then created a simple, generic Repository interface for my Presenters consumption.  

namespace MyDumbView.Repositories

{

    public interface IRepository<T>

    {

        ///

        /// Returns the with the Id

        ///

        ///

The id of the

        ///

        T GetById(int id);

        ///

        /// Persists to sent.

        ///

        ///

The entity to persist

        /// The primary Key of the object persisted

        int Save(T entity);

        ///

        /// Returns all instances of in the system

        ///

        ///

        T[] GetAll();

        ///

        /// Deletes the entity

        ///

        ///

        void Delete(T entity);

       

    }

}

 

A discussion about why I went the generics route is kinda outside the scope of this post, but yeah, it saves a lot of time, because I can now make an interface for getting Person just by doing this.

using MyDumbView.DomainModel;

 

namespace MyDumbView.Repositories

{

    public interface IPersonRepository:IRepository<Person>

    {

       

    }

}

Yeah, I know that my model only had one object, so this didn’t really save anything, but I couldn’t help myself! Anyway, we’ve digressed, this post is supposed to be about MVP / Observer pattern, so let’s get back on track.

Since I’ve got my domain model and repository interface done (if you wanna see the implementation of the repo, look at the attached solution, a discussion of it is outside the scope of this post), it’s now time for the view.

I want this view to support saving and editing of a Person object.

using System;

using MyDumbView.DomainModel;

 

namespace MyDumbView.Presentation.Views

{

    ///

    /// A basic view that allows for the creation and editing of a

    ///

    public interface IPersonEditorView

    {

        ///

        /// The Id of the Person

        ///

        int? PersonId { get; set; }

        ///

        /// The FirstName

        ///

        string FirstName { get; set; }

        ///

        /// The LastName

        ///

        string LastName { get; set; }

        ///

        /// The event to fire when the should be persisted

        ///

        event EventHandler PersonSaved;

        ///

        /// The event to fire when a Person should be loaded from the persistance mechanism.

        ///

        /// PersonId must be set

        event EventHandler PersonLoaded;

 

 

    }

}

Note the use of the two events, PersonSaved and PersonLoaded. Instead of the implementer of this interface calling a PersonSaved method on the presenter, the Presenter will simply subscribe to the event and execute the appropriate method. This means the view only understands what’s going on with itself, and does not have intimate knowledge of the Presenter.

Since I’m a firm believer in TDD, I simply stubbed out the presenter, but DID NOT write any code beyond that. I even commented the names of the unit tests that would be used to test the functionality of the methods. This only takes a few moments and makes unit testing much easier.

Here’s the stubbed code

using System;

using MyDumbView.DomainModel;

using MyDumbView.Presentation.Views;

using MyDumbView.Repositories;

 

namespace MyDumbView.Presentation.Presenters

{

 

    ///

    /// Presenter for an .

    ///

    public class PersonEditorPresenter

    {

        private readonly IPersonEditorView _view;

        private readonly IPersonRepository _repository;

         ///

        /// Creates an instance of

        ///

        ///

the for this presenter

        public PersonEditorPresenter(IPersonEditorView view)

            : this(view, new HttpCachePersonRepository())

        {

        }

        ///

        /// Dependency incjector constructor, allows unit tests to set the

        /// object to use.

        ///

        ///

the for this presenter

        ///

an Instance of to handle persistance

        internal PersonEditorPresenter(IPersonEditorView view, IPersonRepository repository)

        {

             //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterRegistersForEvents()

           

        }

        ///

        /// Executed when the is raised.

        ///

        ///

        ///

        void LoadPerson(object sender, EventArgs e)

        {

            //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonLoadedWithoutIdTest()

            //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonLoadedTest()

             

        }

        ///

        /// Executed when the event is raised.

        ///

        ///

        ///

        void SavePerson(object sender, EventArgs e)

        {

            //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonGetsAddedTest()

            //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonGetsEditedTest()

        }

       

    }

 

 

  

}

 

 

Note the 2 constructors on this object. For unit testing I’ll use the internal constructor by setting the friend attribute on MyDumbView assembly in AssemblyInfo.cs.

[assembly: InternalsVisibleTo("MyDumbView.UnitTests")]

After completing the stubbed presenter, I compiled the project. After a good compile, it was time to start writing the unit tests.

I’m a Rhino Mocks fan, and use it extensively… I’ve found that the Object Mother pattern saves a tremendous amount of time, and makes my unit tests much less brittle.

The way I typically do an Object Mother is create readonly fields that expose the values the mocked objects will return as well as fields that return the actual Mocked object, so you can add more specific expectation or results based on the needs of the specific unit test. This makes assertions nice and simple and makes unit tests much easier to construct.  See below…


public readonly IPersonRepository Repository;

public readonly int SavedPersonId = 2;

 

public readonly int LoadedPersonId = 1;

public readonly Person LoadedPerson;

public readonly string LoadedPersonFirstName = "First Name";

public readonly string LoadedPersonLastName = "Last Name";

private int? _saveResults;

 

Should these be properties? Maybe, but I’m not that concerned since this object will only be consumed by unit tests.

In the constructor, I create the instances of the mocked objects. It accepts and instance of MockRepository to use for creating mocked objects.

///

        /// Default Constructor

        ///

        ///

The instance of to set up mock objects.

        public PersonRepositoryMother(MockRepository mocker)

        {

            Repository = mocker.DynamicMock<IPersonRepository>();

            LoadedPerson = mocker.Stub<Person>();

        }

 

I then create a method that sets up the results for the mocked objects. I like calling it Record(), since it’s always called in a MockRepository’s Record block.

///

        /// Method that sets up expectations for all objects.

        /// It should be called during a block.

        ///

        public void Record()

        {

            //Person

            LoadedPerson.FirstName = LoadedPersonFirstName;

            LoadedPerson.LastName = LoadedPersonLastName;

            LoadedPerson.PersonId = LoadedPersonId;

 

            //Repository

            SetupResult.For(Repository.GetById(LoadedPersonId)).Return(LoadedPerson);

            SetupResult.For(Repository.Save(null)).IgnoreArguments().Return(SaveResults);

        }

 

What is SaveResults? I decided that I’m probably going to need the repository to return a different PersonId based on whether we’re saving or editing a Person object, so I created a property that consumers can set. Nothing special here.

///

        /// The results to return for a call to Repository.Save()

        ///

        public int SaveResults

        {

            private get

            {

                return _saveResults.HasValue ? _saveResults.Value : SavedPersonId;

            }

            set

            {

                _saveResults = value;

            }

        }

With my Object Mother complete, I now have a mocked up version of my repository, my own testable version of a database (or whatever the persistence mechanism is).

Now, on to unit tests: I’ve already mentioned the unit tests needed in my stubbed presenter. I make my unit tests clear and concise as possible. I look at them as the developers spec. To me, unit tests are a heck of a lot easier to read than the specs that BA’s give me, and they enforce requirements a LOT better….

First, the Unit test for the constructor. All it has to do is ensure that the presenter subscribes to the events that the view exposes.

///

        /// This test ensures that the registers for

        /// all events in the .

        ///

        [Test]

        public void PersonEditorPresenterRegistersForEvents()

        {

            var mocker = new MockRepository();

            var mother = new PersonRepositoryMother(mocker);

            var view = mocker.DynamicMock<IPersonEditorView>();

            using(mocker.Record())

            {

                //Expectations

                view.PersonLoaded += null;

                LastCall.IgnoreArguments();

                view.PersonSaved += null;

                LastCall.IgnoreArguments();

            }

           using(mocker.Playback())

           {

              new PersonEditorPresenter(view, mother.Repository);

           }

           

           

        }

 

Simple enough… Of course, this unit test fails, since the constructor of of PersonEditorPresenter does nothing at all yet. Let’s go and fix that. Looking at the unit test, we know exactly what we need to do to make the test turn green.

///

                      

    /// Presenter for an .

    ///

    public class PersonEditorPresenter

    {

        private readonly IPersonEditorView _view;

        private readonly IPersonRepository _repository;

        ///

        /// Creates an instance of

        ///

        ///

the for this presenter

        public PersonEditorPresenter(IPersonEditorView view)

            : this(view, new HttpCachePersonRepository())

        {

            // DO NOT PUT LOGIC HERE, use the

            // PersonEditorPresenter(IPersonEditorView view,IPersonRepository repository)

            // method.

        }

 

        ///

        /// Dependency incjector constructor, allows unit tests to set the

        /// object to use.

        ///

        ///

the for this presenter

        ///

an Instance of to handle persistance

        internal PersonEditorPresenter(IPersonEditorView view,IPersonRepository repository)

        {

            //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterRegistersForEvents()

            _view = view;

            _repository = repository;

            view.PersonLoaded += LoadPerson;

            view.PersonSaved += SavePerson;

        }

 

Ignore the new HttpCachePersonRepository(), just note that it’s the default implementation of IPersonRepository. It’s just a simple HttpCache implementation that persists the Person objects. It could just as well been one that persists to a db, and probably would be in a real world scenario.

Run the PersonEditorPresenterRegistersForEvents test, and VOLA! Green! One test down.

On to the next unit test. Looking back at the PersonEditorPresenter, I see the next UnitTest.

//UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonLoadedWithoutIdTest()

       

Pretty clear what’s needed, right? Someone fired the PersonLoaded event, but never set the view’s PersonId.

[Test] [ExpectedException(typeof(Exception))]

        public void PersonEditorPresenterPersonLoadedWithoutIdTest()

        {

            var mocker = new MockRepository();

            var mother = new PersonRepositoryMother(mocker);

            var view = mocker.DynamicMock<IPersonEditorView>();

            IEventRaiser personLoadedEvent;

            using (mocker.Record())

            {

                mother.Record();

                SetupResult.For(view.PersonId).Return(null);

                view.PersonLoaded += null;

                personLoadedEvent = LastCall.IgnoreArguments().GetEventRaiser();

            }

            using (mocker.Playback())

            {

                var presenter = new PersonEditorPresenter(view, mother.Repository);

                personLoadedEvent.Raise(null, null);

 

            }

 

 

        }

Note that I had the view return null for PersonId, and made sure the the presenter threw an Exception using

 

[ExpectedException(typeof(Exception))].

Yeah, I shouldn’t just be throwing an Exception of type Exception here, but YAGNI anything more for now… Anything more is outside the scope of this post.

Once again, the unit test failed since the view did absolutely nothing yet. But once again, I’ve got pretty clear requirements via the unit test.  Let’s make this test pass now.

///

        /// Executed when the is raised.

        ///

        ///

        ///

        void LoadPerson(object sender, EventArgs e)

        {

           

            if(!_view.PersonId.HasValue)

            {

                //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonLoadedWithoutIdTest()

                throw new Exception("Can not load person without id");

            }

            //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonLoadedTest()

        }

 

Simple enough, and yep, the Unit test passes.

It’s also simple to see the next unit test we need – The one that loads the person object. Let’s go write it…

  ///

        /// This test ensures that the hydrates

        /// the properly during the standard use case.

        ///

        [Test]

        public void PersonEditorPresenterPersonLoadedTest()

        {

            var mocker = new MockRepository();

            var mother = new PersonRepositoryMother(mocker);

            var view = mocker.DynamicMock<IPersonEditorView>();

            IEventRaiser personLoadedEvent;

            using (mocker.Record())

            {

                mother.Record();

                SetupResult.For(view.PersonId).Return(mother.LoadedPersonId);

                //Expectations

                view.FirstName = mother.LoadedPersonFirstName;

                view.LastName = mother.LoadedPersonLastName;

                view.PersonLoaded += null;

                personLoadedEvent = LastCall.IgnoreArguments().GetEventRaiser();

            }

            using (mocker.Playback())

            {

                var presenter = new PersonEditorPresenter(view, mother.Repository);

               

                personLoadedEvent.Raise(null,null);

            }

 

 

        }

 

A discussion of Rhino mocks expectations is outside the scope of this document, but note that I DID NOT use assertions here, but RinoMocks expectations. The reason I typically do that is that in many views we’ll only expose setters, which is great design on read only views. RhinoMocks lets you set up the expectation that the setter is called, instead of checking the getter. I think this is much better practice since we don’t want to test the getter, we want to test the setter.

Now, since we know this unit test will fail, since all that the presenter currently does is throw an exception if PersonId is null, I’ll skip running it. Instead, I’ll get to work making it pass.

Easy enough, since the unit test makes it really clear what the presenter should do, right?

Here’s the code…

///

        /// Executed when the is raised.

        ///

        ///

        ///

        void LoadPerson(object sender, EventArgs e)

        {

           

            if(!_view.PersonId.HasValue)

            {

                //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonLoadedWithoutIdTest()

                throw new Exception("Can not load person without id");

            }

            //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonLoadedTest()

            var person = _repository.GetById(_view.PersonId.Value);

            _view.FirstName = person.FirstName;

            _view.LastName = person.LastName;

        }

 

Compile, run unit test. Unit test passes. No surprises.

Next, we’re on to the PersonSaved event (SavePerson method) in the presenter. The stubbed code tells me what unit tests I’m going to need.

//UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonGetsAddedTest()

            //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonGetsEditedTest()

 

Should this method do 2 things? Probably not, I’m quite possibly violating the Single Responsibility Rule here, oh well. My wife tells me that I’m not perfect; I just had to prove her right!

Let’s write the PersonGetsAddedTest now.

///

        /// This test ensures that when the View returns null for

        /// ,

        /// the presenter passes the null up to the

        /// so that it can handle the add.

        ///

        [Test]

        public void PersonEditorPresenterPersonGetsAddedTest()

        {

           

            var mocker = new MockRepository();

            var mother = new PersonRepositoryMother(mocker);

           

            //Tell repo to return the correct id

            mother.SaveResults = mother.SavedPersonId;

           

            var view = mocker.DynamicMock<IPersonEditorView>();

            var firstName = "firstName";

            var lastName = "lastName";

            var personId = mother.SavedPersonId;

            IEventRaiser personSavedEvent;

            using (mocker.Record())

            {

                mother.Record();

                //Expectations

                Expect.Call(view.FirstName).Return(firstName);

                Expect.Call(view.LastName).Return(lastName);

                view.PersonSaved += null;

                personSavedEvent = LastCall.IgnoreArguments().GetEventRaiser();

                view.PersonId = personId;

            }

            using (mocker.Playback())

            {

                var presenter = new PersonEditorPresenter(view, mother.Repository);

 

                personSavedEvent.Raise(null, null);

            }

 

So, the only expectations we have here is that the event gets fired, and that the view’s PersonId property does get set, and the Views FirstName and LastName properties getters are called. Simple enough, so let’s go make the unit test pass.

///

        /// Executed when the event is raised.

        ///

        ///

        ///

        void SavePerson(object sender, EventArgs e)

        {

            //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonGetsAddedTest()

            //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonGetsEditedTest()

            var person = new Person();

            person.FirstName = _view.FirstName;

            person.LastName = _view.LastName;

            _view.PersonId = _repository.Save(person);

        }

 

Yep, the unit test passes. One unit test to go…

Now we need to make sure that if the view already has PersonId set, we edit the Person, not insert a new one. Actually, we really don’t care if one gets inserted or edited, that’s the responsibility of the repository (and arguably a result of a violation of SOC). Anyway, we’re just going to make sure that the view returns the PersonId.

///

        /// This test ensures that when the View returns a valid id for

        /// ,

        /// the presenter passes the value to the

        /// so that it edits the .

        ///

        [Test]

        public void PersonEditorPresenterPersonGetsEditedTest()

        {

            var mocker = new MockRepository();

            var factory = new PersonRepositoryMother(mocker);

            var view = mocker.DynamicMock<IPersonEditorView>();

            var firstName = "firstName";

            var lastName = "lastName";

            var personId = (int?) factory.LoadedPersonId;

            factory.SaveResults = personId.Value;

            IEventRaiser personSavedEvent;

            using (mocker.Record())

            {

                factory.Record();

    //Expectations               

    Expect.Call(view.FirstName).Return(firstName);

                Expect.Call(view.LastName).Return(lastName);

                SetupResult.For(view.PersonId).Return(personId);

               

                view.PersonSaved += null;

                personSavedEvent = LastCall.IgnoreArguments().GetEventRaiser();

                view.PersonId = personId;

            }

            using (mocker.Playback())

            {

                var presenter = new PersonEditorPresenter(view, factory.Repository);

 

                personSavedEvent.Raise(null, null);

            }

 

 

        }

 

Unit test does fail because we PersonId gets set to LoadedPersonId instead of SavedPersonId. Simple enough to make the unit test pass; just check if the view has PersonId set, if it does, use it.

 

   ///

        /// Executed when the event is raised.

        ///

        ///

        ///

        void SavePerson(object sender, EventArgs e)

        {

            //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonGetsAddedTest()

            //UnitTest:MyDumbView.UnitTests.PersonEditorPresenterTestFixture.PersonEditorPresenterPersonGetsEditedTest()

            var person = new Person();

            if (_view.PersonId.HasValue)

            {

                person.PersonId = _view.PersonId.Value;

            }

            person.FirstName = _view.FirstName;

            person.LastName = _view.LastName;

            _view.PersonId = _repository.Save(person);

        }

 

There we go, fully unit tested, fully functional Presentation Layer!


Nunit Test run

Now for the easy part, make the UI. Since we’ve already tested everything… This will be silly easy.

The markup…

 

DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title>My View Is Dumber Than Your Viewtitle>

   <link rel="stylesheet" href="css/c.css" />

head>

<body>

    <h1>MVP /  Observer pattern, Standard ASPX exampleh1>

    <form id="form1" runat="server">

    <fieldset>

        <legend>Edit a Personlegend>

    <div>

        <asp:Label runat="server" ID="PersonIdLabel" AssociatedControlID="PersonIdControl">IDasp:Label>

        <asp:TextBox runat="server" ID="PersonIdControl" style="width:2em;" />

        <asp:Button runat="server" ID="LoadButton" Text="Load" />

    div>

    <div>

        <asp:Label runat="server" ID="PersonFirstNameLabel" AssociatedControlID="PersonFirstNameControl">First Nameasp:Label>

        <asp:TextBox runat="server" ID="PersonFirstNameControl" />

    div>

    <div>

        <asp:Label runat="server" ID="PersonLastNameLabel" AssociatedControlID="PersonLastNameControl">Last Nameasp:Label>

        <asp:TextBox runat="server" ID="PersonLastNameControl" />

    div>

    <div class="commands">

        <asp:Button runat="server" ID="SaveButton" Text="Save" />

    div>

    fieldset>

    form>

body>

html>

 

And the codebehind, Just mark the Page with the interface and let the IDE do most of the work for us. We just simple fill in the stubbed out implementation. Don’t forget to new up a presenter!

using System;

using System.Web.UI;

using MyDumbView.DomainModel;

using MyDumbView.Presentation.Presenters;

using MyDumbView.Presentation.Views;

 

 

public partial class _Default :Page,IPersonEditorView 

{

    private PersonEditorPresenter presenter;

    ///

    /// creates and instance of

    ///

    ///

    protected override void OnLoad(EventArgs e)

    {

        base.OnLoad(e);

        presenter = new PersonEditorPresenter(this);

 

    }

    ///

    /// Wires up events

    ///

    ///

    protected override void OnInit(EventArgs e)

    {

        base.OnInit(e);

        LoadButton.Click += delegate { PersonLoaded(this, e); };

        SaveButton.Click += delegate { PersonSaved(this, e); };

    }

    #region IPersonEditorView Methods

   

    ///

    /// The , null if we're adding a new one.

    ///

    public int? PersonId

    {

        get

        {

            int x;

            if (int.TryParse(PersonIdControl.Text,out x))

            {

                return x;   

            }

            return null;

        }

        set { PersonIdControl.Text = value.ToString(); }

    }

    ///

    /// The to display

    ///

    public string FirstName

    {

        get { return PersonFirstNameControl.Text; }

        set { PersonFirstNameControl.Text = value; }

    }

    ///

    /// The to display

    ///

    public string LastName

    {

        get { return PersonLastNameControl.Text; }

        set { PersonLastNameControl.Text = value; }

    }

    ///

    /// Event raised when Saved is Clicked

    ///

    public event EventHandler PersonSaved = delegate { };

    ///

    /// Event raised when Load is clicked

    ///

    public event EventHandler PersonLoaded = delegate { };

   

    #endregion

}

As a side note, I’ve found that it saves a lotta coding to declare the events with no-ops

    public event EventHandler PersonSaved = delegate { };

Since it saves the null check, and makes code much more readable.

       

SaveButton.Click += delegate { PersonSaved(this, e); };

Just personal preference, some people find it easier to actually make methods to fire events, I just think it’s more code, and to me, less code is usually better.

No surprises, it just works! When we leave PersonID textbox blank, we add a new person. After adding one, if we enter the ID and click load, it loads one, and if we edit the person, and click save, the Person is saved.

I didn’t like the usability much, so added a button to reset everything right next to the save button.

<div class="commands">

        <asp:Button runat="server" ID="SaveButton" Text="Save" />

        <input type="button" id="AddPerson" value="Add New Person" />

    div>

 

Then, I wired up some simple JS for it.

<asp:ScriptManager runat="server" ID="SM" />

    <script type="text/javascript">

    var personIdControlId = '';

    var personFirstNameControlId = '';

    var personLastNameControlId = '';

    $addHandler(window,"load",load);

    function load()

    {

         $addHandler($get("AddPerson"),"click",reset);

    }

    function reset()

    {

        $get(personIdControlId).value =

        $get(personFirstNameControlId).value =

        $get(personLastNameControlId).value = "";

    }

    script>

 

Wow, that was easy! Now I’m bored, so I’m gunna make a quick AJAX implementation of the same view.

using System;

using MyDumbView.Presentation.Views;

 

public class PersonView : IPersonEditorView

{

 

    public void FirePersonLoaded()

    {

        if(PersonLoaded != null)

        {

            PersonLoaded(this, EventArgs.Empty);

        }

    }

    public void FirePersonSaved()

    {

        if(PersonSaved != null)

        {

            PersonSaved(this, EventArgs.Empty);

        }

    }

 

    #region IPersonEditorView Members

 

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public int? PersonId { get; set; }

    public event EventHandler PersonLoaded;

    public event EventHandler PersonSaved;

 

    #endregion

}

 

Nothing special here except 2 methods to fire the events.

Now let’s make a quick webservice that consumes the view and presenter.

using System.Web.Services;

using MyDumbView.Presentation.Presenters;

 

///

/// A simple webservice to Add and Edit a

///

[WebService(Namespace = "http://www.elliottohara.com/MyDumbView/")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

[System.Web.Script.Services.ScriptService]

public class PersonService :WebService

{

 

 

    [WebMethod]

    public PersonView LoadPerson(PersonView view)

    {

        var presenter = new PersonEditorPresenter(view);

        view.FirePersonLoaded();

        return view;

    }

    [WebMethod]

    public PersonView SavePerson(PersonView view)

    {

        var presenter = new PersonEditorPresenter(view);

        view.FirePersonSaved();

        return view;

    }

 

}

 

Now, a simple page that uses the webservice, it doesn’t even need a codebehind.

DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title>Ajax implementation of a dumb viewtitle>

    <link rel="stylesheet" href="css/c.css" />

head>

<body>

    <h1>MVP /  Observer pattern, Ajax exampleh1>

    <form id="form1" runat="server">

    <div id="Status" class="status">div>

    <fieldset><legend>Add a Personlegend>

    <div>

        <label for="FirstName">First Namelabel>

        <input id="FirstName" />

    div>

    <div>

        <label for="LastName">Last Namelabel>

        <input id="LastName" />

    div>

    <div class="command">

        <input type="button" id="AddNewButton" value="Add" />

    div>

    fieldset>

    <fieldset>

        <legend>Load Edit a Personlegend>

        <div>

            <label for="PersonId">IDlabel>

            <input id="PersonId" style="width:2em;"/><input type="button" value="Load" id="LoadButton" />

        div>

        <div>

        <label for="EditFirstName">First Namelabel>

        <input id="EditFirstName" />

    div>

    <div>

        <label for="EditLastName">Last Namelabel>

        <input id="EditLastName" />

    div>

    <div class="commands">

        <input type="button" id="SaveButton" value="Save" />

    div>

    fieldset>

    <asp:ScriptManager runat="server" ID="ScriptManager">

        <Services>

            <asp:ServiceReference InlineScript="true" Path="~/PersonService.asmx" />

        Services>

    asp:ScriptManager>

    <script type="text/javascript">

        var mapper =

        {

            AddFirstNameId:"FirstName",

            AddLastNameId:"LastName",

            EditFirstNameId:"EditFirstName",

            EditLastNameId:"EditLastName",

            EditPersonId:"PersonId",

            SaveButtonId:"SaveButton",

            LoadButtonId:"LoadButton",

            AddNewButtonId:"AddNewButton",

            StatusId:"Status"

           

        };

    script>

 

    <script src="scripts/AjaxExample.js" type="text/javascript">script>

 

    form>

body>

html>

And AjaxExample.js

// This file requires a ScriptManager and a object named mapper with the appropriate values set

/*

var mapper =

        {

            AddFirstNameId:"FirstName",

            AddLastNameId:"LastName",

            EditFirstNameId:"EditFirstName",

            EditLastNameId:"EditLastName",

            EditPersonId:"PersonID",

            SaveButtonId:"SaveButton",

            LoadButtonId:"LoadButton",

            AddNewButtonId:"AddNewButton",

            StatusId:"Status"

           

        };

*/

$addHandler(window,"load",ajaxOnload);

function ajaxOnload()

{

    $addHandler($get(mapper.SaveButtonId),"click",editPerson);

    $addHandler($get(mapper.LoadButtonId),"click",loadPerson);

    $addHandler($get(mapper.AddNewButtonId),"click",addPerson);

}

function addPerson()

{

   savePerson($v(mapper.AddFirstNameId),$v(mapper.AddLastNameId),null);

}

function editPerson()

{

    savePerson($v(mapper.EditFirstNameId),$v(mapper.EditLastNameId),$v(mapper.EditPersonId));

}

function savePerson(firstName,lastName,personId)

{

    status("");

    var view = new PersonView();

    view.FirstName = firstName;

    view.LastName = lastName;

    view.PersonId = personId;

    PersonService.SavePerson(view,onSavedSuccess,onFailed);

}

function onSavedSuccess(view)

{

    status("Person " + view.PersonId + " Saved.");

    $s(mapper.AddFirstNameId,"");

    $s(mapper.AddLastNameId,"");

}

function loadPerson()

{

    status("");

    $s(mapper.EditFirstNameId,"");

    $s(mapper.EditLastNameId,"");

    var view = new PersonView();

    view.PersonId = $v(mapper.EditPersonId);

    PersonService.LoadPerson(view,onPersonLoadSuccess,onFailed);

}

function onPersonLoadSuccess(view)

{

   

    $s(mapper.EditFirstNameId,view.FirstName);

    $s(mapper.EditLastNameId,view.LastName);

}

function onFailed(err)

{

   status(err.get_message());

}

//Silly utility functions

function $v(id)

{

    return $get(id).value;

}

function $s(id,val)

{

    $get(id).value = val;

}

function status(message)

{

    $get(mapper.StatusId).innerHTML = message;

}

MS Ajax.Net makes wiring up the View easy enough, and once again, everything just works since we’ve tested it all through unit tests…

I hope you liked the example. I’ve really found that TDD makes my job as a developer much more fun, and by making builds run unit tests, we essentially make run time errors compile time errors.  It also ends up saving time, since we’re debugging in NUnit, and not using a UI.

Download complete solution
Run Webform implementation
Run Ajax implementation