2008-10-10 11 views
10

Ich habe nie einen Weg gesehen, dies schön zu machen, würde mich interessieren zu sehen, wie andere es tun. I-Format zur Zeit es wie folgt aus:Wie man Methoden mit großen Parameterlisten formatiert

public Booking createVehicleBooking(Long officeId, 
            Long start, 
            Long end, 
            String origin, 
            String destination, 
            String purpose,   
            String requirements, 
            Integer numberOfPassengers) throws ServiceException { 
/*..Code..*/ 
} 

Antwort

15

Eine große Menge von Parametern wie dies oft (aber nicht immer) ein Indikator, dass Sie ein Objekt verwenden könnte den Parametersatz darzustellen. Dies gilt insbesondere, wenn entweder:

  • Es gibt mehrere Methoden mit ähnlichen großen Parametersätzen, die mit einem einzigen Verfahren unter einem Parameterobjekt ersetzt werden können.

  • Die Methode aufgerufen wird create...

Also Ihr oben Code könnte werden (mein C verzeihen ++, ich bin ein Java-Entwickler):

class BuildVehicleBooking { 
    Long officeId; 
    Long start; 
    Long end; 
    String origin; 
    String destination; 
    String purpose;    
    String requirements; 
    Integer numberOfPassengers; 

    Booking createVehicleBooking() throws ServiceException { ... } 
} 

Dies ist die Builder Pattern . Der Vorteil dieses Musters besteht darin, dass Sie einen komplexen Satz von Parametern in Stücken erstellen können, einschließlich mehrerer Variationen darüber, wie die Parameter miteinander in Beziehung stehen, und sogar Parameter überschreiben, sobald neue Informationen verfügbar sind, bevor schließlich die Methode create aufgerufen wird .

Ein weiterer potenzieller Vorteil ist, dass Sie eine verifyParameters Methode hinzufügen können, die ihre Konsistenz überprüft, bevor Sie so weit wie creating das endgültige Objekt gehen. Dies gilt in Fällen, in denen das Erstellen des Objekts nicht umkehrbare Schritte erfordert, z. B. das Schreiben in eine Datei oder Datenbank.

Beachten Sie, dass dies, wie bei allen Mustern, nicht in jedem Fall der Fall ist und in Ihrem Fall nicht zutrifft. Wenn Ihr Code einfach genug ist, kann es sein, dass dieses Muster es überbaut. Wenn der Code unordentlich wird, kann das Refactoring in dieses Muster eine gute Möglichkeit sein, es zu vereinfachen.

+0

Leider glaube ich nicht, dass ich damit durchkommen kann, weil dies ein SOAP-Endpunkt für einen Web-Service ist, aber dennoch sehr informativ. – abarax

+0

Sie können diese Technik sogar für Web-Services verwenden. Sie müssen Ihre Klasse serialisierbar machen und möglicherweise ein Schema implementieren, abhängig davon, was Sie zum Hosten von Web-Services verwenden (Axis benötigt zum Beispiel, dass ich glaube, während asp.net es für Sie behandelt) – Jeremy

+1

Das Builder-Muster ist nützlich, guter Rat! Für die totale Weltherrschaft (Thread-Sicherheit), stellen Sie sicher, dass die create-Methode kopiert alle Parameter vor ihnen zu validieren. (Auch kleinere Tipps:. Verwenden Sie lange statt Lon, statt Integer int und Getter/Setter-Methoden zur Verfügung stellen) – volley

8
public Booking createVehicleBooking(
    Long officeId, 
    Long start, 
    Long end, 
    String origin, 
    String destination, 
    String purpose,     
    String requirements, 
    Integer numberOfPassengers) 

throws ServiceException { 
/*..Code..*/ 
} 
+0

Wenn es mehrere Ausnahme geworfen wird, führen Sie jede vertikal auch aus? –

+0

Chris - hängt davon ab, wie viele. Wenn genug, dass es von der Seite des Bildschirms läuft, ja. Allgemeine Regel ist: Wenn es von der Seite läuft, richten Sie sie aus. Wenn der Funktionsname zu lang ist, verschachteln und einrücken. –

+1

das ist ziemlich nett. Die einzige Änderung, die ich vornehmen würde, ist, die schließende Klammer auf dieselbe Zeile wie die "Würfe" zu verschieben, so dass Sie leicht erkennen können, dass sie Teil einer größeren Anweisung ist. – nickf

3

Ich bin geneigt, mit mehreren Objekten statt nur einem zu gehen.

So wird es

public Booking createVehicleBooking(Long officeId, DateRange dates, TripDetails trip) 

Während Daterange und Reise Details nur die relevanten Teile der Daten enthalten. Obwohl der dateRange Teil der Reise sein könnte, während Anforderungen und Anzahl der Passagiere von TripDetails remoived werden könnten und Teil der Anfrage waren.

In der Tat gibt es mehrere Möglichkeiten, die Daten zu würfeln, aber ich würde sagen, Ihre große Liste in Gruppen verwandter Parameter zu brechen und ein Objekt für sie zu bauen, wird einen klareren Programmierstil ermöglichen und die Wiederverwendung erhöhen.

Und denken Sie daran es immer möglich ist, Objekte im Objekt einzubetten so dass Sie

public Booking createVehicleBooking(BookingParameters parameters) 

haben, während BookingParameters TripDetails Enthält und Daterange-Objekte sowie die anderen Parameter.

+0

Diese Frage betrifft Formatierung. (Manchmal müssen Sie mit der Code-Basis arbeiten, die Sie vor dem Refactoring eingegeben haben ;-) –

2

auf der rufenden Seite ich dies durch die Verwendung Kommentaren wie benannte Parameter simulieren möchten:

booking.createVehicleBooking(
    getOfficeId(),  // Long officeId 
    startVariable,  // Long start 
    42,     // Long end 
    getOrigin(),  // String origin 
    "destination",  // String destination 
    "purpose",   // String purpose  
    "requirements",  // String requirements 
    3     // Integer numberOfPassengers 
); 
1

Ich mag die eine param pro Zeile Ansatz, die Sie zeigt. Ich finde es sehr einfach, es visuell zu scannen und zu sehen, was da ist.

Ich finde, dass, wenn die Leute so etwas wie Guice verwenden oft Sie mit einer großen Anzahl von params am Ende und das macht es leichter zu lesen.

+0

Wenn Sie eine andere Frage haben, klicken Sie bitte auf die Schaltfläche [Frage stellen] (// stackoverflow.com/questions/ask). – manetsus

+0

Manetsus, welcher Teil meines Textes lässt dich glauben, dass es eine Frage ist? Ich habe darauf hingewiesen, dass es eine Reihe von Bibliotheken von Drittanbietern gibt, die am Ende mit vielen Parametern aufrufen, wo eine vertikale Liste von Parametern das Lesen erleichtert. – Evvo

1

Die Google Java Style Guide bedeutet dies nicht direkt ansprechen, aber ich stimme mit, wie sie in der Guave formatiert Dinge haben, dh

In com.google.common.collect.Collections2.transform:

public static <F, T> Collection<T> transform(
    Collection<F> fromCollection, Function<? super F, T> function) { 
    return new TransformedCollection<>(fromCollection, function); 
} 

In com.google.common.collect.ImmutableRangeMap.toImmutableRangeMap

public static <T, K extends Comparable<? super K>, V> 
    Collector<T, ?, ImmutableRangeMap<K, V>> toImmutableRangeMap(
     Function<? super T, Range<K>> keyFunction, 
     Function<? super T, ? extends V> valueFunction) { 
    return CollectCollectors.toImmutableRangeMap(keyFunction, valueFunction); 
} 

I denke, die Regeln sind:

  • (Versuchen Sie es zu halten auf einer Linie, wenn möglich)
  • Pause nach dem Methodennamen und Klammer
  • einrücken Parameter eine zusätzliche Ebene sie aus dem Körper persönlich

zu unterscheiden, ziehe ich zu brechen nach jedem Parameter, wenn ich überhaupt brechen muss, dh

public static Foo makeFoo(
    Foo foo, 
    Bar bar, 
    Baz baz) 
     throws FooException { 
    f(); 
} 
Verwandte Themen