Как форматировать методы с большими списками параметров

Я никогда не видел способа сделать это красиво, мне было бы интересно увидеть, как это делают другие. В настоящее время я отформатирую его следующим образом:

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

Ответ 1

Большой набор таких параметров часто (но не всегда) является индикатором того, что вы можете использовать объект для представления набора параметров. Это особенно верно, если:

  • Существует несколько методов с похожими большими наборами параметров, которые могут быть заменены одним методом, берущим объект параметра.

  • Метод называется create...

Таким образом, ваш вышеприведенный код может стать (pardon my С++, я разработчик Java):

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

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

Это шаблон Builder. Преимущество этого шаблона состоит в том, что вы можете создавать сложный набор параметров в кусках, включая множественные варианты того, как параметры связаны друг с другом, и даже переписывать параметры по мере поступления новой информации, прежде чем, наконец, вызвать метод create в конец.

Другим потенциальным преимуществом является то, что вы можете добавить метод verifyParameters, который проверял их консистенцию, прежде чем доходить до creating конечного объекта. Это применимо в случаях, когда создание объекта связано с необратимыми шагами, такими как запись в файл или базу данных.

Обратите внимание, что, как и во всех шаблонах, это не применяется в каждом случае и может не применяться в вашем. Если ваш код достаточно прост, то этот шаблон может быть чрезмерным. Если код становится беспорядочным, рефакторинг в этот шаблон может быть хорошим способом его упрощения.

Ответ 2

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

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

Ответ 3

Я склоняюсь к этому с несколькими объектами, а не с одним.

Таким образом, он становится

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

Хотя данные DateRange и Trip содержат только соответствующие части данных. Хотя возможно, что dateRange может быть частью поездки, в то время как требования и количество пассажиров могут быть удалены из TripDetails и сделаны частью запроса.

На самом деле существует несколько способов вырезать данные, но я должен сказать, что вы разбиваете свой большой список на группы связанных параметров, а построение объекта для них позволит создать более четкий стиль программирования и увеличить возможность повторного использования.

И помните, что всегда можно вставлять объекты в объект, что позволяет вам иметь

public Booking createVehicleBooking(BookingParameters parameters)

В то время как BookingParameters содержит объекты TripDetails и DateRange, а также другие параметры.

Ответ 4

На вызывающей стороне мне нравится имитировать именованные параметры, используя следующие комментарии:

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

Ответ 5

Мне нравится один параметр для линейного подхода, который вы показываете. Мне очень легко сканировать его визуально и посмотреть, что представляет.

Я нахожу, что, когда люди используют что-то вроде Guice, вы часто оказываетесь с большим количеством параметров, и это облегчает чтение.

Ответ 6

Руководство по стилю Google Java не затрагивает это напрямую, но я согласен с тем, как они форматировали вещи в Guava, то есть

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

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

Я думаю, что следующие правила:

  • (По возможности старайтесь держать его на одной линии)
  • Перерыв после имени метода и скобки
  • Отметьте параметры одного дополнительного уровня, чтобы отличить их от тела.

Лично я предпочитаю прерывать после каждого параметра, если мне нужно вообще сломаться, т.е.

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