ivanpaulovich/clean-architecture-manga

Output port as argument in execute method

dotarj opened this issue · 2 comments

Hello Ivan,

First of all, thank you very much this repository. Your project perfectly resembles the components that are described in the presentation of Robert C. Martin about clean architecture (https://youtu.be/Nsjsiz2A9mg).

We've set up our first application using this architecture (the version before the mediator was introduced). One of the things we're having discussions about is that it feels a bit magic that the controller executes the use case and then gets the response from the presenter. There is no coupling between the use case interface and the output port interface, which is probably by design, but makes it a bit vague to use. You have to assume that the result of the use case is written to the presenter.

Another approach that we've discussed here is to pass the output port as an argument to the execute method of the use case (considering that we don't use the mediator pattern for executing use cases). This makes explicit that the use case uses the output port to write the results, but of course, couples the use case interface to the output port interface.

What are your thoughts on this?

Hey @dotarj,

First of all, thank you very much this repository. Your project perfectly resembles the components that are described in the presentation of Robert C. Martin about clean architecture

Good to hear that! I fell like mission accomplished :)

There is no coupling between the use case interface and the output port interface, which is probably by design, but makes it a bit vague to use.

Just to clarify there is a coupling set at the DI layer, both Controller and the UseCase instances should use the same Presenter object, The code is similar to this:

services.AddControllers().AddControllersAsServices();
services.AddScoped<DepositPresenter, DepositPresenter>();
services.AddScoped<IOutputPort>(x => x.GetRequiredService<DepositPresenter>());

Another approach that we've discussed here is to pass the output port as an argument to the execute method of the use case (considering that we don't use the mediator pattern for executing use cases)

@unclebob is passing the Presenter as an argument in his sample project, so it should be adherent with his principles:

public interface CodecastSummariesInputBoundary
{
  void summarizeCodecasts(User loggedInUser, CodecastSummariesOutputBoundary presenter);
}

My thoughts are that I prefer Constructor Injection instead of Method Injection when it is possible just because I used to to this way.

Considering that you are working on a team that prefer "passing the presenter as an object", just stick to that because you are already far ahead on the software architecture. You can change it to the constructor injection when the magic behind fade away with time.

I think we will move to method injection as this makes the use case and output port relation a bit more explicit from the controllers perspective.

Thanks for the quick reply!