2008-09-17 13 views
10

getEmployeeNameByBatchId (int BATCHID)
getEmployeeNameBySSN (Object SSN)
getEmployeeNameByEmailId (String EMAILID)
getEmployeeNameBySalaryAccount (SalaryAccount salaryAccount)
Obtener Métodos: Uno vs Muchos

o

getEmployeeName (int typeOfIdentifier, identificador byte [] -> En este método, typeOfIdentifier dice si el identificador es batchID/SSN/emailID/salaryCuenta

¿Cuál de las anteriores es la mejor manera de implementar un método get?

Estos métodos estarían en un servlet y las llamadas se realizarían desde una API que se proporcionaría a los clientes.

+0

Que las batallas religiosas ... ¡COMIENZO! – CodeChimp

Respuesta

9

Por qué no sobrecargar el método getEmployeeName (??)?

getEmployeeName (int BatchID)
getEmployeeName (objeto SSN) (mala idea)
getEmployeeName (String correo electrónico)
etc.

Parece un buen enfoque 'muchos' a mí.

+0

Quizás no siempre sea flexible si hay varios campos del mismo tipo de datos. getEmployeeName (e-mail cadena) getEmployeeName (cadena passportNumber) getEmployeeName (cadena telephoneNumber) .... Muchos – icelava

+0

. Más legible Si necesita todas estas variantes, escríbalas todas. – Gishu

+0

No es un buen enfoque ya que entonces no puede tener que cumplir los criterios del mismo tipo. – jrudolph

3

me gustaría ir con el enfoque de "muchos". Me parece más intuitivo y menos propenso al error.

+1

Menos propenso a errores, pero probablemente más propenso a la duplicación de código. – jrudolph

0

Usaría la primera opción, o la sobrecargaría en este caso, ya que tiene 4 firmas de parámetros diferentes. Sin embargo, ser específico ayuda a comprender el código dentro de 3 meses.

1

La primera opción, sin duda. Ser explícito Será de gran ayuda en el mantenimiento y realmente no hay inconvenientes.

+0

Probablemente tengas 4 métodos casi similares. Eso es más para mantener no menos ... – jrudolph

+0

Su definición de mantenibilidad no es la misma que la mía. –

0

El primero es probablemente el mejor en Java, considerando que es typesafe (a diferencia de la otra). Además, para los tipos "normales", la segunda solución parece proporcionar un uso engorroso para el usuario. Sin embargo, dado que está utilizando Object como el tipo de SSN (que tiene un significado semántico más allá de Object), probablemente no se saldrá con ese tipo de API.

En general, en este caso particular, hubiera utilizado el enfoque con muchos captadores. Si todos los identificadores tienen su propio tipo de clase, podría haber ido por la segunda ruta, pero cambiando internamente en la clase en lugar de un identificador de tipo proporcionado/definido por la aplicación.

0

es la lógica dentro de cada uno de esos métodos en gran parte el mismo?

Si es así, el único método con el parámetro identificador puede tener más sentido (simple y reduciendo el código repetido).

Si la lógica/procedimientos varían en gran medida entre los tipos, puede preferirse un método según el tipo.

1

@Stephan: es difícil sobrecargar un caso como este (en general) porque los tipos de parámetros pueden no ser discriminatorios, p. Ej.,

  • getEmployeeNameByBatchId (int BATCHID)
  • getEmployeeNameByRoomNumber (int roomNumber)

Ver también los dos métodos getEmployeeNameBySSN, getEmployeeNameByEmailId en la publicación original.

0

Como otros sugirieron la primera opción parece ser la buena. Lo segundo puede tener sentido cuando estás escribiendo un código, pero cuando alguien más viene más tarde, es más difícil descubrir cómo usar el código. (Lo sé, usted tiene comentarios y siempre puede profundizar en el código, pero GetemployeeNameById es más fácil de entender)

Nota: Por cierto, el uso de Enum podría ser algo a considerar en algunos casos.

-2

usted está pensando en C/C++.

utilizar objetos en lugar de un byte de identificación (o int).

Mi malo, el enfoque de sobrecarga es mejor y usando el SSN como una clave principal no es tan bueno

public ??? getEmployeeName(Object obj){ 

if (obj instanceof Integer){ 

    ... 

} else if (obj instanceof String){ 

... 

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


} else throw SomeMeaningFullRuntimeException() 

return employeeName 
} 

Creo que es mejor utilizar excepciones sin marcar para la señalización de entrada incorrecta.

documento que lo que el cliente sabe lo que se opone a esperar. O crea tus propios envoltorios. Prefiero la primera opción.

+0

Por qué confiar en excepciones de tiempo de ejecución cuando se puede tener la seguridad de tiempo de compilación estática? – jrudolph

+0

Estoy de acuerdo con jrudolph. Lo que está codificando es puramente antigua "programación de interruptor C". Si bien es mejor que la matriz de bytes, esta no es una buena solución. – paercebal

0

En un caso trivial como éste, me gustaría ir con sobrecarga. Es decir:

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

etc. 

Sólo en casos especiales iba a especificar el tipo de argumento en el nombre del método, es decir, si el tipo de argumento es difícil de determinar, si hay varios tipos de argumentos tha tiene el mismo tipo de datos (batchId y employeeId, ambos int), o si los métodos para recuperar al empleado son radicalmente diferentes para cada tipo de argumento.

No puedo ver por qué lo que jamás uso este

getEmployeeName(int typeOfIdentifier, byte[] identifier) 

ya que requiere tanto destinatario de la llamada y la persona que llama a emitir el valor basado en typeOfIdentifier. Mal diseño.

0

Si vuelve a escribir la pregunta que puede llegar a preguntar:

"seleccione el nombre desde ..."
"SELECT SSN DE ..."
"Seleccione E-mail ..."
vs
"SELECCIONAR * DESDE ..."

Y supongo que la respuesta es fácil y todos lo saben.

¿Qué pasa si cambia la clase de empleado? Por ejemplo, debe eliminar el correo electrónico y agregar un nuevo filtro como departamento. Con la segunda solución, existe un gran riesgo de no detectar ningún error si solo cambia el orden del identificador int "constantes". Con la primera solución, siempre se dará cuenta si está utilizando el método en algunas clases olvidadas que de otra manera se olvidaría modificar al nuevo identificador.

2

Los métodos son un ejemplo perfecto para el uso de la sobrecarga.

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

Si los métodos tienen procesamiento común en el interior, acaba de escribir una getEmplyeeNameImpl más (...) y extraer allí el código común para evitar la duplicación

+0

Pero la línea "getEmployeeName (Object SSN)" va demasiado lejos ... El tipo de "objeto" haría casi cualquier otra sobrecarga de sentido (muy parecido al temor void * de C. – paercebal

3

no me gusta getXByY() - que podría ser genial en PHP, pero simplemente no me gusta en Java (ymmv).

Iría con sobrecarga, a menos que tenga propiedades del mismo tipo de datos. En ese caso, haría algo similar a tu segunda opción, pero en lugar de usar ints, usaría un Enum para seguridad y claridad. Y en lugar de byte [], usaría Object (debido al autoboxing, esto también funciona para primitivos).

0

Personalmente prefiero tener el nombre explícito "... ByRoomNumber" porque si terminas con muchas "sobrecargas" eventualmente introducirás errores no deseados. Ser explícito es la mejor manera.

7

usted podría utilizar algo así:

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)); 
} 

Si lo hace el filtrado de una consulta SQL que usaría la interfaz Filter para componer una cláusula WHERE.

Lo bueno de este enfoque es que se pueden combinar dos filtros con facilidad con:

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

y utilizarlo como esa:

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

Lo que se obtiene es similar a la Criteria API Hibernar.

+0

Este es un gran acercamiento (me gustaría utilizar personalmente y lo han utilizado), pero con una excepción. Realmente considerar de antemano si necesita todo ese código extra de hacer algo tan simple. a veces simple es mejor. – Josh

+0

Suena como DSL para mí. – rpattabi

+0

Overkill. La pregunta se refiere a métodos de acceso, que ya son métodos para acceder a los campos privados. Algunas personas argumentan que esto ya es demasiado trabajo (y que sería un error). lo que se propone es un marco completo de filtros ... el usuario sólo quiere que el nombre del empleado ... :-) – paercebal

1

A veces puede ser más conveniente usar el specification pattern.

Ej: GetEmployee (ISpecification <Empleado> especificación)

Y a continuación, empezar a definir sus especificaciones ...

NameSpecification: ISpecification <Empleado>
{
nombre de la cadena privada;
public NameSpecification (string name) {this.name = name; }
public bool IsSatisFiedBy (Empleado empleado) {return employee.Name == this.name; }
}

NameSpecification spec = new NameSpecification ("Tim");
Empleado tim = MyService.GetEmployee (spec);

0

Estoy de acuerdo con Stephan: Una tarea, un nombre de método, incluso si puede hacerlo de múltiples maneras. La función de sobrecarga del método fue proporcionada exactamente para su caso.

  • getEmployeeName (int BatchID)
  • getEmployeeName (String correo electrónico)
  • etc.

Y evitar su segunda solución a toda costa. Huele a "tu antiguo vacío * de C". Del mismo modo, pasar un "Objeto" Java es casi tan pobre como un C "void *".

0

Si tiene un buen diseño, debería poder determinar si puede usar el enfoque de sobrecarga o si se encontrará con un problema donde si sobrecarga va a terminar teniendo dos métodos con el mismo tipo de parámetro.

sobrecarga parece la mejor manera al principio, pero si al final no ser capaz de añadir un método en el futuro y ensuciar las cosas con el nombramiento que va a ser una molestia.

Personalmente me gustaría para el enfoque de un nombre único por método, de esa manera no se encuentre con problemas más adelante al intentar sobrecargar el mismo parámetro Métodos de objeto. Además, si alguien extendió su clase en el futuro e implementó otro void getEmployeeName (String name), no anularía el suyo.

Para resumir, vaya con un nombre de método único para cada método, la sobrecarga solo puede causar problemas a largo plazo.

1

Usaré los nombres de métodos explícitos. Todos los que mantengan ese código y yo más tarde comprendan qué está haciendo ese método sin tener que escribir comentarios xml.

-1

palo de todas sus opciones en una enumeración, el tener algo como lo siguiente

+0

Esta es una pesadilla tanto para el mantenimiento y la filosofía contrario de la mayoría de las lenguas actuales. Nunca jamás jamás codifiques de esa manera. – paercebal

0

El desacoplamiento entre el proceso de búsqueda y los criterios de búsqueda jrudolf propone en su ejemplo es excelente. Me pregunto por qué no es la solución más votada. ¿Extraño algo?

+0

Porque es una buena idea de marco. Pero si la pregunta se refiere a convención de nomenclatura descriptores de acceso, que no quiere instanciate 10 objetos y hacer comparaciones 10, sólo para obtener algún nombre. Por lo tanto, la solución "jrudolf" puede considerarse exagerada en la mayoría de los casos, y la ** verdadera correcta ** en algunos otros. – paercebal

0

Iría con Query Objects. Funcionan bien para acceder a las tablas directamente. Si está confinado a procedimientos almacenados, pierde parte de su poder, pero aún puede hacerlo funcionar.

Cuestiones relacionadas