He tenido una discusión con un compañero de trabajo sobre romper una return
declaración y la declaración que calcula el valor de retorno en dos líneas.
Por ejemplo
private string GetFormattedValue()
{
var formattedString = format != null ? string.Format(format, value) : value.ToString();
return formattedString;
}
en lugar de
private string GetFormattedValue()
{
return format != null ? string.Format(format, value) : value.ToString();
}
En cuanto al código, realmente no veo un valor en la primera variante. Para mí, este último es más claro, particularmente para los métodos que son cortos. Su argumento fue que la variante anterior es más fácil de depurar, lo cual es un mérito bastante pequeño, ya que VisualStudio nos permite una inspección muy detallada de las declaraciones, cuando la ejecución se detiene debido a un punto de interrupción.
Mi pregunta es, si todavía es un punto válido para escribir código menos claro, ¿solo para hacer más fácil la depuración? ¿Hay más argumentos para la variante con el cálculo dividido y la return
declaración?
fuente
private string GetFormattedValue() => string.Format(format ?? "{0}", value);
Respuestas:
La introducción de variables explicativas es una refactorización bien conocida que a veces puede ayudar a hacer que las expresiones complicadas sean más legibles. Sin embargo, en el caso mostrado,
Además, las versiones más nuevas del depurador de Visual Studio pueden mostrar el valor de retorno de una función en la mayoría de los casos sin introducir una variable superflua (pero tenga cuidado, hay algunas advertencias, eche un vistazo a esta publicación SO más antigua y las diferentes respuestas ).
Entonces, en este caso específico, estoy de acuerdo con usted, sin embargo, hay otros casos en los que una variable explicativa puede mejorar la calidad del código.
fuente
result
como el nombre de la variable. No es mucho más largo y más fácil de depurarresult
menudo solo agrega ruido al código y rara vez aumenta la legibilidad, que es exactamente el punto de mi respuesta. Esto puede justificarse en un contexto en el que ayuda a la depuración, pero evitaría utilizar un depurador que no necesita una variable separada.result
transmite la información de que este es el valor resultante de la función, para que pueda verlo antes de que la función regrese.Dados los hechos que:
a) No hay impacto en el código final ya que el compilador optimiza la variable.
b) Tenerlo separado mejora la capacidad de depuración.
Personalmente llegué a la conclusión de que es una buena práctica separarlos el 99% del tiempo.
No hay desventajas materiales para hacerlo de esta manera. El argumento de que hincha el código es incorrecto, porque el código hinchado es un problema trivial en comparación con el código ilegible o difícil de depurar. Además, este método por sí solo no puede crear código confuso, eso depende completamente del desarrollador.
fuente
A menudo, la introducción de una variable solo para nombrar algún resultado es muy útil cuando hace que el código sea más autodocumentado. En este caso, eso no es un factor porque el nombre de la variable es muy similar al nombre del método.
Tenga en cuenta que los métodos de una línea no tienen ningún valor inherente. Si un cambio introduce más líneas pero aclara el código, es un buen cambio.
Pero, en general, estas decisiones dependen en gran medida de sus preferencias personales. Por ejemplo, encuentro ambas soluciones confusas porque el operador condicional se está utilizando innecesariamente. Hubiera preferido una declaración if. Pero en su equipo puede haber acordado diferentes convenciones. Luego haga lo que sus convenciones sugieran. Si las convenciones guardan silencio en un caso como este, tenga en cuenta que este es un cambio extremadamente menor que no importa a largo plazo. Si este patrón ocurre repetidamente, tal vez inicie una discusión sobre cómo usted, como equipo, desea manejar estos casos. Pero eso es dividir los pelos entre "buen código" y "quizás un código un poco mejor".
fuente
?
y a:
usoif() {
y} else {
- - - -\\ :)
En respuesta a sus preguntas:
Mi pregunta es, si todavía es un punto válido para escribir código menos claro, ¿solo para hacer más fácil la depuración?
Sí. De hecho, parte de su declaración anterior me parece (sin ofender) un poco miope (ver negrita a continuación) " Su argumento fue que la variante anterior es más fácil de depurar, lo cual es un mérito bastante pequeño , ya que VisualStudio nos permite una inspección muy detallada de las declaraciones, cuando la ejecución se detiene debido a un punto de interrupción " .
Hacer la depuración más fácil (casi) nunca es de " mérito pequeño " porque, según algunas estimaciones, el 50% del tiempo del programador se dedica a la depuración ( software de depuración reversible ).
¿Hay más argumentos para la variante con el cálculo dividido y la declaración de devolución?
Sí. Algunos desarrolladores argumentan que el cálculo dividido es más fácil de leer. Esto, por supuesto, ayuda con la depuración, pero también ayuda cuando alguien intenta descifrar las reglas de negocios que su código puede cumplir o aplicar.
NOTA: Las reglas de negocio se pueden cumplir mejor en una base de datos, ya que pueden cambiar con frecuencia. Sin embargo, la codificación clara en esta área sigue siendo primordial. ( Cómo construir un motor de reglas de negocio )
fuente
Yo iría aún más lejos:
¿Por qué?
Usar operadores ternarios para una lógica más compleja sería ilegible, por lo que usaría un estilo como el anterior para declaraciones más complejas. Al usar siempre este estilo, su código es coherente y más fácil de analizar para un humano. Además, al introducir este tipo de coherencia (y usar código hilachas y otras pruebas) puede evitar
goto fail
errores de tipo.Otra ventaja es que su informe de cobertura de código le avisará si olvidó incluir una prueba para
format
que no sea nulo. Este no sería el caso del operador ternario.Mi alternativa preferida: si está en la "obtención de un retorno lo más rápido posible" y no en contra de múltiples retornos de un método:
Por lo tanto, puede mirar el último retorno para ver cuál es el valor predeterminado.
Sin embargo, es importante ser coherente y que todos sus métodos sigan una u otra convención.
fuente
value.ToString()
se llama innecesariamente cuando el formato no es nulo. En el caso general, esto podría incluir cálculos no triviales y puede llevar más tiempo que la versión que incluye una cadena de formato. Considere, por ejemplo, unvalue
que almacena PI a un millón de decimales, y una cadena de formato que solicita solo los primeros dígitos.private string GetFormattedValue() => string.Format(format ?? "{0}", value);
mismo efecto, y use pruebas unitarias para garantizar la corrección en lugar de confiar en el depurador.No creo que tal técnica pueda justificarse por la necesidad de depurar. Me he encontrado con este enfoque mil veces, y de vez en cuando sigo haciendo esto, pero siempre tengo en cuenta lo que dijo Martin Fowler sobre la depuración :
fuente
Creo que algunas personas se están obsesionando con cuestiones tangenciales a la pregunta, como el operador ternario. Sí, mucha gente lo odia, así que tal vez sea bueno mencionarlo de todos modos.
Con respecto al enfoque de su pregunta, mover la declaración devuelta para que sea referenciada por una variable ...
Esta pregunta hace 2 suposiciones con las que no estoy de acuerdo:
Que la segunda variante es más clara o fácil de leer (digo lo contrario es cierto), y
que todos usan Visual Studio. He usado Visual Studio muchas veces y puedo usarlo bien, pero generalmente estoy usando otra cosa. Un entorno de desarrollo que obliga a un IDE específico es uno de los que sería escéptico.
Romper algo con una variable nombrada rara vez hace que algo sea más difícil de leer, casi siempre hace lo contrario. La forma específica en que alguien lo hace podría causar problemas, como si un jefe de autodocumentación lo hace
var thisVariableIsTheFormattedResultAndWillBeTheReturnValue = ...
, obviamente, eso es malo, pero ese es un tema separado.var formattedText = ...
está bien.En este caso específico , y posiblemente en muchos casos ya que estamos hablando de 1-liners, la variable no le dirá mucho que el nombre de la función ya no le dice. Por lo tanto, la variable no agrega tanto. El argumento de depuración aún podría mantenerse, pero nuevamente, en este caso específico, no veo nada que pueda ser su foco al depurar, y siempre se puede cambiar fácilmente más adelante si de alguna manera alguien necesita ese formato para la depuración o cualquier otra cosa.
En general, y solicitó la regla general (su ejemplo fue solo eso, un ejemplo de una forma generalizada), todos los puntos hechos a favor de la variante 1 (2 líneas) son correctos. Esas son buenas pautas para tener. Pero las pautas deben ser flexibles. Por ejemplo, el proyecto en el que estoy trabajando ahora tiene un máximo de 80 caracteres por línea, así que divido muchas líneas, pero comúnmente encuentro líneas de 81-85 caracteres que serían difíciles de dividir o reducir la legibilidad y los dejo. el límite.
Como es poco probable que agregue valor, no haría 2 líneas para el ejemplo específico dado. Haría la variante 2 (la línea 1) porque los puntos no son lo suficientemente fuertes como para hacer lo contrario en este caso.
fuente