En la programación orientada a objetos, por supuesto, no existe una regla exacta sobre la longitud máxima de un método, pero aún así estas dos citas se contradicen entre sí, por lo que me gustaría escuchar lo que piensas.
En Clean Code: A Handbook of Agile Software Craftsmanship , Robert Martin dice:
La primera regla de funciones es que deben ser pequeñas. La segunda regla de funciones es que deberían ser más pequeñas que eso. Las funciones no deben tener 100 líneas de largo. Las funciones casi nunca deben tener 20 líneas de largo.
y da un ejemplo del código Java que ve de Kent Beck:
Cada función en su programa tenía solo dos, tres o cuatro líneas de largo. Cada uno era transparentemente obvio. Cada uno contaba una historia. Y cada uno te llevó al siguiente en un orden convincente. ¡Así de cortas deberían ser tus funciones!
Esto suena genial, pero por otro lado, en Code Complete , Steve McConnell dice algo muy diferente:
Se debe permitir que la rutina crezca orgánicamente hasta 100-200 líneas, décadas de evidencia dicen que las rutinas de tal longitud no son más propensas a errores que las rutinas más cortas.
Y da una referencia a un estudio que dice que las rutinas de 65 líneas o más son más baratas de desarrollar.
Entonces, si bien hay opiniones divergentes sobre el asunto, ¿hay una práctica recomendada funcional para usted?
fuente
switch
declaración con 100case
condiciones es más fácil de mantener que 10 niveles deif
declaraciones anidadas entre sí.Respuestas:
Las funciones normalmente deberían ser cortas, entre 5-15 líneas es mi "regla de oro" personal al codificar en Java o C #. Este es un buen tamaño por varias razones:
Pero no creo que sea útil establecer una regla absoluta, ya que siempre habrá excepciones / razones válidas para divergir de la regla:
Básicamente, use el sentido común , manténgase en tamaños de función pequeños en la mayoría de los casos, pero no sea dogmático al respecto si tiene una buena razón para hacer una función inusualmente grande.
fuente
Si bien estoy de acuerdo con los comentarios de otros cuando dijeron que no hay una regla estricta sobre el número LOC correcto, apuesto a que si miramos hacia atrás en los proyectos que hemos visto en el pasado e identificamos todas las funciones anteriores, digamos 150 líneas de código, yo ' Supongo que llegaríamos a un consenso de que 9 de cada 10 de esas funciones rompen el SRP (y muy probablemente también el OCP), tienen demasiadas variables locales, demasiado flujo de control y generalmente son difíciles de leer y mantener.
Entonces, si bien LOC puede no ser un indicador directo de código incorrecto, ciertamente es un indicador indirecto decente de que cierta función podría escribirse mejor.
En mi equipo caí en la posición de líder y, por alguna razón, la gente parece estar escuchándome. Lo que generalmente decidí es decirle al equipo que, si bien no hay un límite absoluto, cualquier función con más de 50 líneas de código debería, como mínimo, levantar una bandera roja durante la revisión del código, para que lo revisemos y reevaluémoslo por complejidad y violaciones de SRP / OCP. Después de ese segundo vistazo, podríamos dejarlo solo o podríamos cambiarlo, pero al menos hace que la gente piense en estas cosas.
fuente
Entré en un proyecto que no se ha preocupado por las pautas de codificación. Cuando miro el código, a veces encuentro clases con más de 6000 líneas de código y menos de 10 métodos. Este es un escenario de terror cuando tienes que corregir errores.
Una regla general de cuán grande debe ser un método al máximo a veces no es tan buena. Me gusta la regla de Robert C. Martin (tío Bob): "Los métodos deben ser pequeños, más pequeños que pequeños". Intento usar esta regla todo el tiempo. Estoy tratando de mantener mis métodos simples y pequeños aclarando que mi método solo hace una cosa y nada más.
fuente
No se trata del número de líneas, se trata de SRP. De acuerdo con este principio, su método debe hacer una y solo una cosa.
Si su método hace esto Y esto Y esto O eso => probablemente esté haciendo demasiado. Intente ver este método y analizar: "aquí obtengo estos datos, los ordeno y obtengo los elementos que necesito" y "aquí proceso estos elementos" y "aquí finalmente los combino para obtener el resultado". Estos "bloques" deben ser refactorizados a otros métodos.
Si simplemente sigue SRP, la mayoría de su método será pequeño y con clara intención.
No es correcto decir "este método es> 20 líneas, por lo que está mal". Puede ser una indicación de que algo puede estar mal con este método, no más.
Puede tener un cambio de 400 líneas en un método (a menudo sucede en telecomunicaciones), y todavía es responsabilidad única y está perfectamente bien.
fuente
Depende , en serio, realmente no hay una respuesta sólida a esta pregunta porque el lenguaje con el que está trabajando importa, las líneas cinco a quince mencionadas en esta respuesta podrían funcionar para C # o Java, pero en otros idiomas no da Eres mucho para trabajar. Del mismo modo, dependiendo del dominio en el que esté trabajando, puede encontrarse escribiendo valores de configuración de código en una estructura de datos grande. Con algunas estructuras de datos, es posible que tenga decenas de elementos que necesita establecer, ¿debería dividir las cosas en funciones separadas solo porque su función se ejecuta durante mucho tiempo?
Como otros han señalado, la mejor regla general es que una función debe ser una sola entidad lógica que maneje una sola tarea. Si intenta imponer reglas draconianas que dicen que las funciones no pueden ser más largas que n líneas y hace que ese valor sea demasiado pequeño, su código será más difícil de leer a medida que los desarrolladores intenten usar trucos sofisticados para sortear la regla. Del mismo modo, si lo configura demasiado alto, no será un problema y puede generar un código incorrecto a pesar de la pereza. Su mejor opción es realizar revisiones de código para asegurarse de que las funciones manejan una sola tarea y dejarla así.
fuente
Creo que un problema aquí es que la longitud de una función no dice nada sobre su complejidad. LOC (líneas de código) son un mal instrumento para medir cualquier cosa.
Un método no debe ser demasiado complejo, pero hay escenarios en los que se puede mantener fácilmente un método largo. Tenga en cuenta que el siguiente ejemplo no dice que no podría dividirse en métodos, solo que los métodos no cambiarían la capacidad de mantenimiento.
por ejemplo, un controlador para datos entrantes puede tener una declaración de cambio grande y luego un código simple por caso. Tengo ese código: administrar los datos entrantes de un feed. 70 (!) Controladores codificados numéricamente. Ahora, uno dirá "usar constantes" - sí, excepto que la API no las proporciona y me gusta estar cerca de "fuente" aquí. Métodos? Claro, lamentablemente todos tratan datos de las mismas 2 grandes estructuras. No hay beneficio en dividirlos, excepto tal vez tener más métodos (legibilidad). El código no es intrínsecamente complejo: un cambio, dependiendo de un campo. Luego, cada caso tiene un bloque que analiza x elementos de datos y los publica. Sin pesadillas de mantenimiento. Hay una condición "if repetida" que determina si un campo tiene datos (pField = pFields [x], if pField-> IsSet () {blabla}) - lo mismo para cada campo.
Reemplace eso con una rutina mucho más pequeña que contenga un bucle anidado y muchas instrucciones de cambio reales y un método enorme puede ser más fácil de mantener que uno más pequeño.
Entonces, lo siento, LOC no es una buena medida para empezar. En todo caso, se deben utilizar los puntos de complejidad / decisión.
fuente
Solo agregaré otra cita.
Es muy improbable que las funciones que crecen hasta 100-200 sigan esta regla.
fuente
He estado en esta locura, de una forma u otra, desde 1970.
En todo ese tiempo, con dos excepciones a las que llegaré en un momento, NUNCA he visto una "rutina" bien diseñada (método, procedimiento, función, subrutina, lo que sea) que NECESITA ser más de una página impresa ( unas 60 líneas) de largo. La gran mayoría de ellos eran bastante cortos, del orden de 10-20 líneas.
Sin embargo, he visto MUCHO código de "flujo de conciencia", escrito por personas que aparentemente nunca oyeron hablar de la modularización.
Las dos excepciones fueron casos muy especiales. Uno es en realidad una clase de casos de excepción, que agrupo: grandes autómatas de estado finito, implementados como grandes declaraciones de cambio feo, generalmente porque no hay una forma más limpia de implementarlos. Estas cosas generalmente aparecen en equipos de prueba automatizados, analizando registros de datos del dispositivo bajo prueba.
La otra era la rutina de torpedos de fotones del juego STARTRK Matuszek-Reynolds-McGehearty-Cohen, escrito en CDC 6600 FORTRAN IV. Tenía que analizar la línea de comando, luego simular el vuelo de cada torpedo, con perturbaciones, verificar la interacción entre el torpedo y cada tipo de cosa que podría golpear, y, por cierto, simular la recursividad para hacer conectividad de 8 vías en cadenas de novas de torpedear una estrella que estaba al lado de otras estrellas.
fuente
Si encuentro un método largo, podría apostar que este método no se prueba adecuadamente en la unidad o la mayoría de las veces no tiene una prueba unitaria. Si comienza a hacer TDD, nunca construirá métodos de 100 líneas con 25 responsabilidades diferentes y 5 bucles anidados. Las pruebas te obligan a refactorizar constantemente tu desorden y escribir el código limpio del tío Bob.
fuente
No hay reglas absolutas sobre la longitud del método, pero las siguientes reglas han sido útiles:
fuente
¿Los autores quieren decir lo mismo con "función" y "rutina"? Por lo general, cuando digo "función" me refiero a una subrutina / operación que devuelve un valor y un "procedimiento" para uno que no lo hace (y cuya llamada se convierte en una sola declaración). Esta no es una distinción común en todo el SE en el mundo real, pero la he visto en textos de usuario.
De cualquier manera, no hay una respuesta correcta para esto. La preferencia por uno u otro (si es que existe alguna preferencia) es algo que esperaría que fuera muy diferente entre idiomas, proyectos y organizaciones; tal como es con todas las convenciones de código.
El único bit que agregaría es que toda la afirmación "las operaciones largas no son más propensas a errores que las operaciones cortas" no es estrictamente cierta. Además del hecho de que más código equivale a más espacio de error potencial, es muy obvio que dividir el código en segmentos hará que los errores sean más fáciles de evitar y más fáciles de localizar. De lo contrario, no habría razón para romper el código en pedazos, salvo la repetición. Pero esto tal vez sea cierto solo si dichos segmentos están documentados lo suficientemente bien como para que pueda determinar los resultados de una llamada de operación sin leer o rastrear el código real (diseño por contrato basado en especificaciones en lugar de dependencia concreta entre áreas de código).
Además, si desea que las operaciones más largas funcionen bien, es posible que desee adoptar convenciones de código más estrictas para admitirlas. Lanzar una declaración de devolución en el medio de una operación puede estar bien para una operación corta, pero en operaciones más largas esto puede crear una gran sección de código que es condicional pero no obviamente condicional en una lectura rápida (solo por un ejemplo).
Entonces, creo que qué estilo es menos probable que sea una pesadilla llena de errores dependerá en gran medida de las convenciones a las que se adhiera para el resto de su código. :)
fuente
En mi humilde opinión, no debería tener que usar la barra de desplazamiento para leer su función. Tan pronto como necesite mover la barra de desplazamiento, le tomará más tiempo entender cómo funciona la función.
En consecuencia, depende del entorno de programación habitual del trabajo de su equipo (resolución de pantalla, editor, tamaño de fuente, etc.). En los años 80, tenía 25 líneas y 80 columnas. Ahora, en mi editor, muestro casi 50 líneas. El número de columnas que visualizo no cambió ya que dividí mi pantalla en dos para mostrar dos archivos a veces.
En resumen, depende de la configuración de sus compañeros de trabajo.
fuente
Creo que la respuesta de TomTom se acercó a cómo me siento al respecto.
Cada vez me encuentro más complejo ciclomático en lugar de líneas.
Normalmente apunto a no más de una estructura de control por método, con la excepción de los bucles necesarios para manejar una matriz multidimensional.
A veces me encuentro colocando ifs de una línea en casos de cambio porque, por alguna razón, estos tienden a ser casos en los que dividirlo obstaculiza en lugar de ayudar.
Tenga en cuenta que no cuento la lógica de guardia contra este límite.
fuente
En OOP todas las cosas se oponen y hay estas características:
Cuando observa estas reglas, sus métodos generalmente son pequeños, pero no existe ninguna regla para reglas pequeñas o muy pequeñas (por ejemplo, 2-3 líneas). Un beneficio del método pequeño (unidad pequeña, por ejemplo, método o función) son:
fuente