2008-10-10 23 views
10

Nigdy nie widziałem sposobu, aby to ładnie zrobić, chciałbym zobaczyć, jak inni to robią. Obecnie sformatować go tak:Jak formatować metody z dużymi listami parametrów

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

Odpowiedz

15

Duży zestaw parametrów, jak to często (ale nie zawsze) to wskaźnik, który może być używany obiekt do reprezentowania zestaw parametrów. Jest to szczególnie prawdziwe, jeśli:

  • Istnieje kilka metod o podobnych dużych zestawów parametrów, które mogą zostać zastąpione jednym sposobie podejmowania obiektu parametru.

  • Metoda nazywa create...

Więc powyższy kod może stać się (przepraszam mój C++, jestem programistą Java):

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

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

To Wzór Builder . Zaletą tego schematu jest to, że można zbudować złożony zestaw parametrów w częściach, w tym wiele odmian dotyczących wzajemnego powiązania parametrów, a nawet nadpisanie parametrów w miarę pojawiania się nowych informacji, zanim ostatecznie wywołają metodę create na końcu. .

Inną potencjalną zaletą jest to, że można dodać metodę verifyParameters, która sprawdzała ich konsystencję, zanim przejdziemy do ostatecznego obiektu o wartości creating. Ma to zastosowanie w przypadkach, gdy tworzenie obiektu obejmuje nieodwracalne kroki, takie jak zapis do pliku lub bazy danych.

Należy pamiętać, że tak jak w przypadku wszystkich wzorów, nie ma to zastosowania w każdym przypadku i może nie mieć zastosowania w Twoim przypadku. Jeśli twój kod jest wystarczająco prosty, to ten wzorzec może nadużywać go. Jeśli kod jest coraz brudny, refactoring do tego schematu może być dobrym sposobem na jego uproszczenie.

+0

Niestety nie sądzę, że mogę sobie z tym poradzić, ponieważ jest to punkt końcowy SOAP dla usługi internetowej, ale mimo to bardzo informatywny. – abarax

+0

Możesz bezwzględnie stosować tę technikę, nawet w przypadku usług internetowych. Musisz uczynić klasę serializowalną i potencjalnie wdrożyć schemat w zależności od tego, czego używasz do hostowania usług sieciowych (oś, na przykład będzie wymagać, jak sądzę, a asp.net zajmie się dla ciebie) – Jeremy

+1

Wzorzec budowniczego jest przydatny, dobra rada! Aby uzyskać całkowitą dominację nad światem (bezpieczeństwo wątków), upewnij się, że metoda create kopiuje wszystkie parametry przed sprawdzeniem poprawności. (Także, drobne wskazówki: używaj długich zamiast Lon, int zamiast Integer i zapewnij metody getter/setter.) – 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

Jeśli istnieje wiele wyjątków zgłoszonych, to czy wyrównuję każdy z nich pionowo? –

+0

Chris - zależy od tego, ile. Jeśli wystarczy, że ucieknie z boku ekranu, tak. Ogólna zasada brzmi: jeśli wybiegnie z boku, wyrównaj je. Jeśli nazwa funkcji jest zbyt długa, zagnieżdż i wcięcie. –

+1

to całkiem miłe. jedyną zmianą, jakiej dokonam, jest przesunięcie zamykającego nawiasu na tę samą linię, co "rzuty", abyś mógł łatwo zauważyć, że jest częścią większego zdania. – nickf

3

Jestem skłonny podchodzić do tego z kilkoma przedmiotami zamiast tylko jednym.

więc staje się to

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

Podczas DATERANGE i szczegóły podróży zawierać jedynie odpowiednie porcje danych. Chociaż prawdopodobnie dataRange może być częścią podróży, podczas gdy wymagania i liczba pasażerów może zostać usunięta z TripDetails i włączyła część żądania.

W rzeczywistości istnieje kilka sposobów na krojenie danych, ale musiałem powiedzieć, że podzielenie dużej listy na grupy powiązanych parametrów i zbudowanie dla nich obiektu pozwoli na wyraźniejszy styl programowania i zwiększy możliwość ponownego wykorzystania.

I pamiętaj, to jest zawsze możliwe imbed obiektów w tym samym obiekcie co pozwala mieć

public Booking createVehicleBooking(BookingParameters parameters) 

Podczas BookingParameters Zawiera TripDetails i DATERANGE obiektów, jak również innych parametrów.

+0

To pytanie dotyczy formatowania. (Czasami musisz pracować z kodem podanym przed refaktoryzacją ;-) –

2

Na stronie wywołującego lubię symulować nazwanych parametrów za pomocą komentarzy tak:

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

Lubię jedno param za podejściem linii, że jesteś pokazano. Uważam, że bardzo łatwo jest go zeskanować wizualnie i zobaczyć, co jest obecne.

Uważam, że gdy ludzie używają czegoś takiego jak Guice, często kończy się to dużą liczbą paramerów, co ułatwia czytanie.

+0

Jeśli masz inne pytanie, zadaj je, klikając przycisk "Zadaj pytanie" (// stackoverflow.com/questions/ask). – manetsus

+0

Manetsus, która część mojego tekstu sprawia, że ​​myślisz, że to jest pytanie? Wskazałem, że istnieje wiele bibliotek zewnętrznych, które kończą wywoływanie z wieloma parametrami, gdzie posiadanie pionowej listy parametrów ułatwia czytanie. – Evvo

1

Google Java Style Guide nie odnosi się to bezpośrednio, ale zgadzam się z tym, jak oni sformatowanych rzeczy w guawy, tj

W 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); 
} 

W 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 uważam, że obowiązują następujące zasady:

  • (Staraj się trzymać go w jednej linii jeśli to możliwe)
  • przerwy po nazwie metody i klamra
  • wcięcie parametrów jeden dodatkowy poziom, aby odróżnić je od ciała

Osobiście wolę złamać po każdym parametrze, jeśli mam w ogóle przerwać, tj.

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