(Java) Перегрузка: сколько стоит слишком много?
Я использую Java для генерации JCL. У меня есть четыре метода для добавления оператора определения данных. Один принимает символ, один - строку, один - массив (из строк), а другой ничего не имеет для второго параметра.
public void addDD (String label, char classChar) //Generates: SYSIN DD SYSOUT=[classChar]
public void addDD (String label, String dataset) //Generates: SYSIN DD DSN=[dataset]
public void addDD (String label) //Generates: SYSIN DD DUMMY
public void addDD (String label, String datasets[]) //Generates: SYSIN DD *
// DSN=[datasets[0]],
// DSN=[datasets[1]]
Меня беспокоит то, что эти методы не просто принимают разные типы параметров; весь метод изменяется в зависимости от типа. Если это строка, вам нужно "DSN=". Если это символ, вам нужно "SYSOUT=". В то же время я не хочу, чтобы клиент беспокоился об использовании разных имен методов для каждого из этих сценариев.
Мой нынешний дизайн считается плохой практикой или хорошим?
4 ответа
То, что вы делаете, довольно опасно - вы рассчитываете на абонента addDD(String, char)
читать Javadocs и понять, что он не должен использовать addDD(String, String)
вместо.
Вариант 1: переименуйте методы: addDDSysout()
, addDDDsn()
и т.п.
Вариант 2: реализовать все это одним способом:
addDD(String label, String... args)
и убедитесь, что вы можете справиться с чем угодно - без строк в аргументах, одной строки, нескольких строк, одного символа и т. д.
Количество сигнатур методов, необходимых для охвата всех конструкций операторов DD, может стать довольно запутанным.
Например, я не слишком уверен, что метод:
public void addDD (String label, String datasets[])
который генерирует:
//SYSIN DD *
// DSN=[datasets[0]],
// DSN=[datasets[1]]...
будет работать очень хорошо, DD *
указывает на встроенные данные для подражания, и это должно быть завершено с /*
перед объединением дополнительных наборов данных (если есть). Приведенный выше метод, вероятно, должен генерировать простую серию операторов DD следующим образом:
//SYSIN DD
// DSN=[datasets[0]],
// DSN=[datasets[1]]...
Какую подпись вы бы использовали для создания встроенного набора данных? Вероятно, то же самое:
public void addDD (String label, String inlinedata[])
чтобы генерировать:
//SYSIN DD *
inlinedata[0]
inlinedata[1]...
/*
Но оба метода имеют одинаковую подпись - это не работает. Возможно, вам лучше использовать несколько методов, чтобы избежать конфликтов подписей. Или, если вы продолжите использовать перегруженный одиночный метод, убедитесь, что у вас есть все возможные конструкции имени DD, прежде чем углубляться в болото.
В любом случае, это потребует значительного объема документации для конечных пользователей (JCL может быть настоящей собакой языка сценариев для подражания).
Я должен согласиться, что эти вещи часто являются делом вкуса. Но я не уверен, что другие респонденты поняли значение заявления JCL DD. Потому что я не согласен с ними исходя из предметной области вашей проблемы.
Мне нравится ваш дизайн. Я бы не рекомендовал разные имена методов. Это в основном то, что TSO делал с FILE(xxx) против DSN(xxx), и я всегда ненавидел это. Хотя ваши методы дают разные "результаты" во входном потоке считывателя, эти различия вызываются синтаксисом JCL. Чтобы быть более конкретным, они не делают разные вещи. По сути, вы объявляете источник данных / приемник для пакетного задания. Не заставляйте своего пользователя изучать 4 различных метода, чтобы сделать это.
Эти решения всегда частично зависят от вкуса.
В этом конкретном случае я бы предпочел изменить имена методов, поскольку они действительно делают что-то другое. В большинстве случаев перегрузка таких методов просто удобна: наличие варианта char или String в большинстве случаев означает, что char будет преобразован в строку, и эффект будет таким же, как в вашем примере.
Могут быть и другие причины сделать это, как вы (используя рефлексию, чтобы найти правильный метод), но в этом случае я бы рекомендовал написать ясный Javadoc, описывающий, что методы действительно делают, чтобы избежать путаницы.