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]
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]
Hay dos categorías generales de beneficios de la actividad de refactorización.
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]
Hay dos momentos posibles para la refactorización.
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]
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]
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 .
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.
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 automatizada 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.
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.
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 .
{{cite thesis}}
: CS1 maint: bot: estado de URL original desconocido ( enlace )