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 ports/adapters 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.
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);
}
}
This 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).
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 moment, 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.
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?
In this answer to another question, Robert Martin describes exactly a use case where the interactor calls the presenter upon a read request. No mention of MVC, MVVC, etc. can be found, so I guess that the Clean Architecture doesn't play very well with MVC in general?
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.
A possible explanation would be 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. Thus, here the model is not calling the presenter, because the interactor is not the model, but rather the actual implementation of the controller. The model is just the data structure being passed around. This seems to be confirmed by:
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. Since the controller must just be a thin adapter converting one data format to another, it must not contain any application logic, which is thus moved to the interactor.
The article says that the Use-Case is independet of the gui (presenter) so it is the job of the Controller to talk to usecase (aka service or workflow) and presenter
[update 2017-08-29]
if the model uses a presenter-interface this is not a clean mvc, mvp or mvvm architecture any more but something else.