Gelegentlich müssen wir Methoden schreiben, die viele, viele Argumente erhalten, zum Beispiel:
public void doSomething(Object objA , Object objectB ,Date date1 ,Date date2 ,String str1 ,String str2 )
{
}
Wenn ich auf diese Art von Problem stoße, kapsle ich häufig Argumente in eine Karte.
Map<Object,Object> params = new HashMap<Object,Object>();
params.put("objA",ObjA) ;
......
public void doSomething(Map<Object,Object> params)
{
// extracting params
Object objA = (Object)params.get("objA");
......
}
Dies ist keine gute Vorgehensweise. Das Einkapseln von Parametern in eine Karte ist eine reine Verschwendung von Effizienz. Das Gute ist, die saubere Signatur, einfach, andere Parameter mit den wenigsten Änderungen hinzuzufügen. Was ist die beste Vorgehensweise für diese Art von Problem?
Die Verwendung einer Karte mit magischen String-Schlüsseln ist eine schlechte Idee. Sie verlieren jegliche Überprüfung der Kompilierungszeit und es ist wirklich unklar, welche Parameter erforderlich sind. Sie müssten eine sehr vollständige Dokumentation schreiben, um dies auszugleichen. Wirst du dich in ein paar Wochen daran erinnern, was diese Strings sind, ohne auf den Code zu schauen? Was ist, wenn Sie einen Tippfehler gemacht haben? Den falschen Typ verwenden? Sie werden es erst herausfinden, wenn Sie den Code ausführen.
Verwenden Sie stattdessen ein Modell. Erstellen Sie eine Klasse, die ein Container für alle diese Parameter ist. Auf diese Weise behalten Sie die Typensicherheit von Java. Sie können dieses Objekt auch an andere Methoden weitergeben, in Sammlungen ablegen usw.
Wenn der Parametersatz nicht anderweitig verwendet oder weitergegeben wird, kann ein dediziertes Modell natürlich übertrieben sein. Es ist ein Gleichgewicht zu finden, also benutze den gesunden Menschenverstand.
quelle
Wenn Sie viele optionale Parameter haben, können Sie eine fließende API erstellen: Ersetzen Sie eine einzelne Methode durch die Methodenkette
Mit dem statischen Import können Sie innere fließende APIs erstellen:
quelle
Es heißt "Introduce Parameter Object". Wenn Sie feststellen, dass Sie dieselbe Parameterliste an mehreren Stellen übergeben, erstellen Sie einfach eine Klasse, die alle enthält.
Selbst wenn Sie nicht so oft dieselbe Parameterliste übergeben, verbessert dieses einfache Refactoring Ihre Lesbarkeit des Codes, was immer gut ist. Wenn Sie sich Ihren Code 3 Monate später ansehen, ist es einfacher zu verstehen, wann Sie einen Fehler beheben oder eine Funktion hinzufügen müssen.
Es ist natürlich eine allgemeine Philosophie, und da Sie keine Details angegeben haben, kann ich Ihnen auch keine detaillierteren Ratschläge geben. :-)
quelle
XXXParameter param = new XXXParameter();
Verfügung haben, und dann verwendenXXXParameter.setObjA(objA)
; etc ...Zuerst würde ich versuchen, die Methode umzugestalten. Wenn so viele Parameter verwendet werden, kann es in irgendeiner Weise zu lang sein. Eine Aufschlüsselung würde sowohl den Code verbessern als auch möglicherweise die Anzahl der Parameter für jede Methode verringern. Möglicherweise können Sie auch den gesamten Vorgang in eine eigene Klasse umgestalten. Zweitens würde ich nach anderen Fällen suchen, in denen ich dasselbe (oder dieselbe Obermenge) derselben Parameterliste verwende. Wenn Sie mehrere Instanzen haben, signalisiert dies wahrscheinlich, dass diese Eigenschaften zusammengehören. Erstellen Sie in diesem Fall eine Klasse, die die Parameter enthält, und verwenden Sie sie. Zuletzt würde ich bewerten, ob es sich aufgrund der Anzahl der Parameter lohnt, ein Kartenobjekt zu erstellen, um die Lesbarkeit des Codes zu verbessern. Ich denke, dies ist ein persönlicher Anruf - diese Lösung ist in jeder Hinsicht schmerzhaft und der Kompromisspunkt kann unterschiedlich sein. Für sechs Parameter würde ich es wahrscheinlich nicht tun. Für 10 würde ich wahrscheinlich (wenn keine der anderen Methoden zuerst funktioniert).
quelle
Dies ist häufig ein Problem beim Erstellen von Objekten.
In diesem Fall verwenden Sie das Builder-Objektmuster . Es funktioniert gut, wenn Sie eine große Liste von Parametern haben und nicht immer alle benötigen.
Sie können es auch an den Methodenaufruf anpassen.
Es erhöht auch die Lesbarkeit erheblich.
Sie können die Überprüfungslogik auch in die Methoden Builder set .. () und build () einfügen.
quelle
final
? Dies ist die Hauptsache, die mich davon abhält, Hilfsfunktionen zu schreiben. Ich nehme an, ich kann die Felder privat machen und sicherstellen, dass ich sie im Code dieser Klasse nicht falsch ändere, aber ich hoffe auf etwas Eleganteres.Es gibt ein Muster, das als Parameterobjekt bezeichnet wird .
Die Idee ist, ein Objekt anstelle aller Parameter zu verwenden. Selbst wenn Sie später Parameter hinzufügen müssen, müssen Sie diese nur noch dem Objekt hinzufügen. Die Methodenschnittstelle bleibt gleich.
quelle
Sie können eine Klasse erstellen, die diese Daten enthält. Muss zwar aussagekräftig genug sein, aber viel besser als die Verwendung einer Karte (OMG).
quelle
Code Complete * schlägt einige Dinge vor:
* Erste Ausgabe, ich weiß, ich sollte aktualisieren. Es ist auch wahrscheinlich, dass sich einige dieser Ratschläge geändert haben, seit die zweite Ausgabe geschrieben wurde, als OOP immer beliebter wurde.
quelle
Gute Praxis wäre es, umzugestalten. Was bedeutet mit diesen Objekten, dass sie an diese Methode übergeben werden sollten? Sollten sie in ein einzelnes Objekt eingekapselt werden?
quelle
Die Verwendung einer Karte ist eine einfache Möglichkeit, die Anrufsignatur zu bereinigen, aber dann haben Sie ein anderes Problem. Sie müssen in den Hauptteil der Methode schauen, um zu sehen, was die Methode in dieser Map erwartet, wie die Schlüsselnamen lauten oder welche Typen die Werte haben.
Ein sauberer Weg wäre, alle Parameter in einer Objekt-Bean zu gruppieren, aber das behebt das Problem immer noch nicht vollständig.
Was Sie hier haben, ist ein Designproblem. Mit mehr als 7 Parametern für eine Methode werden Sie Probleme haben, sich daran zu erinnern, was sie darstellen und in welcher Reihenfolge sie sind. Von hier aus erhalten Sie viele Fehler, wenn Sie die Methode in der falschen Parameterreihenfolge aufrufen.
Sie benötigen ein besseres Design der App, keine bewährte Methode, um viele Parameter zu senden.
quelle
Erstellen Sie eine Bean-Klasse, legen Sie alle Parameter fest (Setter-Methode) und übergeben Sie dieses Bean-Objekt an die Methode.
quelle
Sehen Sie sich Ihren Code an und sehen Sie, warum all diese Parameter übergeben werden. Manchmal ist es möglich, die Methode selbst umzugestalten.
Durch die Verwendung einer Karte ist Ihre Methode anfällig. Was ist, wenn jemand, der Ihre Methode verwendet, einen Parameternamen falsch schreibt oder eine Zeichenfolge veröffentlicht, in der Ihre Methode eine UDT erwartet?
Definieren Sie ein Übertragungsobjekt . Sie erhalten zumindest eine Typprüfung. Möglicherweise können Sie sogar eine Validierung am Verwendungsort durchführen, anstatt innerhalb Ihrer Methode.
quelle
Dies ist oft ein Hinweis darauf, dass Ihre Klasse mehr als eine Verantwortung trägt (dh Ihre Klasse tut ZU viel).
Siehe das Prinzip der Einzelverantwortung
für weitere Details.
quelle
Wenn Sie zu viele Parameter übergeben, versuchen Sie, die Methode umzugestalten. Vielleicht macht es eine Menge Dinge, die es nicht tun soll. Ist dies nicht der Fall, ersetzen Sie die Parameter durch eine einzelne Klasse. Auf diese Weise können Sie alles in einer einzelnen Klasseninstanz kapseln und die Instanz und nicht die Parameter weitergeben.
quelle
Ich würde sagen, bleib bei der Art und Weise, wie du es vorher getan hast. Die Anzahl der Parameter in Ihrem Beispiel ist nicht viel, aber die Alternativen sind viel schrecklicher.
Karte - Es gibt die Effizienzsache, die Sie erwähnt haben, aber das größere Problem hier sind:
anderes zu verweisen ... Haben Sie Javadocs, in denen genau angegeben ist, welche Schlüssel und
Werte verwendet werden? Wenn Sie dies tun (was großartig ist), ist es auch kein Problem, viele Parameter zu haben.
Wrapper-Objekte - dies verschiebt nur das Problem, da Sie das Wrapper-Objekt zuerst füllen müssen - anstatt direkt zu Ihrer Methode, wird es zum Konstruktor des Parameterobjekts. Ob das Verschieben des Problems angemessen ist oder nicht, hängt von der Wiederverwendung des Objekts ab. Zum Beispiel:
Würde es nicht verwenden: Es würde nur einmal beim ersten Aufruf verwendet werden, also viel zusätzlicher Code für 1 Zeile ...?
Darf es benutzen: Hier kann es ein bisschen mehr. Erstens können die Parameter für 3 Methodenaufrufe berücksichtigt werden. es kann auch 2 andere Zeilen an sich ausführen ... so wird es in gewissem Sinne zu einer Zustandsvariablen ...
Das andere, was die Leute vergessen zu berücksichtigen, ist die Rolle der IDE bei all dem. Wenn Methoden Parameter haben, generieren IDEs den größten Teil des Codes für Sie, und die roten Linien erinnern Sie daran, was Sie bereitstellen / festlegen müssen. Wenn Sie Option 3 verwenden, verlieren Sie diese vollständig. Jetzt ist es an dem Programmierer, es richtig zu machen, und es gibt keine Hinweise während der Codierungs- und Kompilierungszeit ... der Programmierer muss es testen, um es herauszufinden.
Darüber hinaus haben die Optionen 2 und 3, wenn sie unnötig weit verbreitet sind, aufgrund der großen Menge an doppeltem Code, die sie generieren, langfristige negative Auswirkungen auf die Wartung. Je mehr Code vorhanden ist, desto mehr muss gewartet werden, desto mehr Zeit und Geld wird für die Wartung aufgewendet.
quelle