Лучшая практика для передачи многих аргументов методу?

Иногда, мы имеем к методам записи, которые получают много много аргументов, например:

public void doSomething(Object objA , Object objectB ,Date date1 ,Date date2 ,String str1 ,String str2 )
{
}

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

Map<Object,Object> params = new HashMap<Object,Object>();
params.put("objA",ObjA) ;

......

public void doSomething(Map<Object,Object> params)
{
 // extracting params 
 Object objA = (Object)params.get("objA");
 ......
 }

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

81
задан Vadim Kotov 14 August 2017 в 12:57
поделиться

14 ответов

В Эффективная Java , глава 7 (Методы), пункт 40 (Тщательно проектируйте сигнатуры методов), Блох пишет:

Существует три метода сокращения слишком длинных списков параметров:

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

Чтобы узнать подробности, советую купить книгу, она того стоит.

121
ответ дан 24 November 2019 в 09:24
поделиться

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

0
ответ дан 24 November 2019 в 09:24
поделиться

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

Более понятным способом было бы сгруппировать все параметры в объектном компоненте, но это все еще не решает проблему полностью.

Здесь проблема дизайна. Если в методе более 7 параметров, у вас начнутся проблемы с запоминанием того, что они представляют и в каком порядке. Отсюда вы получите множество ошибок, просто вызвав метод в неправильном порядке параметров.

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

2
ответ дан 24 November 2019 в 09:24
поделиться

Хорошей практикой будет рефакторинг. Что насчет этих объектов означает, что они должны быть переданы в этот метод? Должны ли они быть инкапсулированы в один объект?

2
ответ дан 24 November 2019 в 09:24
поделиться

Во-первых, я бы попытался реорганизовать метод. Если он использует такое количество параметров, это может оказаться слишком длинным. Его разрушение улучшило бы код и потенциально уменьшило бы количество параметров для каждого метода. Вы также можете провести рефакторинг всей операции до ее собственного класса. Во-вторых, я бы поискал другие случаи, когда я использую тот же (или расширенный набор) того же списка параметров. Если у вас несколько экземпляров, это, скорее всего, сигнализирует о том, что эти свойства принадлежат друг другу. В этом случае создайте класс для хранения параметров и его использования. Наконец, я бы оценил, оправдывает ли количество параметров создание объекта карты для улучшения читаемости кода. Я думаю, что это личное дело каждого - это решение сопряжено с трудностями, и точки компромисса могут отличаться. По шести параметрам я, наверное, не стал бы этого делать. Для 10 я бы, вероятно, сделал бы (если бы ни один из других методов сначала не сработал).

10
ответ дан 24 November 2019 в 09:24
поделиться

Это называется «Введение объекта параметра». Если вы обнаружите, что передаете один и тот же список параметров в нескольких местах, просто создайте класс, содержащий их все.

XXXParameter param = new XXXParameter(objA, objB, date1, date2, str1, str2);
// ...
doSomething(param);

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

Это, конечно же, общая философия, и, поскольку вы не предоставили никаких подробностей, я также не могу дать вам более подробный совет.: -)

12
ответ дан 24 November 2019 в 09:24
поделиться

Вы можете создать класс для хранения этих данных. Хотя он должен быть достаточно значимым, но намного лучше, чем использование карты (OMG).

5
ответ дан 24 November 2019 в 09:24
поделиться

Создайте класс bean, установите все параметры (метод setter) и передайте этот объект bean методу.

1
ответ дан 24 November 2019 в 09:24
поделиться

Code Complete * предлагает несколько вещей:

  • «Ограничьте количество параметров процедуры примерно семью. Семь - это магическое число для понимания людей» (стр. 108).
  • «Поместите параметры в порядке ввода-изменения-вывода ... Если несколько подпрограмм используют похожие параметры, поместите аналогичные параметры в согласованном порядке» (стр. 105).
  • Переменные состояния или ошибки помещаются последними.
  • Как упоминалось в tvanfosson , передавать только те части структурированных переменных (объектов), которые необходимы программе. Тем не менее, если вы используете большую часть структурированной переменной в функции, просто передайте всю структуру, но имейте в виду, что это в некоторой степени способствует связыванию.

* Первое издание, я знаю, что надо обновить. Кроме того, вполне вероятно, что некоторые из этих советов могли измениться со времени написания второго издания, когда ООП начинало становиться более популярным.

4
ответ дан 24 November 2019 в 09:24
поделиться

Существует шаблон, который называется Объект параметра .

Идея состоит в том, чтобы использовать один объект вместо всех параметров. Теперь, даже если вам понадобится добавить параметры позже, вам просто нужно добавить их к объекту. Интерфейс метода остался прежним.

6
ответ дан 24 November 2019 в 09:24
поделиться

Использование карты с магическими ключами String - плохая идея. Вы теряете любую проверку во время компиляции, и неясно, какие параметры требуются. Вам придется написать очень полную документацию, чтобы компенсировать это. Вспомните ли вы через несколько недель, что это за строки, не заглядывая в код? А что если вы сделаете опечатку? Использовали не тот тип? Вы не узнаете об этом, пока не запустите код.

Вместо этого используйте модель. Создайте класс, который будет контейнером для всех этих параметров. Таким образом, вы сохраните безопасность типов Java. Вы также можете передавать этот объект другим методам, помещать его в коллекции и т.д.

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

68
ответ дан 24 November 2019 в 09:24
поделиться

Если у вас много необязательных параметров, вы можете создать плавный API: замените один метод цепочкой методов

exportWithParams().datesBetween(date1,date2)
                  .format("xml")
                  .columns("id","name","phone")
                  .table("angry_robots")
                  .invoke();

Используя статический импорт, вы можете создать внутренний плавный API:

... .datesBetween(from(date1).to(date2)) ...
24
ответ дан 24 November 2019 в 09:24
поделиться
  • Посмотрите на свой код и поймите, почему передаются все эти параметры. Иногда можно провести рефакторинг самого метода.

  • Использование карты делает ваш метод уязвимым. Что, если кто-то, использующий ваш метод, неправильно напишет имя параметра или отправит строку, в которой ваш метод ожидает UDT?

  • Определите Transfer Object . Это как минимум обеспечит вам проверку типов; возможно, вы даже сможете выполнить некоторую проверку в точке использования, а не внутри вашего метода.

0
ответ дан 24 November 2019 в 09:24
поделиться

Это часто является признаком того, что ваш класс несет более одной ответственности (т.е. ваш класс делает слишком много).

См. Принцип единой ответственности

для более подробной информации.

0
ответ дан 24 November 2019 в 09:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: