Question 1: What is the correct way to build a Use Case (or more than one) with 2 ways to do the same action?
For example:
I have a 3 screens in an iOS app:
1. A map view, which can be "long pressed" and has a camera button.
2. A camera view, which is shown if the user taps the camera button in the map view.
3. A place/pin editing view, which is shown if the user "long presses" the map view, or after the user chooses a photo in the camera view. This editing view has a save button to actually create the place with a photo and the location (long press coordinate or current location in case the camera button was presses).
Title: Create Place
Basic flow:
1. User “long press” on the map.
2. App drops a temporary pin and displays the place editing view.
3. User edits the place information and presses save button.
4. App creates the place and save it.
Title: Create Place
Basic flow:
1. User presses plus button.
2. App displays camera view.
3. User takes a picture.
4. App creates place with current location and picture.
UPDATE based on comments exchanged with bhavik.
Question 2: (Based on bhavik's answer)
So I don't need one presenter for one interactor precisely, I can have 1 interactor and 3 presenters/views.
Is that correct?
Question 3: Should my boundary methods for the interactor always return void?
In bhavik's example they are returning something, but in the VIPER blog and the uncle Bob's video they always return void and the result comes in the form of another boundary method that the interactor calls on the presenter/controller.
Question 4: The VIPER way does not use a controller, only a presenter to talk to the interactor, when the uncle Bob's video uses a controller and a presenter for different interactions with the interactor. Which approach should I take?
Question 5: If my Use Case is something like "Go to other screen", should it even have an interactor? Since the current view will tell its presenter what button was pressed (what view to go to) and this current presenter will tell its wireframe "change to this other wireframe".
So, all in all, there is one - and only one - primary actor for each use case.
A use case can have multiple paths to reach the goal; each of them is considered a use case scenario.
There are four different types of use cases: includes, extents, communicates and generalizes.
There are two different types of use cases: business use cases and system use cases. A business use case is a more abstract description that's written in a technology-agnostic way, referring only to the business process being described and the actors that are involved in the activity.
Question 1: What is the correct way to build a Use Case (or more than one) with 2 ways to do the same action?
In VIPER design, you can create two methods in the same Interactor suitable for each primary and alternates of the use case.
Question 2: (Based on bhavik's answer) So I don't need one presenter for one interactor precisely, I can have 1 interactor and 3 presenters/views.
Based on our discussion and your updates, I think I understand it better.
CameraView
.So, you should have single EditPlacePresenter/View
for EditPlaceInteractor
that pass data Place data with or without Photo.
Question 3: Should my boundary methods for the interactor always return void?
In bhavik's example they are returning something, but in the VIPER blog and the uncle Bob's video they always return void and the result comes in the form of another boundary method that the interactor calls on the presenter/controller.
I think you are referring to the below Presenter method that receives results from the Interactor.
- (void)foundUpcomingItems:(NSArray*)upcomingItems
For the above to work, the Interactor will have delegate instances that will be wired/patched through by the Presenter/Controller looking for result or data. This means the Presenter/Controller is tied to Interactor or their reference or return-function-pointer is passed in each Interactor method call. Is that by design?
I think, Interactor should return data as per the use case. For example Interactor should return the EditPlaceResult with success or failure.
This should be part of the use case. If not then, it should not return anything. It will return void and a separate Interactor will be queried by Presenter to check if Map Place was added successfully or not.
References in the blog:
Question 4: The VIPER way does not use a controller, only a presenter to talk to the interactor, when the uncle Bob's video uses a controller and a presenter for different interactions with the interactor. Which approach should I take?
You need to define VIPER routes for following navigation:
MapView
to CameraView
(Use Location)MapView
to EditPlaceView
(Use Coordinate)CameraView
to EditPlaceView
MapView
if successfulAs per the VIPER blog, view controllers and navigation controllers are used by Presenters and Wireframes.
VIPER Wireframe handles Navigation and makes view controllers become lean, mean, view controlling machines.
Basically Wireframe abstracts away navigation controller and instead provides route definition.
Wireframe
Presenter
Question 5: If my Use Case is something like "Go to other screen", should it even have an interactor? Since the current view will tell its presenter what button was pressed (what view to go to) and this current presenter will tell its wireframe "change to this other wireframe".
No. Navigation as part of use case may not need Interactor. It is transition only. The target Presenter may need an Interactor. For example, CameraView/Presenter
does not need Interactor but EditPlaceView
needs to save the place.
Overall: The idea behind architectural patterns is to divide a given software application into interconnected parts, so as to separate internal representations of information from the ways that information is presented to or accepted from the user. MVC, MVP, MVVM, VIPER all focus on isolating View, Logic and Navigation in one way or other.
Architectural patterns are limited in what they intend to decompose. We have to understand that architectural patterns do not decompose or isolate everything. Also if one architectural pattern delegates certain responsibilities to certain part, other does not do that at all probably or assign multiple responsibilities to single part.
We are allowed to extend or limit the isolation and decomposition to the extent that it justifies the cause and does not impose unnecessary separation of concerns that overrun the cost. You can choose to use navigation controllers and your presenter can take dependency on them without Wireframe routes defined. These controllers then will be responsible for the navigation between screens.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With