J'ai base deux classes, Operation
et Trigger
. Chacun a un certain nombre de sous-classes qui se spécialisent dans certains types d'opérations ou de déclencheurs. Un Trigger
peut déclencher un spécifique Operation
. Alors qu'un Operation
peut être déclenché par un spécifique Trigger
.
J'ai besoin d'écrire le code qui mappe un donné Operation
à un donné Trigger
(ou vice versa), mais je ne sais pas où le mettre.
Dans ce cas, le code n'appartient pas clairement à une classe ou à l'autre classe. Donc, en termes de principe de responsabilité unique, je ne sais pas où le code devrait appartenir.
Je peux voir trois options qui fonctionneraient toutes. Alors que 1 et 2 ne semblent être qu'un choix de sémantique, 3 représente une approche complètement différente.
- Sur la gâchette, par exemple
bool Triggers(Operation o)
. - Sur l'opération, par exemple
bool TriggeredBy(Trigger t)
. - Dans une classe entièrement nouvelle qui gère le mappage, par exemple
bool MappingExists(Trigger t, Operation o)
.
Comment dois-je décider où placer le code de mappage partagé dans le respect d'un principe de responsabilité unique?
Comment gérer la responsabilité unique lorsque la responsabilité est partagée?
Modifier 1.
Ainsi, le code réel ressemble à ceci. Toutes les propriétés sont soit un string
, Guid
, collection<string>
ou enum
. Ils représentent simplement de petites données.
Modifier 2.
La raison du type de retour de bool. Une autre classe va consommer une collection de Trigger
et une collection de Operation
. Il doit savoir où existe une correspondance entre a Trigger
et an Operation
. Il utilisera ces informations pour créer un rapport.
la source
Réponses:
J'y penserais ainsi: comment détermine-t-on quelle opération provoque le déclenchement de quel déclencheur. Il doit s'agir d'un algorithme qui peut évoluer dans le temps ou évoluer en plusieurs algorithmes. Le placer dans les classes Trigger ou Operation implique que ces classes seront capables de gérer de tels scénarios à l'avenir. Notez que je ne le vois pas aussi simple qu'un mappage car il peut y en avoir plus.
Mon choix serait de créer une classe avec des méthodes appropriées, telles que GetOperationForTrigger (Trigger t). Cela permet au code d'évoluer en un ensemble de ces classes dont le choix peut dépendre au moment de l'exécution ou d'autres variables (par exemple le modèle de stratégie).
Notez que l'hypothèse principale dans cette ligne de pensée est d'écrire du code minimal (c'est-à-dire trois classes aujourd'hui) mais pour éviter une refactorisation majeure si la fonctionnalité doit être étendue à l'avenir en ne faisant pas l'hypothèse qu'il y aura toujours exactement une façon de déterminer quel déclencheur provoque quelle opération.
J'espère que cela t'aides. Bien que la réponse soit similaire à user61852, le raisonnement est différent. Par conséquent, l'implémentation sera différente (c.-à-d. Avoir des méthodes explicites au lieu de remplacer les égales, de sorte que le nombre de méthodes peut évoluer dans le temps en fonction des besoins).
la source
J'y suis allé, j'ai fait ça.
Option n ° 3.
Je ne sais pas quelle langue vous utiliserez mais j'utiliserai un pseudo-code très similaire à Java. Si votre langage est C #, vous avez probablement des interfaces et des structures similaires.
Avoir une classe ou une interface de mappage:
equals()
méthode deMapping
sorte que les collections deMapping
peuvent être demandées si elles contiennent un mappage donné.equals()
méthodes appropriées .Comparable
pour pouvoir trier les rapports.Vous pouvez simplement mettre un mappage dans une collection
Plus tard, vous pourrez demander:
la source
Actuellement, vous avez la classe A connaissant la classe B et la classe B connaissant la classe A. C'est beaucoup de couplage en cours.
Par définition, A effectue au moins sa propre opération ET vérifie si B doit être exécuté. L'inverse est vrai avec B. Quelle que soit la première classe appelée, elle devrait pouvoir regarder le résultat et voir si d'autres choses doivent être exécutées.
Essayez de briser ce couplage en divisant vos classes en composants plus petits. J'aime mettre un commentaire en haut de chaque classe expliquant en anglais ce qu'il fait. Si vous devez utiliser des mots comme ET ou si cela va sur une phrase ou deux, vous devez envisager de le décomposer. En règle générale, tout ce qui suit un "et" doit être dans sa propre classe
Vérifiez également si vous pouvez définir une interface qui couvre les fonctionnalités de déclenchement et d'opération. Si vous ne pouvez pas, c'est une autre indication que votre classe devient trop grande. Cela rompra également le couplage entre vos classes.
la source
Trigger
serait couplé à unOperation
. Mais c'est en quelque sorte à quoi ressemblent les données du monde réel. Ils sont couplés, car il y a une cartographie, par exemple ils doivent se connaître pour avoir un sens.