En programación y diseño de software , la refactorización de código es el proceso de reestructurar el código fuente existente —cambiando su factorización— sin modificar su comportamiento externo. La refactorización busca mejorar el diseño, la estructura o la implementación del software (sus atributos no funcionales ), preservando su funcionalidad . Entre las posibles ventajas de la refactorización se incluyen una mayor legibilidad del código y una menor complejidad ; esto puede mejorar la mantenibilidad del código fuente y crear una arquitectura interna o un modelo de objetos más simple, limpio y expresivo para mejorar la extensibilidad . Otro objetivo potencial de la refactorización es la mejora del rendimiento; los ingenieros de software se enfrentan al reto constante de escribir programas más rápidos o que consuman menos memoria. A pesar de la disponibilidad de métricas para evaluar estos atributos, los desarrolladores a menudo no las utilizan al tomar decisiones de refactorización debido a la incertidumbre sobre su utilidad práctica. [ 1 ]
Por lo general, la refactorización aplica una serie de microrefactorizaciones básicas estandarizadas , cada una de las cuales consiste (normalmente) en un pequeño cambio en el código fuente de un programa informático que conserva el comportamiento del software o, al menos, no modifica su conformidad con los requisitos funcionales. Muchos entornos de desarrollo ofrecen soporte automatizado para realizar los aspectos mecánicos de estas refactorizaciones básicas. Si se realiza correctamente, la refactorización del código puede ayudar a los desarrolladores de software a descubrir y corregir errores o vulnerabilidades ocultas o latentes en el sistema, simplificando la lógica subyacente y eliminando niveles innecesarios de complejidad. Si se realiza incorrectamente, puede incumplir el requisito de que la funcionalidad externa no se modifique y, por lo tanto, puede introducir nuevos errores.
Al mejorar continuamente el diseño del código, facilitamos cada vez más su uso. Esto contrasta notablemente con lo que suele ocurrir: poca refactorización y mucha atención dedicada a añadir nuevas funcionalidades rápidamente. Si adquieres el hábito de refactorizar continuamente, verás que es más fácil ampliar y mantener el código.
— Joshua Kerievsky, Refactorización a patrones [ 2 ]
Motivación
La refactorización suele estar motivada por la detección de un código problemático . [ 3 ] Por ejemplo, el método en cuestión puede ser muy extenso o prácticamente idéntico a otro método cercano. Una vez identificados, estos problemas pueden abordarse refactorizando el código fuente o transformándolo en una nueva versión que se comporte igual que antes, pero que ya no presente ese problema.
Para una rutina larga, se pueden extraer una o más subrutinas más pequeñas. Para rutinas duplicadas, la duplicación se puede eliminar y reemplazar con una función compartida. No realizar la refactorización puede resultar en la acumulación de deuda técnica ; por otro lado, la refactorización es uno de los principales medios para saldar la deuda técnica. [ 4 ]
Beneficios
Existen dos categorías generales de beneficios derivados de la actividad de refactorización.
- 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 comprender. [ 5 ] Esto se puede lograr reduciendo las rutinas monolíticas extensas a un conjunto de métodos concisos, bien nombrados y con un solo propósito. También se puede lograr moviendo un método a una clase más apropiada o eliminando comentarios engañosos.
- Extensibilidad . Es más fácil extender las capacidades de la aplicación si utiliza patrones de diseño reconocibles , y proporciona cierta flexibilidad donde antes no existía. [ 2 ]
La ingeniería de rendimiento puede eliminar las ineficiencias en los programas, conocidas como sobrecarga de software, que surgen de las estrategias tradicionales de desarrollo de software que buscan minimizar el tiempo de desarrollo de una aplicación en lugar del tiempo que tarda en ejecutarse. 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. [ 6 ]
Plazos y responsabilidad
Hay dos momentos posibles para refactorizar.
- Refactorización preventiva: el desarrollador original del código lo hace más robusto cuando aún no tiene olores para evitar que se formen olores en el futuro. [ 7 ]
- Refactorización correctiva: un desarrollador posterior realiza una refactorización para corregir los malos olores del código a medida que se producen. [ 7 ]
Un método que equilibra la refactorización preventiva y correctiva es la "responsabilidad compartida para 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 lo prepara para la refactorización, y cuando el código presenta problemas, un desarrollador posterior lleva a cabo la refactorización propiamente dicha. [ 7 ]
Desafíos
La refactorización requiere extraer la estructura del sistema de software, los modelos de datos y las dependencias internas de la aplicación para recuperar el conocimiento de un sistema de software existente. [ 8 ] La rotación de equipos implica un conocimiento incompleto o inexacto del estado actual de un sistema y de las decisiones de diseño tomadas por los desarrolladores que se marchan. Las actividades de refactorización de código posteriores pueden requerir un esfuerzo adicional para recuperar este conocimiento. [ 9 ] Las actividades de refactorización generan modificaciones arquitectónicas que deterioran la arquitectura estructural de un sistema de software. Dicho deterioro afecta a propiedades arquitectónicas como la mantenibilidad y la comprensibilidad, lo que puede llevar a un rediseño completo de los sistemas de software. [ 10 ]
Pruebas
Se deben configurar pruebas unitarias automáticas antes de la refactorización para asegurar que las rutinas sigan comportándose como se espera. [ 11 ] 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 abarcan varios proyectos es almacenar todos los proyectos en un único repositorio , conocido como monorepo . [ 12 ]
Con las pruebas unitarias implementadas, la refactorización se convierte en un ciclo iterativo que consiste en realizar una pequeña transformación del programa , probarla para asegurar su corrección y realizar otra pequeña transformación. Si en algún momento falla una prueba, se deshace el último cambio y se repite de otra manera. Mediante muchos pasos pequeños, el programa pasa de su estado inicial al deseado. Para que este proceso 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. Los defensores de la programación extrema y otros métodos ágiles de desarrollo de software describen esta actividad como una parte integral del ciclo de desarrollo de software . La refactorización se aplica tanto al código de prueba como al código de producción; los estudios empíricos muestran que la refactorización de pruebas se centra principalmente en el código de prueba de baja calidad que presenta malas prácticas , y mejora el acoplamiento, la cohesión y el tamaño del código de prueba, aunque no necesariamente mejora la cobertura del código. [ 13 ]
Técnicas
Aquí se muestran algunos ejemplos de microrefactorizaciones; algunas de ellas pueden aplicarse únicamente a ciertos lenguajes o tipos de lenguaje. Una lista más extensa se puede encontrar en el libro de refactorización de Martin Fowler [ 3 ] y en su sitio web [ 14 ] . Muchos entornos de desarrollo ofrecen soporte automatizado para estas microrefactorizaciones. Por ejemplo, un programador podría hacer clic en el nombre de una variable y seleccionar la refactorización "Encapsular campo" en el menú contextual . El IDE solicitaría entonces información adicional, generalmente con valores predeterminados adecuados y una vista previa de los cambios en el código. Tras la confirmación del programador, se realizarían los cambios necesarios en todo el código.
Análisis estático
El análisis estático de programas (denominado "linting" cuando se realiza en lenguajes interpretados menos estrictos) detecta problemas en un programa válido pero de calidad inferior.
- Grafo de dependencias del programa : representación explícita de las dependencias de datos y control [ 15 ]
- Grafo de dependencia del sistema: representación de llamadas a procedimientos entre PDG [ 16 ]
- Análisis de complejidad ciclométrica .
- Inteligencia de software : realiza ingeniería inversa del estado inicial para comprender las dependencias internas existentes en la aplicación.
Transformaciones
Las transformaciones modifican la representación sintáctica de un programa. Algunas modificaciones alteran la semántica o la estructura del programa, mejorando así su flexibilidad o robustez. Dichas modificaciones requieren conocimiento del dominio del problema y de la lógica prevista, por lo que su automatización resulta inviable. Existen modificaciones que facilitan la lectura y modificación del programa, sin alterar su lógica subyacente; estas transformaciones sí pueden automatizarse.
- Técnicas que permiten una mayor abstracción
- Campo encapsulado : obliga al código a acceder al campo con métodos getter y setter.
- Generalizar tipos : crear tipos más generales para permitir un mayor intercambio de código.
- Reemplazar el código de verificación de tipos con estado/estrategia [ 17 ]
- Reemplazar condicional con polimorfismo [ 18 ]
- Técnicas para dividir el código en partes más lógicas.
- La modularización divide el código en unidades semánticas reutilizables que presentan interfaces claras, bien definidas y fáciles de usar.
- La función "Extraer clase" traslada parte del código de una clase existente a una nueva clase.
- Método de extracción: para convertir parte de un método más extenso en un método nuevo. Al dividir el código en fragmentos más pequeños, resulta más fácil de comprender. Esto también se aplica a las funciones .
- Técnicas para mejorar los nombres y la ubicación del código
- Mover método o mover campo: mover a una clase o archivo fuente más apropiado.
- Cambiar el nombre del método o del campo: cambiar el nombre por uno nuevo que revele mejor su propósito.
- En programación orientada a objetos (POO), desplazarse a una superclase.
- Empujar hacia abajo: en POO, mover a una subclase [ 14 ]
- Detección automática de clones [ 19 ]
Refactorización de hardware
Si bien el término refactorización se refería originalmente 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 una forma abreviada de referirse a 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 los lenguajes de descripción de hardware como lenguajes de programación , [ 20 ] la refactorización de hardware debe considerarse un campo independiente 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 mejora no funcional radica en que el código refactorizado puede ser procesado por herramientas de síntesis estándar, mientras que el código original no. Mike Keating, miembro de Synopsys , también investigó la refactorización de lenguajes de descripción de hardware digital, aunque de forma manual. [ 22 ] [ 23 ] Su objetivo es simplificar la comprensión de sistemas complejos, 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 hecho informalmente durante décadas, la disertación doctoral de William Griswold de 1991 [ 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 William Opdyke de 1992 [ 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 se debe (o no se debe) aplicar el método.
El libro de Martin Fowler, Refactoring: Improving the Design of Existing Code, es la referencia canónica.
Los términos "factoring" y "factoring out" se han utilizado de esta manera en la comunidad Forth desde al menos principios de la década de 1980. El capítulo seis del libro de Leo Brodie , Thinking Forth (1984) [ 28 ] , está dedicado al tema.
En programación extrema, la técnica de refactorización Extract Method tiene esencialmente el mismo significado que factorizar en Forth: descomponer una "palabra" (o función ) en funciones más pequeñas y fáciles de mantener.
Las refactorizaciones también pueden reconstruirse [ 29 ] a posteriori para producir descripciones concisas de cambios de software complejos registrados en repositorios de software como Git .
Herramientas
Muchas herramientas de desarrollo de software cuentan con funciones para la refactorización. Algunos ejemplos son:
- Android Studio
- Admite la refactorización de Java y C++.
- Código de aplicación
- Admite la refactorización de Objective-C , C y C++.
- Delfos
- Admite la refactorización de Object Pascal .
- Kit de herramientas para la reingeniería de software de DMS
- Admite la refactorización a gran escala para C , C++ , C# , COBOL , Java , PHP y otros lenguajes.
- Eclipse
- Mediante complementos, admite la refactorización de Java y, en menor medida, de C++, PHP, Ruby y JavaScript.
- IntelliJ IDEA
- Admite la refactorización de Java.
- JDeveloper
- Admite la refactorización de Java.
- NetBeans
- Admite la refactorización de Java.
- PhpStorm
- Admite la refactorización de PHP.
- PyCharm
- Admite la refactorización de Python.
- PyDev
- Admite la refactorización de Python .
- Charla informal
- La mayoría de los dialectos incluyen potentes herramientas de refactorización. Muchos utilizan el navegador de refactorización original creado a principios de los 90 por Ralph Johnson .
- Asistencia visual
- Admite la refactorización de C# y C++.
- Visual Studio
- Admite la refactorización de .NET y C++.
- Código de Visual Studio
- Admite la refactorización de muchos lenguajes mediante complementos.
- WebStorm
- Admite la refactorización de JavaScript.
- Wing IDE
- Admite la refactorización de Python.
- Xcode
- Admite la refactorización de C, Objective-C y Swift . [ 30 ]
- Creador de Qt
- Admite la refactorización de C++, Objective-C y QML [ 31 ]
Véase también
Referencias
- ↑ Tempero, Ewan; Ralph, Paul (2026-03-16). "Haciendo útiles las métricas de software". arXiv : 2603.16012 .
{{cite arXiv}}CS1 maint: falta la clase ( enlace ). Un bot completará esta cita pronto. Haz clic aquí para saltarte la cola. - 1 2 Kerievsky, Joshua (2004). Refactoring to Patterns . Addison Wesley.
- 1 2 Fowler, Martin (1999). Refactoring. Improving the Design of Existing Code . Addison-Wesley. pp. 63 y ss . ISBN 978-0-201-48567-7.
- ↑ Suryanarayana, Girish (noviembre de 2014). Refactoring for Software Design Smells . Morgan Kaufmann. pág. 258. ISBN 978-0-12-801397-7.
- ↑ Martin, Robert (2009). Código limpio . Prentice Hall.
- ↑ 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 las computadoras después de la ley de Moore?" . Science . 368 (6495) eaam9744. Bibcode : 2020Sci...368m9744L . doi : 10.1126/science.aam9744 . PMID 32499413 .
- 1 2 3 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.
- ↑ Haendler, Thorsten; Neumann, Gustaf (2019). «Un marco para la evaluación y formación de competencias en refactorización de software». Actas de la 11.ª Conferencia Internacional Conjunta sobre Descubrimiento del Conocimiento, Ingeniería del Conocimiento y Gestión del Conocimiento . págs. 307–316 . doi : 10.5220/0008350803070316 . ISBN 978-989-758-382-7. S2CID 204754665 .
- ↑ Nassif, Matthieu; Robillard, Martin P. (noviembre de 2017). Revisión de la pérdida de conocimiento inducida por la rotación de personal en proyectos de software . Conferencia Internacional IEEE de 2017 sobre Mantenimiento y Evolución del Software (ICSME). págs. 261–272 . doi : 10.1109/ICSME.2017.64 . ISBN 978-1-5386-0992-7. S2CID 13147063 .
- ↑ 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 .
- ↑ Fowler, Martin (1999). Refactoring: improving the design of existing code . Reading, MA: Addison-Wesley. ISBN 978-0-201-48567-7OCLC 41017370
- ↑ Smart, John Ferguson (2008). Java Power Tools . O'Reilly Media, Inc. pág. 301. ISBN 978-1-4919-5454-6Consultado el 26 de julio de 2018 .
- ↑ Martins, Luana; Pontillo, Valeria; Costa, Heitor; Ferrucci, Filomena; Palomba, Fabio; Machado, Ivan (2024). "Refactorización del código de prueba al descubierto: ¿dónde y cómo afecta a la calidad y eficacia del código de prueba?". Ingeniería de Software Empírica . 30 (1): 27. doi : 10.1007/s10664-024-10577-y .
- 1 2 (sin embargo, estos solo tratan sobre POO). Técnicas de refactorización en el sitio web de refactorización de Fowler
- ↑ Ferrante, Jeanne; Ottenstein, Karl J.; Warren, Joe D. (julio de 1987). "El grafo de dependencia de programas 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 .
- ↑ Donglin, Linag; Harrold, MJ (noviembre de 2008). «Segmentación de objetos mediante grafos de dependencia del sistema». Actas de la Conferencia Internacional sobre Mantenimiento de Software (Cat. n.º 98CB36272) . IEEE. págs. 319–349 . doi : 10.1109/ICSM.1998.738527 . ISBN 978-0-8186-8779-2. S2CID 18160599 .
- ↑ "Reemplazar el código de verificación de tipos con Estado/Estrategia" .
- ↑ "Reemplazar condicional por polimorfismo" .
- ↑ Bruntink, M.; van Deursen, A.; Tourwe, T.; van Engelen, R. (2004). "Una evaluación de técnicas de detección de clones para preocupaciones transversales". Actas de la 20.ª Conferencia Internacional IEEE sobre Mantenimiento de Software . IEEE. doi : 10.1109/ICSM.2004.1357804 .
- ↑ Lenguajes de descripción de hardware#HDL y lenguajes de programación
- ↑ Kaiping Zeng, Sorin A. Huss, "Refinamientos de arquitectura mediante la refactorización de código de modelos VHDL-AMS de comportamiento". ISCAS 2006
- ↑ M. Keating, "Complejidad, abstracción y los desafíos del diseño de sistemas complejos", en el tutorial de DAC'08Archivado el 28/03/2016 en Wayback Machine : "Superando la brecha de verificación: de C++ a RTL para el diseño práctico".
- ↑ M. Keating, P. Bricaud: Manual de metodología de reutilización para diseños de sistemas en un chip , Kluwer Academic Publishers, 1999.
- ↑ Opdyke, William F. ; Johnson, Ralph E. (septiembre de 1990). "Refactoring: An Aid in Designing Application Frameworks and Evolving Object-Oriented Systems". Proceedings of the Symposium on Object Oriented Programming Emphasizing Practical Applications (SOOPPA) . ACM.
- ↑ Griswold, William G (julio de 1991). Reestructuración de programas como ayuda para el mantenimiento de software (PDF) (tesis doctoral). Universidad de Washington . Recuperado el 24 de diciembre de 2011 .
- ↑ Opdyke, William F (junio de 1992). Refactoring Object-Oriented Frameworks (Postscript comprimido) (tesis doctoral). Universidad de Illinois en Urbana-Champaign . Recuperado el 12 de febrero de 2008 .
- ↑ "Martin Fowler, "MF Bliki: Etimología de la refactorización"" .
- ↑ Brodie, Leo (2004). Pensando en el futuro . Fig Leaf Press, Forth Interest. pp. 171–196 . ISBN 0-9764587-0-5Archivado del original el 16 de diciembre de 2005. Consultado el 3 de mayo de 2020 .
- ↑ Sokolov, Andriy. "¿Qué es la refactorización de código?" .
- ↑ "Novedades de Xcode 9" .
- ↑ "Información general | Documentación de Qt Creator" .
Lecturas adicionales
- Wake, William C. (2003). Refactoring Workbook . Addison-Wesley. ISBN 978-0-321-10929-3.
- Mens, T.; Tourwe, T. (febrero de 2004). "Una revisión de la refactorización de software" . IEEE Transactions on Software Engineering . 30 (2): 126– 139. Bibcode : 2004ITSEn..30..126M . doi : 10.1109/tse.2004.1265817 . ISSN 0098-5589 . S2CID 206778272 .
- Feathers, Michael C. (2004). Trabajar eficazmente con código heredado . Prentice Hall. ISBN 978-0-13-117705-5.
- Kerievsky, Joshua (2004). Refactoring To Patterns . Addison-Wesley. ISBN 978-0-321-21335-8.
- Arsenovski, Danijel (2008). Refactorización profesional en Visual Basic . Wrox. ISBN 978-0-470-17979-6.
- Arsenovski, Danijel (2009). Refactorización profesional en C# y ASP.NET . Wrox. ISBN 978-0-470-43452-9.
- Ritchie, Peter (2010). Refactoring with Visual Studio 2010. Packt. ISBN 978-1-84968-010-3.
Enlaces externos
- ¿Qué es la refactorización? (Artículo de c2.com)
- Página principal de Martin Fowler sobre refactorización
- Refactorización de código
- Programación extrema
- Neologismos tecnológicos