Wie kommt es, dass zu viele Instanzvariablen zu doppeltem Code führen?

19

Nach Refactoring zu Mustern :

Wenn eine Klasse versucht, zu viel zu tun, werden häufig zu viele Instanzvariablen angezeigt. Wenn eine Klasse zu viele Instanzvariablen enthält, darf der doppelte Code nicht weit hinterherhinken.

Wie kommt es, dass zu viele Instanzvariablen zu doppeltem Code führen?

q126y
quelle
2
Einfach ausgedrückt: nBoolesche Variablen erzeugen zum Beispiel einen internen Zustandsraum von 2^n. Meistens, obwohl Ihr Objekt nicht so viele beobachtbare Zustände hat , aber weil Sie all diesen Zustand in ein einziges Objekt gepackt haben, müssen Sie intern immer noch alle behandeln.
biziclop

Antworten:

23

Zu viele Instanzvariablen stehen nicht in direktem Zusammenhang mit doppeltem Code oder umgekehrt. Diese Aussage ist in dieser Allgemeinheit falsch. Man kann zwei separate Klassen ohne doppelten Code in eine Klasse werfen - das erzeugt eine neue Klasse mit nicht getrennten Verantwortlichkeiten und zu vielen Instanzvariablen, aber immer noch ohne doppelten Code.

Aber wenn Sie eine Klasse mit zu vielen Verantwortlichkeiten im realen Code finden, ist die Wahrscheinlichkeit groß, dass der Programmierer, der sie geschrieben hat, sich nicht für sauberen Code oder SOLID-Prinzipien interessiert hat (zumindest nicht zu dem Zeitpunkt, als er diesen Code geschrieben hat) Es ist nicht unwahrscheinlich, dass andere Codegerüche wie doppelter Code darin vorkommen.

Beispielsweise wird das Anti-Pattern "Copy-Paste Reuse" häufig angewendet, indem eine alte Methode kopiert und einige geringfügige Änderungen daran vorgenommen werden, ohne dass eine ordnungsgemäße Umgestaltung erforderlich ist. Manchmal muss man eine Mitgliedsvariable duplizieren und auch ein wenig ändern, damit dies funktioniert. Dies kann zu einer Klasse mit zu vielen Instanzvariablen führen (genauer: zu viele sehr ähnlich aussehende Instanzvariablen). In einer solchen Situation können die ähnlichen Instanzvariablen ein Indikator für wiederholten Code an anderer Stelle in der Klasse sein. Wie Sie bemerkt haben, ist dies jedoch ein künstliches Beispiel, und ich würde daraus keine allgemeine Regel schließen.

Doc Brown
quelle
11

Zu viele Instanzvariablen bedeuten zu viel Status. Zu viel Status führt zu doppeltem Code, der sich für jeden Status nur geringfügig unterscheidet.

Dies ist eine klassische einzelne konkrete Klasse, die zu viele Dinge tut, die Unterklassen oder Kompositionen sein sollten.

Wenn Sie einige Klassen mit zu vielen Instanzvariablen finden, werden Sie feststellen, dass sie einen viel zu hohen Status beibehalten und viele doppelte Codepfade aufweisen, die für jeden Fall nur geringfügig spezialisiert sind, aber so kompliziert sind, dass sie nicht in wiederverwendbare Methoden unterteilt werden können. Dies ist auch eine der größten Quellen von side effects.

Es gibt mindestens eine Ausnahme, die nicht in diese Kategorie fällt und auf einfache Weise behoben werden kann. ImmutableObjekte haben dieses Problem nicht, da es sich um feste Zustände handelt und keine Gefahr für verworrene Zustandsverwaltung oder Nebenwirkungen besteht.


quelle
7

Die Aussage, die Sie zitieren, soll in einem bestimmten Kontext gesehen werden.

Nach meiner Erfahrung kann ich nicht bestätigen, dass "viele Instanzvariablen im Allgemeinen doppelten Code anzeigen". Beachten Sie auch, dass dies zu den "Code-Gerüchen" gehört und es angeblich widersprüchliche Gerüche gibt. Schauen Sie hier:

http://c2.com/cgi/wiki?CodeSmell

Sie werden amüsanterweise feststellen, dass "zu viele Instanzvariablen" genauso gut wie "zu wenige Instanzvariablen" riechen.

Es gibt jedoch Probleme mit Instanzvariablen, sei es zu wenige oder zu viele:

  1. Jede Instanzvariable kann eine Art Status des Objekts bedeuten. Stati brauchen immer eine sorgfältige Behandlung. Sie müssen sicherstellen, dass Sie alle möglichen Kombinationen von Stati abgedeckt haben, um unerwartetes Verhalten zu vermeiden. Sie müssen sich jetzt immer klar machen: Welchen Status hat mein Objekt gerade? Unter diesem Gesichtspunkt weisen viele Instanzvariablen möglicherweise darauf hin, dass die Klasse nicht mehr verwaltet werden kann. Dies kann auch darauf hinweisen, dass eine Klasse zu viele Aufgaben ausführt, da sie so viele Stati benötigt.

  2. Jede Instanzvariable erfordert die Kontrolle darüber, welche Methoden die Variable auf welche Weise verändern. Sie kennen also plötzlich nicht mehr alle Köche, die kochen. Einer von ihnen, der spät abends müde programmiert wird, wird Ihre Suppe verderben. Nochmals: Zu viele solcher Variablen führen dazu, dass Code nur schwer zu durchdringen ist.

  3. Die andere Seite: Zu wenige Instanzvariablen können dazu führen, dass viele Methoden ihre Informationen mit zu viel Arbeit und zu vielen Parametern verarbeiten müssen. Sie spüren dies, wenn Sie vielen Ihrer Methoden einen bestimmten, gleichen Parameter zuweisen und alle Methoden mit diesem Parameter auf eine ähnliche Weise verfahren. In dieser Situation fängt Ihr Code an, sich aufzublähen. Sie werden am Ende viele Bildschirme nach oben und unten scrollen, um einige einfache Dinge zusammenzubringen. Hier kann ein Refactoring helfen: eine Instanzvariable und einen eindeutigen Zugang dazu einführen. Dann befreie alle Methoden.

  4. Last but not least: Wenn viele Instanzvariablen einer Klasse jeweils einen Setter und Getter haben, kann dies darauf hinweisen, dass andere Klassen diese erste Klasse nicht richtig verwenden. Es gibt eine Diskussion über " Warum Getter und Setter böse sind ". Kurz gesagt, wenn eine Klasse Rectangleeinige anbietet getX()und Dutzende anderer Klassen diese verwenden rectangle.getX(), schreiben Sie Code, der nicht robust gegen den "Ripple-Effekt" ist (inwieweit beeinflusst eine Codeänderung anderen Code). Fragen Sie einfach, was passiert, wenn Sie den Typ von intauf ändern double. Nach dieser Diskussion sollten viele der rectangle.getX()Anrufe in der Tat besser Anrufe seinrectanlge.calculateThisThingForMe(). Daher kann sehr indirekt duplizierter Code aus vielen Instanzvariablen hervorgehen, da viele Klassen in der Umgebung viele Get- und Setter verwenden, die sehr ähnliche Dinge tun, dh kopierte Dinge, die besser innerhalb der Klasse verschoben werden sollten.

Viele oder wenige Instanzvariablen bleiben ein ständiger Kompromiss und ändern sich in beide Richtungen, während die Software wächst.

peter_the_oak
quelle
Das R-to-P-Zitat ist zu allgemein, weshalb mir diese Antwort gefällt. Mein Take Away ist: Wenn wir genügend Eigenschaften zur Verfügung stellen, kann und wird ein Client diese nehmen und eine eigene Version einer bestimmten Funktionalität schreiben - # 4 oben. Das Problem kann so tief wie die Objektzusammensetzung gehen - siehe # 2: Ich sehe das zu oft in unserem Code. (a) "Warum haben sie die <whatever> -Klasse nicht benutzt (um einen Teil dieses unorganisierten Zustands zu korrigieren)?" oder (b) "Warum haben sie keine neue Klasse gebildet? Ich kann nicht alles im Auge behalten." Und sicher haben wir mehrere Klassen, die die Funktionalität intern duplizieren, da keine zusammenhängende Klasse vorhanden ist.
Radarbob
6

Einfach ausgedrückt: Schlechte Trennung von Bedenken innerhalb des Codes führt zu Code, der nicht modular ist, führt zu schlechter Wiederverwendung, führt zu doppeltem Code.

Wenn Sie nie versuchen, die Funktionalität zu wiederholen, erhalten Sie keinen doppelten Code, und viele Instanzvariablen sind kein Problem.

Wenn Sie versuchen, die Funktionalität zu wiederholen, kann monolithischer Code, der nicht modular ist, nicht wiederverwendet werden. Es macht zu viel und kann nur das tun, was es tut. Um etwas Ähnliches, aber nicht dasselbe zu tun, ist es "einfacher", auszuschneiden und einzufügen, als den monolithischen Code aufzubrechen. Erfahrene Programmierer wissen, dass duplizierter Code der Weg zur Hölle ist.

Während also viele Instanzvariablen selbst nicht die Hauptursache des Problems sind, ist es ein starker "Geruch", dass das Problem auftaucht.

Die Sprache "kann nicht weit hinterher sein" ist schwächer als das Sprichwort "muss unbedingt folgen", so dass der Autor nicht behauptet, dass es passieren muss, aber irgendwann passieren wird; Wenn Sie Funktionen wiederverwenden müssen, dies jedoch nicht können, da der Code nicht modular ist.

simbo1905
quelle