Как установить значения по умолчанию на неправильные или пустые параметры метода?

В данный момент у меня есть этот код (и мне не нравится он):

private RenderedImage getChartImage (GanttChartModel model, String title,
                                     Integer width, Integer height,
                                     String xAxisLabel, String yAxisLabel,
                                     Boolean showLegend) {
    if (title == null) {
        title = "";
    }
    if (xAxisLabel == null) {
        xAxisLabel = "";
    }
    if (yAxisLabel == null) {
        yAxisLabel = "";
    }
    if (showLegend == null) {
        showLegend = true;
    }
    if (width == null) {
        width = DEFAULT_WIDTH;
    }
    if (height == null) {
        height = DEFAULT_HEIGHT;
    }
    ...
}

Как я могу улучшить его?

У меня есть некоторые мысли о представлении объекта, который будет содержать все эти параметры как поля и затем, возможно, будет возможно применить шаблон разработчика. Но все еще не имейте ясного видения, как реализовать это, и я не уверен, что это стоит быть сделанным. Какие-либо другие идеи?

5
задан Carl Manaster 12 June 2015 в 00:35
поделиться

6 ответов

Так много параметров метода определенно являются запахом кода. Я бы сказал, что объект Chart ждет своего рождения. Вот основная схема:

 private RenderImage getChartImage(Chart chart) { 
     //etc.
 }
 private static class Chart {
      private GanttChartModel model;
      private String title = "";
      //etc, initializing each field with its default value.
      private static class Builder {
           private Chart chart;
           public Builder(GanttChartModel model) {
                chart = new Chart();
                chart.model = model;
           }
           public setTitle(String title) {
                if (title != null) {
                    chart.title = title;
                }
           }
      }
  }

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

3
ответ дан 14 December 2019 в 13:30
поделиться

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

Объект может быть построен по частям:

ChartOptions options = new ChartOptions()
   .setHeight(10)
   .setWidth(100)

getChartImage(model, options);

и т. Д.

Если это не сработает, вы можете, по крайней мере, инкапсулировать нулевую проверку:

private <A> A checkNull(A object, A default)
{
  return object == null ? default : object;
}
1
ответ дан 14 December 2019 в 13:30
поделиться

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

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

Использование построителя может выглядеть следующим образом:

RenderedImage image = RenderedImageBuilder.getNew(model)
                      .title("title").width(100).height(100)
                      .showLegend().build();

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

1
ответ дан 14 December 2019 в 13:30
поделиться

Ну, я думаю о том, есть ли некоторая поддержка фреймворка аннотации @NotNull, если у метода есть эта аннотация, фреймворк проверит все его параметры.

@NotNull public void doSomething (параметр a, параметр b) { }

0
ответ дан 14 December 2019 в 13:30
поделиться

Я бы переместил эту логику в методы установки класса, объект которого вы возвращаете.

public class MyRenderedImage implements RenderedImage {

    public MyRenderedImage(String title, ...) {
        // constructor should call setters that do validation/coercion
    }

    public void setTitle(String title) {
        if (title == null) {
            this.title = "";
        }
    }

    ...
}

Другой вариант, который следует рассмотреть, - создать исключение InvalidArgumentException , но похоже, что вы уже знаете, что хотите сделать.

1
ответ дан 14 December 2019 в 13:30
поделиться

Вы можете создать изначально построенные значения карты. Затем вы можете сделать что-то вроде этого:

private RenderedImage getChartImage(GanttChartModel model, String title,
        Integer width, Integer height, String xAxisLabel,
        String yAxisLabel, Boolean showLegend) {

    title = removeNull(KEY_TITLE,title);
    xAxisLabel = removeNull(KEY_X,xAxisLabel);
    yAxisLabel = removeNull(KEY_Y,yAxisLabel);
    showLegend = removeNull(KEY_LEG,showLegend);
    width = removeNull(KEY_W,width);
    height = removeNull(KEY_H,height);
}

//initialize the defaultMap with the key-value of default pairs
Map<Object,Object> defaultMap;

private Object removeNull(Object keyTitle, Object value) {
    if(value==null){
        return defaultMap.get(keyTitle);
    }
    return value;
}
0
ответ дан 14 December 2019 в 13:30
поделиться
Другие вопросы по тегам:

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