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.
First, let me strongly recommend that you read Robert Martin's book titled Clean Architecture if you haven't.
I assume that you have read it, but I don't know for sure, because many questions that are very similar to yours were asked before he even published said book.
If you have read his book, then go back and take a look at Chapter 26: 'The Main Component' again.
If you don't own the book (and for anybody else who doesn't), let me summarize the given chapter for you.
The first few paragraphs of the chapter say:
In every system, there is at least one component that creates, coordinates, and oversees the others. I call this component main.
The Main component is the ultimate detail--the lowest-level policy. It is the initial entry point of the system. Nothing, other than the operating system, depends on it. Its job is to create all the Factories, Strategies, and other global facilities, and then hand control over to the high-level abstract portions of the system.
And the 'Conclusion' section of that chapter says:
Think of Main as a plugin to the application--a plugin that sets up the initial conditions and configurations, gathers all the outside resources, and then hands control over to the high-level policy of the application.
Let me specify something really quick. I will mention (and already have mentioned) the word 'component', but technically a component is not a thing in the sense of code.
Put simply (maybe too simply), a 'component' is just the word that Uncle Bob uses to refer to what is essentially a group of related code/code files (refer to his book if you want his actual definition).
Therefore, when I speak about a 'component', remember that I am actually talking about the code within that 'component'.
How then does one component depend on another then?
Well, according to Uncle Bob, a component (a grouping of code) dependency is created any time you reference anything in a different component; whether that be an interface, a type definition, or even a simple variable name.
Keep this in mind, because technically a component cannot be injected into another.
When I speak of injecting one component into another, I am almost always talking about dependency injection specifically on the level of the interfaces/classes that are contained in those components.
Now, back to the quotes: those mean that the Main component, which is the entry point of your program (such as the 'main' file in C++, or the first file to run in your NodeJS server, for example), should either instantiate the concrete classes and give ('inject' is the technical term for it) them to the dependents, or should give the dependents a Factory (which is a design pattern for those of you who don't know) whereby they can instantiate the concrete classes themselves.
In Chapter 14: 'Component Coupling' of Robert Martin's book, he provides an image that I think illustrates the topic of Chapter 26 very nicely:
Note: This is a Component dependency graph.
Notice how many components 'Main' depends on but also notice how absolutely no components depend on 'Main'.
This is because the 'Main' component does all the wiring together of all the other components, so that they don't have to know about each others' concrete class implementations but can instead depend only on the interfaces/abstractions.
Now that you (hopefully) have a basic understanding of what I'm trying to say, let's discuss the order in which dependency injection happens.
Note: It is important to be reminded that I am talking exclusively in the context of interfaces/classes after this point.
The order in which you create and inject the dependencies into each other depends (pun not intended) on two things:
- The dependency injection mechanism;
If you inject the dependencies through the constructor, then obviously the dependencies must be created before the dependent and injected into the dependent during its creation.
However, if you can inject the dependencies through a method on the dependent, then obviously the dependency can be created after the dependent and simply injected then.
If you are using an injection mechanism that can be done at any point (such as through a method), then the next point doesn't really apply.
- The kinds of the dependencies.
Are the dependencies using dependencies, or are they implementing/inheriting dependencies?
For example, imagine that a concrete class inside of Component B
uses an interface from Component A
.
This means that the concrete class is expecting the interface to be implemented elsewhere by a different class.
It is only using the interface, not inheriting from it.
Now imagine that Component C
has a concrete class in it that uses an interface that is in the same component as itself.
This concrete class does not implement said interface, it only uses it:
The implementation for the interface actually resides in Component D
:
Let me phrase this again: Within Component C
, a concrete class uses an interface, but that interface is actually implemented in Component D
.
The 'uses' and 'implements' relationships are both equally dependencies, but this is the important part: when it comes to the order in which dependencies should be injected, only the 'uses' relationships matter.
Let me illustrate that statement with an example:
First, let's imagine that you have a dependency graph that looks like this:
As I said earlier, the only relationships we're looking for in this context are the uses relationships, so consider only the black arrows.
Component #4
depends on Component #3
;
Component #4
depends on Component #2
which depends on Component #1
;
Let's imagine that we're injecting all of the dependencies through constructors.
In pseudo-code, the Main component would look something like:
// Instantiate the concrete implementation within Component #1:
implementation1 = new Implementation1()
// Instantiate the concrete implementation within Component #2 while injecting its dependency into it:
implementation2 = new Implementation2(implementation1)
// Instantiate the concrete implementation within Component #3:
implementation3 = new Implementation3()
// Instantiate the concrete class within Component #4 while injecting both of its dependencies into it:
implementation4 = new Implementation4(implementation2, implementation3)
// Okay, everything has been wired together, now hand control off to your highest level application logic.
It's important to note that Implementation3
could have easily been instantiated before Implementation1
and Implementation2
, but I decided to instantiate them in numerical order, because it is easier to think about that way.
Best Answer
An understandable misunderstanding
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 callsAddProductToBasketInteractor.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.