Вопрос

getEmployeeNameByBatchId(int BatchID)
getEmployeeNameBySSN(SSN объекта)
getEmployeeNameByEmailId(Строка emailID)
getEmployeeNameBySalaryAccount(Зарплатный счет salaryAccount)

или

getEmployeeName(int typeOfIdentifier, идентификатор байта []) -> В этих методах typeOfIdentifier сообщает, является ли идентификатор BatchID /SSN /emailID /salaryAccount

Какой из вышеперечисленных способов лучше реализовать метод get?

Эти методы были бы в сервлете, и вызовы выполнялись бы из API, который предоставлялся бы клиентам.

Это было полезно?

Решение

Почему бы не перегрузить метод getEmployeeName(??)?

getEmployeeName(int BatchID)
getEmployeeName(SSN объекта)(плохая идея)
getEmployeeName(Строка электронной почты)
и т.д.

Мне кажется, это хороший подход "многих".

Другие советы

Вы могли бы использовать что-то вроде этого:

interface Employee{
    public String getName();
    int getBatchId();
}
interface Filter{
    boolean matches(Employee e);
}
public Filter byName(final String name){
    return new Filter(){
        public boolean matches(Employee e) {
            return e.getName().equals(name);
        }
    };
}
public Filter byBatchId(final int id){
    return new Filter(){
        public boolean matches(Employee e) {
            return e.getBatchId() == id;
        }
    };
}
public Employee findEmployee(Filter sel){
    List<Employee> allEmployees = null;
    for (Employee e:allEmployees)
        if (sel.matches(e))
            return e;
    return null;
}
public void usage(){
    findEmployee(byName("Gustav"));
    findEmployee(byBatchId(5));
}

Если вы выполняете фильтрацию с помощью SQL-запроса, вы бы использовали Filter интерфейс для составления предложения WHERE.

Плюсом такого подхода является то, что вы можете легко комбинировать два фильтра с:

public Filter and(final Filter f1,final Filter f2){
    return new Filter(){
        public boolean matches(Employee e) {
            return f1.matches(e) && f2.matches(e);
        }
    };
}

и используй это вот так:

findEmployee(and(byName("Gustav"),byBatchId(5)));

То, что вы получаете, похоже на Criteria API в режиме гибернации.

Я бы предпочел подход "многих".Мне это кажется более интуитивным и менее подверженным ошибкам.

Мне не нравится getXByY() - это может быть круто в PHP, но мне просто не нравится в Java (ymmv).

Я бы предпочел перегрузку, если только у вас нет свойств того же типа данных.В этом случае я бы сделал что-то похожее на ваш второй вариант, но вместо использования целых чисел я бы использовал Enum для безопасности типов и ясности.И вместо byte[] я бы использовал Object (из-за автоматической упаковки это также работает для примитивов).

Эти методы являются прекрасным примером использования перегрузки.

getEmployeeName(int batchID)
getEmployeeName(Object SSN)
getEmployeeName(String emailID)
getEmployeeName(SalaryAccount salaryAccount)

Если методы имеют общую обработку внутри, просто напишите еще один getEmplyeeNameImpl(...) и извлеките оттуда общий код, чтобы избежать дублирования

Первый вариант, без вопросов.Будьте откровенны.Это значительно повысит ремонтопригодность, и в этом действительно нет никаких недостатков.

@Стефан:трудно перегружать подобный случай (в общем случае), потому что типы параметров могут не быть дискриминационными, например,

  • getEmployeeNameByBatchId(int BatchID)
  • getEmployeeNameByRoomNumber(внутренний номер комнаты)

Смотрите также два метода getEmployeeNameBySSN, getEmployeeNameByEmailId в исходной публикации.

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

Иногда может быть удобнее использовать шаблон спецификации.

Например:GetEmployee(определение<Employee> спецификация)

А затем приступайте к определению ваших технических характеристик...

Спецификация наименования :Спецификация<Employee>
{
имя частной строки;
общедоступная спецификация имени (строковое имя) { this.name = имя;}
public bool IsSatisFiedBy(Сотрудник employee) { вернуть сотрудника.Имя == this.name;}
}

Спецификация NameSpecification = новая спецификация NameSpecification("Tim");
Время сотрудника = MyService.Получить Employee (спецификация);

Я бы использовал первый вариант или перегрузил его в этом случае, поскольку у вас есть 4 разных сигнатуры параметров.Однако конкретность помогает понять код через 3 месяца.

Является ли логика внутри каждого из этих методов в значительной степени одинаковой?

Если это так, то единственный метод с параметром identifier может иметь больше смысла (простой и сокращающий количество повторяющихся кодов).

Если логика / процедуры сильно различаются между типами, может быть предпочтительным метод для каждого типа.

Как предлагали другие, первый вариант кажется хорошим.Второе может иметь смысл, когда вы пишете код, но когда позже появляется кто-то другой, понять, как использовать код, становится сложнее.(Я знаю, у вас есть комментарии, и вы всегда можете углубиться в код, но GetemployeeNameById более понятен)

Примечание:Кстати, в некоторых случаях следует учитывать использование перечислений.

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

getEmployeeName( int batchID );
getEmployeeName( Object SSN );

etc.

Только в особых случаях я бы указывал тип аргумента в имени метода, т.е.если тип аргумента трудно определить, если существует несколько типов аргументов, которые имеют один и тот же тип данных (BatchID и EmployeeID, оба int), или если методы получения employee радикально отличаются для каждого типа аргумента.

Я не понимаю, зачем мне вообще это использовать

getEmployeeName(int typeOfIdentifier, byte[] identifier)

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

Если вы перепишете вопрос, то в конечном итоге сможете задать его:

"ВЫБЕРИТЕ имя ИЗ списка ..."
"ВЫБЕРИТЕ SSN ИЗ списка..."
"ВЫБЕРИТЕ адрес электронной почты ИЗ..."
против.
"ВЫБРАТЬ * ИЗ..."

И я думаю, что ответ на этот вопрос прост, и все это знают.

Что произойдет, если вы измените класс Employee?Например.:Вы должны удалить электронное письмо и добавить новый фильтр, например "Отдел".При втором решении у вас есть огромный риск не заметить никаких ошибок, если вы просто измените порядок "констант" идентификатора int.С помощью первого решения вы всегда будете замечать, используете ли вы метод в каких-то давно забытых классах, которые в противном случае забыли бы изменить на новый идентификатор.

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

Я согласен со Стефаном:Одна задача, одно название метода, даже если вы можете сделать это несколькими способами.Функция перегрузки метода была предусмотрена именно для вашего случая.

  • getEmployeeName(int BatchID)
  • getEmployeeName(Строка электронной почты)
  • и т.д.

И избегать ваше второе решение любой ценой.Это пахнет как "твоя старая пустота * С".Аналогично, передача Java "Object" - это почти такой же плохой стиль, как C "void *".

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

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

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

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

Разделение между процессом поиска и критериями поиска, предлагаемыми юдольфом в его примере, является превосходным.Интересно, почему это не самое популярное решение?Я что-то пропустил?

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

Первый, вероятно, лучший в Java, учитывая, что он безопасен для типов (в отличие от других).Кроме того, для "обычных" типов второе решение, по-видимому, обеспечивает только громоздкое использование для пользователя.Однако, поскольку вы используете Object в качестве типа для SSN (который имеет семантическое значение за пределами Object), вам, вероятно, не сойдет с рук этот тип API.

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

поместите все ваши параметры в перечисление, чтобы получилось что-то вроде следующего

GetEmployeeName(Enum identifier)
{
    switch (identifier)
    case eBatchID:
    {
        // Do stuff
    }
    case eSSN:
    {
    }
    case eEmailId:
    {
    }
    case eSalary:
    {
    }
    default:
    {
        // No match
        return 0;
    }
}

enum Identifier
{
    eBatchID,
    eSSN,
    eEmailID,
    eSalary
}

Вы думаете о C / C ++.

Используйте объекты вместо байта идентификатора (или int).

Мой плохой, подход с перегрузкой лучше, и использование SSN в качестве первичного ключа не так хорошо

public ??? getEmployeeName(Object obj){

if (obj instanceof Integer){

  ...

} else if (obj instanceof String){

...

} else if .... // and so on


} else throw SomeMeaningFullRuntimeException()

return employeeName
}

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

Задокументируйте это, чтобы клиент знал, каких объектов ожидать.Или создайте свои собственные обертки.Я предпочитаю первый вариант.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top