stringtranslate.com

Refactorización de código

En programación informática y diseño de software , la refactorización de código es el proceso de reestructuración del código fuente existente (cambiando la factorización ) sin cambiar su comportamiento externo. La refactorización tiene como objetivo mejorar el diseño, la estructura y/o la implementación del software (sus atributos no funcionales ), al tiempo que se preserva su funcionalidad . Las posibles ventajas de la refactorización pueden incluir una mejor legibilidad del código y una menor complejidad ; estas pueden mejorar la capacidad de mantenimiento del código fuente y crear una arquitectura interna o un modelo de objetos más simple, más limpio o más expresivo para mejorar la extensibilidad . Otro objetivo potencial de la refactorización es mejorar el rendimiento; los ingenieros de software se enfrentan al desafío constante de escribir programas que funcionen más rápido o utilicen menos memoria.

Por lo general, la refactorización aplica una serie de microrrefactorizaciones básicas estandarizadas , cada una de las cuales es (normalmente) un cambio minúsculo en el código fuente de un programa informático que preserva el comportamiento del software o, al menos, no modifica su conformidad con los requisitos funcionales. Muchos entornos de desarrollo proporcionan soporte automatizado para realizar los aspectos mecánicos de estas refactorizaciones básicas. Si se hace bien, la refactorización de código puede ayudar a los desarrolladores de software a descubrir y corregir errores o vulnerabilidades ocultos o latentes en el sistema simplificando la lógica subyacente y eliminando niveles innecesarios de complejidad. Si se hace mal, puede no cumplir con el requisito de que no se modifique la funcionalidad externa y, por lo tanto, puede introducir nuevos errores.

Al mejorar continuamente el diseño del código, hacemos que sea cada vez más fácil trabajar con él. Esto contrasta claramente con lo que ocurre normalmente: poca refactorización y mucha atención para agregar nuevas características de manera oportuna. Si adquiere el hábito higiénico de refactorizar continuamente, descubrirá que es más fácil ampliar y mantener el código.

—  Joshua Kerievsky, Refactorización a patrones [1]

Motivación

La refactorización suele estar motivada por la detección de un olor extraño en el código . [2] Por ejemplo, el método en cuestión puede ser muy largo o puede ser un duplicado casi idéntico de otro método cercano. Una vez identificados, estos problemas se pueden solucionar refactorizando el código fuente o transformándolo en una nueva forma que se comporte igual que antes pero que ya no "huela".

En el caso de una rutina larga, se pueden extraer una o más subrutinas más pequeñas; o en el caso de rutinas duplicadas, se puede eliminar la duplicación y reemplazarla con una función compartida. Si no se realiza la refactorización, se puede acumular deuda técnica ; por otro lado, la refactorización es uno de los principales medios para saldar la deuda técnica. [3]

Beneficios

Hay dos categorías generales de beneficios de la actividad de refactorización.

  1. Mantenibilidad . Es más fácil corregir errores porque el código fuente es fácil de leer y la intención de su autor es fácil de entender. [4] Esto se puede lograr reduciendo grandes rutinas monolíticas a un conjunto de métodos concisos, bien nombrados y de propósito único. Se puede lograr moviendo un método a una clase más apropiada o eliminando comentarios engañosos.
  2. Extensibilidad . Es más fácil ampliar las capacidades de la aplicación si utiliza patrones de diseño reconocibles y proporciona cierta flexibilidad donde antes no existía. [1]

La ingeniería de rendimiento puede eliminar las ineficiencias de los programas, conocidas como "software bloat", que surgen de las estrategias tradicionales de desarrollo de software que apuntan a minimizar el tiempo de desarrollo de una aplicación en lugar del tiempo que lleva ejecutarla. La ingeniería de rendimiento también puede adaptar el software al hardware en el que se ejecuta, por ejemplo, para aprovechar los procesadores paralelos y las unidades vectoriales. [5]

Tiempo y responsabilidad

Hay dos momentos posibles para la refactorización.

  1. Refactorización preventiva: el desarrollador original del código hace que el código sea más robusto cuando aún está libre de olores para evitar la formación de olores en el futuro. [6]
  2. Refactorización correctiva: un desarrollador posterior realiza una refactorización para corregir los errores de código a medida que ocurren. [6]

Un método que equilibra la refactorización preventiva y correctiva es la "responsabilidad compartida de la refactorización". Este enfoque divide la acción de refactorización en dos etapas y dos roles. El desarrollador original del código simplemente prepara el código para la refactorización y, cuando el código huele mal, un desarrollador posterior lleva a cabo la acción de refactorización real. [6]

Desafíos

La refactorización requiere extraer la estructura del sistema de software, los modelos de datos y las dependencias entre aplicaciones para recuperar el conocimiento de un sistema de software existente. [7] La ​​rotación de equipos implica la falta de conocimiento o la falta de conocimiento preciso sobre el estado actual de un sistema y sobre las decisiones de diseño tomadas por los desarrolladores que se van. Las actividades de refactorización de código posteriores pueden requerir un esfuerzo adicional para recuperar este conocimiento. [8] Las actividades de refactorización generan modificaciones arquitectónicas que deterioran la arquitectura estructural de un sistema de software. Tal deterioro afecta a las propiedades arquitectónicas, como la capacidad de mantenimiento y la comprensión, lo que puede llevar a un nuevo desarrollo completo de los sistemas de software. [9]

Las actividades de refactorización de código se protegen con inteligencia de software cuando se utilizan herramientas y técnicas que proporcionan datos sobre algoritmos y secuencias de ejecución de código. [10] Proporcionar un formato comprensible para el estado interno de la estructura del sistema de software, los modelos de datos y las dependencias entre componentes es un elemento fundamental para formar una comprensión de alto nivel y luego puntos de vista refinados de lo que se debe modificar y cómo. [11]

Pruebas

Se deben configurar pruebas unitarias automáticas antes de la refactorización para garantizar que las rutinas sigan comportándose como se espera. [12] Las pruebas unitarias pueden aportar estabilidad incluso a refactorizaciones grandes cuando se realizan con una única confirmación atómica . Una estrategia común para permitir refactorizaciones seguras y atómicas que abarquen varios proyectos es almacenar todos los proyectos en un único repositorio , conocido como monorepo . [13]

Una vez que se han realizado las pruebas unitarias, la refactorización es un ciclo iterativo que consiste en realizar una pequeña transformación del programa , probarla para garantizar su corrección y realizar otra pequeña transformación. Si en algún momento una prueba falla, el último cambio pequeño se deshace y se repite de una manera diferente. A través de muchos pasos pequeños, el programa pasa de donde estaba a donde se desea que esté. Para que este proceso tan iterativo sea práctico, las pruebas deben ejecutarse muy rápidamente, o el programador tendría que dedicar una gran parte de su tiempo a esperar a que finalicen las pruebas. Los defensores de la programación extrema y otros desarrollos de software ágiles describen esta actividad como una parte integral del ciclo de desarrollo de software .

Técnicas

A continuación se muestran algunos ejemplos de microrrefactorizaciones; algunas de ellas pueden aplicarse únicamente a determinados lenguajes o tipos de lenguaje. Se puede encontrar una lista más larga en el libro de refactorización de Martin Fowler [2] [ página necesaria ] y en el sitio web. [14] Muchos entornos de desarrollo proporcionan soporte automatizado para estas microrrefactorizaciones. Por ejemplo, un programador podría hacer clic en el nombre de una variable y luego seleccionar la refactorización "Encapsular campo" en un menú contextual . El IDE solicitaría entonces detalles adicionales, normalmente con valores predeterminados razonables y una vista previa de los cambios en el código. Después de la confirmación por parte del programador, llevaría a cabo los cambios necesarios en todo el código.

Refactorización de hardware

Aunque el término refactorización originalmente se refería exclusivamente a la refactorización de código de software, en los últimos años también se ha refactorizado código escrito en lenguajes de descripción de hardware . El término refactorización de hardware se utiliza como un término abreviado para la refactorización de código en lenguajes de descripción de hardware. Dado que la mayoría de los ingenieros de hardware no consideran que los lenguajes de descripción de hardware sean lenguajes de programación , [20] la refactorización de hardware debe considerarse un campo separado de la refactorización de código tradicional.

Zeng y Huss propusieron la refactorización automática de descripciones de hardware analógico (en VHDL-AMS ). [21] En su enfoque, la refactorización preserva el comportamiento simulado de un diseño de hardware. La medida no funcional que mejora es que el código refactorizado puede procesarse con herramientas de síntesis estándar, mientras que el código original no. La refactorización de lenguajes de descripción de hardware digital, aunque sea manual, también ha sido investigada por Mike Keating , miembro de Synopsys . [22] [23] Su objetivo es hacer que los sistemas complejos sean más fáciles de entender, lo que aumenta la productividad de los diseñadores.

Historia

El primer uso conocido del término "refactorización" en la literatura publicada fue en un artículo de septiembre de 1990 de William Opdyke y Ralph Johnson . [24] Aunque la refactorización de código se ha realizado de manera informal durante décadas, la disertación de doctorado de 1991 de William Griswold [25] es uno de los primeros trabajos académicos importantes sobre la refactorización de programas funcionales y procedimentales, seguida por la disertación de 1992 de William Opdyke [26] sobre la refactorización de programas orientados a objetos, [27] aunque toda la teoría y la maquinaria han estado disponibles desde hace mucho tiempo como sistemas de transformación de programas . Todos estos recursos proporcionan un catálogo de métodos comunes para la refactorización; un método de refactorización tiene una descripción de cómo aplicar el método e indicadores de cuándo debe (o no debe) aplicar el método.

El libro de Martin Fowler Refactoring: Improving the Design of Existing Code es la referencia canónica. [ ¿según quién? ]

Los términos "factorización" y "factorización externa" se han utilizado de esta manera en la comunidad Forth al menos desde principios de los años 1980. El capítulo seis del libro de Leo Brodie Thinking Forth (1984) [28] está dedicado a este tema.

En programación extrema, la técnica de refactorización del método Extract tiene esencialmente el mismo significado que la factorización en Forth: dividir una "palabra" (o función ) en funciones más pequeñas y más fáciles de mantener.

Las refactorizaciones también se pueden reconstruir [29] post hoc para producir descripciones concisas de cambios de software complejos registrados en repositorios de software como CVS o SVN.

Refactorización de código automatizada

Muchos editores de software e IDE cuentan con soporte para refactorización automatizada. A continuación, se incluye una lista de algunos de estos editores, o los denominados navegadores de refactorización .

Véase también

Referencias

  1. ^ ab Kerievsky, Joshua (2004). Refactorización a patrones . Addison Wesley.
  2. ^ ab Fowler, Martin (1999). Refactorización. Mejorar el diseño del código existente. Addison-Wesley. pp. 63 y siguientes. ISBN 978-0-201-48567-7.
  3. ^ Suryanarayana, Girish (noviembre de 2014). Refactorización para el diseño de software . Morgan Kaufmann. pág. 258. ISBN 978-0128013977.
  4. ^ Martin, Robert (2009). Código limpio . Prentice Hall.
  5. ^ Leiserson, Charles E.; Thompson, Neil C.; Emer, Joel S.; Kuszmaul, Bradley C.; Lampson, Butler W.; Sanchez, Daniel; Schardl, Tao B. (2020). "Hay mucho espacio en la cima: ¿Qué impulsará el rendimiento de la computadora después de la ley de Moore?". Science . 368 (6495): eaam9744. doi : 10.1126/science.aam9744 . PMID  32499413.
  6. ^ abc Fraivert, Dov; Lorenz, David H. (2022). "Soporte lingüístico para la prevención del deterioro de la refactorización". Actas de la 21.ª Conferencia internacional ACM SIGPLAN sobre programación generativa: conceptos y experiencias . págs. 122–134. doi :10.1145/3564719.3568688. ISBN. 978-1-4503-9920-3.
  7. ^ Haendler, Thorsten; Neumann, Gustaf (2019). "Un marco para la evaluación y la formación de competencias de refactorización de software". Actas de la 11.ª Conferencia conjunta internacional sobre descubrimiento de conocimientos, ingeniería del conocimiento y gestión del conocimiento . págs. 307–316. doi : 10.5220/0008350803070316 . ISBN . 978-989-758-382-7.S2CID204754665  .​
  8. ^ Nassif, Matthieu; Robillard, Martin P. (noviembre de 2017). Revisiting Turnover-Induced Knowledge Loss in Software Projects ( Revisitando la pérdida de conocimiento inducida por la rotación en proyectos de software). Conferencia internacional IEEE de 2017 sobre mantenimiento y evolución de software (ICSME). págs. 261–272. doi :10.1109/ICSME.2017.64. ISBN 978-1-5386-0992-7. Número de identificación del sujeto  13147063.
  9. ^ van Gurp, Jilles; Bosch, Jan (marzo de 2002). "Erosión del diseño: problemas y causas". Journal of Systems and Software . 61 (2): 105–119. doi :10.1016/S0164-1212(01)00152-2.
  10. ^ Hassan, Ahmed E.; Xie, Tao (noviembre de 2010). "Inteligencia de software: el futuro de la minería de datos de ingeniería de software". Actas del taller FSE/SDP sobre el futuro de la investigación en ingeniería de software (FoSER '10) . págs. 161–166. doi :10.1145/1882362.1882397. S2CID  3485526.
  11. ^ Novais, Renato; Santos, José Amancio; Mendonça, Manoel (2017). "Evaluación experimental de la combinación de múltiples estrategias de visualización para el análisis de la evolución del software". Revista de sistemas y software . 128 : 56–71. doi :10.1016/j.jss.2017.03.006.
  12. ^ Fowler, Martin (1999). Refactorización: mejora del diseño del código existente. Reading, MA: Addison-Wesley. ISBN 978-0201485677.OCLC 41017370  .
  13. ^ Smart, John Ferguson (2008). Herramientas de potencia de Java. "O'Reilly Media, Inc.", pág. 301. ISBN 9781491954546. Recuperado el 26 de julio de 2018 .
  14. ^ ab (estos solo se refieren a programación orientada a objetos). Técnicas de refactorización en el sitio web de refactorización de Fowler
  15. ^ Ferrante, Jeanne; Ottenstein, Karl J.; Warren, Joe D. (julio de 1987). "El gráfico de dependencia del programa y su uso en optimización". ACM Transactions on Programming Languages ​​and Systems . 9 (3). ACM: 319–349. doi : 10.1145/24039.24041 . S2CID  505075.
  16. ^ Donglin, Linag; Harrold, MJ (noviembre de 2008). "Corte de objetos mediante gráficos de dependencia del sistema". Actas de la Conferencia internacional sobre mantenimiento de software (n.º de cat. 98CB36272) . IEEE. págs. 319–349. doi :10.1109/ICSM.1998.738527. ISBN. 978-0-8186-8779-2.S2CID18160599  .​
  17. ^ "Reemplazar el código de verificación de tipos con Estado/Estrategia".
  18. ^ "Reemplazar condicional por polimorfismo".
  19. ^ Bruntink, M.; van Deursen, A.; Tourwe, T.; van Engelen, R. (2004). "Una evaluación de las técnicas de detección de clones para cuestiones transversales". Actas de la 20.ª Conferencia Internacional IEEE sobre Mantenimiento de Software . IEEE. doi :10.1109/ICSM.2004.1357804.
  20. ^ Lenguajes de descripción de hardware#HDL y lenguajes de programación
  21. ^ Kaiping Zeng, Sorin A. Huss, "Refinamientos de la arquitectura mediante la refactorización de código de modelos VHDL-AMS conductuales". ISCAS 2006
  22. ^ M. Keating: "Complejidad, abstracción y los desafíos del diseño de sistemas complejos", en el tutorial DAC'08 [1] Archivado el 28 de marzo de 2016 en Wayback Machine "Cerrando la brecha de verificación: C++ a RTL para un diseño práctico"
  23. ^ M. Keating, P. Bricaud: Manual de metodología de reutilización para diseños de sistemas en un chip , Kluwer Academic Publishers, 1999.
  24. ^ Opdyke, William F .; Johnson, Ralph E. (septiembre de 1990). "Refactorización: una ayuda para diseñar marcos de aplicación y desarrollar sistemas orientados a objetos". Actas del Simposio sobre programación orientada a objetos con énfasis en aplicaciones prácticas (SOOPPA) . ACM.
  25. ^ Griswold, William G (julio de 1991). Reestructuración de programas como ayuda para el mantenimiento de software (PDF) (tesis doctoral). Universidad de Washington . Consultado el 24 de diciembre de 2011 .
  26. ^ Opdyke, William F (junio de 1992). Refactoring Object-Oriented Frameworks (tesis doctoral). Universidad de Illinois en Urbana-Champaign. Archivado desde el original el 16 de diciembre de 2019. Consultado el 12 de febrero de 2008 .{{cite thesis}}: CS1 maint: bot: estado de URL original desconocido ( enlace )
  27. ^ "Martin Fowler, "MF Bliki: Etimología de la refactorización"".
  28. ^ Brodie, Leo (2004). Pensando en el futuro. Fig Leaf Press, Forth Interest. págs. 171–196. ISBN 0-9764587-0-5Archivado desde el original el 16 de diciembre de 2005 . Consultado el 3 de mayo de 2020 .
  29. ^ Sokolov, Andriy. "¿Qué es la refactorización de código?".
  30. ^ "Novedades en Xcode 9".
  31. ^ "Descripción general | Documentación de Qt Creator".

Lectura adicional

Enlaces externos