Cada vez que me encuentro escribiendo la misma lógica más de una vez, generalmente la incluyo en una función, por lo que solo hay un lugar en mi aplicación para mantener esa lógica. Un efecto secundario es que a veces termino con una o dos funciones de línea como:
function conditionMet(){
return x == condition;
}
O
function runCallback(callback){
if($.isFunction(callback))
callback();
}
¿Es esto perezoso o una mala práctica? Solo pregunto porque esto da como resultado una mayor cantidad de llamadas a funciones para piezas muy pequeñas de lógica.
programming-practices
coding-standards
Mark Brown
fuente
fuente
Assert.AreEqual<int>(expected, actual, message, arg1, arg2, arg3, ...);
. El segundo está bien como está. Potencialmente incluiría una bandera de bool opcional que dictaría si lanzar una excepción / etc. en caso de que la devolución de llamada no sea una función.def yes(): return 'yes'
Respuestas:
Jeje, señor Brown, si pudiera persuadir a todos los desarrolladores que conozco para que mantengan sus funciones tan pequeñas como esta, créanme, ¡el mundo del software sería un lugar mejor!
1) La legibilidad de su código aumenta diez veces.
2) Tan fácil de entender el proceso de su código debido a la legibilidad.
3) SECO - No te repitas - ¡Te estás ajustando muy bien a esto!
4) comprobable. Las funciones diminutas son un millón de veces más fáciles de probar que los métodos de 200 líneas que vemos con demasiada frecuencia.
Ah, y no te preocupes por el "salto de funciones" en términos de rendimiento. Las compilaciones "Release" y las optimizaciones del compilador se encargan de esto muy bien, y el rendimiento es el 99% del tiempo en algún otro lugar del diseño de sistemas.
¿Es esto perezoso? - Muy al contrario!
¿Es esta una mala práctica? - Absolutamente no. Es mejor utilizar esta forma de hacer métodos que las bolas de alquitrán o los "Objetos de Dios" que son tan comunes.
Sigan con el buen trabajo, mi compañero artesano;)
fuente
Diría que un método refactorizado es demasiado corto si:
Ex:
o...
Ex:
Este podría ser un patrón válido, pero simplemente alinearía el método configureDialog (), en este ejemplo, a menos que tuviera la intención de anularlo o reutilizar este código en otro lugar.
fuente
¿Puede una función ser demasiado corta? En general no.
De hecho, la única forma de garantizar que:
Es mantener sus funciones lo más pequeñas posible. O, en otras palabras, extraiga funciones de sus funciones hasta que no pueda extraer más. Yo llamo a esto "Extraer hasta que te caigas".
Para explicar esto: Una función es un ámbito con fragmentos de funcionalidad que se comunican por variables. Una clase también es un ámbito con trozos de funcionalidad que se comunican por variables. Por lo tanto, una función larga siempre se puede reemplazar por una o más clases con un método pequeño.
Además, una función que es lo suficientemente grande como para permitirle extraer otra función de ella, está haciendo más de una cosa por definición . Entonces, si puede extraer una función de otra, debe extraer esa función.
Algunas personas temen que esto conduzca a una proliferación de funciones. Tienen razón Va a. Eso es realmente algo bueno. Es bueno porque las funciones tienen nombres. Si tiene cuidado al elegir buenos nombres, entonces estas funciones actúan como publicaciones de signos que dirigen a otras personas a través de su código. De hecho, las funciones bien nombradas dentro de clases bien nombradas dentro de espacios de nombres bien nombrados son una de las mejores formas de asegurarse de que sus lectores NO se pierdan.
Hay mucho más sobre esto en el Episodio III de Clean Code en cleancoders.com
fuente
Wow, la mayoría de estas respuestas no son de mucha ayuda.
No debe escribirse ninguna función cuya identidad sea su definición . Es decir, si el nombre de la función es simplemente el bloque de código de la función escrito en inglés, entonces no lo escriba como una función.
Considera tu función
conditionMet
y esta otra función,addOne
(perdóname por mi JavaScript oxidado):conditionMet
es una definición conceptual adecuada;addOne
Es una tautología .conditionMet
es bueno porque no sabes lo queconditionMet
implica simplemente diciendo "condición cumplida", pero puedes ver por quéaddOne
es tonto si lo lees en inglés:Por amor a cualquier cosa que pueda ser sagrada, por favor, ¡no escribas funciones tautológicas!
(¡Y por la misma razón, no escriba comentarios para cada línea de código !)
fuente
function nametoolong() { return name.size > 15; }
ofunction successorIndex(x) { return x + 1; }
Entonces, el problema con sus funciones es en realidad que su nombre es malo.Diría que si cree que la intención de algún código puede mejorarse agregando un comentario, en lugar de agregar ese comentario, extraiga el código en su propio método. No importa cuán pequeño sea el código.
Entonces, por ejemplo, si su código se vería así:
haz que se vea así en su lugar:
con
O, en otras palabras, no se trata de la longitud del método, sino del código autodocumentado.
fuente
if x == PIXEL_ON
. Usar una constante puede ser tan descriptivo como usar un método, y es un poco más breve.Creo que esto es exactamente lo que quieres hacer. En este momento, esa función podría ser solo una o dos líneas, pero con el tiempo podría crecer. También tener más llamadas a funciones le permite leer las llamadas a funciones y comprender lo que está sucediendo allí. Esto hace que su código sea muy SECO (no se repita), lo cual es mucho más fácil de mantener.
fuente
conditionMet
es un nombre demasiado genérico y no toma argumentos, por lo que prueba algún estado? (x == xCondition) en la mayoría de los idiomas y situaciones es tan expresivo como 'xConditition'.Estoy de acuerdo con todas las otras publicaciones que he visto. Este es un buen estilo.
La sobrecarga de un método tan pequeño puede ser nula, ya que el optimizador puede optimizar la llamada y alinear el código. Un código simple como este permite al optimizador hacer su mejor trabajo.
El código debe estar escrito para mayor claridad y simplicidad. Intento limitar un método a uno de dos roles: tomar decisiones; o realizando trabajos. Esto puede generar métodos de una línea. Cuanto mejor estoy haciendo esto, mejor encuentro mi código.
Un código como este tiende a tener alta cohesión y bajo acoplamiento, lo cual es una buena práctica de codificación.
EDITAR: una nota sobre los nombres de los métodos. Use un nombre de método que indique lo que el método no hace y cómo lo hace. Encuentro que verb_noun (_modifier) es un buen esquema de nombres. Esto da nombres como Find_Customer_ByName en lugar de Select_Customer_Using_NameIdx. El segundo caso tiende a ser incorrecto cuando se modifica el método. En el primer caso, puede intercambiar toda la implementación de la base de datos del Cliente.
fuente
Refactorizar una línea de código en una función parece excesivo. Puede haber casos excepcionales, como ver muuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu como por ver líneas o expresiones muy complejas, no haría esto a menos que sepa que la función crecerá en el futuro.
y su primer ejemplo sugiere el uso de globales (que pueden o no hablar de otros problemas en el código), lo refactorizaría aún más y convertiría esas dos variables como parámetros:
El
conditionMet
ejemplo podría ser útil si la condición era larga y repetitiva, como por ejemplo:fuente
conditionMet
función es solo un==
operador detallado . Eso probablemente no sea útil.conditionMet (x, relation condition) {
aquí, donde pasas x, '==' y relación. Entonces no necesita repetir el código para '<', '>', '<=', '! =' Y así sucesivamente. Por otro lado, la mayoría de los idiomas tienen estas construcciones incorporadas a medida que los operadores (condición x ==) hacen exactamente eso. Las funciones para las declaraciones atómicas están un paso demasiado lejos.Considera esto:
Una simple función de detección de colisión:
Si escribiste ese delineador "simple" en tu código todo el tiempo, eventualmente podrías cometer un error. Además, sería realmente tortuoso escribir eso una y otra vez.
fuente
#define
;)No, y eso rara vez es un problema. Ahora, si alguien siente que ninguna función debería ser más larga que una línea de código (si tan solo pudiera ser así de simple), eso sería un problema y de alguna manera perezoso porque no está pensando en lo que es apropiado.
fuente
function isAdult () = { age >= 18; }
pero seguramente noisAtLeast18
.Diría que son demasiado cortos, pero esta es mi opinión subjetiva.
Porque:
Las funciones que son largas son malas, pero las funciones que son más cortas que 3 líneas y realizan solo 1 cosa son igualmente malas en mi humilde opinión.
Entonces diría que solo escriba una función pequeña si es:
Apuesto a que el próximo desarrollador (senior) tendrá mejores cosas que hacer que recordar todas sus funciones SetXToOne. Entonces se convertirán en peso muerto muy pronto de cualquier manera.
fuente
No me gusta el ejemplo no. 1, por el nombre genérico i.
conditionMet
no parece ser genérico, por lo que representa una condición específica? Me gustaEsto estaría bien Es una diferencia semántica, mientras que
No estaría bien para mí.
Tal vez se usa con frecuencia y puede estar sujeto a cambios posteriores:
está bien también Si lo usa varias veces, solo necesita cambiar un solo lugar, si es necesario, tal vez la crema batida sea posible mañana.
no es atómico y debería darle una buena oportunidad de prueba.
Si necesita pasar una función, por supuesto, pase lo que quiera y escriba funciones que parezcan tontas.
Pero en general, veo muchas más funciones, que son demasiado largas, que funciones que son demasiado cortas.
Una última palabra: algunas funciones solo parecen apropiadas, porque están escritas demasiado detalladas:
Si ves, es lo mismo que
no tendrás problemas con
en lugar de
fuente
¡No hay código como ningún código!
Hazlo simple y no compliques demasiado las cosas.
¡No es ser perezoso, está haciendo tu trabajo!
fuente
Sí, está bien tener una función de código corto. En el caso de métodos como "getters", "setters", "accesors" es muy común, como se mencionó en las respuestas anteriores.
A veces, esas funciones cortas de "accesores" son virtuales, porque cuando se reemplazan en subclases las funciones tendrán más código.
Si desea que su función no sea tan breve, bueno, en muchas funciones, ya sean globales o métodos, generalmente uso una variable de "resultado" (estilo pascal) en lugar de un retorno directo, es muy útil cuando utilizo un depurador.
fuente
Demasiado corto nunca es un problema. Algunas razones para las funciones cortas son:
Reusabilidad
Por ejemplo, si tiene una función, como un método establecido, puede afirmarla para asegurarse de que los parámetros son válidos. Esta comprobación debe realizarse en todas partes donde se establezca la variable.
Mantenibilidad
Puede usar alguna declaración que piense que en el futuro puede cambiar. Por ejemplo, ahora muestra un símbolo en una columna, pero más tarde eso podría cambiar a otra cosa (o incluso un pitido).
Uniformidad
Está utilizando, por ejemplo, el patrón de fachada y lo único que hace una función es pasar exactamente la función a otra sin cambiar los argumentos.
fuente
Cuando le da un nombre a una sección de código, es esencialmente para darle un nombre . Esto puede ser por varias razones, pero el punto crucial es si puede darle un nombre significativo que se agregue a su programa. Nombres como "addOneToCounter" no agregarían nada, pero lo
conditionMet()
harían.Si necesita una regla para averiguar si el fragmento es demasiado corto o demasiado largo, considere cuánto tiempo le lleva encontrar un nombre significativo para el fragmento. Si no puede hacerlo dentro de un período de tiempo razonable, entonces el fragmento no tiene un tamaño adecuado.
fuente
No, pero puede ser demasiado conciso.
Recuerde: el código se escribe una vez, pero se lee muchas veces.
No escriba código para el compilador. Escríbalo para futuros desarrolladores que tendrán que mantener su código.
fuente
Sí, querida, la función podría ser cada vez más pequeña y si es buena o mala depende del idioma / marco que esté utilizando.
En mi opinión, trabajo principalmente en tecnologías front-end, las funciones pequeñas se usan principalmente como funciones auxiliares, seguramente las usará mucho cuando trabaje con filtros pequeños y use la misma lógica en su aplicación. Si su aplicación tiene demasiada lógica común, habrá muchas funciones pequeñas.
Pero en una aplicación donde no tiene una lógica común, no estará obligado a realizar pequeñas funciones, pero puede dividir su código en segmentos donde le resulte fácil de administrar y comprender.
En general, dividir su gran código en una función pequeña es un enfoque muy bueno. En marcos e idiomas modernos, seguramente lo hará, p. Ej.
es una función anónima en ES 2017 JavaScript y mecanografiado
en el código anterior puede ver 3 declaraciones de funciones y 2 llamadas a funciones, esta es una simple llamada de servicio en Angular 4 con Typecript. Puedes considerarlo como tus requisitos
Las anteriores son 3 funciones anónimas en lenguaje clojure
La anterior es una declaración funcional en clojure
Entonces sí, las FUNCIONES pueden ser más pequeñas pero si es bueno o malo si tiene funciones como:
Bueno, no es una buena práctica hacerlo, pero ¿qué pasa si está usando esta función en una etiqueta HTML como lo hacemos en Angular Framework si no hubiera soporte para Incremento o Disminución en Plantillas Angulares de HTML? Entonces esta habría sido la solución para yo.
Tomemos otro ejemplo
El ejemplo anterior es imprescindible cuando se juega cuando las matrices dentro de Plantillas HTML Angulares. Entonces a veces tendrás que crear pequeñas funciones
fuente
No estoy de acuerdo con casi la respuesta dada en este momento.
Recientemente encontré un colega que escribe a todos los miembros de la clase de la siguiente manera:
Este podría ser un buen código en casos esporádicos, pero seguramente no si define muchas clases que tienen muchas y muchas propiedades. No quiero decir, con esto, que los métodos como los anteriores no se escribirán. Pero, si termina escribiendo la mayor parte del código como "envoltorio" de la lógica real, hay algo mal.
Probablemente, el programador pierde la lógica general, teme los cambios futuros y la refactorización del código.
La definición de la interfaz se debe a una necesidad real; de hecho, si necesita establecer y obtener una propiedad simple (sin mucha lógica, lo que hace que el miembro sea más corto), será posible. Pero, si la necesidad real podría analizarse de una manera diferente, ¿por qué no definir una interfaz más intuitiva?
Para responder realmente a la pregunta, por supuesto que no, y la razón es muy obvia: el método / propiedad / whatelse se definirá para lo que necesita. Incluso una función virtual vacía tiene una razón para existir.
fuente