Le nombre d'interfaces augmente souvent lorsqu'un objet générique est utilisé dans différents environnements. En C #, les variantes de IComparable, IEqualityComparer et IComparer permettent de trier dans des configurations distinctes, donc vous pourriez finir par les implémenter toutes, certaines d'entre elles peut-être plus d'une fois puisque vous pouvez implémenter les versions génériques fortement typées ainsi que les versions non génériques , vous pouvez en outre implémenter plusieurs génériques.
Prenons un exemple de scénario, disons une boutique en ligne où vous pouvez acheter des crédits avec lesquels vous pouvez acheter autre chose (les sites de photos utilisent souvent ce schéma). Vous pourriez avoir une classe "Valuta" et une classe "Credits" qui héritent de la même base. Valuta a quelques surcharges d'opérateur astucieuses et des routines de comparaison qui vous permettent de faire des calculs sans vous soucier de la propriété "Currency" (ajouter des livres en dollars par exemple). Les crédits sont beaucoup plus simples mais ont un autre comportement distinct. En voulant pouvoir les comparer les uns aux autres, vous pourriez finir par implémenter IComparable ainsi que IComparable et les autres variantes d'interfaces de comparaison sur les deux (même s'ils utilisent une implémentation commune que ce soit dans la classe de base ou ailleurs).
Lors de l'implémentation de la sérialisation, ISerializable, IDeserializationCallback sont implémentés. Ensuite, implémenter des piles annuler-refaire: IClonable est ajouté. Fonctionnalité IsDirty: IObservable, INotifyPropertyChanged. Permettre aux utilisateurs de modifier les valeurs à l'aide de chaînes: IConvertable ... La liste peut continuer indéfiniment ...
Dans les langues modernes, nous voyons une tendance différente qui aide à séparer ces aspects et à les placer dans leurs propres classes, en dehors de la classe principale. La classe ou l'aspect extérieur est ensuite associé à la classe cible à l'aide d'annotations (attributs). Il est souvent possible de rendre les classes d'aspect externes plus ou moins génériques.
L'utilisation d'attributs (annotation) est sujette à réflexion. Un inconvénient est une perte de performance mineure (initiale). Un inconvénient (souvent émotionnel) est que les principes tels que l'encapsulation doivent être assouplis.
Il existe toujours d'autres solutions, mais pour chaque solution astucieuse, il y a un compromis ou un problème. Par exemple, l'utilisation d'une solution ORM peut exiger que toutes les propriétés soient déclarées virtuelles. Les solutions de sérialisation peuvent exiger des constructeurs par défaut sur vos classes. Si vous utilisez l'injection de dépendances, vous pourriez finir par implémenter 23 interfaces sur une seule classe.
À mes yeux, 23 interfaces ne doivent pas nécessairement être mauvaises par définition. Il pourrait y avoir un schéma bien pensé derrière cela, ou une détermination de principe telle que d'éviter l'utilisation de la réflexion ou des croyances d'encapsulation extrêmes.
Chaque fois que vous changez de travail ou que vous devez vous baser sur une architecture existante. Mon conseil est de se familiariser d'abord, ne pas essayer de tout refaçonner trop rapidement. Écoutez le développeur d'origine (s'il est toujours là) et essayez de comprendre les pensées et les idées derrière ce que vous voyez. Lorsque vous posez des questions, ne le faites pas pour le décomposer, mais pour apprendre ... Oui, tout le monde a ses propres marteaux en or, mais plus vous pouvez collecter de marteaux, plus vous vous entendrez facilement avec vos collègues.