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.
That's certainly not Clean, Onion, or Hexagonal Architecture. That is this:
Not that MVC has to be done that way
You can use many different ways to communicate between modules and call it MVC. Telling me something uses MVC doesn't really tell me how the components communicate. That isn't standardized. All it tells me is that there are at least three components focused on their three responsibilities.
Some of those ways have been given different names:
And every one of those can justifiably be called MVC.
Anyway, none of those really capture what the buzzword architectures (Clean, Onion, and Hex) are all asking you to do.
Add the data structures being flung around (and flip it upside down for some reason) and you get:
One thing that should be clear here is that the response model does not go marching through the controller.
If you are eagle eye'd, you might have noticed that only the buzzword architectures completely avoid circular dependencies. That means the impact of a code change won't spread by cycling through components. The change will stop when it hits code that doesn't care about it.
Wonder if they turned it upside down so that the flow of control would go through clockwise. More on that, and these "white" arrow heads, later.
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?
Since communication from Controller to Presenter is meant to go through the application "layer" then yes making the Controller do part of the Presenters job is likely a leak. This is my chief criticism of VIPER architecture.
Why separating these is so important could probably be best understood by studying Command Query Responsibility Segregation.
#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.
It's the API that you send output through, for this particular use case. It's no more than that. The interactor for this use case doesn't need to know, nor want to know, if output is going to a GUI, a CLI, a log, or an audio speaker. All the interactor needs to know is the very simplest API possible that will let it report the results of it's work.
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.
The reason the output port is different from the input port is that it must not be OWNED by the layer that it abstracts. That is, the layer that it abstracts must not be allowed to dictate changes to it. Only the application layer and it's author should decide that the output port can change.
This is in contrast to the input port which is owned by the layer it abstracts. Only the application layer author should decide if it's input port should change.
Following these rules preserves the idea that the application layer, or any inner layer, does not know anything at all about the outer layers.
#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).
The important thing about that "white" arrow is that it lets you do this:
You can let the flow of control go in the opposite direction of dependency! That means the inner layer doesn't have to know about the outer layer and yet you can dive into the inner layer and come back out!
Doing that has nothing to do with using the "interface" keyword. You could do this with an abstract class. Heck you could do it with a (ick) concrete class so long as it can be extended. It's simply nice to do it with something that focuses only on defining the API that Presenter must implement. The open arrow is only asking for polymorphism. What kind is up to you.
Why reversing the direction of that dependency is so important can be learned by studying the Dependency Inversion Principle. I mapped that principle onto these diagrams here.
#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.
No that's really it. The point of making sure the inner layers don't know about the outer layers is that we can remove, replace, or refactor the outer layers confident that doing so wont break anything in the inner layers. What they don't know about won't hurt them. If we can do that we can change the outer ones to whatever we want.
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.
The problem here is now whatever knows how to ask for the data has to also be the thing that accepts the data. Before the Controller could call the Usecase Interactor blissfully unaware of what the Response Model would look like, where it should go, and, heh, how to present it.
Again, please study Command Query Responsibility Segregation to see why that's important.
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.
Yes! Telling, not asking, will help keep this object oriented rather than procedural.
#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?
Anything that works is viable. But I wouldn't say that the second option you presented faithfully follows Clean Architecture. It might be something that works. But it's not what Clean Architecture asks for.
An understandable misunderstanding
The interactor executes a usecase dependent on the message.
You actually got the words right, but I'm seeing from your graphic that this can be interpreted in 2 different ways. You interpreted it as
"The interactor chooses a usecase dependent on the message."
But it's rather
"The interactor executes a use case with the data from the message."
In your defense, the terminology can be confusing and sometimes different names are used to describe the same things.
An interactor represents a use case, not a list of use cases
In a way, an "Interactor" is a "use case". This is way easier to explain with an example though.
Imagine a web shop. In a business sense, you have the use case "add a product to the basket." The "recipe" for what happens in that use case is written down in a AddProductToBasketInteractor
.
Now your user enters a number and presses a button in the outer "frameworks and drivers" layer. That layer passes the raw information on to your controller.
The controller puts the product ID and the number for the amount into a AddProductToBasketRequest
- that's your "message". Then it calls AddProductToBasketInteractor.Execute(AddProductToBasketRequest)
.
Dependent on the message
Now, "executes a usecase dependent on the message" just means that what the interactor does has to do with the input it gets.
For example, how many products to add is dependent on the data in the message.
Maybe if the customer adds 10, they get 5% off.
Maybe the product ID does not exist, so it never actually changes the basket and returns an AddProductToBasketResult
with an error flag.
No list of interactors
Your interactors "stand alone", they don't have to be put into a list of use cases.
An interactor coordinates "workers" in the "interface adapters" layer, so that a use case (the business term) happens.
Best Answer
This picture shows a generalized view of various elements that form the components and the interfaces between the layers. When I say interfaces, I don't mean the interface types (like in C# and Java, represented in UML by the
<<interface>>
stereotype), but I use the term in a more general way - to denote the set of public (externally visible) elements exposed by a software component (so, public methods and properties in the case of a class, or the set of "surface level" classes of a component or a layer, etc.). The diagram is generalized in the sense that you don't have to have all the elements on it as classes in your program. You'll see what I mean in a moment.So, the interface (in the sense described above) of the Use Case Interactor consists of two things - the Input Port interface type and the Request Model data structure. The Request Model is the input to the Interactor that goes through the input port; this doesn't have to be a class or a data structure, it could just be the list of parameters to a method defined on the input port - but is shown here in a more generalized way as its own thing. The Controller interprets the request (from the view), figures out what it means in terms of the business logic and the supported use cases, and then calls the appropriate method on the appropriate use case, with the appropriate parameters (so it either constructs a parameter list or an instance of the Request Model structure) - this is how the "request" (reinterpreted in the context of a given use case) is passed on.
Now, note that the Request Model is conceptually owned and defined by the use case, it's part of its interface (the so called provided interface), and that it has to be on that side of the architectural boundary, in order for the use case layer to remain independent of the upper layers (the rule about the direction of the dependencies). The contract between the layers there is that the Use Case is sort of saying "here, I provide these methods and these data structures for them to use as input if you need to use the services I offer".
Similarly, the Output Port interface type and the Response Model data structure form together an interface for an extension point (a so called required interface). I.e., this is a place where you can take some behavior and plug it into the use case. This is what the Presenter does by implementing the Output Port; this allows the use case to call the Presenter without ever knowing that it even exists. This is classic dependency inversion, and again, it controls the direction of the coupling across the architectural boundary. Again, the Response Model could be a separate data structure or simply a list of parameters. The contract defined by the use case is "you can plug in here by implementing this interface, and I'll call you and provide data using these data structures".
Now, one point of possible confusion is that in a real application, you won't usually have things named like "OutputPort" or "UseCaseInteractor". These are just generic names used to talk about these concepts. A Use Case Interactor will have some meaningful name, e.g. "Reservations" (well, meaningful in the context of the domain that's being modeled); the Output Port could be an interface called "IReservationsObserver", and anything that wanted to observe interesting changes would implement that interface and register itself with the Reservations object (this is just one possibility, don't take that as a rule - it's an example off the top of my head, based on the Observer Pattern). The Input Port could be an interface called "IReservations" that would provide reservations-related methods; maybe something like "MakeReservation(ReservationRequestDetails details)", where "ReservationRequestDetails" is the Request Model (a data model for the specific use case scenario).
The (green, presentation layer) Request is a part of the Controller's interface (it's conceptually owned by the Controller)2. Often, the data it contains will not be in a suitable format for the use case layer (say, numbers could be represented as strings, or it may contain presentation-specific fields that make no sense in other layers); the Controller takes that, and then uses it as a basis to construct a (red, use case layer) Request Model that more directly expresses the input to the use case.
Also, just to be clear, there generally isn't just one Use Case Interactor that handles all the use cases. Also, as you've seen by now, you shouldn't take the diagram too literally; the Use Case Interactor box could represent one class, but it could also be a stand-in for a small group of collaborating classes. In the same vain, the Request and Response models could actually represent a group of types that serve as parameters to various methods on the external boundary of the use case.
You don't have to do that; what you want to do is to control the direction and the number of dependencies between the layers. The outer layer depends on anything that it directly references from the inner layer (any of the types or any other elements1 from the inner layer that it uses in any way - as a service, for internal logic, parameters, etc.). These referenced types/elements form the "outer surface" - the exposed public interface of the inner layer. These have to be relatively stable against changes; if you make changes to those, they will propagate to the outer layer, because it directly depends on them. Behind this "outer surface" the inner layer is effectively encapsulated, so you can restructure and refactor it.
Now, in the image you've provided, the dependency structure is such that the presentation layer does not have any knowledge of the concrete Use Case Interactor, which means that it's internal to the Use Cases layer, and that you can fiddle with it more or less without affecting the outer components. But you don't have to have that exact dependency structure. The Input Port doesn't have to be an interface type, it could be a concrete or an abstract base class, or you may opt to not have it at all. In the latter case, the Controller would directly depend on the Interactor, which would make the Interactor part of the "surface level" types. Then if you wanted to change or reorganize the internal implementation, you would make sure to not make changes to the public elements of the Interactor, and, if the changes are more involved, you would maybe extract a subset of its code into a new class during refactoring - which would then lead to the structure similar to the one on the diagram - except what was your Interactor would now assume the role of, say, the Input Port.
I hope you see that use cases are objects designed to do specific things (support specific usage scenarios), so in general there's no much point in making a generic interface for a group of them (that's not the idea), although it may make sense to do so in specific cases.
1 "other elements" could be anything that's part of the "contract" between the two layers - an expectation that certain data will have a particular structure (even though it isn't explicitly defined as a type), a convention of some sort, etc.
2 The View/ViewModel/Controller part of this diagram is a little ambiguous; the exact dependency structure there depends on the MVC/MVP variant used. The View may have a direct reference to the Controller, for example (in order to call it and pass the Request). Or not - maybe the Controller polls or subscribes to an event queue that's not shown. The interaction between the View and the ViewModel may be supported by the data-binding mechanism of the framework used. The Presenter could be merged with the ViewModel, or even with the Controller, etc.