Le principe de responsabilité unique indique que "une classe devrait avoir une raison pour laquelle le changement".
Dans le motif MVC, le travail du contrôleur est de médier entre la vue et le modèle. Il offre une interface pour la vue pour signaler les actions effectuées par l'utilisateur de l'interface graphique (par exemple, permettant à la vue d'appeler controller.specificButtonPressed()
) et est capable d'appeler les méthodes appropriées sur le modèle afin de manipuler ses données. Ou invoquer ses opérations (par exemple, model.doSomething()
).
Cela signifie que:
Cela signifie que c'est deux raisons de changer: une modification de l'interface graphique et une modification de la logique de l'entretien.
Si l'interface graphique change, par exemple Un nouveau bouton est ajouté, le contrôleur peut avoir besoin d'ajouter une nouvelle méthode pour permettre la vue de signaler un utilisateur Appuyez sur ce bouton.
Et si la logique commerciale dans le modèle change, le contrôleur peut avoir à modifier afin d'invoquer les méthodes correctes sur le modèle.
Par conséquent, le contrôleur a deux raisons possibles de changer. Est-ce qu'il casse SRP?
Si vous continuez par conséquent pour raisonner sur le SRP, vous viendrez remarquer que "la responsabilité unique" est en fait un terme spongieux. Notre cerveau humain est en quelque sorte capable de faire la distinction entre différentes responsabilités et les responsabilités multiples peuvent être résumées dans une responsabilité "générale". Par exemple, imaginez dans une famille commune de 4 personnes, un membre de la famille est responsable de la fabrication du petit-déjeuner. Maintenant, pour faire cela, il faut faire bouillir des œufs et du pain grillé et bien sûr mettre en place une tasse saine de thé vert (oui, le thé vert est le meilleur). De cette façon, vous pouvez casser "faire du petit déjeuner" en morceaux plus petits qui sont ensemble résumés pour "faire du petit déjeuner". Notez que chaque pièce est également une responsabilité que par exemple. être délégué à une autre personne.
Retour au MVC: Si la médiation entre le modèle et la vue ne sont pas une responsabilité mais deux, quelle serait la prochaine couche d'abstraction ci-dessus, combinant ces deux? Si vous ne pouvez pas en trouver un, vous n'avez pas non plus résumé correctement ou il n'y en a aucun ce qui signifie que vous avez tout compris. Et je sens que c'est le cas avec un contrôleur, gérant une vue et un modèle.
Si une classe a "deux raisons possibles de changer", alors oui, il viole SRP.
Un contrôleur doit généralement être léger et disposer de la seule responsabilité de manipuler le domaine/modèle en réponse à un événement gigueur de l'interface graphique. Nous pouvons considérer chacune de ces manipulations à utiliser essentiellement des cas ou des caractéristiques.
Si un nouveau bouton est ajouté à l'interface graphique, le contrôleur doit seulement avoir à modifier si ce nouveau bouton représente une nouvelle fonctionnalité (c'est-à-dire opposé à un seul bouton qui existait à l'écran 1 mais n'existait pas encore l'écran 2, et il est alors ajouté à l'écran 2). Il faudrait également être un nouveau changement correspondant dans le modèle pour appuyer cette nouvelle fonctionnalité/fonctionnalité. Le contrôleur a toujours la responsabilité de manipuler le domaine/modèle en réponse à un événement gigueur de l'interface graphique.
Si la logique commerciale dans le modèle change en raison d'un bogue étant corrigé et que le contrôleur modifie, il s'agit donc d'un cas particulier (ou peut-être que le modèle enfreint le capital ouvert). Si la logique commerciale dans le modèle change pour prendre en charge une nouvelle fonctionnalité/fonctionnalité, cela n'a pas nécessairement d'impact sur le contrôleur - uniquement si le contrôleur doit exposer cette fonctionnalité (ce qui serait presque toujours le cas, sinon pourquoi serait-il ajouté à le modèle de domaine s'il ne sera utilisé). Donc, dans ce cas, le contrôleur doit également être modifié, pour prendre en charge la manipulation du modèle de domaine de cette nouvelle manière en réponse à un événement gui-à-plan.
Si le contrôleur doit changer car, disons, la couche de persistance est modifiée à partir d'un fichier plat vers une base de données, le contrôleur enfreint certainement SRP. Si le contrôleur fonctionne toujours sur la même couche d'abstraction, cela peut aider à la réalisation de SRP.
Le contrôleur ne violera pas SRP. Comme vous l'indiquez, sa responsabilité est de médialiser entre les modèles et la vue.
Cela étant dit, le problème avec votre exemple est que vous attachez des méthodes de contrôleur à la logique dans la vue, c'est-à-dire controller.specificButtonPressed
. Nommer les méthodes de cette façon liens le contrôleur à votre interface graphique, vous n'avez pas réussi à abstraire des choses. Le contrôleur doit porter sur l'exécution d'actions spécifiques, c'est-à-dire controller.saveData
ou controller.retrieveEntry
. L'ajout d'un nouveau bouton dans l'interface graphique ne signifie pas nécessairement ajouter une nouvelle méthode au contrôleur.
En appuyant sur un bouton dans la vue, signifie faire quelque chose, mais tout ce qui est peut-être facilement déclenché dans un nombre quelconque de parasites ou même pas à travers la vue.
de l'article Wikipedia sur SRP
Martin définit une responsabilité comme une raison de changer et conclut qu'une classe ou un module devrait en avoir un, et une seule, la raison de changer. Par exemple, envisagez un module qui compile et imprime un rapport. Un tel module peut être changé pour deux raisons. Premièrement, le contenu du rapport peut changer. Deuxièmement, le format du rapport peut changer. Ces deux choses changent pour des causes très différentes; un fondé et un cosmétique. Le principe de responsabilité unique indique que ces deux aspects du problème sont réellement deux responsabilités distinctes et doivent donc être dans des classes ou des modules distincts. Ce serait une mauvaise conception de couper deux choses qui changent pour différentes raisons à différents moments.
Le contrôleur n'est pas concerné par ce qui est dans la vue que lorsque l'une de ses méthodes est appelée qu'il fournit des données spécifiées à la vue. Il suffit de connaître la fonctionnalité du modèle jusqu'à ce qu'elle sait qu'il doit appeler des méthodes qu'ils auront. Cela ne sait rien de plus que ça.
Sachant qu'un objet a une méthode disponible pour appeler n'est pas la même chose que sa fonctionnalité.
Une responsabilité unique des contrôleurs est d'être le contrat qui médiate entre la vue et le modèle. La vue ne devrait être responsable que de l'écran, le modèle ne devrait être responsable que de la logique commerciale. C'est la responsabilité des contrôleurs de combler ces deux responsabilités.
C'est tout bien et bon mais de s'aventurer un peu des universités; Un contrôleur en MVC est généralement composé de nombreuses méthodes d'action plus petites. Ces actions correspondent généralement à ce que cela peut faire. Si je vends des produits, je vais probablement avoir une entreprise de produits. Ce contrôleur aura des actions telles que GetReviews, PRESHPECS, AddtOcart ECT ...
La vue a le SRP de l'affichage de l'interface utilisateur et une partie de cet interface utilisateur comprend un bouton indiquant AddtOcart.
Le contrôleur a le SRP de connaître toutes les vues et modèles impliqués dans le processus.
Les contrôleurs AddtOcart Action ont le SRP spécifique de connaître tous ceux qui doivent être impliqués lorsqu'un article est ajouté à un chariot.
Le modèle de produit contient le SRP de la logique de produits de modélisation et le modèle PompageCart possède le SRP de la modélisation de la manière dont les articles sont enregistrés pour une vérification ultérieure. Le modèle utilisateur a un SRP de modélisation de l'utilisateur qui ajoute des trucs à leur panier.
Vous pouvez et devriez réutiliser des modèles pour que votre entreprise soit effectuée et que ces modèles doivent être couplés à un moment donné de votre code. Le contrôleur contrôle chaque moyen unique que le couplage se produit.