In a previous post, I mentioned that I was rewriting WhatsMySpeed (now called HowsMyFuel and posted publicly on Github) using TDD and the VIP architecture. I’m committing changes at each step of the TDD cycle. I’m exploring to see if commit comments on Git can be used blog style. Let me know if this works for you.
One of the reasons in VIP of separating the ViewController into 3 components (ViewController+Presenter+Interactor) is to eliminate the Massive View Controller, so common in iOS apps. I’m discovering that one of the up sides to doing this is that I can move many of the unit tests from application to logic tests.
View controller tests typically require running in OCUnit application tests. OCUnit application tests are slower, since the app bundle is loaded. I don’t know how much slower yet, but I hope to test this later, as the number of unit tests gets larger.
So what goes into the View Controller vs the Presenter or Interactor? Normally the View Controller does nearly all the work. That’s why iOS view controllers tend to be huge. And huge typically means hard to read, even harder to unit test. However, I’m attempting to reduce the size and complexity of the view controller by removing all business logic. By that, I mean the logic that decides what an event does.
ViewController should contain basic iOS glue stuff; outlets, actions, etc.
Presenter should contain display-specific business logic, without interacting with the models.
Interactor should implement the business logic, aka use cases. It maps model data to the form needed by the Presenter and/or ViewController.
For example, the HowsMyFuel code as of April 25, 2013 contains code to register a tap gesture recognizer, and handle the tap event to recenter the map display when it is tapped. As is often the case, the event handling code is about 5 times the size of the business logic, which obscures the business logic, or intended behavior. To fix that, I’m going to elevate the business logic into the Presenter, where the expected behavior will be made crystal clear (when map is tapped, recenter the display on the user). Since this behavior is related directly to the UI display, I’ll put it in the Presenter. If it was dealing with Model data and/or not UI display specific, then I’d elevate it even higher to the Interactor.