Dans son livre «Clean Architecture», l'oncle Bob dit que le présentateur devrait mettre les données qu'il reçoit dans quelque chose qu'il appelle le «View Model».
Est-ce la même chose que le «ViewModel» du modèle de conception Model-View-ViewModel (MVVM) ou est-ce un simple objet de transfert de données (DTO)?
S'il ne s'agit pas d' un simple DTO, comment est-il lié à la vue? La vue obtient-elle des mises à jour via une relation Observateur?
Je suppose que cela ressemble plus au ViewModel de MVVM, car au chapitre 23 de son livre, Robert Martin dit:
Le travail du présentateur consiste à accepter les données de l'application et à les formater pour la présentation afin que la vue puisse simplement les déplacer à l'écran. Par exemple, si l'application souhaite qu'une date s'affiche dans un champ, elle remettra au présentateur un objet Date. Le présentateur formatera ensuite ces données dans une chaîne appropriée et les placera dans une structure de données simple appelée le modèle de vue, où la vue pourra les trouver.
Cela implique que le View est en quelque sorte connecté au ViewModel, au lieu de simplement le recevoir comme argument de fonction par exemple (comme ce serait le cas avec un DTO).
Une autre raison pour laquelle je pense que c'est parce que si vous regardez l'image, le présentateur utilise le modèle de vue, mais pas la vue. Alors que le présentateur utilise à la fois la limite de sortie et le DTO des données de sortie.
S'il ne s'agit ni d'un DTO ni du ViewModel de MVVM, veuillez préciser de quoi il s'agit.
la source
ViewModel
est un wrapper pourController
,Presenter
etViewModel
dans l'architecture propre de Uncle Bob.Controller
->ICommand
etPresenter
->data-binding mechanism
.Réponses:
Nan.
Ce serait ceci :
Cela a des cycles. L'oncle Bob a soigneusement évité les cycles .
Au lieu de cela, vous avez ceci:
Qui n'a certainement pas de cycles. Mais vous vous demandez comment la vue connaît une mise à jour. Nous y reviendrons dans un instant.
Pour citer Bob de la page précédente:
Alors, bien sûr, si vous le souhaitez.
Mais je soupçonne fortement ce qui vous dérange vraiment, c'est ceci :
Ce joli petit abus d'UML contraste la direction de la dépendance du code source avec la direction du flux de contrôle. C'est là que se trouve la réponse à votre question.
Dans une relation d'utilisation:
le flux de contrôle va dans le même sens que la dépendance du code source.
Dans une relation de mise en œuvre:
le flux de contrôle va généralement dans la direction opposée à la dépendance du code source.
Ce qui signifie que vous regardez vraiment ceci:
Vous devriez être en mesure de voir que le flux de contrôle ne va jamais passer du présentateur à la vue.
Comment est-ce possible? Qu'est-ce que ça veut dire?
Cela signifie que la vue a son propre thread (ce qui n'est pas si inhabituel) ou (comme le souligne @Euphoric) que le flux de contrôle entre dans la vue à partir d'autre chose non représenté ici.
S'il s'agit du même thread, la vue saura quand le modèle de vue sera prêt à être lu. Mais si c'est le cas et que la vue est une interface graphique, il sera difficile de repeindre l'écran lorsque l'utilisateur le déplace pendant qu'il attend la base de données.
Si la vue a son propre thread, elle a son propre flux de contrôle. Cela signifie que pour l'implémenter, la vue devra interroger le modèle de vue pour remarquer les changements.
Puisque le présentateur ne sait pas que la vue existe et que la vue ne sait pas que le présentateur existe, ils ne peuvent pas s’appeler du tout. Ils ne peuvent pas se lancer des événements. Tout ce qui peut arriver, c'est que le présentateur écrira sur le modèle de vue et que la vue lira le modèle de vue. Chaque fois que ça en a envie.
Selon ce diagramme, la seule chose que le partage View et Presenter est la connaissance du View-Model. Et ce n'est qu'une structure de données. Ne vous attendez donc pas à ce qu'il ait un comportement.
Cela peut sembler impossible, mais il peut être fait fonctionner même si le View-Model est complexe. Un petit champ mis à jour est tout ce que la vue devrait interroger pour détecter un changement.
Maintenant, bien sûr, vous pouvez insister pour utiliser le modèle d'observateur, ou demander à quelque chose de structuré de vous cacher ce problème, mais veuillez comprendre que vous n'êtes pas obligé de le faire.
Voici un peu de plaisir que j'ai eu pour illustrer le flux de contrôle:
Notez que chaque fois que vous voyez le flux aller à l'encontre des directions que j'ai définies précédemment, ce que vous voyez est un retour d'appel. Cette astuce ne nous aidera pas à accéder à la vue. Eh bien, sauf si nous revenons d'abord à ce qu'on appelle le contrôleur. Ou vous pouvez simplement changer la conception pour pouvoir accéder à la vue. Cela corrige également ce qui ressemble au début d'un problème de yo-yo avec Data Access et son interface.
La seule autre chose à apprendre ici, en plus de cela, est que l'interacteur de cas d'utilisation peut à peu près appeler les choses dans l'ordre qu'il veut tant qu'il appelle le présentateur en dernier.
la source
Je trouve ce problème trop confus et cela prendrait beaucoup de texte et de temps pour expliquer correctement le problème car je pense que vous comprenez mal Martin's Clean Architecture et MVVM.
La première chose à noter est que le diagramme que vous avez publié est incomplet. Il ne montre que la «logique métier», mais il manque une sorte d '«orchestrateur» qui fait réellement bouger les pièces dans le bon ordre.
Le code de l'orchestrateur serait aussi simple que
Je crois avoir entendu Martin en parler dans l'un de ses discours sur l'architecture propre.
Une autre chose à souligner est que la remarque de candied_orange sur le manque de cycles est fausse. Oui, les cyclés n'existent pas (et ne devraient pas) dans l'architecture du code. Mais les cycles entre les instances d'exécution sont courants et conduisent souvent à une conception plus simple.
C'est le cas dans MVVM. Dans MVVM, View dépend de ViewModel, et ViewModel utilise des événements pour informer View de ses modifications. Cela signifie que dans la conception des classes, il n'y a que des dépendances entre les classes View et Model, mais pendant l'exécution, il y a une dépendance cyclique entre les instances de View et ViewModel. Pour cette raison, il n'y a pas besoin d'orchestrateur, car ViewModel fournira un moyen d'affichage pour savoir quand se mettre à jour. C'est pourquoi les "notifications" dans ce diagramme utilisent une ligne "squigly" et non une ligne directe. Cela signifie que View observe les changements dans ViewModel, et non que ViewModel dépend de View.
La chose la plus importante que vous devriez retenir de Martin's Clean Architecture n'est pas la conception elle-même, mais la façon dont vous gérez les dépendances. L'un des points critiques qu'il soulève dans ses exposés est que lorsqu'il y a une frontière, alors toutes les dépendances de code traversant cette frontière la traversent dans une seule direction. Dans le diagramme, cette frontière est représentée par une double ligne. Et il y a beaucoup d'inversion de dépendance via les interfaces (
InputBoundary
,OutputBoundary
etDataAccessInterface
) qui corrige le sens de dépendance du code.En revanche, l'
ViewModel
architecture propre est tout simplement DTO sans logique. Cela est rendu évident par la<DS>
balise. Et c'est la raison pour laquelleorchestrator
est nécessaire, carView
je ne saurai pas quand exécuter sa logique.Si je devais "aplatir" le diagramme en quoi ressemblerait-il pendant l'exécution, il ressemblerait à ceci:
Ainsi, lors de l'exécution, les dépendances sont dans une "mauvaise" direction, mais c'est très bien.
Je recommande de regarder son discours sur l'architecture propre pour mieux comprendre son raisonnement.
la source