I am little confused with the benefit of protocols in VIPER architecture. I understand that DI (Dependency Injection) achieved via protocols and helps avoid direct dependency between objects - I Agree.
But i am looking at a real benefit from usage perspective, an example may be - especially how protocols help benefit in unit testing (testing the Interactor portion).
Can't we achieve the same via method Callback's using blocks? Hope someone can help me understand from usage perspective with some example
Cheers
Using a callback, e.g. from the Interactor to the Presenter, can make it harder to test the Presenter.
When writing tests for how the Presenter processes input (sent from the Interactor) your test would have to call some method on the Presenter that would cause the Presenter to make a call on the Interactor, which would cause the Interactor to send data to the Presenter.
By having the Presenter implement a protocol defined by the Interactor, your test can just directly call the appropriate input method on the Presenter.
As far as declaring protocols, I practice TDD in the style of mock roles, not objects (http://www.jmock.org/oopsla2004.pdf). The protocols help provide a better abstraction by focusing on what the object does (its role), not how it does it.
Protocols, on their own, are of little value for the unit tests. Your unit tests will provide test doubles (http://martinfowler.com/bliki/TestDouble.html) for the dependencies of the system under test. Even if you expose dependencies as concrete classes you can still create test doubles for your test.
In Objective-C, you can use a mocking library, such as OCMock (http://ocmock.org), or OCMockito (https://github.com/jonreid/OCMockito), to create stubs, spies, or mocks of the concrete class.
In Swift, you could create your test doubles by subclassing each of the concrete classes used as dependencies.
In short, protocols are not used to ease unit testing, but to describe at a higher level of abstraction, what the application does.
Here is an example of how having the abstract protocols were beneficial after the fact:
I created a protocol to represent the actions a user could perform on a screen, e.g.
ProfileUserActions
, that had actions such aschangeName
, andchangeAddress
. The Presenter implementedProfileUserActions
, and the View accepted aProfileUserActions
as a dependency. When the user tapped a button on screen, the View would send the appropriate message to itsuserActions
object.When I wanted to add analytics, I was able to create a new, independent
ProfileAnalytics
class which also implementedProfileUserActions
. I inserted the analytics object between the View and the Presenter, which allowed the app to capture analytics, without having to modify either the View or the Presenter.