Иногда, мы имеем к методам записи, которые получают много много аргументов, например:
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");
......
}
Это не хорошая практика, инкапсулируйте параметрические усилители в карту, полностью трата эффективности. Хорошая вещь, чистая подпись, легкая добавить другие параметрические усилители с наименьшим количеством модификации. какова лучшая практика для этого вида проблемы?
В Эффективная Java , глава 7 (Методы), пункт 40 (Тщательно проектируйте сигнатуры методов), Блох пишет:
Существует три метода сокращения слишком длинных списков параметров:
Чтобы узнать подробности, советую купить книгу, она того стоит.
Если вы передаете слишком много параметров, попробуйте выполнить рефакторинг метода. Может быть, он делает много вещей, которых не должен делать. Если это не так, попробуйте заменить параметры одним классом. Таким образом, вы можете инкапсулировать все в один экземпляр класса и передавать экземпляр, а не параметры.
Использование карты - простой способ очистить сигнатуру вызова, но тогда возникает другая проблема. Вам нужно заглянуть внутрь тела метода, чтобы увидеть, что метод ожидает в этой карте, каковы имена ключей или какие типы имеют значения.
Более понятным способом было бы сгруппировать все параметры в объектном компоненте, но это все еще не решает проблему полностью.
Здесь проблема дизайна. Если в методе более 7 параметров, у вас начнутся проблемы с запоминанием того, что они представляют и в каком порядке. Отсюда вы получите множество ошибок, просто вызвав метод в неправильном порядке параметров.
Вам нужен лучший дизайн приложения, а не лучшая практика для отправки большого количества параметров.
Хорошей практикой будет рефакторинг. Что насчет этих объектов означает, что они должны быть переданы в этот метод? Должны ли они быть инкапсулированы в один объект?
Во-первых, я бы попытался реорганизовать метод. Если он использует такое количество параметров, это может оказаться слишком длинным. Его разрушение улучшило бы код и потенциально уменьшило бы количество параметров для каждого метода. Вы также можете провести рефакторинг всей операции до ее собственного класса. Во-вторых, я бы поискал другие случаи, когда я использую тот же (или расширенный набор) того же списка параметров. Если у вас несколько экземпляров, это, скорее всего, сигнализирует о том, что эти свойства принадлежат друг другу. В этом случае создайте класс для хранения параметров и его использования. Наконец, я бы оценил, оправдывает ли количество параметров создание объекта карты для улучшения читаемости кода. Я думаю, что это личное дело каждого - это решение сопряжено с трудностями, и точки компромисса могут отличаться. По шести параметрам я, наверное, не стал бы этого делать. Для 10 я бы, вероятно, сделал бы (если бы ни один из других методов сначала не сработал).
Это называется «Введение объекта параметра». Если вы обнаружите, что передаете один и тот же список параметров в нескольких местах, просто создайте класс, содержащий их все.
XXXParameter param = new XXXParameter(objA, objB, date1, date2, str1, str2);
// ...
doSomething(param);
Даже если вы не так часто передаете один и тот же список параметров, этот простой рефакторинг все равно улучшит читаемость вашего кода, что всегда хорошо. Если вы посмотрите на свой код через 3 месяца, вам будет легче понять, когда вам нужно исправить ошибку или добавить функцию.
Это, конечно же, общая философия, и, поскольку вы не предоставили никаких подробностей, я также не могу дать вам более подробный совет.: -)
Вы можете создать класс для хранения этих данных. Хотя он должен быть достаточно значимым, но намного лучше, чем использование карты (OMG).
Создайте класс bean, установите все параметры (метод setter) и передайте этот объект bean методу.
Code Complete * предлагает несколько вещей:
* Первое издание, я знаю, что надо обновить. Кроме того, вполне вероятно, что некоторые из этих советов могли измениться со времени написания второго издания, когда ООП начинало становиться более популярным.
Существует шаблон, который называется Объект параметра .
Идея состоит в том, чтобы использовать один объект вместо всех параметров. Теперь, даже если вам понадобится добавить параметры позже, вам просто нужно добавить их к объекту. Интерфейс метода остался прежним.
Использование карты с магическими ключами String - плохая идея. Вы теряете любую проверку во время компиляции, и неясно, какие параметры требуются. Вам придется написать очень полную документацию, чтобы компенсировать это. Вспомните ли вы через несколько недель, что это за строки, не заглядывая в код? А что если вы сделаете опечатку? Использовали не тот тип? Вы не узнаете об этом, пока не запустите код.
Вместо этого используйте модель. Создайте класс, который будет контейнером для всех этих параметров. Таким образом, вы сохраните безопасность типов Java. Вы также можете передавать этот объект другим методам, помещать его в коллекции и т.д.
Конечно, если набор параметров не будет использоваться в других методах или передаваться по кругу, специальная модель может оказаться излишней. Необходимо соблюдать баланс, поэтому руководствуйтесь здравым смыслом.
Если у вас много необязательных параметров, вы можете создать плавный API: замените один метод цепочкой методов
exportWithParams().datesBetween(date1,date2)
.format("xml")
.columns("id","name","phone")
.table("angry_robots")
.invoke();
Используя статический импорт, вы можете создать внутренний плавный API:
... .datesBetween(from(date1).to(date2)) ...
Посмотрите на свой код и поймите, почему передаются все эти параметры. Иногда можно провести рефакторинг самого метода.
Использование карты делает ваш метод уязвимым. Что, если кто-то, использующий ваш метод, неправильно напишет имя параметра или отправит строку, в которой ваш метод ожидает UDT?
Определите Transfer Object . Это как минимум обеспечит вам проверку типов; возможно, вы даже сможете выполнить некоторую проверку в точке использования, а не внутри вашего метода.
Это часто является признаком того, что ваш класс несет более одной ответственности (т.е. ваш класс делает слишком много).
См. Принцип единой ответственности
для более подробной информации.