¿Cuál es una buena práctica de código de cuándo hacer una función / método para pequeños segmentos de código repetitivos?

12

Muchas veces a lo largo de la escritura de programas más grandes me he preguntado después de cuántas copias y pastas tiene sentido poner el código en una función o método y ¿cuál es una buena regla general? He estado usando una regla general de cuatro líneas o más y aparece más de dos veces, luego hago una función / método simple que contiene ese código. ¿Puedes pensar en una mejor práctica u ofrecer algunos consejos? Esta es más una pregunta de patrón de diseño general que una pregunta específica del idioma.


fuente

Respuestas:

29

Utilizo funciones en parte como una forma de documentar el código. Llamar a una función con un nombre significativo facilita la comprensión del código. En algunos casos, incluso una función con una sola línea tiene sentido.

Por ejemplo, en "Código limpio", Robert C. Martin da el siguiente ejemplo: ¿Cuál preferiría ver? Esta:

// Check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) &&
    (employee.age > 65))

¿O esto?

if (employee.isEligibleForFullBenefits())

No siempre estoy de acuerdo con él, pero en este caso sí. El código debe ser legible, no solo cuando lo escribe y conoce todos los detalles, sino también a las 9 p.m., cuando tiene que corregir errores en el código de otra persona. No se recomienda mirar fijamente una condición prolongada e intentar descubrir todos los negativos dobles. Si solo puede ponerle un nombre (no solo las condiciones, sino cada pieza de código que escriba), se volverá mucho más simple.

Nunca me he arrepentido de poner algo en una función, y si te preocupa el rendimiento, primero perfila.

omrib
fuente
2
Seguir esta práctica simple eventualmente le permitirá escribir el código de la aplicación a un nivel relativamente alto. Las pequeñas funciones se recopilan en pequeñas clases y pronto está convirtiendo especificaciones funcionales en código casi palabra por palabra.
Kevin Cline
11
Me encantó este ejemplo. De repente ya no necesitas ese comentario. Esta es una regla general : si su comentario se puede convertir a una variable o nombre de función, ¡hágalo!
Karoly Horvath
Estoy de acuerdo con omrib aquí, a menudo se trata de limpiar el código, lo que lo hace más legible que cualquier otra regla general. Si termino reutilizando algo, lo extraeré a un método. Sin embargo, mi IDE y herramientas a menudo ayudan con eso, por lo que es fácil y rápido de hacer.
Travis
+1 Este tipo de código podría incluso ser más rápido, al menos si necesita ser editado por JIT: solo paga por lo que usa.
Trabajo
1
también conocido como Intención de revelar nombres .
rwong
13

Existe un malentendido generalizado de que las llamadas a funciones solo deben realizarse para evitar segmentos de código repetitivos. Mi regla general es que cualquier unidad lógica de trabajo debe convertirse en una función, incluso cuando se usa solo en un solo lugar. Esto generalmente conduce a una mejor legibilidad y le permite escribir código autodocumentado, donde los nombres de las funciones reemplazan los comentarios y no necesita escribir comentarios adicionales que expliquen lo que está haciendo.

Lie Ryan
fuente
1
¿Ves hasta dónde llegarán los programadores para evitar escribir un comentario?
Alger
1
@Alger como deberían
MatrixFrog
6

Si se usa en más de un lugar, y

  • es probable que cambie, o
  • es complicado acertar

luego conviértalo en una función o método. Las piezas largas de código repetido, en mi experiencia, naturalmente caerán en una de estas categorías (generalmente la primera, pero luego las categorías se superponen mucho;). Por supuesto, todo lo que tiene que estar en la interfaz también es una función / método en sí mismo.

Fred Foo
fuente
3
La pregunta es: ¿por qué no escribirías una función para un fragmento de código que se repite comúnmente, incluso si no fue difícil de corregir o es probable que cambie? (Mi regla general: si se repite y es más largo que llamar a una función, conviértala en una función)
Winston Ewert
Yo iría aún más lejos. Como programador, debes eliminar todo tipo de repeticiones . Ya sea en la base de datos (normalizar), algunas pruebas manuales (reemplazarlas con pruebas unitarias) o implementar (automatizar).
Karoly Horvath
@ Winston: eso depende del idioma que se utilice. No todas las construcciones pueden capturarse naturalmente como una función, la función puede ocupar más espacio que el código original (piense en C y regrese por puntero), las llamadas a funciones pueden incurrir en gastos generales.
Fred Foo
@larsman, tengo curiosidad a qué se refiere con "(piense en C y regrese por puntero)". Pero lo que estás diciendo es a lo que estaba tratando de llegar con mi regla de oro. Llamar a la función tiene que ser más fácil (es decir, capturar naturalmente y ocupar menos espacio) y luego implementar los contenidos de la función.
Winston Ewert
Si una pieza de código calcula varios valores, digamos float x, int yy double density, entonces, configurar esos cálculos como una función C puede ser más complicado que simplemente repetir el código, ya que debe idear una forma de obtener los tres valores. Si los cálculos repetidos en sí mismos son triviales, a veces es mejor dejarlos en línea.
Fred Foo
4

Casi siempre, especialmente si cada duplicado representa la misma operación desde un punto de vista conceptual. Si se realiza de la misma manera, pero en diferentes tipos, realice una implementación genérica.

El único motivo por el que no puedo pensar es el mantenimiento: a veces puede ser más conveniente evitar crear una dependencia entre cosas separadas, incluso a costa de alguna duplicación.

Nicola Musatti
fuente
Tenga cuidado con el tipeo de patos, si por ahora la implementación es similar, pero la funcionalidad es efectivamente diferente, entonces la fusión de los dos hace que sea molesto dividirse. Especialmente en lenguajes con poco soporte de IDE (hey, trabajo en C ++ ...)
Matthieu M.
Por otro lado, al mantenerlos separados, tiene dos funciones que hacen lo mismo para probar, la mitad de posibilidades de que se ejerza su código, dos lugares en los que puede aparecer el mismo error y debe recordar corregir el que el error aún no se ha detectado. Me gustaría seguir trabajando en C ++, a pesar de la mala compatibilidad con IDE ;-)
Nicola Musatti
1

Una búsqueda de " refactorización " lo llevará a muchos recursos para las "mejores prácticas" de la industria para este proceso tan común. El artículo algo famoso, Once and Only Once es una gran referencia histórica que explica lo que algunos ven como "mejores prácticas" para las inquietudes planteadas por su pregunta. Además, el concepto aún más general se conoce como Don't Repeat Yourself (DRY) . Para obtener un conjunto realmente profundo de respuestas a su pregunta, lea el gran clásico de Martin Fowler , Refactoring: Improving the Design of Existing Code , que cubre algunos de los consejos más conocidos para la refactorización , que es lo que intenta intuitivamente lograr. !

John Tobler
fuente
0

Si el código se repite exactamente en más de una vez y la sección repetida no cambiará en un futuro cercano, lo dividiré en una función.

Steven D.
fuente
1
si va a cambiar, aún hay más razones para refactorizarlo. Entonces solo tendrás que cambiarlo una vez
Shug
0

Eso depende de la naturaleza de la cohesión del código repetido. Si la sección repetida del código está realizando una función específica, entonces es un excelente candidato para convertirse en un método, en parte debido al principio DRY , en parte porque si la función necesita ser optimizada o corregida, entonces solo hay una sección de código para tratar.

Si la asociación es coincidente, es mejor repetir el código en lugar de convertirlo en un método. Si necesita agregar algo en el medio de una de las secuencias de código para satisfacer uno de los usos de ese fragmento, si está en un método, el cambio que realice puede afectar otros usos de ese método.

Vea el artículo de Wikipedia sobre el concepto de cohesión de código .

Jay Elston
fuente
Si la asociación parece coincidente, es probable que los dos procesos compartan una idea común, y probablemente debería explorar si los dos procesos son en realidad dos facetas de la misma cosa. Más a menudo que no, lo es.
Lie Ryan
0

Debe distinguir entre funciones en el sentido de programación estructurada y métodos de una clase.

En su ejemplo, lo que ha mostrado es un método que, como tal, no debe codificarse en línea.

Puede que tenga que validar una cadena para ver si es un número o no, en este caso, utiliza una función y se aplican la mayoría de las respuestas anteriores.

Esta distinción es importante especialmente en grandes proyectos.

En la medida de lo posible, trate de separar las reglas de negocio (que son métodos) de los algoritmos informáticos (que son funciones de programación pura).

Ninguna posibilidad
fuente