10 Stimmen

Ist es eine gute Praxis, Reflexion in Ihrer Geschäftslogik zu verwenden?

Ich muss an einer Anwendung arbeiten, die aus zwei Hauptteilen besteht:

  • Der Geschäftslogikteil mit spezifischen Geschäftsklassen (z.B. Buch, Bibliothek, Autor, ...)
  • Ein generischer Teil, der Bücher, Bibliotheken, ... in Datenrastern anzeigen kann, sie einer Datenbank zuordnet, ...).

Der generische Teil verwendet Reflection, um die Daten aus den Geschäftsklassen zu erhalten, ohne dass spezielle Datengitter- oder Datenbanklogik in die Geschäftsklassen geschrieben werden muss. Dies funktioniert gut und ermöglicht es uns, neue Geschäftsklassen (z. B. LibraryMember) hinzuzufügen, ohne das Datengitter und die Datenbanklogik anpassen zu müssen.

Im Laufe der Jahre wurde jedoch Code zu den Business-Klassen hinzugefügt, der ebenfalls Reflection nutzt, um Dinge in den Business-Klassen zu erledigen. Wenn z. B. der Autor eines Buches geändert wird, werden Beobachter aufgerufen, um dem Autor selbst mitzuteilen, dass er dieses Buch zu seiner Sammlung der von ihm geschriebenen Bücher (Author.Books) hinzufügen soll. In diesen Beobachtern werden nicht nur die Instanzen übergeben, sondern auch Informationen, die direkt von der Reflexion abgeleitet sind (FieldInfo wird dem Beobachteraufruf hinzugefügt, damit der Aufrufer weiß, dass das Feld "Author" des Buches geändert wurde).

Ich sehe durchaus Vorteile in der Verwendung von Reflection in diesen generischen Modulen (wie dem Datengitter oder der Datenbankschnittstelle), aber es scheint mir, dass die Verwendung von Reflection in den Geschäftsklassen eine schlechte Idee ist. Sollte die Anwendung nicht so weit wie möglich ohne Reflection funktionieren? Oder ist die Verwendung von Reflection die "normale Arbeitsweise" im 21. Jahrhundert?

Ist es eine gute Praxis, Reflexion in Ihrer Geschäftslogik zu verwenden?

EDIT : Eine Klarstellung zu der Bemerkung von Kirk:

  • Stellen Sie sich vor, dass Author einen Beobachter auf Book implementiert.
  • Book ruft alle seine Beobachter auf, wenn sich ein Feld von Book ändert (wie Titel, Jahr, #Seiten, Autor, ...). Die 'FieldInfo' des geänderten Feldes wird an den Beobachter übergeben.
  • Der Author-observer entscheidet dann anhand dieser FieldInfo, ob er an dieser Änderung interessiert ist. In diesem Fall, wenn FieldInfo für das Feld Author of Book ist, wird der Author-Observer seinen eigenen Vektor von Books aktualisieren.

12voto

Dan Bryant Punkte 27022

Die Hauptgefahr bei Reflection besteht darin, dass die Flexibilität zu unorganisiertem, unwartbarem Code führen kann, vor allem, wenn jüngere Entwickler für Änderungen eingesetzt werden, die den Reflection-Code möglicherweise nicht vollständig verstehen oder so sehr in ihn verliebt sind, dass sie ihn zur Lösung aller Probleme verwenden, selbst wenn einfachere Tools ausreichen würden.

Meiner Beobachtung nach führt eine zu starke Verallgemeinerung zu einer zu starken Verkomplizierung. Noch schlimmer wird es, wenn sich herausstellt, dass die tatsächlichen Grenzfälle vom allgemeinen Entwurf nicht abgedeckt werden können, so dass Hacks erforderlich sind, um die neuen Funktionen termingerecht einzubauen, wodurch Flexibilität in Komplexität umgewandelt wird.

7voto

Jay Punkte 26044

Ich vermeide die Verwendung von Reflexionen. Ja, sie macht Ihr Programm flexibler. Aber diese Flexibilität hat einen hohen Preis: Es gibt keine Kompilierzeitüberprüfung von Feldnamen oder Typen oder anderen Informationen, die Sie durch Reflection sammeln.

Wie bei vielen anderen Dingen auch, kommt es darauf an, was Sie tun. Wenn Ihre Logik so beschaffen ist, dass Sie die gefundenen Feldnamen (oder was auch immer) NIEMALS mit einem konstanten Wert vergleichen, dann ist die Verwendung von Reflection wahrscheinlich eine gute Sache. Wenn Sie aber die Reflexion verwenden, um Feldnamen zu finden, und dann in einer Schleife nach den Feldern "Autor" und "Titel" suchen, haben Sie gerade eine komplexere Simulation eines Objekts mit zwei benannten Feldern erstellt. Und was ist, wenn Sie nach "Autor" suchen, obwohl das Feld eigentlich "Autorenname" heißt, oder Sie beabsichtigen, nach "Autor" zu suchen und geben versehentlich "Auhtor" ein? Jetzt haben Sie Fehler, die erst zur Laufzeit auftauchen, anstatt zur Kompilierungszeit markiert zu werden.

Bei fest kodierten Feldnamen kann Ihnen Ihre IDE jede Stelle nennen, an der ein bestimmtes Feld verwendet wird. Mit Reflexion ... nicht so einfach zu erkennen. Vielleicht können Sie eine Textsuche nach dem Namen durchführen, aber wenn Feldnamen als Variablen weitergegeben werden, kann es sehr schwierig werden.

Ich arbeite gerade an einem System, bei dem die ursprünglichen Autoren Reflexion und ähnliche Techniken liebten. Es gibt alle möglichen Stellen, an denen sie eine Instanz einer Klasse erstellen müssen, und anstatt einfach "new" und die Klasse zu sagen, erstellen sie ein Token, das sie in einer Tabelle nachschlagen, um den Klassennamen zu erhalten. Was bringt das? Ja, wir könnten die Tabelle ändern, um das Token auf einen anderen Namen abzubilden. Und das bringt uns ... was? Wann haben Sie das letzte Mal gesagt: "Oh, überall, wo mein Programm eine Instanz von Customer erzeugt, möchte ich eine Instanz von NewKindOfCustomer erzeugen." Wenn Sie Änderungen an einer Klasse vornehmen, ändern Sie die Klasse und erstellen nicht eine neue Klasse, sondern behalten die alte aus Nostalgiegründen bei.

Um ein ähnliches Thema aufzugreifen, erstelle ich regelmäßig Dateneingabebildschirme, indem ich die Datenbank nach einer Liste von Feldnamen, -typen und -größen frage und sie dann von dort aus gestalte. Das hat den Vorteil, dass ich das gleiche Programm für alle einfacheren Dateneingabebildschirme verwenden kann - ich gebe einfach den Tabellennamen als Parameter ein - und wenn ein Feld hinzugefügt oder gelöscht wird, ist keine Änderung des Codes erforderlich. Aber das funktioniert nur, solange ich mich nicht um die Felder kümmere. Sobald ich anfange, Validierungen oder Nebeneffekte zu haben, die für diesen Bildschirm spezifisch sind, macht das System mehr Ärger als es wert ist, und ich bin besser dran, wenn ich auf explizitere Kodierung zurückgreife.

3voto

John Nicholas Punkte 4658

Ich neige dazu, Reflexion nicht zu verwenden, wo ich es helfen kann. durch die Verwendung von Schnittstellen und Codierung gegen diese kann ich viele Dinge tun, die einige Reflexion für verwenden würde.

Aber ich bin ein großer Fan von "wenn es funktioniert, dann funktioniert es".

Auch durch die Verwendung von Reflexion haben Sie wahrscheinlich etwas, das ziemlich leicht angepasst werden kann.

Dh der einzige Einwand, den die meisten haben würde, ist ziemlich religiös ... und wenn Ihre Leistung ist in Ordnung und der Code ist wartbar und klar .... wen kümmert es?

Bearbeiten: Auf der Grundlage Ihrer Bearbeitung würde ich in der Tat Schnittstellen verwenden, um zu erreichen, was Sie wollen. Es sei denn, ich missverstehe Sie.

3voto

Kirk Woll Punkte 72923

Ausgehend von Ihrer Bearbeitung klingt es so, als würden Sie Reflexion verwenden rein als Mechanismus für Identifizierung Felder. Dies steht im Gegensatz zu dynamischem Verhalten wie aufschauend die Felder, was nach Möglichkeit vermieden werden sollte (da solche Suchvorgänge in der Regel Zeichenketten verwenden, die die statische Typsicherheit beeinträchtigen). Verwendung von FieldInfo um einen Bezeichner für ein Feld bereitzustellen, ist ziemlich harmlos, obwohl es einige Interna (die Info-Klasse) auf eine nicht ganz ideale Weise offenlegt.

2voto

Sachin Shanbhag Punkte 52789

Ich denke, es ist eine gute Idee, sich von Reflection fernzuhalten, wenn es möglich ist, aber scheuen Sie sich nicht, darauf zurückzugreifen, wenn es eine bessere oder flexiblere Lösung für Ihr Problem bietet. Die Leistungseinbußen für alles außer engen Schleifenoperationen sind im Gesamtschema einer Anwendung oder einer Webformularanforderung wahrscheinlich minimal.

Nur ein guter Artikel zum Thema Reflexion -

http://www.simple-talk.com/dotnet/.net-framework/a-defense-of-reflection-in-.net/

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X