¿Deberíamos cambiar el nombre de los métodos sobrecargados?

14

Suponga una interfaz que contiene estos métodos:

Car find(long id);

List<Car> find(String model);

¿Es mejor cambiarles el nombre de esta manera?

Car findById(long id);

List findByModel(String model);

De hecho, cualquier desarrollador que use esta API no necesitará mirar la interfaz para conocer los posibles argumentos de los find()métodos iniciales .

Entonces mi pregunta es más general: ¿Cuál es el beneficio de usar métodos sobrecargados en el código ya que reduce la legibilidad?

Mik378
fuente
44
Cualquiera de los métodos es aceptable siempre y cuando sea consistente.
ChrisF
Existe una relación entre sobrecargar y anular un método. Sin embargo, este artículo favorece su sugerencia. Puede ser de interés: roseindia.net/javatutorials/…
NoChance

Respuestas:

23

Este es un problema relativamente menor en comparación con muchas otras prácticas de mala legibilidad a las que podría ser susceptible, por lo que diría que es principalmente una cuestión de gusto cómo nombra sus métodos.

Dicho esto, si vas a hacer algo al respecto, seguiría esta práctica:

  • Sobrecarga si ...

    Los métodos obedecen casi el mismo contrato, pero simplemente operan con entradas diferentes (imagine un operador telefónico que puede buscar su cuenta por su número de identificación fiscal personal, su número de cuenta o su nombre y fecha de nacimiento). Esto incluye devolver el mismo tipo de salida .

  • Use un nombre diferente si ...

    Los métodos hacen cosas sustancialmente diferentes o devuelven resultados diferentes (como su caso). Puede considerar usar un nombre diferente si uno accede a la base de datos y el otro no.

    Además, si el tipo devuelto es diferente, también cambiaría el verbo para indicar que:

    Car findById(long id);
    
    List findAllByModel(String model);
    
Nicole
fuente
3
FWIW, lo diría con un poco más de fuerza: "Los métodos obedecen exactamente el mismo contrato ..." Es decir, el tipo de argumento / conteo no importa: la semántica de la llamada a la función es idéntica de todos modos. Si el tipo / argumento de argumento es importante, entonces no debe sobrecargarse.
mcmcc
4

Recomendaría usar un nombre diferente, en todos los casos. Es posible que en algún momento en el futuro, desee agregar otro método, por ejemplo List<Car> findByMake(String make), en contraste con List<Car> findByModel(String model). Entonces, de repente, llamar a todo finddeja de tener sentido. También es menos probable que sus métodos se usen incorrectamente sin darse cuenta, si sus nombres dan más información sobre cómo deben usarse.

Dawood dice que reinstalar a Mónica
fuente
1
Para ser justos, esto no sería un problema si la funcionalidad estuviera representada más explícitamente por objetos: find(Make val)y find(Model val). Entonces, los métodos de conveniencia, como findByMake(String val)sería mucho más claro lo que realmente están haciendo. Después de todo, a Stringno es una marca o un modelo, por lo que el método debería explicar lo que realmente está haciendo.
Nicole
4

Si cambia el nombre de un método, ya no se sobrecargará. En sí mismo, la sobrecarga no necesariamente hace que el código sea menos legible, sin embargo, puede hacer que la implementación sea más difícil de seguir si la sintaxis no es clara.

Muchos lenguajes usan la sobrecarga de métodos como un medio para presentar una interfaz a la funcionalidad donde los parámetros pueden ser opcionales y los valores predeterminados para los parámetros opcionales están implícitos. Esto es particularmente cierto para los idiomas que no admiten una sintaxis de parámetros predeterminada en la declaración del método.

Entonces haciendo esto:

void MyMethod(int param1, int param2 = 10)
{
    ...
}

te salva de hacer esto:

void MyMethod(int param1)
{
    MyMethod(param1, Param2Default);
}

void MyMethod(int param1, int param2)
{
    ....
}

En cuanto a cuál es más legible, eso realmente se reduce a usted. Personalmente, prefiero la segunda opción, especialmente cuando la lista de parámetros se está alargando un poco, pero supongo que en realidad no importa siempre que sea coherente en toda su API.

La dificultad con la sobrecarga se produce cuando desea funciones que hacen esencialmente lo mismo y donde desea que las listas de parámetros sean las mismas, pero los tipos de retorno sean diferentes. La mayoría de los idiomas no saben cómo diferenciar entre dos métodos con el mismo nombre, pero con diferentes tipos de retorno. En este punto, debe pensar en usar genéricos, cambiar la interfaz de parámetros o cambiar el nombre de uno de sus métodos para indicar la diferencia en el tipo de retorno. Aquí es donde la legibilidad puede convertirse en un gran problema, si no se conforma con un esquema de nombres simple y claro para hacer frente a situaciones como esta.

Nombrar sus métodos sobrecargados GetSomething()y GetSomethingEx()no va a decir mucho sobre cuáles son las diferencias entre sus métodos, especialmente si son los tipos de retorno las únicas diferencias entre ellos. Por otro lado, GetSomethingAsInt()yGetSomethingAsString() contarle un poco más sobre lo que están haciendo los métodos, y aunque no es estrictamente una sobrecarga, sí indica que los dos métodos hacen cosas similares, pero devuelven diferentes tipos de valores. Sé que hay otras formas de nombrar métodos, sin embargo, para ilustrar el punto, estos ejemplos crudos deberían servir.

En el ejemplo de OP, el cambio de nombre no es estrictamente necesario porque los parámetros del método son diferentes, sin embargo, hace que las cosas sean un poco más claras para nombrar un método más específicamente. Al final, todo se reduce al tipo de interfaz que desea presentar a sus usuarios. La decisión de no sobrecargar no debe basarse únicamente en su propia percepción de legibilidad. Los métodos de sobrecarga pueden, por ejemplo, simplificar una interfaz API y reducir la cantidad de métodos que un desarrollador puede necesitar recordar, por otro lado, puede ofuscar la interfaz en un grado que luego requiere que un desarrollador lea la documentación del método para comprender qué formulario del método a usar, mientras que tener una cantidad de métodos nombrados de manera similar pero descriptiva puede hacer que sea más evidente simplemente leyendo un nombre de método en cuanto a su propósito.

S.Robins
fuente
0

Favorezca la sobrecarga siempre que los métodos devuelvan lo mismo y sigan el mismo contrato. La sobrecarga libera el código de llamada de comprometerse innecesariamente con el tipo de parámetro.

Suponga que la función de llamada recibe una consulta de búsqueda como parámetro y realiza algún otro procesamiento antes y / o después de la llamada a find.

void tryToSellCars(String which) {
    /* grab an airhorn, inflatable tube guy... */
    List<Car> cars = find(which);
    /* expound virtues of each car in detail... */
}

Si desea cambiar el tipo de esa consulta por cualquier motivo en el futuro (por ejemplo, desde una cadena de identificación simple a un objeto de consulta con todas las funciones de algún tipo), puede hacer ese cambio en la función de llamada simplemente cambiando la firma de la función aceptar el nuevo tipo de parámetro sin preocuparse por cambiar el método que llama en su clase.

void tryToSellCar(CarQuery which) {
    /* grab airhorn, inflate tube guy... */
    List<Car> cars = find(which)
    /* expound virtues of each car in detail... */
}

Si implementa findByIdy por findByQueryObjectseparado, tendría que buscar cada llamada para realizar ese cambio. En el ejemplo, solo cambié una palabra y terminé.

sqykly
fuente
Esta respuesta supone, por supuesto, que está utilizando un lenguaje que admite la sobrecarga con errores en tiempo de compilación para un parámetro no válido. Si está escribiendo JavaScript o Ruby o cualquier otro lenguaje que no admita la sobrecarga de forma nativa, siempre usaría el verbose findByFoopara detectar desajustes de tipo anteriormente.
2013