Felder gegen Methodenargumente [geschlossen]

9

Ich habe gerade angefangen, eine neue Klasse zu schreiben, und mir ist aufgefallen, dass ich viele Methodenargumente hinzugefügt habe, die nicht unbedingt benötigt werden. Dies folgt der Gewohnheit, einen Status in Klassen zu vermeiden, der für einen Methodenaufruf spezifisch ist, anstatt eine allgemeine Konfiguration oder Abhängigkeiten der Klasse zu sein.

Dies bedeutet, dass viele Methoden, die keine Argumente haben könnten, eins, zwei oder drei ergeben.

Ich würde gerne Ihre Meinung dazu hören, was Sie von diesem Kompromiss halten und wie Sie entscheiden, welchen Ansatz Sie in welcher Situation wählen möchten.

Da Code bei der Beschreibung von Code oft einfacher zu verstehen ist als Englisch, habe ich eine kleine Zusammenfassung erstellt, die beide Varianten enthält: https://gist.github.com/JeroenDeDauw/6525656

Jeroen De Dauw
quelle
Argumente, die nur als lokale Variable verwendet werden (nicht global für die Lebensdauer des Objekts), sollten nur im Gültigkeitsbereich sein, solange dies sinnvoll ist. Ich finde es sehr irritierend, wenn Entwickler den Nichtinstanzstatus als Instanzstatus speichern, weil dies der Fall ist praktisch ... Nur meine Meinung. Macht es schwierig zu sehen, wie der Ausführungsfluss tatsächlich ist.
Max
Die Verwendung von Parametern und die Möglichkeit, dass die Klasse sich darum kümmert, ob sie während der Ausführung einer Methode den Status ändern muss oder nicht, knüpft gut an das Prinzip "Tell Don't Ask" an . Denken Sie daran, dass Tell nicht fragen nicht bedeutet, dass Sie ein Objekt nicht nach seinem Zustand abfragen können ( eklatanter Stecker )
Marjan Venema

Antworten:

2

Da die einzige extern sichtbare Methode Ihres Beispiels ist updateTable, halte ich es für in Ordnung, Felder anstelle von Methodenparametern zu verwenden.

Wenn dies Teil einer allgemeineren Klasse ist (z TableTools ), würde ich die Hilfsmethoden, die den Status benötigen, in eine versteckte innere Klasse verschieben.

Pseudocode-Beispiel:

class TableTools {
    ...
    public void updateTable(currentTable, newTable) {
        TableUpdater u = new TableUpdater(schemaModifier, currentTable, newTable);
        u.removeRemovedFields();
        u.addAddedFields();
     }

     private class TableUpdater { ... }
}

Auf diese Weise vermeiden Sie Felder, die nur von einer öffentlichen Methode verwendet werden. Darüber hinaus ist der Code in dem Sinne threadsicher, dass jeder Aufruf von updateTable eine eigene Kopie von TableUpdater und damit der Instanzvariablen von TableUpdater verwendet.

Heinzi
quelle
7

Durch die Verwendung von Feldern wird die Möglichkeit aktiviert, Multithreading für die Methoden verfügbar zu machen, die diese Felder verwenden.

Die Verwendung solcher Felder ist unter dem Gesichtspunkt der Wiederverwendbarkeit und Wartbarkeit nur geringfügig besser als die Verwendung globaler Felder. Der entscheidende Punkt hierbei ist, dass komplexe Setups eine sorgfältige und aktuelle Dokumentation darüber erfordern, welche Methoden welche Felder verwenden und / oder überlisten. etwas, das Sie nicht tun müssen, wenn Sie Argumente verwenden.

Ratschenfreak
quelle
Multhithreading ist für meinen Anwendungsfall nicht relevant, wie es in PHP der Fall ist. Ich stimme zu, dass dieser Ansatz schlecht ist, wenn die Art und Weise, wie die Felder verwendet werden, nicht trivial ist. In diesem Fall werden sie nur mit der einzigen öffentlichen Methode beschrieben (und immer beschrieben). Ich gehe nicht davon aus, dass dies Probleme verursacht. Da Felder wie dieses nur geringfügig besser sind als globale Felder, bin ich mir nicht sicher, was Sie meinen. Können Sie das näher erläutern?
Jeroen De Dauw
7

In Laienwörtern:

  • Methoden sollten so wenig Argumente wie möglich haben (Martins Clean Code)
  • Eines der Merkmale von Objekten ist, dass sie einen Zustand haben können (und sollten)
  • Nicht statische Methoden, die nicht mit dem Status des Objekts arbeiten, dh alles als Parameter empfangen, sind nicht zusammenhängend
  • Nicht kohäsive Methoden können genauso gut statisch gemacht und in einer Utility-Klasse gruppiert werden

Meiner bescheidenen Meinung nach gehören nicht zusammenhängende Methoden zu einer Utility-Klasse und nicht zu einer Klasse mit einem Domain-Namen.

Tulains Córdova
quelle
1

Verwenden Sie im aktuellen Fall keine Felder! Zwei "Threads", die das Objekt gleichzeitig verwenden, verwirren sich ernsthaft. Sie müssen auch keine echten, separaten Threads sein (daher die Anführungszeichen). Wenn Sie das Objekt für eine Tabelle einrichten, dann eine Methode aufrufen, die es für eine andere Tabelle verwendet, und dann versuchen, die ursprüngliche Einrichtung zu verwenden, liegt ein Problem vor. Halten Sie sich vorerst an die Parameter.

Was Sie wollen , hier zu tun ist , eine neue Aktualisierungs Klasse erstellen , die nur in einem Fall verwendet wird. Die ursprüngliche Klasse könnte über eine Methode verfügen, um bei Bedarf eine Instanz zu erstellen. Die neue Klasse hätte Felder. Sie haben das Beste aus beiden Welten. Manchmal ist es einfacher, sich nur an die Parameter zu halten, aber in Ihrem Beispiel kommen Sie bereits dahin, wo eine separate Klasse besser wäre.

RalphChapin
quelle
0

Ich denke, dass die Auswahl der tatsächlichen Situation entsprechen sollte, wie Sie es sehen. Wenn ein Element zu einer Instanz gehört, sollte es als Feld angesehen werden. Wenn sich das Element außerhalb der Instanz befindet, sollte es als Methodenparameter übergeben werden.

Wir sollten uns in diesem Fall nicht von der Wirksamkeit (der Unterschied ist ohnehin unbedeutend) oder (Gott sei Dank!) Leichtigkeit des Tippens leiten lassen, sondern von der Verständlichkeit und Natürlichkeit des Codes.

Gangnus
quelle
0

Meiner Meinung nach sollte, wenn Sie Code schreiben, der etwas mit etwas tut , Parameter verwendet werden, die definieren, welche Dinge er tun soll, und sein Name sollte so weit wie möglich definieren, was er damit tut.

Wenn Sie Code schreiben, der eine Aktion verpackt , die für etwas ausgeführt werden soll , sollten Sie die Dinge, für die sie ausgeführt werden soll, in ein Objekt einschließen und an Ihr Objekt übergeben, das etwas tut .

Diese Aktion dann zu einer Art Meta-Beschreibung der Aufrufe der Methoden der ersten, die Sie möglicherweise zu einem späteren Zeitpunkt ausführen können, indem Sie sie in die Warteschlange stellen oder aus irgendeinem Grund sogar entscheiden, sie überhaupt nicht auszuführen.

Ihre Frage bedeutet also, dass es sich um eine Aktion oder eine Funktion handelt . Eine Aktion kann verschoben oder abgebrochen werden und sollte daher das enthalten, worauf sie einwirkt. Eine Funktion sofort ausgeführt, sodass die Parameter nicht beibehalten werden müssen.

Sie können rückgängig machen und Aktion, aber keine Funktion .

OldCurmudgeon
quelle