Programación de copiar y pegar - Copy-and-paste programming

La programación de copiar y pegar , a veces denominada simplemente pegar , es la producción de código de programación de computadora altamente repetitivo , como se produce mediante operaciones de copiar y pegar . Es principalmente un término peyorativo; quienes usan el término a menudo implican una falta de competencia en programación. También puede ser el resultado de limitaciones tecnológicas (por ejemplo, un entorno de desarrollo insuficientemente expresivo) ya que normalmente se utilizarían subrutinas o bibliotecas. Sin embargo, hay ocasiones en las que la programación de copiar y pegar se considera aceptable o necesaria, como en el caso del texto estándar , el desenrollado de bucles (cuando el compilador no lo admite automáticamente) o ciertos modismos de programación, y es compatible con algunos editores de código fuente en en forma de fragmentos .

Orígenes

La programación de copiar y pegar a menudo la realizan programadores sin experiencia o estudiantes, que encuentran difícil o irritante el acto de escribir código desde cero y prefieren buscar una solución preescrita o una solución parcial que puedan utilizar como base para su propio problema. resolviendo. (Ver también Programación de culto a Cargo )

Los programadores sin experiencia que copian código a menudo no comprenden completamente el código preescrito que están tomando. Como tal, el problema surge más de su inexperiencia y falta de coraje en la programación que del acto de copiar y pegar, per se. El código a menudo proviene de fuentes dispares, como el código de amigos o compañeros de trabajo, foros de Internet , código proporcionado por los profesores / TA del estudiante o libros de texto de ciencias de la computación . El resultado corre el riesgo de ser un choque desarticulado de estilos y puede tener un código superfluo que aborde problemas para los que ya no se requieren nuevas soluciones.

Otro problema es que los errores se pueden introducir fácilmente mediante suposiciones y elecciones de diseño realizadas en fuentes independientes que ya no se aplican cuando se colocan en un nuevo entorno.

Dicho código también puede, en efecto, ofuscarse involuntariamente , ya que los nombres de variables, clases, funciones y similares generalmente no se modifican, aunque su propósito puede ser completamente diferente en el nuevo contexto.

La programación de copiar y pegar también puede ser el resultado de una comprensión deficiente de las características comunes en los lenguajes de computadora, como las estructuras de bucle, las funciones y las subrutinas.

Duplicación

El código repetitivo se refactoriza mediante el uso de un mecanismo de abstracción como function .

Aplicar código de biblioteca

Los programadores experimentados también pueden copiar y pegar, que a menudo tienen sus propias bibliotecas de fragmentos de código bien probados y listos para usar y algoritmos genéricos que se adaptan fácilmente a tareas específicas.

Al ser una forma de duplicación de código , la programación de copiar y pegar tiene algunos problemas intrínsecos; tales problemas se agravan si el código no conserva ningún vínculo semántico entre el texto fuente y las copias. En este caso, si se necesitan cambios, se pierde tiempo buscando todas las ubicaciones duplicadas. (Esto se puede mitigar parcialmente si el código original y / o la copia se comentan correctamente; sin embargo, incluso entonces, el problema sigue siendo realizar las mismas ediciones varias veces. Además, debido a que el mantenimiento del código a menudo omite la actualización de los comentarios, los comentarios que describen dónde encontrar los fragmentos de código remotos son notorios por estar desactualizados).

Los seguidores de las metodologías orientadas a objetos objetan además el uso de la "biblioteca de códigos" de copiar y pegar. En lugar de hacer múltiples copias mutadas de un algoritmo genérico, un enfoque orientado a objetos abstraería el algoritmo en una clase encapsulada reutilizable . La clase está escrita de manera flexible, con soporte total de herencia y sobrecarga , de modo que todo el código de llamada se puede interconectar para usar este código genérico directamente, en lugar de mutar el original. Como se requiere funcionalidad adicional, la biblioteca se amplía (manteniendo la compatibilidad con versiones anteriores ). De esta forma, si el algoritmo original tiene un error que corregir o puede mejorarse, todo el software que lo utilice se beneficiará.

Código de ramificación

El código de ramificación es una parte normal del desarrollo de software de un gran equipo, lo que permite el desarrollo paralelo en ambas ramas y, por lo tanto, ciclos de desarrollo más cortos. La ramificación clásica tiene las siguientes cualidades:

  • Está gestionado por un sistema de control de versiones que admite la ramificación.
  • Las sucursales se fusionan una vez que se completa el desarrollo paralelo.

Copiar y pegar es una alternativa menos formal a la ramificación clásica, que se utiliza a menudo cuando se prevé que las ramificaciones divergirán cada vez más con el tiempo, como cuando un nuevo producto se separa de un producto existente.

Como una forma de derivar un nuevo producto, la programación de copiar y pegar tiene algunas ventajas. Porque la nueva iniciativa de desarrollo no toca el código del producto existente:

  • No es necesario realizar una prueba de regresión del producto existente, lo que ahorra tiempo de control de calidad asociado con el lanzamiento del nuevo producto y reduce el tiempo de comercialización .
  • No hay riesgo de que se introduzcan errores en el producto existente, lo que podría alterar la base de usuarios instalada.

Las desventajas son:

  • Si el nuevo producto no difiere tanto como se anticipó del producto existente, es posible que sea necesario respaldar dos bases de código (al doble del costo) donde se hubiera hecho. Esto puede llevar a costosas refactorizaciones y fusiones manuales en el futuro.
  • La base de código duplicado duplica el tiempo necesario para implementar los cambios que se pueden desear en ambos productos; esto aumenta el tiempo de comercialización para dichos cambios y, de hecho, puede acabar con las ganancias de tiempo logradas al ramificar el código en primer lugar.

De manera similar a lo anterior, la alternativa a un enfoque de copiar y pegar sería un enfoque modular:

  • Empiece por factorizar el código que ambos productos compartirán en bibliotecas.
  • Utilice esas bibliotecas (en lugar de una segunda copia del código base) como base para el desarrollo del nuevo producto.
  • Si se prevé una tercera, cuarta o quinta versión adicional del producto en el futuro, este enfoque es mucho más fuerte, porque las bibliotecas de código listas para usar acortan drásticamente el ciclo de vida de desarrollo para cualquier producto adicional después de la segunda.

Tareas repetitivas o variaciones de una tarea.

Dificultad y riesgo de mantener el código escrito mediante la programación de copiar y pegar

Una de las formas más dañinas de la programación de copiar y pegar ocurre en el código que realiza una tarea repetitiva, o variaciones de la misma tarea básica dependiendo de alguna variable. Cada instancia se copia desde arriba y se pega de nuevo, con modificaciones menores. Los efectos nocivos incluyen:

  • El enfoque de copiar y pegar a menudo conduce a métodos grandes (un mal olor a código ).
  • Cada instancia crea un código duplicado, con todos los problemas discutidos en secciones anteriores, pero con un alcance mucho mayor. Son frecuentes decenas de duplicaciones; cientos son posibles. Las correcciones de errores, en particular, se vuelven muy difíciles y costosas en dicho código.
  • Dicho código también adolece de importantes problemas de legibilidad, debido a la dificultad de discernir exactamente qué difiere entre cada repetición. Esto tiene un impacto directo en los riesgos y costos de revisar el código.
  • El modelo de programación procedimental desaconseja enérgicamente el método de copiar y pegar para tareas repetitivas. Bajo un modelo de procedimiento, un enfoque preferido para las tareas repetitivas es crear una función o subrutina que realice una sola pasada a través de la tarea; esta subrutina es luego llamada por la rutina principal, ya sea repetitivamente o mejor aún, con alguna forma de estructura de bucle. Dicho código se denomina "bien descompuesto" y se recomienda por ser más fácil de leer y extensible.
  • La regla general aplicable a este caso es " no te repitas ".

Elección de diseño deliberada

La programación de copiar y pegar se acepta ocasionalmente como una técnica de programación válida. Esto se ve más comúnmente en el texto estándar, como las declaraciones de clase o la importación de bibliotecas estándar, o al usar una plantilla de código existente (con contenido vacío o funciones de código auxiliar) como marco para completar.

El uso de modismos de programación y patrones de diseño es similar a la programación de copiar y pegar, ya que también usan código de fórmulas. En algunos casos, esto se puede expresar como un fragmento , que luego se puede pegar cuando dicho código sea necesario, aunque a menudo simplemente se recuerda de la mente del programador. En otros casos, los modismos no se pueden reducir a una plantilla de código. Sin embargo, en la mayoría de los casos, incluso si un idioma puede reducirse a código, será lo suficientemente largo como para que se abstraiga en una función o lo suficientemente corto como para que pueda teclearse directamente.

El lenguaje de programación Subtext es un proyecto de investigación destinado a "despenalizar" cortar y pegar. El uso de este lenguaje, cortar y pegar es el modelo de interacción principal y, por lo tanto, no se considera un anti-patrón.

Ejemplo

Un ejemplo simple es un bucle for, que podría expresarse como . for (int i=0; i!=n; ++i) {}

El código de muestra que utiliza un bucle for podría ser:

void foo(int n) {
    for (int i=0; i!=n; ++i) {
       /* body */
    }
}

El código de bucle podría haber sido generado por el siguiente fragmento (especificando tipos y nombres de variables):

    for ($type $loop_var = 0; $loop_var != $stop; ++$loop_var) {
        /* body */
    }

Ver también

Referencias

enlaces externos