De vez en cuando me encuentro con métodos en los que un desarrollador elige devolver algo que no es crítico para la función. Quiero decir, cuando veo el código, aparentemente funciona igual de bien que, void
y después de un momento de reflexión, pregunto "¿Por qué?" ¿Te suena familiar?
A veces estoy de acuerdo en que la mayoría de las veces es mejor devolver algo como a bool
o int
, en lugar de simplemente hacer un void
. Sin embargo, no estoy seguro, en general, sobre los pros y los contras.
Dependiendo de la situación, devolver un mensaje int
puede hacer que la persona que llama sepa la cantidad de filas u objetos afectados por el método (por ejemplo, 5 registros guardados en MSSQL). Si un método como "InsertSomething" devuelve un valor booleano, puedo tener el método diseñado para devolverlo true
si tiene éxito, de lo contrario false
. La persona que llama puede elegir actuar o no con esa información.
Por otra parte,
- ¿Puede conducir a un propósito menos claro de una llamada al método? La codificación incorrecta a menudo me obliga a verificar el contenido del método. Si devuelve algo, le dice que el método es del tipo que tiene que hacer algo con el resultado devuelto.
- Otro problema sería, si la implementación del método es desconocida para usted, ¿qué decidió devolver el desarrollador que no es una función crítica? Por supuesto que puedes comentarlo.
- El valor de retorno debe procesarse, cuando el procesamiento podría finalizar en el paréntesis de cierre del método.
- ¿Qué pasa debajo del capó? ¿Se obtuvo el método llamado
false
debido a un error arrojado? ¿O devolvió falso debido al resultado evaluado?
¿Cuales son tus experiencias con esto? ¿Cómo actuarías en esto?
fuente
void
al menos le permite al desarrollador saber que el valor de retorno del método es intrascendente; realiza una acción, en lugar de calcular un valor.Respuestas:
En el caso de un valor de retorno bool para indicar el éxito o el fracaso de un método, prefiero el
Try
paradigma de prefijo utilizado en varios métodos .NET.Por ejemplo, un
void InsertRow()
método podría generar una excepción si ya existe una fila con la misma clave. La pregunta es, ¿es razonable suponer que la persona que llama se asegura de que su fila sea única antes de llamar a InsertRow? Si la respuesta es no, entonces también proporcionaría unbool TryInsertRow()
que devuelve falso si la fila ya existe. En otros casos, como los errores de conectividad de db, TryInsertRow aún podría lanzar una excepción, suponiendo que mantener la conectividad de db es responsabilidad de la persona que llama.fuente
En mi humilde opinión, devolver un "código de estado" proviene de tiempos históricos, antes de que las excepciones se volvieran comunes en lenguajes de nivel medio a superior, como C #. Hoy en día es mejor lanzar una excepción si algún error inesperado impidió que su método tenga éxito. De esa manera, es seguro que el error no pasa desapercibido y la persona que llama puede tratarlo según corresponda. Entonces, en estos casos, está perfectamente bien que un método no devuelva nada (es decir
void
) en lugar de un indicador de estado booleano o un código de estado entero. (Por supuesto, uno debe documentar qué excepciones puede arrojar el método y cuándo).Por otro lado, si es una función en sentido estricto, es decir, realiza algunos cálculos basados en parámetros de entrada y se espera que devuelva el resultado de ese cálculo, el tipo de retorno es obvio.
Hay un área gris entre los dos, cuando uno puede decidir devolver alguna información "adicional" del método, si se considera útil para sus llamantes. Como su ejemplo sobre el número de filas afectadas en una inserción. O para un método para colocar un elemento en una colección asociativa, puede ser útil devolver el valor anterior asociado con esa clave, si hubiera alguna. Dichos usos pueden identificarse analizando cuidadosamente los escenarios de uso (conocidos y anticipados) de una API.
fuente
La respuesta de Peter cubre bien las excepciones. Otra consideración aquí implica la separación de consulta de comando
El principio CQS dice que un método debería ser un comando o una consulta y no ambos. Los comandos nunca deben devolver un valor, solo modifican el estado y las consultas solo deben devolver y no modificar el estado. Esto mantiene la semántica muy clara y ayuda a que el código sea más legible y mantenible.
Hay algunos casos donde violar el principio CQS es una buena idea. Estos generalmente están relacionados con el rendimiento o la seguridad de los hilos.
fuente
Cualquiera sea el camino que vayas a caminar con esto. No tiene valores de retorno para su uso futuro (por ejemplo, las funciones siempre devuelven verdaderas), esto es una pérdida de esfuerzo terrible y no hace que el código sea más claro de leer. Cuando tenga un valor de retorno, siempre debe usarlo, y para poder usarlo debe tener al menos 2 valores de retorno posibles.
fuente
Solía escribir muchas funciones vacías. Pero desde que empecé con el método de encadenar crack, comencé a devolver esto en lugar de anular; también podría dejar que alguien se aproveche de la devolución porque no puedes hacer sentadillas con vacío. Y si no quieren hacer nada con él, simplemente pueden ignorarlo.
fuente
Ruby
algún momento? Eso es lo que me introdujo al método de encadenamiento.return Thing.Change1().Change2();
espera cambiarThing
y devolver una referencia al original, o si se espera que devuelva una referencia a algo nuevo que difiere del original, mientras deja el original sin tocar.