Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I like Clean Architecture. There is a particularly annoying, but powerful piece: the Presenter. While it makes for some awkward code, it does separate concerns.

The controller has a use case, which is the business logic, injected into it. The controller also has the Presenter injected into it. The controller invokes like so: UseCase.execute(input, Presenter).

The use case does its thing. Then calls presenter.present(ResultData). The presenter can be responsible for creating the actual response on the wire. It is also responsible for getting data from the database for lists, and other UI features. Finally, the Presenter invokes whatever machinations are required write update the client. In the case of HTML, the presenter knows which template to invoke. In JSON, just serialize the output.

What's awkward about it is the .present when in failure, which in Go is all the time.

if err != nil { presenter.present(FailureStruct) return }

This is repeated all over the place. That return is important. Since the result is not returned from the UseCase, getting this wrong could lead to failure.

In my code, the Unit of Work is managed by two entities: the controller and the presenter. The controller gets everything warmed up. The presenter knows when all the data calls complete. If the presenter is for an HTML page that needs to get data, the presenter is essentially a micro controller that couples the use case to the view.

All of this is tucked away nicely. The domain gets to drive a lot. Everything is testable since the presenter is

type CreateUserPresenter interface { present(Output) }

Interfaces for everyone. Use Case has interfaces for the domain repositories it needs. Controller gets injected, or in my case calls a factory, the use case and presenter.

Things are actually decoupled. No more transaction scripts spread across multiple thinly veiled layers.



Why is the result not returned from the use case?


To truly seperate the controller from the process of invoking the use case and view. A better question is why does the use case have the presenter pushed as part of the invocation? You could easily have a use case take an input and nothing else. Why have the controller get an instance of the presenter, pass that to the use case, then have the use case call the presenter? The answer is that it makes explicit the fact that there will be a response. It also allows the controller to either directly, or indirectly, more likely indirectly, get the UI component ready.

In my codes case, the presenter is gained through a factory method. The factory takes the response for the request, context and that's it. It creates the REST response handler that holds onto the response struct, in Go. This allows the system to safely switch the thread underneath the actual request/response of the handler. Since the Use Case gets the presenter as an argument, it naturally carries the presenter when the thread changes without having to store it into the Context.

All of this fits nicely with Go. Go handlers return void. So in the handler, my controller, the use case kicks off, and the handler is done. The presenter sets the response code, body, and anything else.

For more information. https://softwareengineering.stackexchange.com/questions/3570...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: