I am trying to implement VIPER architecture on iOS in Swift.
The problem I have is how to set up the object graph. Please ignore the Router and the Entity as it is not relevant to my problem. That leaves us with the Interactor, Presenter, and the View.
Interactor - business logic, has state, does work, accepts commands. Presenter - transforms abstract data to presentation format, or ask interactor to do work. View - presents presentable info, sends actions to Presenter to translate to business logic requests.
The communication between these three components is bidirectional and the Interactor and View are not aware of each other:
Interactor <-> Presenter <-> View.
All are defined as protocols. (interfaces in other languages...) Each concrete component conforms to its corresponding a protocol (i.e. implements an interface)...and those components only see each other as interfaces.
Here comes the problem:
For the presenter to work correctly, it simply has to have a reference to an Interactor instance where the business logic and state sits. Same goes for the View, it cannot work correctly without a reference to a properly initialized Presenter instance.
I have two options:
OPTION A: 1) The presenter will have a required initializer which will take in an interactor instance. 2) The view will have a required initializer which will take in a presenter instance. 3) I will enforce this in protocols.
OPTION B: 1) There will be a public .interactor variable on the presenter, and this will be settable on a presenter instance. 2) There will be a public .presenter variable on the view, and this will be settable in a view instance.
Option A with initializers gives me a mechanism that ensures things are set up in the right order and they are initialized to a valid state. However, this leads to having to replicate the same mechanism in unit testing where mocks, stub implementations of those protocols actually have to have those initializers and initialize with each other..that means now I have a chain of mocks depending on each other which smells.
Option B prevents the problem with a chain of mocks, but then I will potentially have objects in invalid state, or I have to actually unit-test the router methods that sets up the dependency chain. But then I will be able to only deal with one layer of mocks for each unit test case. At least in theory I think, I haven't try that yet.
Which approach is correct? Or is there some other approach? Can you advise please?