Иногда нам приходится писать методы, которые получают много аргументов, например:
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");
......
}
Это не очень хорошая практика, инкапсуляция параметров в карту - полная потеря эффективности. Хорошо то, что чистая подпись позволяет легко добавлять другие параметры с минимальным количеством изменений. что лучше всего подходит для такого рода проблем?
Использование карты с волшебными клавишами String - плохая идея. Вы теряете любую проверку времени компиляции, и действительно неясно, какие параметры требуются. Вам нужно будет написать очень полную документацию, чтобы это исправить. Вы вспомните через несколько недель, что это за строки, не глядя на код? Что, если вы допустили опечатку? Используете неправильный тип? Вы не узнаете, пока не запустите код.
Вместо этого используйте модель. Создайте класс, который будет контейнером для всех этих параметров. Таким образом вы сохраните безопасность типов Java. Вы также можете передать этот объект другим методам, поместить его в коллекции и т. Д.
Конечно, если набор параметров нигде не используется или не передается, специализированная модель может оказаться излишней. Необходимо найти баланс, поэтому руководствуйтесь здравым смыслом.
источник
Если у вас много необязательных параметров, вы можете создать свободный API: замените один метод цепочкой методов
exportWithParams().datesBetween(date1,date2) .format("xml") .columns("id","name","phone") .table("angry_robots") .invoke();
Используя статический импорт, вы можете создавать внутренние плавные API:
источник
Это называется «Введение объекта параметра». Если вы обнаружите, что передаете один и тот же список параметров в нескольких местах, просто создайте класс, содержащий их все.
XXXParameter param = new XXXParameter(objA, objB, date1, date2, str1, str2); // ... doSomething(param);
Даже если вы не так часто передаете один и тот же список параметров, этот простой рефакторинг все равно улучшит читаемость вашего кода, что всегда хорошо. Если вы посмотрите на свой код через 3 месяца, вам будет легче понять, когда вам нужно исправить ошибку или добавить функцию.
Конечно, это общая философия, и, поскольку вы не предоставили никаких деталей, я также не могу дать вам более подробный совет. :-)
источник
XXXParameter param = new XXXParameter();
доступный, а затем использоватьXXXParameter.setObjA(objA)
; и т.д ...Сначала я бы попробовал реорганизовать метод. Если он использует такое количество параметров, это может оказаться слишком длинным. Его разрушение улучшило бы код и потенциально уменьшило бы количество параметров для каждого метода. Вы также можете провести рефакторинг всей операции до ее собственного класса. Во-вторых, я бы поискал другие случаи, когда я использую тот же (или расширенный набор) того же списка параметров. Если у вас несколько экземпляров, это, вероятно, сигнализирует о том, что эти свойства принадлежат друг другу. В этом случае создайте класс для хранения параметров и его использования. Наконец, я бы оценил, оправдывает ли количество параметров создание объекта карты для улучшения читаемости кода. Я думаю, что это личное дело каждого - это решение сопряжено с трудностями, и точки компромисса могут отличаться. По шести параметрам я, наверное, не стал бы этого делать. Для 10 я бы, вероятно, сделал бы (если бы ни один из других методов сначала не сработал).
источник
Это часто проблема при построении объектов.
В этом случае используйте шаблон объекта построителя , он хорошо работает, если у вас большой список параметров и не всегда нужны все они.
Вы также можете адаптировать его к вызову метода.
Это также значительно увеличивает удобочитаемость.
public class BigObject { // public getters // private setters public static class Buider { private A f1; private B f2; private C f3; private D f4; private E f5; public Buider setField1(A f1) { this.f1 = f1; return this; } public Buider setField2(B f2) { this.f2 = f2; return this; } public Buider setField3(C f3) { this.f3 = f3; return this; } public Buider setField4(D f4) { this.f4 = f4; return this; } public Buider setField5(E f5) { this.f5 = f5; return this; } public BigObject build() { BigObject result = new BigObject(); result.setField1(f1); result.setField2(f2); result.setField3(f3); result.setField4(f4); result.setField5(f5); return result; } } } // Usage: BigObject boo = new BigObject.Builder() .setField1(/* whatever */) .setField2(/* whatever */) .setField3(/* whatever */) .setField4(/* whatever */) .setField5(/* whatever */) .build();
Вы также можете поместить логику проверки в методы Builder set .. () и build ().
источник
final
? Это главное, что мешает мне писать вспомогательные функции. Я полагаю, что могу сделать поля частными и убедиться, что я не изменяю их неправильно в коде этого класса, но я надеюсь на что-то более элегантное.Есть шаблон, который называется объектом Parameter .
Идея состоит в том, чтобы использовать один объект вместо всех параметров. Теперь, даже если вам понадобится добавить параметры позже, вам просто нужно добавить их к объекту. Интерфейс метода остался прежним.
источник
Вы можете создать класс для хранения этих данных. Тем не менее, он должен быть достаточно значимым, но намного лучше, чем использование карты (OMG).
источник
Code Complete * предлагает несколько вещей:
* Первое издание, я знаю, что мне нужно обновить. Кроме того, вполне вероятно, что некоторые из этих советов могли измениться с тех пор, как было написано второе издание, когда ООП начинало становиться более популярным.
источник
Хорошей практикой будет рефакторинг. Что насчет этих объектов означает, что они должны быть переданы в этот метод? Должны ли они быть инкапсулированы в один объект?
источник
Использование карты - это простой способ очистить подпись вызова, но тогда у вас возникает другая проблема. Вам нужно заглянуть внутрь тела метода, чтобы увидеть, что метод ожидает от этой карты, каковы имена ключей или какие типы имеют значения.
Более чистый способ - сгруппировать все параметры в объектном компоненте, но это все еще не решает проблему полностью.
Здесь проблема с дизайном. Если в методе более 7 параметров, у вас возникнут проблемы с запоминанием того, что они представляют и в каком порядке. Отсюда вы получите множество ошибок, просто вызвав метод в неправильном порядке параметров.
Вам нужен лучший дизайн приложения, а не лучшая практика для отправки большого количества параметров.
источник
Создайте класс компонента, установите все параметры (метод установки) и передайте этот объект компонента методу.
источник
Посмотрите на свой код и поймите, почему передаются все эти параметры. Иногда можно провести рефакторинг самого метода.
Использование карты делает ваш метод уязвимым. Что, если кто-то, использующий ваш метод, неправильно напишет имя параметра или отправит строку, в которой ваш метод ожидает UDT?
Определите объект передачи . Это как минимум обеспечит вам проверку типов; возможно, вы даже сможете выполнить некоторую проверку в точке использования, а не внутри вашего метода.
источник
Это часто указывает на то, что ваш класс несет более одной ответственности (т. Е. Ваш класс делает СЛИШКОМ много).
См. Принцип единой ответственности
для получения дополнительной информации.
источник
Если вы передаете слишком много параметров, попробуйте выполнить рефакторинг метода. Может быть, он делает много вещей, которых не должен делать. Если это не так, попробуйте заменить параметры одним классом. Таким образом вы можете инкапсулировать все в одном экземпляре класса и передавать экземпляр, а не параметры.
источник
Я бы посоветовал придерживаться того же пути, что и раньше. Количество параметров в вашем примере невелико, но альтернативы намного ужаснее.
Карта - Вы упомянули об эффективности, но вот более серьезная проблема:
другому ... У вас есть документация javadoc, в которой точно указано, какие ключи и
значения используются? Если да (и это здорово), то наличие большого количества параметров тоже не проблема.
Объекты-оболочки - это просто устраняет проблему, поскольку вам нужно заполнить объект-оболочку в первую очередь - вместо того, чтобы напрямую к вашему методу, это будет к конструктору объекта параметра. Определение целесообразности перемещения проблемы зависит от повторного использования указанного объекта. Например:
Не использовал бы его: он будет использоваться только один раз при первом вызове, поэтому много дополнительного кода для работы с 1 строкой ...?
Может использовать: Здесь он может немного больше. Во-первых, он может учитывать параметры для трех вызовов методов. он также может выполнять 2 другие строки сам по себе ... так что он становится в некотором смысле переменной состояния ...
Другая вещь, которую люди забывают учитывать, - это роль IDE во всем этом. Когда у методов есть параметры, IDE генерируют для вас большую часть кода, и у вас есть красные линии, напоминающие вам, что вам нужно предоставить / установить. При использовании варианта 3 ... вы полностью теряете это. Теперь программист должен сделать это правильно, и во время кодирования и компиляции нет никаких подсказок ... программист должен проверить это, чтобы узнать.
Кроме того, варианты 2 и 3, если они будут приняты широко и без необходимости, будут иметь долгосрочные негативные последствия с точки зрения обслуживания из-за большого количества генерируемого дублированного кода. Чем больше кода, тем больше нужно поддерживать, тем больше времени и денег тратится на его поддержку.
источник