¿Existe tal cosa como tener demasiadas funciones / métodos privados?

61

Entiendo la importancia de un código bien documentado. Pero también entiendo la importancia del código de autodocumentación . Cuanto más fácil sea leer visualmente una función particular, más rápido podremos avanzar durante el mantenimiento del software.

Dicho esto, me gusta separar las funciones de big en otras más pequeñas. Pero lo hago hasta un punto donde una clase puede tener más de cinco de ellos solo para servir a un método público. Ahora multiplique cinco métodos privados por cinco públicos, y obtendrá alrededor de veinticinco métodos ocultos que probablemente solo serán llamados una vez por esos públicos.

Claro, ahora es más fácil leer esos métodos públicos, pero no puedo evitar pensar que tener demasiadas funciones es una mala práctica.

[Edit◆

La gente me ha estado preguntando por qué creo que tener demasiadas funciones es una mala práctica.

La respuesta simple: es una sensación visceral.

Por un poco, mi creencia no está respaldada por ninguna hora de experiencia en ingeniería de software. Es solo una incertidumbre que me dio un "bloqueo de escritor", pero para un programador.

En el pasado, solo he estado programando proyectos personales. Es solo recientemente que me mudé a proyectos basados en equipos. Ahora, quiero asegurarme de que otros puedan leer y entender mi código.

No estaba seguro de qué mejorará la legibilidad. Por un lado, estaba pensando en separar una función grande en otra más pequeña con nombres inteligibles. Pero había otra cara de mí que decía que solo era redundante.

Por lo tanto, estoy pidiendo que esto me ilumine para elegir el camino correcto.

[Edit◆

A continuación, incluí dos versiones de cómo podría resolver mi problema. El primero lo resuelve al no separar grandes trozos de código. El segundo hace cosas separadas.

Primera versión:

public static int Main()
{
    // Displays the menu.
    Console.WriteLine("Pick your option");
    Console.Writeline("[1] Input and display a polynomial");
    Console.WriteLine("[2] Add two polynomials");
    Console.WriteLine("[3] Subtract two polynomials");
    Console.WriteLine("[4] Differentiate two polynomials");
    Console.WriteLine("[0] Quit");
}

Segunda versión:

public static int Main()
{
    DisplayMenu();
}

private static void DisplayMenu()
{
    Console.WriteLine("Pick your option");
    Console.Writeline("[1] Input and display a polynomial");
    Console.WriteLine("[2] Add two polynomials");
    Console.WriteLine("[3] Subtract two polynomials");
    Console.WriteLine("[4] Differentiate two polynomials");
    Console.WriteLine("[0] Quit");
}

En los ejemplos anteriores, este último llama a una función que solo se usará una vez durante todo el tiempo de ejecución del programa.

Nota: el código anterior está generalizado, pero es de la misma naturaleza que mi problema.

Ahora, aquí está mi pregunta: ¿cuál? ¿Elijo el primero o el segundo?

    
pregunta skizeey 14.02.2011 - 00:26

10 respuestas

32
  

Ahora multiplique cinco métodos privados por cinco públicos, y obtendrá alrededor de veinticinco métodos ocultos que probablemente solo serán llamados una vez por esos públicos.

Esto es lo que se conoce como Encapsulation , que crea un Abstracción de control en el nivel superior. Esto es algo bueno.

Esto significa que cualquier persona que lea su código, cuando llegue al método startTheEngine() en su código, puede ignorar todos los detalles del nivel inferior como openIgnitionModule() , turnDistributorMotor() , sendSparksToSparkPlugs() , injectFuelIntoCylinders() , activateStarterSolenoid() , y todas las otras funciones complejas, pequeñas, que deben ejecutarse para facilitar la función mucho más grande y abstracta de startTheEngine() .

A menos que el problema con el que esté lidiando en su código resuelva directamente con uno de esos componentes, los mantenedores de código pueden seguir adelante, ignorando la funcionalidad encapsulada y de espacio aislado.

Esto también tiene la ventaja adicional de que facilita la prueba del código . Por ejemplo, puedo escribir un caso de prueba para turnAlternatorMotor(int revolutionRate) y probar su funcionalidad completamente independiente de los otros sistemas. Si hay un problema con esa función y la salida no es lo que esperaba, entonces sé cuál es el problema.

El código que no se divide en componentes es mucho más difícil de probar. De repente, sus mantenedores solo miran lo que sería una abstracción en lugar de poder profundizar en componentes medibles.

Mi consejo es que sigas haciendo lo que estás haciendo, ya que tu código se escalará, será fácil de mantener y se podrá usar y actualizar durante los próximos años.

    
respondido por el jmort253 14.02.2011 - 05:10
21

Sí y no. El principio fundamental es: un método debe hacer una cosa y solo una cosa

Es correcto "dividir" tu método en métodos más pequeños. Entonces, nuevamente, esos métodos deberían ser lo suficientemente generales como para que no solo solamente sirvan ese método "grande" sino que sean reutilizables en otros lugares. En algunos casos, un método seguirá una estructura de árbol simple, como un método de inicialización que llama a InitializePlugins, InitializeInterface, etc.

Si tienes un método / clase realmente grande, generalmente es una señal de que te está yendo mucho y debes hacer un poco de refactorización para romper el "blob". Los perphaps ocultan cierta complejidad en otra clase bajo una abstracción, y usan inyección de dependencia

    
respondido por el Homde 14.02.2011 - 00:40
16

Creo que, en general, es mejor errar en el lado de demasiadas funciones en lugar de muy pocas. Las dos excepciones a esa regla que he visto en la práctica son para DRY y YAGNI . Si tiene muchas funciones casi idénticas, debe combinarlas y usar parámetros para evitar que se repita. También puede tener demasiadas funciones si las creó "por si acaso" y no se están utilizando. No veo absolutamente nada de malo en tener una función que solo se use una vez si agrega legibilidad y facilidad de mantenimiento.

    
respondido por el Karl Bielefeldt 14.02.2011 - 04:16
10
La gran respuesta de

jmort253 me inspiró a seguir con un "sí, pero" responde ...

Tener muchos métodos privados pequeños no es algo malo, pero presta atención a esa sensación inquietante que te está haciendo publicar una pregunta aquí :). Si llega a un punto en el que está escribiendo pruebas que se centran solo en métodos privados (llamándolos directamente o configurando un escenario tal que se llame a uno de cierta manera para que pueda probar el resultado) Deberías dar un paso atrás.

Lo que puedes tener es una nueva clase con su propia interfaz pública más enfocada que intenta escapar. En ese momento, es posible que desee pensar en extraer una clase para encapsular esa parte de la funcionalidad de sus clases existentes que actualmente vive en un método privado. Ahora su clase original puede usar su nueva clase como una dependencia, y puede escribir pruebas más enfocadas contra esa clase directamente.

    
respondido por el Pete Hodgson 14.02.2011 - 09:14
8

Casi todos los proyectos OO a los que me he unido sufrieron mal las clases que eran demasiado grandes y los métodos demasiado largos.

Cuando siento la necesidad de un comentario que explique la siguiente sección de código, luego extraigo esa sección en un método separado. A largo plazo, esto hace que el código sea más corto. Esos pequeños métodos se reutilizan más de lo que inicialmente esperaría. Comienzas a ver oportunidades para reunir un grupo de ellos en una clase separada. Pronto estará pensando en su problema a un nivel superior, y todo el esfuerzo irá mucho más rápido. Las nuevas funciones son más fáciles de escribir, ya que puedes construir sobre esas pequeñas clases que creaste con esos pequeños métodos.

    
respondido por el kevin cline 15.02.2011 - 00:09
7

Una clase con 5 métodos públicos y 25 métodos privados no me parece tan grande. Solo asegúrate de que tus clases tengan responsabilidades bien definidas y no te preocupes demasiado por la cantidad de métodos.

Dicho esto, esos métodos privados deberían centrarse en un aspecto específico de toda la tarea, pero no de una manera "doSomethingPart1", "doSomethingPart2". Usted no gana nada si esos métodos privados son solo piezas de una larga historia dividida arbitrariamente, cada una sin sentido fuera de todo el contexto.

    
respondido por el user281377 14.02.2011 - 10:15
4

Extracto del Código limpio de R. Martin (pág. 176):

  

Incluso los conceptos tan fundamentales como la eliminación de la duplicación, la expresividad del código y el SRP se pueden llevar demasiado lejos. En un esfuerzo por hacer que nuestras clases y métodos sean pequeños, podemos crear demasiadas clases y métodos pequeños. Así que esta regla [minimizar el número de clases y métodos] sugiere que también mantengamos nuestra función   y la clase cuenta bajo.   Los recuentos de clase alta y de métodos son a veces el resultado de un dogmatismo sin sentido.

    
respondido por el user2418306 02.09.2016 - 18:26
3

Algunas opciones:

  1. Eso está bien. Simplemente nombre los métodos privados así como usted nombra sus métodos públicos. Y nombra bien tus métodos públicos.

  2. Resuma algunos de estos métodos de ayuda en clases de ayuda o módulos de ayuda. Y asegúrese de que estas clases / módulos de ayuda tengan un nombre correcto y sean abstracciones sólidas en sí mismas.

respondido por el yfeldblum 14.02.2011 - 00:31
1

No creo que haya un problema de "demasiados métodos privados" si se siente así, probablemente sea un síntoma de una arquitectura de código deficiente.

Así es como lo pienso ... Si la arquitectura está bien diseñada, generalmente es obvio dónde debería estar el código que hace X. Es aceptable si hay un par de excepciones a esto, pero estas deben ser verdaderamente excepcionales, de lo contrario refactorizará la arquitectura para manejarlas como estándar.

Si el problema es que al abrir su clase, está lleno de métodos privados que dividen partes más grandes en partes más pequeñas de código, entonces tal vez este sea un síntoma de falta de arquitectura. En lugar de clases y arquitectura, esta área de código se implementó de manera procesal dentro de una clase.

Encontrar un equilibrio aquí depende del proyecto y sus requisitos. El argumento contrario a esto es el dicho de que un programador junior puede eliminar la solución en 50 líneas de código que toma clases de un arquitecto 50.

    
respondido por el Michael Shaw 02.09.2016 - 21:13
0
  

¿Existe tal cosa como tener demasiadas funciones / métodos privados?

Sí.

En Python, el concepto de "privado" (tal como lo usa C ++, Java y C #) no existe realmente.

Hay una convención de nomenclatura "tipo de privada", pero eso es todo.

Privado puede llevar a código difícil de probar. También puede romper el "principio abierto-cerrado" al hacer que el código se cierre simplemente.

En consecuencia, para las personas que han usado Python, las funciones privadas no tienen valor. Solo haz todo lo público y hazlo con él.

    
respondido por el S.Lott 14.02.2011 - 12:10

Lea otras preguntas en las etiquetas