Considere una función sin parámetros ( editar: no necesariamente) que realiza una sola línea de código y se llama solo una vez en el programa (aunque no es imposible que se vuelva a necesitar en el futuro).
Podría realizar una consulta, verificar algunos valores, hacer algo relacionado con expresiones regulares ... cualquier cosa oscura o "hacky".
La razón detrás de esto sería evitar evaluaciones difícilmente legibles:
if (getCondition()) {
// do stuff
}
¿Dónde getCondition()
está la función de una línea?
Mi pregunta es sencilla: ¿es una buena práctica? Me parece bien, pero no sé a largo plazo ...
getCondition
? Si es tan pequeño y se usa con poca frecuencia como usted dice, entonces darle un nombre no está logrando nada.Respuestas:
Depende de esa línea. Si la línea es legible y concisa por sí misma, la función puede no ser necesaria. Ejemplo simplista:
OTOH, si la función le da un buen nombre a una línea de código que contiene, por ejemplo, una expresión compleja y difícil de leer, está perfectamente justificada (para mí). Ejemplo contribuido (dividido en varias líneas para facilitar la lectura aquí):
fuente
taxPayer
sea global en este escenario. Quizás esta clase esTaxReturn
, ytaxPayer
es un atributo.Sí, esto puede usarse para satisfacer las mejores prácticas. Por ejemplo, es mejor tener una función claramente nombrada que haga algún trabajo, incluso si es solo una línea de largo, que tener esa línea de código dentro de una función más grande y necesitar un comentario de una línea que explique lo que hace. Además, las líneas de código vecinas deben realizar tareas en el mismo nivel de abstracción. Un contraejemplo sería algo así como
En este caso, definitivamente es mejor mover la línea media a una función con un nombre sensato.
fuente
petrolFlag |= 0x006A;
sin ningún tipo de toma de decisiones, sería mejor simplemente decirpetrolFlag |= A_B_C;
sin una función adicional. Presumiblemente,engageChoke()
solo debería llamarse sipetrolFlag
cumple con ciertos criterios y eso debería decir claramente 'Necesito una función aquí'. Solo una cuestión menor, esta respuesta es básicamente acertada de lo contrario :)mixLeadedGasoline()
, ¡no tendría que hacerlo!Creo que en muchos casos esa función es un buen estilo, pero puede considerar una variable booleana local como alternativa en los casos en que no necesite usar esta condición en otro lugar, por ejemplo:
Esto le dará una pista al lector de código y evitará la introducción de una nueva función.
fuente
IsEngineReadyUnlessItIsOffOrBusyOrOutOfService
).Además de la respuesta de Peter , si es posible que esa condición deba actualizarse en algún momento en el futuro, al encapsularla de la forma en que sugiere que solo tendría un único punto de edición.
Siguiendo el ejemplo de Peter, si esto
se convierte en esto
Realiza una única edición y se actualiza universalmente. Mantenibilidad sabia, esto es una ventaja.
En cuanto al rendimiento, la mayoría de los compiladores de optimización eliminarán la llamada a la función y de todos modos alinearán el bloque de código pequeño. La optimización de algo como esto en realidad puede reducir el tamaño del bloque (eliminando las instrucciones necesarias para la llamada a la función, devolución, etc.), por lo que normalmente es seguro hacerlo incluso en condiciones que de otro modo podrían evitar la inserción.
fuente
seemsGreen
no sea confiable con objetos livianos será irrelevante si el código nunca se preocupa si los objetos livianos son verdes. Sin embargo, si la definición de "ligero" cambia, de modo que algunos objetos no verdes que devuelven verdaderoseemsGreen
no se informan como "ligero", entonces dicho cambio en la definición de "ligero" podría romper el código que prueba los objetos ser verde". En algunos casos, las pruebas de ecología y peso juntas en el código pueden hacer que la relación entre las pruebas sea más clara que si fueran métodos separados.Además de la legibilidad (o como complemento), esto permite escribir funciones en el nivel adecuado de abstracción.
fuente
Depende. A veces es mejor encapsular una expresión en una función / método, incluso si es solo una línea. Si es complicado de leer o lo necesita en varios lugares, entonces lo considero una buena práctica. A largo plazo, es más fácil de mantener, ya que ha introducido un único punto de cambio y una mejor legibilidad .
Sin embargo, a veces es algo que no necesitas. Cuando la expresión sea fácil de leer de todos modos y / o solo aparezca en un lugar, no la envuelva.
fuente
Creo que si solo tiene algunos, está bien, pero el problema surge cuando hay muchos en su código. Y cuando se ejecuta el compilador o el interpitor (según el idioma que utilice), va a esa función en la memoria. Digamos que tiene 3 de ellos, no creo que la computadora se dé cuenta, pero si comienza a tener cientos de esas pequeñas cosas, el sistema tiene que registrar funciones en la memoria que solo se llaman una vez y luego no se destruyen.
fuente
He hecho esto exactamente recientemente en una aplicación que he estado refactorizando, para hacer explícito el significado real del código sin comentarios:
fuente
if
abreviar? Este enfoque local (lambda) hace que laPaymentButton_Click
función (como un todo) sea más difícil de leer. EnlblCreditCardError
su ejemplo, parece ser un miembro, por lo que tambiénHaveError
es un predicado (privado) que es válido para el objeto. Tiendo a rechazar esto, pero no soy un programador de C #, así que me resisto.CheckInputs()
???Mover esa línea a un método bien nombrado hace que su código sea más fácil de leer. Muchos otros ya lo han mencionado ("código autodocumentado"). La otra ventaja de pasarlo a un método es que facilita la prueba unitaria. Cuando se aísla en su propio método y se prueba la unidad, puede estar seguro de que si se encuentra un error, no estará en este método.
fuente
Ya hay muchas buenas respuestas, pero hay un caso especial que vale la pena mencionar .
Si su declaración de una línea necesita un comentario , y puede identificar claramente (lo que significa: nombre) su propósito, considere extraer una función mientras mejora el comentario en el documento API. De esta forma, hace que la llamada a la función sea más rápida y fácil de entender.
Curiosamente, se puede hacer lo mismo si actualmente no hay nada que hacer, sino un comentario que recuerde las expansiones necesarias (en un futuro muy cercano 1) ), así que esto,
bien podría cambiar a esto
1) debes estar realmente seguro de esto (ver el principio de YAGNI )
fuente
Si el lenguaje lo admite, generalmente uso funciones anónimas etiquetadas para lograr esto.
En mi humilde opinión, este es un buen compromiso porque le brinda el beneficio de legibilidad de no tener la expresión complicada que satura la
if
condición mientras evita saturar el espacio de nombres global / paquete con pequeñas etiquetas desechables. Tiene el beneficio adicional de que la función "definición" está justo donde se está utilizando, lo que facilita la modificación y lectura de la definición.No tiene que ser solo funciones predicadas. También me gusta encapsular la placa de caldera repetida en funciones pequeñas como esta (funciona particularmente bien para la generación de listas pitónicas sin saturar la sintaxis de paréntesis). Por ejemplo, el siguiente ejemplo demasiado simplificado cuando se trabaja con PIL en python
fuente
[] == False
o alguna otra cosa. equivalencia pitónica similar que no es "siempre" intuitiva. Básicamente es una forma de señalar que someCondition es, de hecho, un predicado.[] != False
pero[]
es Falso como cuando lo lanzan a un boollen([complicated expression producing a list]) == 0
, en lugar de usar loTrue if [blah] else False
que aún requiere que el lector sepa que [] se evalúa como False.