2010-06-10 4 views
3

Часто методы времени принимают более трех параметров, которые имеют одинаковый тип, например.Параметры метода путаницы

void mymethod (String param1, String param2, String param3) 

, то это очень легко для клиента перепутать заказы параметров, например, инвертирующий param1 и Param2:

mymethod (param2, param1, param3); 

... что может быть причиной большого количества времени, затраченного отладки, что должно быть тривиальным вопросом. Любые советы о том, как избежать такой ошибки (кроме модульных тестов)?

ответ

7
+0

Это дерьмо, серия множества параметров String не является безопасным по типу, поскольку ее очень легко транспонировать неправильный параметр в неправильном месте. Посмотрите на мой ответ для лучшего примера. В этом конкретном случае компилятор может помочь вам заметить ошибки, потому что один неверный параметр вводит в неправильное место. Используйте его ... –

+0

Я согласен с mP, именованные параметры imho подходят только в том случае, если у метода есть несколько необязательных комбинаций параметров (что часто означает, что в любом случае должны быть несколько методов или по-разному типизированные параметры). – dbemerlin

0

На других языках, которые их поддерживают, использование названных параметров является очевидным способом справиться с этим. http://www.artima.com/weblogs/viewpost.jsp?thread=118828 содержит несколько советов, в том числе способ предоставить поддельные именованные параметры в Java.

-1

Если ваш метод принимает более 4 параметров, то у вас есть уродливый API.

Почему все ваши типы параметров Строки. Имеет ли смысл создавать классы для представления этих значений типа String, а не просто использовать String для everthing.

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

Person create(FirstName firstName, LastName lastName, Address address); 

Часто программы используют строку в качестве контейнера для всех видов данных, whcih приводит к плохим программам, редко проверяют их данные. Создавая специальные классы, даже если они содержат одно свойство String, можно добавить некоторую проверку на завод и точно знать, что это допустимое значение. Естественно, ваши струнные контейнеры также должны быть неизменными - у геттеров только нет сеттеров.

Посмотрите на Java Puzzlers от Джоша Блоха, чтобы узнать больше советов и мудрости.

+0

В вашем примере было бы лучше использовать класс Name со свойствами FirstName и LastName, устраняя необходимость в одном параметре ... который (я думаю) именно то, что вы пытаетесь объяснить. – dbemerlin

+0

Не совсем. Многие маленькие классы лучше, чем крупные, делают все классы. Создавая семью людей, лучше создать LastName один раз и передать его, каждый из которых создал людей. Это означает, что фамилию нужно проверять только один раз, а не один раз для каждого члена семьи. Если у кого-то в семье есть другая фамилия, то естественно создать другое LastName. –

+0

Могут быть и случаи, когда Person имеет несколько заданных имен, каждое из которых представлено экземпляром FirstName. Возможно, в этом случае имя GivenName будет лучшим именем класса. В любом случае принцип применяется, если наши классы небольшие и простые, мы можем объединить их вместе, чтобы собрать более полезные классы. Из моего дальнейшего примера видно, что мое предложение бесконечно лучше и более расширяемо. –

1

Лучшее решение было бы использовать классы данных вместо многих параметров. Похоже, вы слишком полагаетесь на примитивные объекты (строки, ints, ...), просто создавайте классы для связанных данных. Если нет хорошего отношения, вы также можете использовать классы с одним свойством, таким образом компилятор будет жаловаться, если порядок неверен, а ваш код является расширяемым, если вам в какой-то момент нужно больше свойств (т. Е. Метод теперь не просто требуется имя элемента, но также идентификатор).

Если это не вариант, то вы можете попробовать придерживаться шаблона для упорядочения параметров (что-то вдоль линий «параметра 1 всегда исходная строка, ...)

4

Используйте Javadoc, это является вашим другом.

с любой хороший IDE, делая мыши над именем метода должно дать вам окно наконечника инструмента с полезной информацией.
Я знаю, что с Eclipse, если ваш Javadoc использует @param метка, ваши шансы на путаницу, какой параметр сильно снизится.

+0

высоко оценил, что диск с голосом, кто бы вы ни были. пожалуйста, объясните нам, как вы чувствуете, что документация - это плохо? – JustJeff

-1

Лучше всего на Java создать простой параметр JavaBean, то есть простой старый объект Java (POJO), с геттерами и сеттерами для каждого из параметров. Затем, ваш метод подписи может быть:

void mymethod (Parameters parametersObject) 

и параметры JavaBean бы setParam1 (...), setParam2 (...), setParam3 (...) и т. д., а также могут выполнять некоторую базовую внутреннюю проверку, предоставлять значения по умолчанию и т. д.

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

3

Как указано в ответе на лету. Именованные параметры очень помогли бы, и вы можете эмулировать что-то подобное на Java, как описано в этом question.

В большинстве случаев, особенно если вы используете api, который используется третьими лицами, вы хотите иметь объекты данных, которые хранят параметры для конструкторов или методов, которые принимают более трех параметров. Это шаблон под названием parameter objects. Это позволяет вам выполнять проверку ввода в объекте параметра и поддерживать методы чистыми и т. Д.

Если вы создаете объект параметра, который имеет только сеттеры, у вас есть четкое именование для того, чтобы клиент мог видеть, куда его поместить. Как и в этом примере:

public printAddress(String name, String street, String city) {...} 
print address(name, street, city); 

Если вы используете объект параметра у вас есть что-то подобное:

public printAddress(Address address) {...} 

Address address = new Address(); 
address.setName(name); 
address.setStreet(street); 
address.setCity(city); 

printAddress(address); 

Это больше кода, но это будет гораздо более удобным для чтения. Если вы хотите уменьшить количество требуемых кодов, вы можете пойти с method chaining. Заставьте сеттеры вернуть объект, над которым они работают. Теперь код будет выглядеть следующим образом:

public printAddress(Address address) {...} 
printAddress(new Address().setName(name).setStreet(street).setCity(city)) 

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

Смежные вопросы