Die Anzahl der Schnittstellen wächst häufig, wenn ein generisches Objekt in verschiedenen Umgebungen verwendet wird. In C # ermöglichen die Varianten von IComparable, IEqualityComparer und IComparer das Sortieren in unterschiedlichen Konfigurationen, sodass Sie möglicherweise alle von ihnen implementieren, einige davon möglicherweise mehrmals, da Sie sowohl die generischen stark typisierten Versionen als auch die nicht generischen Versionen implementieren können Außerdem können Sie mehr als eines der Generika implementieren.
Nehmen wir ein Beispielszenario, sagen wir einen Webshop, in dem Sie Credits kaufen können, mit denen Sie etwas anderes kaufen können (auf Stock-Foto-Sites wird dieses Schema häufig verwendet). Möglicherweise haben Sie eine Klasse "Valuta" und eine Klasse "Credits", die dieselbe Basis erben. Valuta verfügt über einige raffinierte Operatorenüberladungen und Vergleichsroutinen, mit denen Sie Berechnungen durchführen können, ohne sich um die Eigenschaft "Currency" sorgen zu müssen (z. B. Hinzufügen von Pfund zu Dollar). Credits sind viel einfacher, haben aber ein anderes Verhalten. Wenn Sie diese miteinander vergleichen möchten, könnten Sie IComparable sowie IComparable und die anderen Varianten von Vergleichsschnittstellen auf beiden implementieren (auch wenn sie eine gemeinsame Implementierung verwenden, sei es in der Basisklasse oder anderswo).
Bei der Implementierung der Serialisierung werden ISerializable und IDeserializationCallback implementiert. Anschließend Undo-Redo-Stacks implementieren: IClonable wird hinzugefügt. IsDirty-Funktionalität: IObservable, INotifyPropertyChanged. Zulassen, dass Benutzer die Werte mithilfe von Zeichenfolgen bearbeiten können: IConvertable ... Die Liste kann fortgesetzt werden ...
In modernen Sprachen sehen wir einen anderen Trend, der hilft, diese Aspekte zu trennen und sie in ihre eigenen Klassen außerhalb der Kernklasse einzuteilen. Die äußere Klasse oder der äußere Aspekt wird dann mit Hilfe von Annotationen (Attributen) der Zielklasse zugeordnet. Oft ist es möglich, die äußeren Aspektklassen mehr oder weniger allgemein zu gestalten.
Die Verwendung von Attributen (Annotation) ist reflexionspflichtig. Ein Nachteil ist der geringfügige (anfängliche) Leistungsverlust. Ein (oft emotionaler) Nachteil ist, dass Prinzipien wie die Verkapselung gelockert werden müssen.
Es gibt immer andere Lösungen, aber für jede raffinierte Lösung gibt es einen Kompromiss oder einen Haken. Wenn Sie beispielsweise eine ORM-Lösung verwenden, müssen möglicherweise alle Eigenschaften als virtuell deklariert werden. Serialisierungslösungen erfordern möglicherweise Standardkonstruktoren für Ihre Klassen. Wenn Sie die Abhängigkeitsinjektion verwenden, werden möglicherweise 23 Schnittstellen in einer einzelnen Klasse implementiert.
In meinen Augen müssen 23 Schnittstellen per Definition nicht schlecht sein. Möglicherweise steckt dahinter ein gut durchdachtes Schema oder eine grundsätzliche Bestimmung wie die Vermeidung von Reflexionen oder extremen Einkapselungsüberzeugungen.
Wann immer Sie einen Job wechseln oder auf einer bestehenden Architektur aufbauen müssen. Mein Rat ist, sich erst einmal voll und ganz vertraut zu machen, nicht alles zu schnell umzugestalten. Hören Sie dem ursprünglichen Entwickler zu (falls er noch da ist) und versuchen Sie, die Gedanken und Ideen hinter dem, was Sie sehen, herauszufinden. Wenn Sie Fragen stellen, tun Sie dies nicht, um sie zu zerstören, sondern um zu lernen ... Ja, jeder hat seine eigenen goldenen Hämmer, aber je mehr Hämmer Sie sammeln können, desto leichter werden Sie mit Kollegen zurechtkommen.