Clean Architecture: Should each view have its own presenter and viewmodel?
https://softwareengineering.stackexchange.com/questions/408326
-
09-03-2021 - |
문제
I am still thinking about clean architecture and just ran into a question regarding the higher levels (Views and Presenters) I am posting Uncle Bobs picture first here that you remember what I am talking about:
Lets say I have a small application where CRUD operations can be performed for customers.
Lets also say there are three ways to output the customer data to the user:
- A form component, where a new customer with name and birthdate can be updated.
(The same form is also used to create a new customer, but in this case I do not need to load existing data)
- A detail component where the name and birthdate of the customer are shown on the screen.
- A PDF-Export where a customer should be displayed in a PDF with the birthdate in US-Format. If the customer is exactly 60 years old, the birthdate should be decorated with special color - these customers get a present. :)
Now lets say I want to implement this. My approach for this looks like this:
You can see that I have only one class for output data (one file) and also just one abtract presenter class that gets the OutputData.
But then I have three concrete presenters with three concrete view models that are responsible for my views. Now my doubts:
Is this correct? Did I understand the clean architecture?
My concrete presenters and my viewmodels for the HTML form and the HTML detail are exactly the same. This feels redundant. Should I avoid this and re-use my view models for both scenarios? Or should I stick with the borders, as the requirements of the future might change for forms, so that I need seperate models/concrete presenters?
If I finally want no US-Format in the date anymore, but lets say... european one. Do I need a new concrete presenter, just for this? Or should the presenter ask the use-case for the global format of the application and then decide on the base of that?
If customers that are 60 should receive a birthday present - this logic has to be in a use case. But I am a little lost where this would go... Probably another use case that gets every night all customers from the repository that are 60 and sends a present... ? But this would not relate at all with the decoration in my view model? So the information about the number "60" would be in my viewmodel and my use case? Two redundant times? Or how?
해결책
Is this correct? Did I understand the clean architecture?
If you want to create a solution consistent with clean architecture you have a number of issues.
Dependencies should only cross boundaries going in one direction. That keeps the inside from needing to know about the outside. That means the outside can change and the inside won't care. This also helps keep your object graph acyclical. It keeps code changes from cycling through your code. Instead of dependencies tending to form a maze they they tend to form trees.
My concrete presenters and my viewmodels for the HTML form and the HTML detail are exactly the same. This feels redundant. Should I avoid this and re-use my view models for both scenarios? Or should I stick with the borders, as the requirements of the future might change for forms, so that I need separate models/concrete presenters?
Your View Model
and Output Data
objects shouldn't be the same. If they are that means the Presenter
hasn't done anything useful. It's not the views job to transform how data is presented. That's the presenters job.
If I finally want no US-Format in the date anymore, but lets say... european one. Do I need a new concrete presenter, just for this? Or should the presenter ask the use-case for the global format of the application and then decide on the base of that?
Your Database
, and Entities
should have an agreed on way to store dates. But your Presenters
should be free to present those dates in any form they wish.
If customers that are 60 should receive a birthday present - this logic has to be in a use case. But I am a little lost where this would go... Probably another use case that gets every night all customers from the repository that are 60 and sends a present... ? But this would not relate at all with the decoration in my view model? So the information about the number "60" would be in my viewmodel and my use case? Two redundant times? Or how?
If a user typed in a date, or selected today's date, and sent that date to the correct Controller
it would build an Input Data
with that date in it, using a way to express dates that the Controller
and Use Case
agree on.
The Controller
then calls the correct Use Case Interactor
and passes the Input Data
. The Use Case Interactor
uses either the Entities
or the Data Access
(or both) to get a list of people with birthdays on this date and uses that list to build Output Data
. Output Data
need not be a result set. It can conform to any structure that the Use Case
and Presenter
agree on. It may simply be a collection.
The Use Case
calls the Presenter
and passes the Output Data
. The Presenter
is now free to put last name first, first name first, draft happy birthday emails to be sent to each person, or send one email with a list of these people to a florist. Which one it does depends entirely on which presenter you configured to receive this.
Views should not do real work. They should be striped of interesting logic and simply be things you throw data at. Data that is already in its final form.