[parameters] Wie viele Konstruktorargumente sind zu viele?



Answers

Ich sehe, dass einige Leute sieben als obere Grenze empfehlen. Offensichtlich ist es nicht wahr, dass Menschen sieben Dinge gleichzeitig in ihrem Kopf halten können; Sie können sich nur an vier erinnern (Susan Weinschenk, 100 Dinge, die jeder Designer über Menschen wissen muss , 48). Trotzdem halte ich vier für etwas wie eine hohe Erdumlaufbahn. Aber das liegt daran, dass mein Denken von Bob Martin verändert wurde.

In Clean Code argumentiert Onkel Bob für drei als allgemeine obere Grenze für die Anzahl der Parameter. Er macht den radikalen Anspruch (40):

Die ideale Anzahl von Argumenten für eine Funktion ist null (niladisch). Als nächstes kommt eins (monadisch), dicht gefolgt von zwei (dyadisch). Drei Argumente (triadisch) sollten nach Möglichkeit vermieden werden. Mehr als drei (polyadic) erfordern eine ganz spezielle Begründung - und sollten dann nicht verwendet werden.

Er sagt dies wegen der Lesbarkeit; aber auch wegen der Testbarkeit:

Stellen Sie sich die Schwierigkeit vor, alle Testfälle zu schreiben, um sicherzustellen, dass alle verschiedenen Kombinationen von Argumenten korrekt funktionieren.

Ich ermutige Sie, eine Kopie seines Buches zu finden und seine vollständige Diskussion der Funktionsargumente zu lesen (40-43).

Ich stimme denen zu, die das Prinzip der einheitlichen Verantwortung erwähnt haben. Es ist schwer für mich, zu glauben, dass eine Klasse, die mehr als zwei oder drei Werte / Objekte ohne vernünftige Vorgaben benötigt, wirklich nur eine Verantwortung hat und nicht besser mit einer anderen extrahierten Klasse wäre.

Wenn Sie nun Ihre Abhängigkeiten über den Konstruktor einfügen, sind Bob Martins Argumente, wie einfach es ist, den Konstruktor aufzurufen, nicht so sehr anwendbar (weil es normalerweise nur einen Punkt in Ihrer Anwendung gibt, an den Sie das anschließen, oder Sie selbst) habe einen Rahmen, der es für dich tut). Das Single Responsibility-Prinzip ist jedoch immer noch relevant: Sobald eine Klasse vier Abhängigkeiten hat, halte ich das für einen Geruch, dass sie viel Arbeit macht.

Wie bei allen Dingen in der Informatik gibt es jedoch zweifellos Fälle, in denen eine große Anzahl von Konstruktorparametern vorhanden ist. Verändern Sie den Code nicht, um die Verwendung einer großen Anzahl von Parametern zu vermeiden. Wenn Sie jedoch eine große Anzahl von Parametern verwenden, halten Sie an und denken Sie darüber nach, da dies bedeuten kann, dass Ihr Code bereits verzerrt ist.

Question

Nehmen wir an, Sie haben eine Klasse namens Kunde, die folgende Felder enthält:

  • Nutzername
  • Email
  • Vorname
  • Familienname, Nachname

Lassen Sie uns auch sagen, dass gemäß Ihrer Geschäftslogik alle Kundenobjekte diese vier Eigenschaften definieren müssen.

Jetzt können wir das ganz einfach tun, indem wir den Konstruktor zwingen, jede dieser Eigenschaften anzugeben. Aber es ist ziemlich einfach zu sehen, wie dies außer Kontrolle geraten kann, wenn Sie gezwungen sind, dem Kundenobjekt mehr benötigte Felder hinzuzufügen.

Ich habe Klassen gesehen, die mehr als 20 Argumente in ihren Konstruktor einbringen, und es ist nur ein Schmerz, sie zu benutzen. Wenn Sie diese Felder jedoch nicht benötigen, besteht die Gefahr, dass Sie undefinierte Informationen oder, noch schlimmer, Objektreferenzierungsfehler erhalten, wenn Sie sich beim Aufrufen dieser Eigenschaften auf den aufrufenden Code verlassen.

Gibt es Alternativen dazu oder müssen Sie nur entscheiden, ob die Anzahl der Konstruktorargumente zu viel ist, als dass Sie damit leben könnten?




Ich denke, alles hängt von der Situation ab. Für etwas wie Ihr Beispiel, eine Kundenklasse, würde ich nicht die Gefahr eingehen, dass diese Daten bei Bedarf undefiniert sind. Auf der anderen Seite würde das Übergeben einer Struktur die Argumentliste auflösen, aber Sie müssten immer noch eine Menge Dinge in der Struktur definieren.




Stil zählt viel, und wenn es einen Konstruktor mit mehr als 20 Argumenten gibt, sollte das Design geändert werden. Sorgen Sie für angemessene Standardeinstellungen.




Wenn Sie unantastbar viele Argumente haben, dann packen Sie sie einfach zusammen in Strukturen / POD-Klassen, vorzugsweise als innere Klassen der Klasse deklariert, die Sie konstruieren. Auf diese Weise können Sie die Felder immer noch benötigen, während Sie den Code, der den Konstruktor aufruft, vernünftig lesen können.




Ich stimme dem 7-Punkte-Limit zu, das Boojiboy erwähnt. Darüber hinaus kann es sich lohnen, anonyme (oder spezialisierte) Typen, IDictionary oder Indirection über den Primärschlüssel zu einer anderen Datenquelle zu betrachten.




Wenn es nicht mehr als 1 Argument ist, verwende ich immer Arrays oder Objekte als Konstruktorparameter und verlasse mich auf die Fehlerprüfung, um sicherzustellen, dass die erforderlichen Parameter vorhanden sind.




Ich denke, Ihre Frage ist mehr über das Design Ihrer Klassen als über die Anzahl der Argumente im Konstruktor. Wenn ich 20 Daten (Argumente) benötige, um ein Objekt erfolgreich zu initialisieren, würde ich wahrscheinlich in Erwägung ziehen, die Klasse aufzulösen.




Links