Когда метод имеет слишком много параметров?
При отладке кода клиента веб-сервиса сегодня (в Java, с jax-ws) я столкнулся с методом веб-сервиса с умопомрачительным количеством 97 параметров!
Мне пришлось создать тестовый пример, который вызывает этот метод, и я заметил несколько вещей:
- Кодовая помощь / наведение не очень хорошо масштабируется. Я использую Eclipse, а всплывающая подсказка над методом имеет ширину экрана и охватывает несколько строк.
- Мне пришлось копировать значения параметров из предыдущего захвата xml, и было практически невозможно вспомнить «где я» – когда у меня был указатель, расположенный после запятой, и, прежде чем вводить какое-то значение, я часто ошибочно использовал тип данных – я набрал Integer вместо String и наоборот.
- Даже после того, как я написал все параметры, у меня все еще были некоторые ошибки, и подпись не соответствовала. К сожалению, Eclipse отмечает всю строку в красном как ошибку, так что найти, где ошибка занимает еще больше времени 🙁
Итак, это заставило меня задуматься, как вы думаете, это максимальное разумное количество параметров для метода? И если вы можете изменить эту подпись веб-сервиса, как вы думаете, ее можно улучшить?
- Когда использовать значения без знака над подписанными?
- Что такое экзистенциальный тип?
- Система типов в Scala завершена. Доказательство? Пример? Выгоды?
- Что такое магическое число, и почему это плохо?
- Сложны ли зависимости круговых classов от стиля стиля кодирования?
- Передавать по ссылке или передавать по значению?
- Является ли использование многих статических методов плохим?
- Когда это делать?
- Почему писать закрытый TCP-разъем хуже, чем читать?
- Случай использования в реальном мире побитовых операторов
- Проверить петли сверху или снизу? (while vs. do while)
- Пока против
- Что такое функция батута?
Нет четкого предела, но мне неудобно более 3-4 параметров. AFAIR Дядя Боб Мартин в « Чистом кодексе» рекомендует максимум 3.
Существует несколько рефакторингов для уменьшения количества параметров метода (подробнее см. « Эффективная работа с устаревшим кодом » Майкла Перса). Это приходит мне на ум:
- инкапсулировать многие связанные параметры в один объект (например, вместо
String surName, String firstName, String streetAddress, String phoneNumber
передать объектPerson
содержащий эти поля) - передавать параметры в конструкторе или других вызовах метода до вызова этого метода
Когда вы должны спросить, это, вероятно, слишком много.
Как говорит Стив Макконнелл в Code Complete , золотое правило составляет 4 +/- 3 параметра. Для обычного человека трудно запомнить более 4 параметров, 5-7 следует использовать только в особых случаях, и вы никогда не должны использовать 8 или более.
Великий Будда! Девяносто семь????
Хорошая практика обычно советует о макс. от шести до восьми. Конечно, ymmv, и может быть веская причина, время от времени, девятый. Но 97 ?? !!
Несколько мыслей … это просто данные или решения принимаются на основе их ценностей?
Если многие / наиболее влияют на управление streamом, вы получаете почти незаметный (даже понятный или проверяемый) «дизайн» (для небольших значений «дизайн»).
Если это просто данные, они могут быть сгруппированы в структуры и указатели этих структур?
Есть ли у вас проектная документация? Мог бы это объяснить, что происходит.
О, и, «Опасность, Уилл Робинсон» – любой, кто открыто передаст 97 параметров, может также передать любое число – не так очевидно – как глобальные переменные.
Ps не знают, как Eclipse работает на Java, но с C / C ++, если вы поместите параметры на отдельные строки
char DoEverything( int meaninglessParameterName1, char *meaninglessParameterName2, .... long double *meaninglessParameterName97) { return !NULL;}
Eclipse фактически идентифицирует строку с плохим параметром
Хорошо, если вы сделаете объект JSON, вы можете обернуть все 97 (или больше) в этот объект и только отправить один объект.
Если его более 5-10 параметров, то создайте объект, который принимает параметры вместо этого, это может быть типизированный dataset, структура или что-то еще.
Вместо :
Mywebservice.CreateUser(Firstname, LastName, Age,Sex, Haircolor,AmountOfFingers,AmountOfTeeht,Childrens,,,,,,,,,,,,,and so on)
Делать:
Dim MyUser as new UserObject MyUser.Firstname="Stefan" ...and so on... MyWebservice.CreateUser(UserObject)
По моему собственному опыту, я обнаружил, что сигнатуры методов начинают запутываться и запоминаться с более чем 5 или 6 параметрами. И как только вы получите 10 параметров, это просто смешно.
Эти параметры действительно необходимо объединить в объект (или небольшой набор объектов), в котором хранятся все данные. В службах, которые я использую, каждая операция обслуживания всегда принимает один объект запроса и возвращает один объект Response.
Что касается веб-служб, я предпочитаю обрабатывать параметры как один объект. В то время как контракт с вашими данными может измениться, ваш серийный контракт не будет. Это делает ваши услуги более перспективными.
Для всего остального я нахожусь для 3 параметров и ocassionally идти до 5.
Ну, я бы предложил перегрузить метод, чтобы у вас были более простые реализации метода. Это может быть особенно полезно, если многие из параметров редко меняются и могут быть назначены по умолчанию. Однако, если память работает, я не думаю, что вы можете перегружать вызов веб-службы (вы должны использовать отдельное имя метода).
Другим возможным решением является инкапсуляция параметров в какой-то class метаданных, целью которого является сохранение параметров. Это упростило бы подпись метода. Однако в некоторых отношениях вы просто выгружаете проблему в class параметров. Но, если параметры можно отнести к темам, эта техника может быть использована путем использования нескольких classов метаданных, каждая из которых будет включена в качестве параметра для веб-службы. Это должно упростить вещи и помочь вам обмануть этого монстра.
Наконец, трудно сказать без каких-либо подробностей, но, безусловно, этот код является серьезным кандидатом на рефакторинг. У меня нет жесткого правила относительно количества параметров для метода, кроме того, чтобы принять общий принцип простоты и удобочитаемости.