¿Los métodos largos son siempre malos? [cerrado]


64

Entonces, mirando alrededor, noté algunos comentarios sobre los métodos largos como una mala práctica.

No estoy seguro de estar siempre de acuerdo en que los métodos largos son malos (y me gustaría recibir opiniones de otros).

Por ejemplo, tengo algunas vistas de Django que procesan un poco los objetos antes de enviarlos a la vista, un método largo de 350 líneas de código. Tengo mi código escrito para que se ocupe de los parámetros: ordenar / filtrar el conjunto de consultas, luego, poco a poco, se procesa un poco en los objetos que mi consulta ha devuelto.

Entonces, el procesamiento es principalmente una agregación condicional, que tiene reglas suficientemente complejas que no se pueden hacer fácilmente en la base de datos, por lo que tengo algunas variables declaradas fuera del bucle principal y luego se modifican durante el bucle.

variable_1 = 0
variable_2 = 0
for object in queryset :
     if object.condition_condition_a and variable_2 > 0 :
     variable 1+= 1
     .....
     ...    
     . 
      more conditions to alter the variables

return queryset, and context 

Entonces, de acuerdo con la teoría, debo factorizar todo el código en métodos más pequeños, de modo que tenga el método de visualización como máximo de una página.

Sin embargo, después de haber trabajado en varias bases de código en el pasado, a veces encuentro que hace que el código sea menos legible, cuando necesitas saltar constantemente de un método a otro para descubrir todas las partes, mientras mantienes el método más externo en tu cabeza.

Encuentro que con un método largo que está bien formateado, puede ver la lógica más fácilmente, ya que no se oculta en los métodos internos.

Podría factorizar el código en métodos más pequeños, pero a menudo se usa un bucle interno para dos o tres cosas, por lo que daría como resultado un código más complejo o métodos que no hacen una cosa sino dos o tres (alternativamente Podría repetir bucles internos para cada tarea, pero luego habrá un golpe de rendimiento).

Entonces, ¿hay algún caso en que los métodos largos no siempre sean malos? ¿Siempre hay un caso para los métodos de escritura, cuando solo se usarán en un lugar?

ACTUALIZACIÓN: Parece que hice esta pregunta hace más de un año.

Entonces refactoré el código después de la respuesta (mixta) aquí, lo dividí en métodos. Es una aplicación de Django que recupera conjuntos complejos de objetos relacionados de la base de datos, por lo que el argumento de la prueba está fuera (probablemente habría llevado la mayor parte del año crear objetos relevantes para los casos de prueba. Tengo un tipo de "esto se hizo ayer" ambiente de trabajo antes de que nadie se queje). Corregir errores en esa parte del código es marginalmente más fácil ahora, pero no de manera masiva.

antes de :

#comment 1 
bit of (uncomplicated) code 1a  
bit of code 2a

#comment 2 
bit of code 2a
bit of code 2b
bit of code 2c

#comment 3
bit of code 3

ahora:

method_call_1
method_call_2
method_call_3

def method_1 
    bit of (uncomplicated) code 1a  
    bit of code 2a

def method_2 
    bit of code 2a
    bit of code 2b
    bit of code 2c

def method_3
    bit of code 3

156
Todos los absolutos son malos. Siempre.
Joachim Sauer el

30
Veo el argumento "extraer métodos si puede reutilizarlos" con bastante frecuencia (en esta o en formas similares), pero no lo compro: si el método está haciendo más de una cosa, debe extraer los métodos para facilitar la lectura / mantenibilidad incluso si esos nuevos métodos se invocan desde un solo lugar en su código.
Joachim Sauer el

44
@gnat: wow, ¿no sería algún tipo de integración manual (a través de un preprocesador) en el paso de compilación una mejor solución aquí?
Joachim Sauer el

11
Uno de los mejores programadores que conozco comentó que si realmente quieres una medida, el número de variables locales es mejor que la longitud real. Estaba trabajando en un optimizador de ruta complejo donde las tripas eran un método de varios cientos de líneas, pero la cantidad de estado (variables locales) que se mantenía era muy pequeña.
Chuu

2
Los métodos largos no siempre son malos; pero son algo que siempre debes mirar y preguntarte "¿es esto malo?"
Carson63000

Respuestas:


80

No, los métodos largos no siempre son malos.

En el libro Code Complete , se mide que los métodos largos a veces son más rápidos y fáciles de escribir, y no conducen a problemas de mantenimiento.

De hecho, lo que es realmente importante es mantenerse SECO y respetar la separación de las preocupaciones. En algún momento, el cálculo es largo para escribir, pero realmente no causará problemas en el futuro.

Sin embargo, desde mi experiencia personal, la mayoría de los métodos largos tienden a carecer de separación de preocupaciones. De hecho, los métodos largos son una forma fácil de detectar que algo PUEDE estar mal en el código, y que se requiere un cuidado especial aquí al hacer la revisión del código.

EDITAR: A medida que se hacen comentarios, agrego un punto interesante a la respuesta. De hecho, también verificaría las métricas de complejidad para la función (NPATH, complejidad ciclomática o incluso mejor CRAP).

De hecho, recomiendo no verificar tales métricas en funciones largas, sino incluir alertas en ellas con herramientas automatizadas (como checkstyle para java, por ejemplo) EN CADA FUNCIÓN.


41
+1: "No, los métodos largos no siempre son malos", pero casi siempre son malos
Binary Worrier

67
Los cuerpos largos del método son un olor de código clásico : no es en sí un problema, pero es una indicación de que probablemente haya un problema allí.
Joachim Sauer el

66
+1, pero aún así recomendaría verificar la complejidad ciclomática del método largo. Los valores altos indican métodos que son efectivamente imposibles de probar por unidad (y los métodos largos rara vez carecen de lógica de control de flujo).
Daniel B

11
Yo uso nombres de métodos para minimizar los comentarios. Lo que a veces conduce a cosas como "getSelectedNodeWithChildren", pero mi colega sigue diciéndome que mi código es muy fácil de leer. También trato de evitar abreviaturas, son agradables de escribir, pero no tan agradables de leer.
K ..

44
@ da_b0uncer Esa también es una política que sigo. Es más difícil leer el código que escribirlo, por lo que un esfuerzo adicional al escribir para que el código sea más legible vale la pena.
deadalnix

55

La mayor parte del enfoque aquí parece estar siempre alrededor de la palabra . Sí, los absolutos son malos, y la ingeniería de software es casi tanto arte como ciencia, y todo eso ... pero voy a tener que decir que para el ejemplo que diste, el método sería mejor si se dividiera arriba. Estos son los argumentos que normalmente usaría para justificar la división de su método:

Legibilidad: no estoy seguro acerca de los demás, pero no puedo leer 350 líneas de código rápidamente. Sí, si es mi propio código, y puedo hacer muchas suposiciones al respecto, podría leerlo muy rápidamente, pero eso no viene al caso. Considere cuánto más fácil sería leer ese método, si consistiera en 10 llamadas a otros métodos (cada uno con un nombre descriptivo). Al hacer esto, ha introducido una estratificación en el código, y el método de alto nivel le da al lector un breve resumen con respecto a lo que está sucediendo.

Editar: para expresarlo de otra manera, piense que es así: ¿cómo explicaría ese método a un nuevo miembro del equipo? Seguramente tiene alguna estructura que puede resumir en las líneas de "bueno, comienza haciendo A, luego B, luego a veces C, etc.". Tener un breve método de "descripción general" que llama a otros métodos hace que esta estructura sea obvia. Es extremadamente raro encontrar 350 líneas de código que no se benefician; el cerebro humano no está destinado a lidiar con listas de cientos de elementos, los agrupamos.

Reutilización: los métodos largos tienden a tener baja cohesión; a menudo hacen más de una cosa. La baja cohesión es el enemigo de la reutilización; Si combina múltiples tareas en un método, terminará siendo reutilizado en menos lugares de lo que debería haber sido.

Capacidad de prueba y cohesión: mencioné la complejidad ciclomática en un comentario anterior: es una medida bastante buena de cuán complejo es su método. Representa el límite inferior del número de rutas únicas a través de su código, dependiendo de las entradas (edición: corregida según el comentario de MichaelT). También significa que para probar adecuadamente su método, necesitaría tener al menos tantos casos de prueba como su número de complejidad ciclomática. Desafortunadamente, cuando juntas partes de código que realmente no dependen entre sí, no hay forma de estar seguro de esta falta de dependencia, y la complejidad tiende a multiplicarse. Puede pensar en esta medida como una indicación de la cantidad de cosas diferentes que está tratando de hacer. Si es demasiado alto, es hora de dividir y conquistar.

Refactorización y estructura: los métodos largos a menudo son signos de que falta una estructura en el código. A menudo, el desarrollador no pudo determinar cuáles son los puntos en común entre las diferentes partes de ese método, y dónde podría trazarse una línea entre ellas. Darse cuenta de que un método largo es un problema y tratar de dividirlo en métodos más pequeños es el primer paso en un camino más largo para identificar realmente una mejor estructura para todo. Quizás necesite crear una clase o dos; ¡no será necesariamente más complejo al final!

También creo que en este caso, la excusa para tener un método largo es "... algunas variables declaradas fuera del ciclo principal se alteran durante el ciclo". No soy un experto en Python, pero estoy bastante seguro de que este problema podría solucionarse trivialmente mediante alguna forma de pasar por referencia.


13
+1 por rechazar siempre la parte de la pregunta y centrarse en la carne: si los métodos largos son o no malos. Creo que el OP está buscando justificación como si su escenario fuera un caso límite, aunque generalmente cuando escucho a la gente explicar sus malas prácticas según sea necesario para el escenario poco común, es solo porque no se esforzaron mucho por usar las buenas prácticas. Los escenarios poco comunes son realmente muy poco comunes, lamentablemente los métodos largos son bastante comunes.
Jimmy Hoffa

2
Bien mirando la lista anterior: la legibilidad, diría por experiencia anterior, aumenta al tener el método por más tiempo, con muchos comentarios y bien formateado, en lugar de tener que saltar sobre el código del método a los métodos, aunque esto probablemente sea bastante subjetivo. No espero que las partes del código se reutilicen. La mayor parte de la reutilización del código se logra por herencia en este momento.
wobbily_col

1
@wobbily_col Por cierto, si está buscando un texto bien escrito que explique la razón de tener métodos más cortos, lea los primeros capítulos de Clean Code , que hace un buen trabajo de explicación.
Daniel B

55
@wobbily_col Dices que tener que saltar demasiado para entender el código con muchos métodos es confuso, creo que el punto que falta aquí es la importancia de nombrar. Si un método está bien nombrado, no necesita mirarlo para saber qué está haciendo, el método de llamada debe ser completamente comprensible sin ningún conocimiento subyacente de lo que están haciendo los métodos, por ejemplo, ¿alguna vez ha usado someVar.toString()y sentido? ¿Necesitabas ver el código de toString para saber qué está haciendo? Acabas de leer más allá debido a la buena denominación de métodos.
Jimmy Hoffa

44
En una nota al margen, tener un método que necesita n parámetros también es un olor a código e indica que el método puede hacer más de una cosa. Lo mismo ocurre con tener un método difícil de nombrar. Y si realmente necesita todos esos parámetros, generalmente son parte de un concepto más amplio, que puede y debe incluirse en una clase propia. Por supuesto, podríamos encontrar un ejemplo que sea mejor no usar esta regla; mi punto es que si ve un método así, investígalo a fondo, probablemente sea malo de alguna manera.
KL

28

Los métodos largos siempre son malos, pero ocasionalmente son mejores que las alternativas.


55
sin una explicación, esta respuesta puede volverse inútil en caso de que alguien más publique una opinión opuesta. Por ejemplo, si alguien publica un reclamo como "Los métodos largos nunca son malos, pero ocasionalmente son peores que las alternativas". , ¿cómo podría esta respuesta ayudar al lector a elegir dos opiniones opuestas? Considere editarlo en una mejor forma
mosquito

9

Los métodos largos son un código de olor . Por lo general, indican que algo anda mal, pero no es una regla estricta. Por lo general, los casos en los que están justificados implican muchas reglas comerciales estatales y bastante complejas (como ha encontrado).

En cuanto a su otra pregunta, con frecuencia es útil separar fragmentos de lógica en métodos separados, incluso si solo se llaman una vez. Hace que sea más fácil ver la lógica de alto nivel y puede hacer que el manejo de excepciones sea un poco más limpio. ¡Siempre y cuando no tenga que pasar veinte parámetros para representar el estado de procesamiento!


7

Los métodos largos no siempre son malos. Por lo general, son una señal de que puede haber un problema.

En el sistema en el que estoy trabajando tenemos media docena de métodos que tienen más de 10,000 líneas de largo. Uno tiene actualmente 54.830 líneas de largo. Y esta bien.

Estas funciones ridículamente largas son muy simples y se autogeneran. Ese gran monstruo de 54.830 líneas de largo contiene los datos diarios de movimiento polar del 1 de enero de 1962 al 10 de enero de 2012 (nuestro último lanzamiento). También lanzamos un procedimiento mediante el cual nuestros usuarios pueden actualizar ese archivo autogenerado. Ese archivo fuente contiene los datos de movimiento polar de http://data.iers.org/products/214/14443/orig/eopc04_08_IAU2000.62-now , traducido automáticamente a C ++.

Leer ese sitio web sobre la marcha no es posible en una instalación segura. No hay conexión con el mundo exterior. La descarga del sitio web como una copia local y el análisis en C ++ tampoco es una opción; el análisis es lento , y esto tiene que ser rápido. Descarga, traducción automática a C ++ y compilación: ahora tiene algo que es rápido. (Simplemente no lo compile optimizado. Es sorprendente cuánto tiempo tarda un compilador optimizador en compilar 50,000 líneas de código de línea recta extremadamente simple. Mi computadora tarda más de media hora en compilar ese archivo optimizado. Y la optimización no logra absolutamente nada No hay nada que optimizar. Es un simple código de línea recta, una declaración de asignación tras otra.)


66
"una declaración de asignación tras otra" ... lo llamaría un "archivo de datos". ¿Por qué es código?
Joachim Sauer

3
@JoachimSauer: porque analizar un archivo de datos grande en tiempo de ejecución en una configuración de Monte Carlo es una mala idea. Una muy, muy mala idea.
David Hammen

44
@DavidHammen: luego hágalo en el momento de la inicialización, al igual que obliga a su vinculador / cargador a hacerlo. O escriba el archivo de datos como una estructura C en un archivo de encabezado, en lugar de un código C. Al menos entonces el cargador se cargaría como un bloque de datos.
Javier

3
@Javier: Incluso en el momento de la inicialización, puede ser una muy mala idea, al menos en una configuración de Monte Carlo. Una simulación que tarda unos minutos en iniciarse, pero solo unos segundos para correr va en contra de la corriente de decenas de miles de carreras durante la noche. Cambiar las tareas clave de tiempo de inicialización para compilar tareas de tiempo soluciona ese problema. Hemos probado varias técnicas, incluido el enfoque de estructura de datos compilados. Simplemente no funciona o sería muy difícil hacer que funcione en algunos casos (por ejemplo, un modelo de gran gravedad). El enfoque de código de línea recta es fácil de generar automáticamente, fácil de verificar. Es solo un código feo.
David Hammen

77
+1 historia interesante. El código generado no es realmente el código fuente, por supuesto, por lo que se podría argumentar que esto no 'rompe' la regla. se supone que el generador de código en sí mismo tenía buenos métodos cortos
jk.

7

Digamos que hay formas buenas y malas de romper un método largo. Tener que "[mantener] el método más externo en tu cabeza" es una señal de que no lo estás dividiendo de la manera más óptima, o que tus submétodos están mal nombrados. En teoría, hay casos en los que un método largo es mejor. En la práctica, es extremadamente raro. Si no puede encontrar la manera de hacer que un método más corto sea legible, pídale a alguien que revise su código y pídales específicamente ideas para acortar los métodos.

En cuanto a los múltiples bucles que causan un supuesto impacto en el rendimiento, no hay forma de saberlo sin medir. Múltiples bucles más pequeños pueden ser significativamente más rápidos si significa que todo lo que necesita puede permanecer en caché. Incluso si hay un impacto en el rendimiento, generalmente es insignificante a favor de la legibilidad.

Diré que a menudo los métodos largos son más fáciles de escribir , aunque son más difíciles de leer . Por eso proliferan aunque a nadie le gusten. No hay nada de malo en planificar desde el principio para refactorizar antes de registrarlo.


1
"No hay nada de malo en planificar desde el principio para refactorizar antes de registrarlo". +1 por eso. La mayoría de los IDE de hoy en día tienen herramientas de refactorización que también lo hacen extremadamente fácil. Pero hay un método inverso donde delegas cosas a funciones inexistentes, y luego vas y completas los métodos, pero nunca he podido codificar de esa manera, por mucho que lo haya intentado.
Tjaart

+1 por "Tener que" [mantener] el método más externo en tu cabeza "es una señal de que no lo estás dividiendo de la manera más óptima"
Michael Shaw

4

Los métodos largos pueden ser más eficientes desde el punto de vista computacional y espacial, puede ser más fácil ver la lógica y más fácil depurarlos. Sin embargo, estas reglas solo se aplican cuando solo un programador toca ese código. El código será difícil de extender si no es atómico, esencialmente la siguiente persona tendrá que comenzar desde cero y luego depurar y probar esto tomará para siempre, ya que no está utilizando ningún código bueno conocido.


34
Siempre hay al menos dos programadores involucrados: "usted" y "usted, dentro de tres semanas".
Joachim Sauer el

3

Hay algo que llamamos descomposición funcional que implica dividir sus métodos más largos en métodos más pequeños siempre que sea posible. Como mencionó que su método implica ordenar / filtrar, es mejor que tenga métodos o funciones separados para estas tareas.

Precisamente, su método debe centrarse en realizar solo 1 tarea.

Y si necesita llamar a otro método por algún motivo, continúe con el método que ya está escribiendo. También para fines de legibilidad, puede agregar comentarios. Convencionalmente, los programadores usan comentarios de varias líneas (/ ** / en C, C ++, C # y Java) para las descripciones de los métodos y usan comentarios de una sola línea (// en C, C ++, C # y Java). También hay buenas herramientas de documentación disponibles para una mayor legibilidad del código (por ejemplo, JavaDoc ). También puede buscar comentarios basados en XML si es un desarrollador de .Net.

Los bucles impactan el rendimiento del programa y pueden causar sobrecarga de la aplicación si no se usan correctamente. La idea es diseñar su algoritmo de tal manera que use bucles anidados lo menos posible.


También conocido como "Una función debe hacer UNA COSA".
lorddev

3

Está perfectamente bien escribir funciones largas. Pero varía según el contexto si realmente lo necesita o no. Por ejemplo, algunos de los mejores algoritmos se expresan mejor cuando es una pieza. Por otro lado, un gran porcentaje de rutinas en programas orientados a objetos serán rutinas accesorias, que serán muy cortas. Algunas de las largas rutinas de procesamiento que tienen largas cajas de interruptores, si las condiciones pueden optimizarse a través de métodos controlados por tablas.

Hay una excelente discusión breve en Code Complete 2 sobre la duración de las rutinas.

La mejor longitud máxima teórica 497 a menudo se describe como una o dos páginas de listado de programas, 66 a 132 líneas. Los programas modernos tienden a tener volúmenes de rutinas extremadamente cortas mezcladas con algunas rutinas más largas.

Décadas de evidencia dicen que las rutinas de tal longitud no son más propensas a errores que las rutinas más cortas. Deje que cuestiones como la profundidad de anidamiento, el número de variables y otras consideraciones relacionadas con la complejidad dicten la duración de la rutina en lugar de imponer una longitud.

Si desea escribir rutinas de más de 200 líneas, tenga cuidado. Ninguno de los estudios que informaron una disminución en el costo, una disminución en las tasas de error, o ambos con rutinas más grandes distinguidas entre tamaños de más de 200 líneas, y es probable que se encuentre con un límite superior de comprensibilidad al pasar 200 líneas de código. 536 restricción per se.


2

Otra votación que casi siempre está mal. Sin embargo, encuentro dos casos básicos en los que es la respuesta correcta:

1) Un método que básicamente solo llama a un montón de otros métodos y no funciona realmente en sí mismo. Tiene un proceso que lleva 50 pasos, se obtiene un método con 50 llamadas. Por lo general, no se gana nada al tratar de romper eso.

2) Despachadores. El diseño OOP ha eliminado la mayoría de estos métodos, pero las fuentes de datos entrantes son, por su propia naturaleza, solo datos y, por lo tanto, no pueden seguir los principios de OOP. No es exactamente inusual tener algún tipo de rutina de despachador en el código que maneja los datos.

También diría que uno ni siquiera debería considerar la pregunta cuando se trata de cosas autogeneradas. Nadie está tratando de entender lo que hace el código autogenerado, no importa si es fácil de entender para un humano.


1
El proceso de 50 pasos probablemente se puede resumir en varios segmentos. Los pasos 1 a 9 son verificaciones de parámetros, por lo tanto, cree un nuevo método llamado verificación de parámetros. (Estoy seguro de que hay algunos ejemplos en los que esto no es posible. Me interesaría ver uno).
sixtyfootersdude

@sixtyfootersdude: Claro, podrías romperlo. No dije que era imposible, dije que no había nada que ganar al dividirlo. Si bien no fueron 50 pasos, he golpeado algo así: crear un mundo de juegos. # 1 creó el mundo vacío, # 2 creó el terreno y luego un montón de pasos después de eso lo masajearon de una manera u otra.
Loren Pechtel

& sixtyfootersdude: es sorprendente cómo sabes el código que nunca has visto y cómo mejorarlo.
gnasher729

2

Quería abordar el ejemplo que diste:

Por ejemplo, tengo algunas vistas de Django que procesan un poco los objetos antes de enviarlos a la vista, un método largo de 350 líneas de código. Tengo mi código escrito para que se ocupe de los parámetros: ordenar / filtrar el conjunto de consultas, luego, poco a poco, se procesa un poco en los objetos que mi consulta ha devuelto.

En mi empresa, nuestro proyecto más grande se basa en Django y también tenemos funciones de visión prolongada (muchas son más de 350 líneas). Yo diría que los nuestros no necesitan ser tan largos, y nos están haciendo daño.

Estas funciones de vista están haciendo un montón de trabajo vagamente relacionado que se debe extraer al modelo, las clases auxiliares o las funciones auxiliares. Además, terminamos reutilizando las vistas para hacer cosas diferentes, que en su lugar deberían dividirse en vistas más coherentes.

Sospecho que sus puntos de vista tienen características similares. En mi caso, sé que causa problemas y estoy trabajando para hacer cambios. Si no está de acuerdo con que está causando problemas, entonces no necesita arreglarlo.


2

No sé si alguien ya ha mencionado esto, pero una de las razones por las cuales los métodos largos son malos es porque generalmente involucran varios niveles diferentes de abstracción. Tienes variables de bucle y todo tipo de cosas que suceden. Considere la función ficticia:

function nextSlide() {
  var content = getNextSlideContent();
  hideCurrentSlide();
  var newSlide = createSlide(content);
  setNextSlide(newSlide);
  showNextSlide();
}

Si estuviera haciendo toda la animación, cálculo, acceso a datos, etc. en esa función, habría sido un desastre. La función nextSlide () mantiene una capa de abstracción consistente (el sistema de estado de la diapositiva) e ignora otras. Esto hace que el código sea legible.

Si tiene que ingresar constantemente a métodos más pequeños para ver lo que hacen, entonces el ejercicio de dividir la función ha fallado. El hecho de que el código que está leyendo no esté haciendo cosas obvias en los métodos secundarios no significa que los métodos secundarios sean una mala idea, solo que se hizo incorrectamente.

Cuando creo métodos, generalmente termino dividiéndolos en métodos más pequeños como una especie de estrategia de dividir y conquistar. Un método como

   if (hasMoreRecords()) { ... }

es ciertamente más legible que

if (file.isOpen() && i < recordLimit && currentRecord != null) { ... } 

¿Derecho?

Estoy de acuerdo en que las declaraciones absolutas son malas y también estoy de acuerdo en que generalmente un método largo es malo.


1

Historia verdadera. Una vez encontré un método que tenía más de dos mil líneas de largo. El método tenía regiones que describían lo que estaba haciendo en esas regiones. Después de leer una región, decidí hacer un método de extracción automatizado, nombrándolo de acuerdo con el nombre de la región. para cuando terminé, el método no era más que 40 llamadas al método de aproximadamente cincuenta líneas cada una y todo funcionó igual.

Lo que es demasiado grande es subjetivo. A veces, un método no puede desglosarse más allá de lo que es actualmente. Es como escribir un libro. La mayoría de la gente está de acuerdo en que los párrafos largos generalmente deben dividirse. Pero a veces, solo hay una idea y dividirla causa más confusión de la que causaría la longitud de ese párrafo.


0

El objetivo de un método es ayudar a reducir la regurgitación del código. Un método debe tener una función específica de la que es responsable. Si termina volviendo a escribir código en numerosos lugares, corre el riesgo de que el código tenga resultados inesperados si se cambian las especificaciones que el software está diseñado para abordar.

Para que un método tenga 350 líneas sugeriría que muchas de las tareas que está llevando a cabo se replican en otro lugar, ya que es inusual requerir una cantidad tan grande de código para llevar a cabo una tarea especializada.


Ayuda a reducir el código, ¿qué ?
Avner Shahar-Kashtan

@ AvnerShahar-Kashtan, probablemente quiere decir "duplicación" :-)
Péter Török

0

No son realmente los métodos largos los que son una mala práctica, es más bien dejarlos así que es malo.

Quiero decir que el acto real de refactorizar su muestra de:

varaible_1 = 0
variable_2 = 0
for object in queryset :
     if object.condition_condition_a and variable_2 > 0 :
     variable 1+= 1
     .....
     ...    
     . 
      more conditions to alter the variables

return queryset, and context 

a

Status status = new Status();
status.variable1 = 0;
status.variable2 = 0;
for object in queryset :
     if object.condition_condition_a and status.variable2 > 0 :
     status.variable1 += 1
     .....
     ...    
     . 
      more conditions to alter the variables (status)

return queryset, and context 

y luego a

class Status {
    variable1 = 0;
    variable2 = 0;

    void update(object) {
        if object.condition_condition_a and variable2 > 0 {
            variable1 += 1
        }
    }
};

Status status = new Status();
for object in queryset :
     status.update(object);
     .....
     ...    
     . 
      more conditions to alter the variables (status)

return queryset, and context 

ahora está en camino no solo a un método mucho más corto, sino a uno mucho más útil y comprensible.


0

Creo que el hecho de que el método es muy largo es algo para verificar, pero definitivamente no es un antipatrón instantáneo. La gran cosa a tener en cuenta en los métodos enormes es un montón de anidamiento. Si usted tiene

foreach(var x in y)
{
    //do ALL the things
    //....
}

y el cuerpo del bucle no está extremadamente localizado (es decir, podría enviarle menos de 4 parámetros), entonces probablemente sea mejor convertirlo a:

foreach(var x in y)
{
    DoAllTheThings(x);
}
...
void DoAllTheThings(object x)
{
    //do ALL the things
    //....
}

A su vez, esto puede reducir enormemente la duración de una función. Además, asegúrese de buscar código duplicado en la función y moverlo a una función separada

Finalmente, algunos métodos son largos y complicados y no hay nada que pueda hacer. Algunos problemas necesitan soluciones que no se prestan a un código fácil. Por ejemplo, analizar una gramática de mucha complejidad puede hacer métodos realmente largos que realmente no se pueden hacer sin empeorarlo.


0

La verdad es que depende. Como se mencionó, si el código no separa las preocupaciones e intenta hacer todo en un método, entonces es un problema. La separación del código en múltiples módulos facilita la lectura del código, así como la escritura del código (por parte de múltiples programadores). Para empezar, es una buena idea adherirse a un módulo (clase) por archivo fuente.

En segundo lugar, cuando se trata de funciones / procedimientos:

void setDataValueAndCheckForRange(Data *data) {/*code*/} 

es un buen método si comprueba el rango de solo "Datos". Es un método MALO cuando se aplica el mismo rango para múltiples funciones (ejemplo de código incorrecto):

void setDataValueAndCheckForRange(Data *data){ /*code */}
void addDataValuesAndCheckForRange(Data *result, Data *d1, Data *d2){ /*code*/}
void subDataValuesAndCheckForRange(Data *result, Data *d1, Data *d2){ /*code*/}
void mulDataValuesAndCheckForRange(Data *result, Data *d1, Data *d2){ /*code*/}

Esto debe ser refactorizado para:

bool isWithinRange(Data *d){ /*code*/ }
void setDataValue(Data *d) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 
void addDataValue(Data *d, Data *d1, Data *d2) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 
void subDataValue(Data *d, Data *d1, Data *d2) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 
void mulDataValue(Data *d, Data *d1, Data *d2) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 

REUTILIZA el código tanto como sea posible. Y eso es posible cuando cada función de su programa es SIMPLE (no necesariamente fácil).

CITA: LA MONTAÑA está compuesta de pequeños granos de tierra. El océano está formado por pequeñas gotas de agua .. (- Sivananda)


0

Los métodos largos tienden a ser "malos" en los lenguajes imperativos que favorecen las declaraciones, los efectos secundarios y la mutabilidad, precisamente porque esas características aumentan la complejidad y, por lo tanto, los errores.

En los lenguajes de programación funcionales, que favorecen las expresiones, la pureza y la inmutabilidad, hay menos motivos de preocupación.

En lenguajes funcionales e imperativos por igual, siempre es mejor factorizar fragmentos de código reutilizables en rutinas comunes de nivel superior, pero en lenguajes funcionales que admiten el alcance léxico con funciones anidadas, etc., en realidad es mejor encapsulación para ocultar subrutinas dentro de la parte superior -nivel (método) que dividirlos en otras funciones de nivel superior.


Sin embargo, en lenguajes funcionales, los métodos largos son mucho menos comunes.
itsbruce
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.