Presenter и Repository

Использую Dagger2 и Moxy для MVP. Как я понял, Presenter может обращаться к Repository для загрузки и выгрузки данных из БД. Но я никак не могу понять, как следует создавать экземпляр репозитория: в Activity с помощью Dagger-а и передавать в презентер или в самом презентере?

Clean Architecture: Use case containing the presenter or returning data?

The Clean Architecture suggests to let a use case interactor call the actual implementation of the presenter (which is injected, following the DIP) to handle the response/display. However, I see people implementing this architecture, returning the output data from the interactor, and then let the controller (in the adapter layer) decide how to handle it. Is the second solution leaking application responsibilities out of the application layer, in addition to not clearly defining input and output ports to the interactor?

Input and output ports

Considering the Clean Architecture definition, and especially the little flow diagram describing relationships between a controller, a use case interactor, and a presenter, I’m not sure if I correctly understand what the “Use Case Output Port” should be.

Clean architecture, like hexagonal architecture, distinguishes between primary ports (methods) and secondary ports (interfaces to be implemented by adapters). Following the communication flow, I expect the “Use Case Input Port” to be a primary port (thus, just a method), and the “Use Case Output Port” an interface to be implemented, perhaps a constructor argument taking the actual adapter, so that the interactor can use it.

Code example

To make a code example, this could be the controller code:

Presenter presenter = new Presenter(); Repository repository = new Repository(); UseCase useCase = new UseCase(presenter, repository); useCase->doSomething(); 

The presenter interface:

// Use Case Output Port interface Presenter {     public void present(Data data); } 

Finally, the interactor itself:

class UseCase {     private Repository repository;     private Presenter presenter;      public UseCase(Repository repository, Presenter presenter)     {         this.repository = repository;         this.presenter = presenter;     }      // Use Case Input Port     public void doSomething()     {         Data data = this.repository.getData();         this.presenter.present(data);     } } 

On the interactor calling the presenter

The previous interpretation seems to be confirmed by the aforementioned diagram itself, where the relation between the controller and the input port is represented by a solid arrow with a “sharp” head (UML for “association”, meaning “has a”, where the controller “has a” use case), while the relation between the presenter and the output port is represented by a solid arrow with a “white” head (UML for “inheritance”, which is not the one for “implementation”, but probably that’s the meaning anyway).

Furthermore, in this answer to another question, Robert Martin describes exactly a use case where the interactor calls the presenter upon a read request:

Clicking on the map causes either the placePinController to be invoked. It gathers the location of the click, and any other contextual data, constructs a placePinRequest data structure and passes it to the PlacePinInteractor which checks the location of the pin, validates it if necessary, create a Place entity to record the pin, constructs a EditPlaceReponse object and passes it to the EditPlacePresenter which brings up the place editor screen.

To make this play well with MVC, I could think that the application logic that traditionally would go into the controller, here is moved to the interactor, because we don’t want any application logic to leak outside the application layer. The controller in the adapters layer would just call the interactor, and maybe do some minor data format conversion in the process:

The software in this layer is a set of adapters that convert data from the format most convenient for the use cases and entities, to the format most convenient for some external agency such as the Database or the Web.

from the original article, talking about Interface Adapters.

On the interactor returning data

However, my problem with this approach is that the use case must take care of the presentation itself. Now, I see that the purpose of the Presenter interface is to be abstract enough to represent several different types of presenters (GUI, Web, CLI, etc.), and that it really just means “output”, which is something a use case might very well have, but still I’m not totally confident with it.

Now, looking around the Web for applications of the clean architecture, I seem to only find people interpreting the output port as a method returning some DTO. This would be something like:

Repository repository = new Repository(); UseCase useCase = new UseCase(repository); Data data = useCase.getData(); Presenter presenter = new Presenter(); presenter.present(data);  // I'm omitting the changes to the classes, which are fairly obvious 

This is attractive because we’re moving the responsibility of “calling” the presentation out of the use case, so the use case doesn’t concern itself with knowing what to do with the data anymore, rather just with providing the data. Also, in this case we’re still not breaking the dependency rule, because the use case still doesn’t know anything about the outer layer.

However, the use case doesn’t control the moment when the actual presentation is performed anymore (which may be useful, for example to do additional stuff at that point, like logging, or to abort it altogether if necessary). Also, notice that we lost the Use Case Input Port, because now the controller is only using the getData() method (which is our new output port). Furthermore, it looks to me that we’re breaking the “tell, don’t ask” principle here, because we’re asking the interactor for some data to do something with it, rather than telling it to do the actual thing in the first place.

To the point

So, is any of these two alternatives the “correct” interpretation of the Use Case Output Port according to the Clean Architecture? Are they both viable?

Clean Architecture: May the Controller talk to the Presenter directly?

From what I understand from the ‘Clean Architecture’, the controller determines which usecase to execute dependent on the input of the user. If the input from the CLI for example is invalid, the controller already knows that something is wrong, so that the controller could directly talk to the presenter in order to show an error or does this violate anything? The following options I have in mind:

  1. The controller could have an extra usecase for that, so that the interactor sends a message to the Presenter. This seems to be like a detour. Is the idea of an extra usecase for wrong inputs in that case correct?

  2. The Controller could directly talk to the presenter or would that violate something, because the presenter would depend on the controller.

What is the idea of the ‘Clean Architecture’ in that case?