11
votes

Organiser des interfaces

Je suis juste en train de lire Principes agiles, modèles et pratiques en C # par R. Martin et M. Martin et ils suggèrent dans leur livre, de conserver toutes vos interfaces dans un projet séparé, par exemple. interfaces .

Par exemple, si j'ai un projet GUI , contient toutes mes classes d'interface graphique personnalisées, je garderai leurs interfaces dans les interfaces / em> projet. Spécifiquement, j'ai eu une classe CustomButton dans GUI , je garderais l'interface ICUSTOMBUTON dans interfaces .

L'avantage est que toute classe ayant besoin d'un ICUSTOMBUTON n'a pas besoin d'une référence à gui elle-même, mais seulement au projet les interfaces le projet.

aussi, si une classe dans le GUI Changement de projet et le faire en sorte que ce soit reconstruit, seuls les projets faisant directement référence au CustomButton auraient besoin de recompilation, alors que ceux qui se réfèrent à l'ICUSTOMBUTON peuvent rester intacts.

Je comprends ce concept, mais voir un problème:

permet de dire que j'ai cette interface: xxx

Comme vous pouvez le constater, il fait référence à Animatorstrategy, qui est une classe concrète et Par conséquent, assisterait dans un autre projet, permettrons de l'appeler l'animation . Maintenant, le projet d'interface doit faire référence à Animation . D'autre part, si Animation utilise une interface définie dans interfaces , elle doit également référence à celle-ci.

Dépendance cyclique - "Ici, nous venons".

La seule solution de ce problème, que je vois, est que toutes les méthodes définies dans les interfaces prennent des entrées elles-mêmes. Essayer de mettre en œuvre cela, il aura probablement probablement un effet domino toutefois et nécessitera rapidement une interface pour être mis en œuvre même pour les classes les plus élémentaires.

Je ne sais pas si j'aimerais faire face à ces frais généraux Développement.

Toute suggestion?


0 commentaires

4 Réponses :


3
votes

La réponse simple est animatrategy devrait également être une interface. La mise en œuvre de l'animateur est dans le projet d'animation, mais l'interface serait dans une animationInterfaces ou des interfaces (au besoin) Projet.

Je n'aurais pas nécessairement un seul projet d'interfaces, mais un pour chaque regroupement fonctionnel. Les clients d'animation feraient référence aux animations et les clients de l'interface graphique de l'interface graphique référendraient des guitrissements.

De cette façon, vous conservez vos contrats, sans mélanger aucune implémentation.

Pour ce que ça vaut la peine, je préfère aller dans l'autre sens avec des conventions de dénomination. Placez les interfaces dans l'animation et les implémentations dans AnimationImpl (ou similaires). De cette façon, vous référenciez le nom fonctionnel.


0 commentaires

-2
votes

Qu'en est-il de définir une interface avec des méthodes qui prennent des types génériques? Par exemple xxx

si vous avez besoin de quelques restrictions sur T variable , vous pouvez faire: xxx

Iotherinterface est également défini dans votre projet d'interfaces. Ensuite, tant que votre classe particulière hérite des deux ithing et iulterInterface , vous pouvez utiliser la méthode DomyThing et transmettre dans une instance de votre particulier classe sans avoir une dépendance circulaire. Votre code pourrait devenir: xxx

L'interface n'a aucune référence à la classe de béton animateur .


1 commentaires

C'est une bonne idée, mais ressemble plus à un hack pour moi. Les interfaces sont là pour épeler des contrats. Comment T semble-t-il quel type de stratégie à attendre? Si j'avais Ianimpatable, je n'aurais pas besoin de T.



17
votes

méfiez-vous de toujours, toujours et jamais - surtout près de tous, aucun, ni tous.

devriez-vous toujours mettre tous d'entre vous interfaces dans un assemblage séparé? Non - pas nécessairement.

Si vous mettez des interfaces que vous attendez des consommateurs externes de votre code pour mettre en œuvre - éventuellement. Je mettrais des interfaces dans un assemblage externe si vous vous attendez à ce que plusieurs assemblées dans votre projet ne soient pas sur elles - cela peut aider à rompre les dépendances de couplage. J'ai également utilisé cette pratique pour résoudre des problèmes de référencement circulaire, lorsque les assemblages doivent être conscients des interfaces les unes des autres.

Je ne mettez pas d'interfaces utilisées uniquement en interne dans un projet dans un assemblage séparé. Je ne promouve pas non plus les interfaces dans leur propre assemblée lorsque mes projets sont relativement petits - ou les interfaces ne sont pas destinées à être utilisées sans l'assemblage qui en dépend.

Quant à l'exemple que vous avez présenté - je vous suggère d'envisager de ne pas référencer les classes de votre système à partir d'interfaces. Dans la mesure du possible, j'essaie d'avoir des interfaces uniquement référence d'autres interfaces - cela empêche les choses relativement découplées. Vous ne pouvez pas toujours y parvenir - et donc lorsque vous avez ces types d'interfaces - vous devez les conserver avec l'assemblage qu'ils dépendent.

Si vous décidez de mettre des interfaces dans un assemblage séparé - vous ne devez pas nécessairement les mettre dans un seul assemblage. Vous voudrez peut-être les briser par leur utilisation prévue - de cette façon, les consommateurs peuvent tirer simplement les interfaces qui sont pertinentes pour un domaine particulier de fonctionnalité.


1 commentaires

Merci pour votre réponse. J'essayais d'avoir la tête autour du trempet (principe d'inversion de dépendance). Bien qu'il soit beau en théorie (classes de niveau inférieur en fonction des classes de niveau supérieur et non de l'inverse), il est difficile de mettre en œuvre et de maintien dans la pratique. Il est tellement plus facile de conserver des interfaces avec les classes qui les implémentent. Je suppose que dans ce cas, je suis d'accord avec votre suggestion de "compliquer" la conception de cette manière, si elle devient nécessaire.



1
votes

Je pense que les dépendances cycliques peuvent être inévitables, même si vous déclarez tout comme des interfaces, car il pourrait y avoir une méthode de montage FOO qui prend un paramètre ibar et une méthode dans la barre d'assemblage, qui prend un paramètre ifoo.

Je dirais qu'il n'y a pas de recette universelle pour cela, mais vous devriez plutôt utiliser "sens commun" pour diviser les interfaces dans les assemblages au besoin.


0 commentaires