views:

218

answers:

1

Hi,

I'm working on .NET 3.5 form application with slightly complicated behaviour. It's for a book inventory. To give you an idea, a workflow would be:

  • The user enters an ISBN code
  • If the ISBN is valid, check whether it exists,
  • If it's valid and it exists, show book details and enable save button, if not, show 'add book'-button,
  • If it's not valid, show error,
  • Eventually, the user will click 'save', so the entry will have to be saved.

That's four responsibilities:

  • Validate ISBN,
  • Check book existence,
  • Show book details,
  • Save new book details.

My question is: Should I keep the application logic in one MVP-structure or should I split it into four MVP-structures, one for each responsibility?

Keeping it in one MVP-structure would

  • make the model more complicated
  • make the tests setup more complicated (lots of setup code for each test to choose the right validator,returned book etc. even if they're not used),
  • make the presentation logic easier to follow

Keeping it in separate MVP-structures would

  • make the model simpler,
  • create more but simpler tests for each presenter,
  • put complexity in the interactions between the presenters (how would I signal a presenter that an ISBN is valid so that book details can be shown?)

I'm trying for the Presenter First-principles, so: - Keep the view dumb (so no events like "Presenter one validated the ISBN"), - Keep the presenters stateless, - Keep the models simple (enough)

Anyone has an idea on what's the best way to do this?

+1  A: 

I would go with one Presenter but delegate the validation etc of ISBN numbers to a Service.

Something along these lines in the presenter to handle an ISBN being entered:

public void IsbnEntered()
{
    var isbn = view.Isbn;

    if (isbnService.NumberIsValid(isbn))
    {
        var details = isbnService.RetrieveDetailsForIsbn(isbn);

        if (details != null)
        {
            view.Display(details);
            view.EnableSaveButton();
        }
        else
        {
            view.DisplayError("ISBN could not be found");
        }
    }
    else
    {
        view.DisplayError("Invalid ISBN");
    }
}

Here the responsibilities are well defined. The IsbnService is responsible for ISBN handling, the View for display and input retrieval and the Presenter manages the interaction between the two.

Garry Shutler
This is my current approach (except that I have a separate isbn verifier and item loader), but this of course means that I have to initialize all kinds of mock services to test this behaviour in the presenter, even if some mocks are never used. That quickly gets old :)Any idea on that?
Lennaert
I'd have a separate verifier and loader too, but kept it a little simpler for the example. You could use an auto mocking container http://www.lostechies.com/blogs/joshuaflanagan/archive/2009/02/03/auto-mocking-explained.aspx as that will create all the dependencies you need, then you only have to...
Garry Shutler
worry about setting up the mocks you will actually use in your test, the others will be created for you and never be used. Along with the AAA test style this has streamlined my tests a lot. Another approach I've used is a test base class per controller, then you only establish the dependencies once.
Garry Shutler