Refactoring Opsorcing
Refactoring Opsorcing
Refactoring Opsorcing
net/publication/261724775
CITATION READS
1 956
1 author:
Mariano Mendez
Universidad de Buenos Aires
27 PUBLICATIONS 45 CITATIONS
SEE PROFILE
Some of the authors of this publication are also working on these related projects:
Scientific Fortran Legacy: Modernizing, Updating and Parallelization issues View project
All content following this page was uploaded by Mariano Mendez on 19 May 2017.
Trabajo de Especialización
1. Introducción 1
1.1. El Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2. Software Restructuring . . . . . . . . . . . . . . . . . . . . . . 3
2. Refactorización 9
2.1. La Decadencia del Código Fuente . . . . . . . . . . . . . . . . 9
2.2. Mal Olor en el Código Fuente . . . . . . . . . . . . . . . . . . 11
2.3. Refactoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.3.1. El Comportamiento Externo . . . . . . . . . . . . . . 13
2.3.2. Caracterı́sticas Internas y Externas del Software . . . . 14
2.3.3. Un Ejemplo de Refactorización . . . . . . . . . . . . . 14
2.3.4. Otro Ejemplo Menos Trivial . . . . . . . . . . . . . . . 25
3. Herramientas de Refactorización 29
3.1. Entornos Integrados de Desarrollo . . . . . . . . . . . . . . . . 29
3.2. Herramientas Comerciales . . . . . . . . . . . . . . . . . . . . 30
3.2.1. Smalltalk . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.2.2. Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.2.3. .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.2.4. C/C++ . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.2.5. Visual Basic . . . . . . . . . . . . . . . . . . . . . . . . 34
3.2.6. Delphi . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.2.7. Erlang . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.2.8. Haskell . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.2.9. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.3. Otras Aplicaciones de Refactoring . . . . . . . . . . . . . . . 36
3.3.1. Refactorización de Modelos . . . . . . . . . . . . . . . 36
3.3.2. Refactorización y la Web . . . . . . . . . . . . . . . . 37
3.3.3. Refactorización de Programas Orientados a Aspectos . 37
3.3.4. Economı́a de la Refactorización . . . . . . . . . . . . . 38
i
4. Refactorización de Código Estructurado 39
4.1. La Programación Estructurada . . . . . . . . . . . . . . . . . 39
4.2. Lenguajes de Programación . . . . . . . . . . . . . . . . . . . 40
4.2.1. C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.2.2. FORTRAN . . . . . . . . . . . . . . . . . . . . . . . . 41
4.2.3. COBOL . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.3. Refactorización de Código Fuente Estructurado en C . . . . . 43
4.4. Refactorización de Código Fuente Estructurado en COBOL . . 48
4.5. Refactorización de Código Fuente Estructurado en FORTRAN 49
5. Conclusiones 53
5.1. Futuros Trabajos . . . . . . . . . . . . . . . . . . . . . . . . . 54
ii
Capı́tulo 1
Introducción
1.1. El Software
El cambio es un factor que ejerce continuamente presión sobre el software
[8]. Lo sobresaliente de este caso es que una vez terminada la producción del
mismo, el cambio sigue ejerciendo presiones sobre el producto, algo difı́cil de
que suceda en la industria de la manufactura. Esto es debido, según Brooks,
a dos motivos: el primero a que el software puede sufrir modificaciones más
fácilmente que por ejemplo un edificio, el segundo a que el software está con-
stituido por su funcionalidad, y justamente la funcionalidad es el aspecto que
está sujeto a más presiones para cambiar.
1
50 años de vida. Según las investigaciones hechas en los últimos años el por-
centaje de proyectos de desarrollo que no logran completarse es muy elevado
[53], como ası́ también el sobreprecio y la modificación de calendarios inter-
minables. Un ejemplo muy gráfico de este hecho es el sistema de entrega de
equipaje del aeropuerto de Denver. Un proyecto que debı́a estar entregado
para octubre de 1993 y en su lugar fue terminado en marzo de 1995, con un
retraso de unos 16 meses aproximadamente y con un costo muy por encima
del presupuestado [15].
2
de mantenimiento del software, ésta constituye la fase que requiere de más
esfuerzos dentro del ciclo de vida del desarrollo del producto. Entre el 60 %
y el 70 % de todo el esfuerzo es utilizado en la etapa de mantenimiento. Es-
ta etapa se divide en: mantenimiento correctivo, mantenimiento adaptativo,
mantenimiento preventivo y mantenimiento perfectivo [26] [12].
3
código fuente nació como la “aplicación de modificaciones al código fuente
para hacerlo más fácil de cambiar y de comprender, o hacerlo menos suscepti-
ble a errores cuando futuros cambios sean aplicados” [2]. Cabe destacar que
en la definición utilizada por Arnold se excluye a la reestructuración para
cualquier otro propósito, como la mejora del código para aumentar perfor-
mance, la transformación de código para paralelizar, etc. Vista como tal, la
reestructuración es una herramienta que podrı́a ayudar a resolver el proble-
ma del enorme esfuerzo que se requiere en la fase de mantenimiento, dentro
del ciclo de vida del desarrollo del software. Existen otros motivos por los
cuales, según Arnold [2], la reestructuración del código fuente debe ser tenida
en cuenta por los ingenieros de Software:
• Facilitar la documentación.
• Facilitar las tareas de testing.
• Facilitar las tareas de auditorı́a.
• Reducir potencialmente la complejidad del software.
4
en costo de mantenimiento que una aplicación puede aportar a otra; b) por el
ahorro que proporciona la reutilización de componentes en otras aplicaciones;
y c) por el ahorro incurrido en la ampliación del ciclo de vida del sistema
previo a su reposición por uno nuevo. Como puede verse la reestructuración
de código fuente reduce los costos de mantenimiento, a su vez aumenta la
posibilidad de reutilización de componentes en otros sistemas y amplı́a el
ciclo de vida del sistema aumentando de esta manera el valor del mismo [2].
Por ende, es importante a la hora de planear la aplicación de reestructuración
de código evaluar como ese proceso de reestructuración aumentará el valor
actual del sistema.
Puede encontrarse otra definición del concepto de reestructuración de
software aportada por Chikofsky y Cross [13] : “es una transformación de
una forma de representación a otra en el mismo nivel de abstracción, mien-
tras se mantiene el mismo comportamiento externo del sistema en cuestión
(funcionalidad y semántica). Una transformación de reestructuración básica-
mente se aplica en la apariencia del sistema, como por ejemplo la alteración
del código para mejorar su estructura, en el sentido tradicional del diseño
estructurado. Mientras que la reestructuración crea nuevas versiones que im-
plementan o proponen cambios al sistema, no hace modificaciones debido a
variaciones en los requerimientos del sistema. Esto puede acercar a tener una
adecuada comprensión del mismo que sugiera cambios que mejoren aspectos
del sistema”.
5
Reestructuración con pre-procesador [29] : Se sustituye código
fuente con directivas más fáciles de comprender que posteri-
ormente serán reemplazadas por el código original.
6
Eliminación de go-to: todas las técnicas abajo enumeradas en
este apartado, intentan eliminar los go-to no estructurados de
un programa:
• Early goto-less approach [7].
• RETROFIT (tm)[36].
• Doble conversión.
7
de los datos de una aplicación.
8
Capı́tulo 2
Refactorización
9
3. Autoregulación - El proceso de evolución del programa se autoregula
con una distribución de medidas de atributos de producto y procesos
cercana a la normal.
10
de que su estructura interna sea erosionada como una piedra sometida a los
avatares del viento.
Código duplicado. Se deben eliminar las lı́neas de código que son exac-
tamente iguales en varios sitios, o bien eliminar lı́neas de código muy
parecidas o con estructura similar en varios sitios.
Métodos muy largos. En este caso hay que particionar el código fuente
en trozos y extraerlos para crear métodos más pequeños, que sean más
fáciles de mantener y de reusar.
11
tener que realizar esta repetición a lo largo del código fuente, o incluso
evitan tener que ponerlo en algún lado.
2.3. Refactoring
El primer uso conocido del término refactorización en la literatura se
encuentra publicado en el artı́culo Refactoring: An Aid in Designing Appli-
cation Frameworks and Evolving Object-Oriented Systems por William F.
Opdyke y Ralph E. Johnson [45]. La refactorización surge como un intento
de mejorar la producción de software reusable. El desarrollo de software es
un proceso complejo y continuo en el cual un producto transita, a lo largo de
su construcción, por un proceso iterativo (desarrollo espiral, desarrollo por
prototipos, desarrollo de tipo iterativo incremental, otros). El desarrollo de
software re-usable es un proceso aun más complejo pues éste es el resultado
de varias iteraciones de diseño, incluso cuando éste ya ha sido reusado, por
ende los cambios a los que está sujeto, no lo afectan únicamente a él sino
también al software que lo utiliza [44]. En base a ello la refactorización surge
como “el proceso en el cual se aplican cambios en un sistema de software de
forma tal que no altere el comportamiento externo del código, mejorando su
estructura interna” [21].
Esta definición, que no deja de ser muy abierta, plantea una serie de cues-
tiones: ¿En qué consiste el comportamiento externo del software? ¿El área
de aplicabilidad de la refactorización está restringida únicamente a software
reusable? ¿Puede extenderse este concepto a otros productos del proceso de
12
desarrollo, o es solamente aplicable a código fuente? ¿En qué consiste la es-
tructura interna? ¿Cuándo, dónde, por qué refactorizar?
Existen además otros dominios en los cuales se pueden definir otros as-
pectos que hacen al comportamiento externo. En las aplicaciones web, el
contenido puede pasar a formar parte del comportamiento externo o como
se especifica en [43] el conjunto de nodos y los links de navegación entre los
nodos y el conjunto de operaciones disponibles para el usuario y la semántica
de cada operación, pueden ser considerados comportamiento externo, desde
el punto de vista de la refactorización.
13
2.3.2. Caracterı́sticas Internas y Externas del Software
Otro punto destacable aportado por el trabajo de [39] es el efecto de los
procesos de refactorización sobre la calidad del software. El software posee
caracterı́sticas que se manifiestan en forma externa y otras que son propias de
la estructura interna del mismo, definidas como caracterı́sticas internas. En
las primeras encontramos conceptos como robustez, extensibilidad, perfor-
mance, reusabilidad, etc. Entre las caracterı́sticas internas nos encontramos
con los conceptos de comprensibilidad, legibilidad, correctitud, redundan-
cia, etc. Los procesos de refactorización pueden afectar a las caracterı́sticas
internas: al aplicar reducción de código redundante, al aplicar cambios de
nombres de métodos o variables. Pero también pueden afectar a factores o
caracterı́sticas externas que hacen a la calidad del software, por ejemplo la
performance. Si bien se cree que la refactorización de código fuente afecta
negativamente en cuanto a la performance [21], existen estudios que demues-
tran lo contrario. Refactorizaciones tendientes a reemplazar intrucciones if
con polimorfismo mejoran la performance de la aplicación gracias a las opti-
mizaciones que hacen los compiladores actuales [39].
La clase Producto
Representa a un producto que es vendido en la tienda.
14
class Producto {
public const int SOFTWARE=1;
public const int HARDWARE=2;
public const int NOAPLICA=0;
La clase Compra
Representa la compra de un producto
class Compra {
private Producto _producto;
private int _cantidad;
15
_cantidad = cantidad;
}
La clase Factura
Representa el importe a pagar por todas las compras realizadas: esta clase
es la que se encarga de determinar el valor a pagar de todas las compras re-
alizadas.
Esta clase posee un método llamado facturar() que es el encargado de calcular
el valor total y estado de cuenta de la factura, aplicar el impuesto correspon-
diente y además calcular puntos por las compras realizadas. Ver diagrama de
secuencia figura 2.2
class Factura {
16
public string Facturar() {
double totalFactura;
IEnumerator it = _compras.GetEnumerator();
int puntaje = 0;
int ticket = "";
totalFactura = 0;
while (it.MoveNext) {
double valorCompra = 0;
Compra compra = it.Current;
//Calcular el valor de una compra de la factura
switch (compra.Producto.Tipo){
case Producto.HARDWARE:
valorCompra = compra.Producto.Precio * 10.5;
break;
case Producto.SOFTWARE:
valorCompra = compra.Producto.Precio * 21;
break;
case Producto.NOAPLICA:
valorCompra = compra.Producto.Precio;
break;
}
// calcular bonificacion
puntaje++;
if (compra.Producto.Tipo() == Producto.HARDWARE && compra.Cantidad >1 ) puntaje++;
// Calcular el valor Total de la factura
totalFactura += valorCompra;
// imprimir
ticket= "\t" + compra.Producto.Nombre + "\t" + compra.Cantidad +"\t" +valorCompra + "\n";
}
// Totalizar
ticket = "El total de su compra es :" + totalFactura.ToString() + "\n";
ticket = "Su puntaje acumunlado en esta compra es: " + puntaje + "\n";
}
}
17
Teniendo en cuenta las secciones anteriores, lo primero que salta a la vista
en estas tres clases es la extensión del método facturar(). Existe una refactor-
ización propuesta en este caso en [21] que es llamada “extracción de método”
(extract method), que consiste básicamente en dividir un método muy ex-
tenso en dos más pequeños, con el objetivo de hacer más manejable el código
fuente. Es un hecho comprobable, que es más fácil de seguir y comprender
un método que entre en las 24 filas de un monitor que, aquel que ocupe más
lı́neas y haga que sea necesario scroll para poder hacer el seguimiento.
totalFactura = 0;
while (it.MoveNext) {
double valorCompra = 0;
Compra compra = it.Current;
//Calcular el valor de una compra de la factura
switch (compra.Producto.Tipo){
case Producto.HARDWARE:
valorCompra = compra.Producto.Precio * 10.5;
break;
case Producto.SOFTWARE:
valorCompra = compra.Producto.Precio * 21;
break;
case Producto.NOAPLICA:
valorCompra = compra.Producto.Precio;
break;
}
// calcular bonifica
puntaje++;
if (compra.Producto.Tipo() == Producto.HARDWARE && compra.Cantidad >1 ) puntaje++;
// Calcular el valor Total de la factura
totalFactura += valorCompra;
// imprimir
ticket= "\t" + compra.Producto.Nombre + "\t" + compra.Cantidad +"\t" +valorCompra + "\n";
}
// Totalizar
ticket = "El total de su compra es :" + totalFactura.ToString() + "\n";
ticket = "Su puntaje acumulado en esta compra es: " + puntaje + "\n";
}
18
int puntaje = 0;
int ticket = "";
totalFactura = 0;
while (it.MoveNext) {
double valorCompra = 0;
Compra compra = it.Current;
//Calcular el valor de una compra de la factura
valorCompra =CalcularCompra(compra);
// calcular bonifica
puntaje++;
if (compra.Producto.Tipo() == Producto.HARDWARE && compra.Cantidad >1 ) puntaje++;
// Calcular el valor Total de la factura
totalFactura += valorCompra;
// imprimir
ticket= "\t" + compra.Producto.Nombre + "\t" + compra.Cantidad +"\t" +valorCompra + "\n";
}
// Totalizar
ticket = "El total de su compra es :" + totalFactura.ToString() + "\n";
ticket = "Su puntaje acumunlado en esta compra es: " + puntaje + "\n";
}
19
Si bien este cambio ha aportado mejoras desde el punto de vista de la
estructura interna del código fuente, y además se ha validado que el com-
portamiento externo del mismo no ha cambiado (testing) es innegable que se
podrı́a mejorar aun más esta estructura interna.
class Compra {
20
}
}
Tras haber aplicado este cambio, que desde el punto de la programación ori-
entada a objetos es más lógico que el método CalcularCompra pertenezca a
la clase Compra que a la clase Factura. Otra vez se han aplicado cambios
internos que no modifican el comportamiento externo, pero aportan a la es-
tructura del código fuente mejoras sustanciales.
1. Add Parameter
6. Collapse Hierarchy
21
17. Extract Class
22
42. Move Class by Gerard M. Davison
23
67. Replace Delegation with Inheritance
24
92. Use a Connection Pool
93. Wrap entities with session
Fowler [21] considera que erróneamente puede llegarse a la conclusión,
que refactorizar es aplicar pequeños cambios al código fuente variando im-
perceptiblemente o no el comportamiento externo del mismo. Solamente los
cambios que hacen que el software sea más fácil de entender son considerados
para el autor, como refactorización.
¿Cuales serı́an los pasos a seguir para lograr transformar el diseño exis-
tente? Para ello se deberán aplicar algunas de las refactorizaciones propuestas
por Fowler:
25
Figura 2.4: Diagrama de clases refactorizado
Chain Constructors
Compose Method
26
Encapsulate Classes with Factory
Extract Adapter
Extract Composite
Extract Parameter
Inline Singleton
Unify Interfaces
27
Algunos de ellos son autodescriptivos, por ejemplo, Replace Implicit Tree
with Composite, permite reemplazar una estructura claramente similar a la
de un árbol por el patrón Composite. Otro ejemplo interesante de observar
es cómo sustituir código enmarañado que varı́a según estados por el patrón
State, o extraer un método de cálculo con Strategy(figura 2.5).
28
Capı́tulo 3
Herramientas de
Refactorización
29
Figura 3.2: Eclipse
3.2.1. Smalltalk
Smalltalk Refactoring Browser
Esta herramienta se desarrolló para VisualWorks, VisualWorks/ENVY,
y IBM Smalltalk. Incluye las caracterı́sticas del entorno de ventanas
estándar de Smalltalk además con técnicas de refactorización.
(http://st-www.cs.uiuc.edu/users/brant/Refactory/RefactoringBrowser.html).
3.2.2. Java
InteliJ Idea IDE que es capaz de aplicar algunas técnicas de refac-
toring como: renombrar, extraer métodos, introducir variables, etc.
(http://www.jetbrains.com/idea/index.html)
JFactor
Es en realidad una familia de productos que provee herramientas para
aplicar técnicas de refactorización. Éste es capaz de integrarse al en-
torno de desarrollo VisualAge. Este producto permite aplicar las sigu-
ientes refactorizaciones: extract method, rename method variables, in-
troduce explaining variable, inline temp, replace magic number with
symbolic constant, inline method, rename method, safe delete method,
pull up method, push down method, introduce foreign method, rename
field, pull up field, push down field, encapsulate field, extract super-
class, extract interface.
(http://old.instantiations.com/jfactor/default.htm)
30
XRefactory
Es una herramienta de desarrollo de software para C y Java que propor-
ciona la posibilidad de aplicar técnicas de refactorización. Una de sus
notables caracterı́sticas es que este producto es un plug-in para Emacs.
Además soporta otros lenguajes de programación como C (figura 3.3).
Otra caracterı́stica de este producto es que sus creadores afirman que
31
IDEs soportados por la herramienta
Caracterı́sticas:
Transmogrify
El propósito principal de esta aplicación es la de refactorizar código
fuente, pudiendo ésta aplicar:
32
error. En el caso que sea aplicable se realiza el cambio y se realiza copia
de seguridad de los fuentes.
(http://transmogrify.sourceforge.net/ )
JavaRefactor
Este producto es un plug-in para Jedit. Permite aplicar refactorización
basado en un catálogo de refactorizaciones para Java. Con este pro-
ducto se puede renombrar clases, atributos, métodos y paquetes; hacer
PushDown y PullUp de métodos y atributos a través de una jerarquı́a
de clases. Otras refactorizaciones serán incluidas en futuras versiones
según sus creadores.
(http://plugins.jedit.org/plugins/?JavaRefactor)
CodeGuide
Este producto es un entorno integrado de desarrollo para Java que
ofrece la posibilidad de aplicar refactoring al código fuente Java escrito
con esta herramienta.
(http://www.omnicore.com/en/)
CloneDR
Este producto detecta y elimina código fuente duplicado en aplicaciones
de gran envergadura. Según sus creadores, se repite entre el 10 - 25 %
del código fuente escrito en aplicaciones con un gran número de lı́neas
de código. Esta herramienta permite detectar esta redundancia y mod-
ificar el mismo para reducir las repeticiones (figura 3.4).
3.2.3. .NET
C# Refactory
Esta es una herramienta para aplicar refactorización al entorno de pro-
gramación de Visual Studio .Net como un plug-in. El cátalogo de refac-
torizaciones que proporciona es reducido: extract method, decompose
conditional, extract variable, introduce explaining variable, extract su-
perclass, extract interface, copy class, push up members, rename type,
rename member, rename parameter, rename local variable.
(http://www.xtreme-simplicity.net/CSharpRefactory.html)
33
Refactor! - Ver descripción en el apartado de Visual Basic
Visual Assist X
Esta herramienta es un plug-in para Visual Studio. Permite realizar
las siguientes refactorizaciones: Rename, Extract Method, Encapsulate
Field, Change Signatura, Move Implementation to Source File, Add
Member, Add Similar Member, Document Method, Create Declaration,
Create Implementation. (http://www.wholetomato.com/)
JustCode!
Herramienta que agrega más refactorizaciones a las que vienen por
defecto en Visual Studio .Net. Es distribuida como plug-in. Soporta
refactorizaciones para C#, Visual Basic.net y ASP.net.
(http://www.omnicore.com/en/justcodefeatures.htm)
3.2.4. C/C++
SlickEdit
Editor multi-lenguaje y multi-plataforma, dentro de sus caracterı́sticas
proporciona la posibilidad de la aplicación de refactorizaciones al código
fuente escrito con esta herramienta.
(http://www.slickedit.com/)
Ref++
Plug-in para Visual Estudio .net que proporciona caracterı́sticas de
refactorización para C++.
34
conditional, simplify expression, introduce local, introduce constant,
inline temp, replace temp with query, split temporary variable, move
initialization to declaration, split initialization from declaration, move
declaration near reference (figura 3.5).
(http://msdn.microsoft.com/es-es/vbasic/ms789083.aspx)
(http://www.aivosto.com/project/project.html)
3.2.6. Delphi
ModelMaker
Esta herramienta permite aplicar técnicas de refactorización a progra-
mas pascal o delphi. Permite realizar refactorizaciones como por ejem-
plo: Extract Method, Extract Class / Interface, Rename Parameter
etc.
3.2.7. Erlang
Erlang es un lenguaje diseñado por Ericsson, está orientado a la pro-
gramación concurrente. En su origen fue creado para construir aplicaciones
distribuidas, tolerantes a fallas, soft-real-time y de funcionamiento continuo.
Está considerado como lenguaje funcional.
Wrangler
Es una herramienta de refactorización construida para Erlang, que per-
mite aplicar refactorizaciones al código Erlang en forma interactiva.
35
Aun se encuentra en su fase de prototipo. Esta herramienta no es com-
ercial.
(http://www.cs.kent.ac.uk/projects/forse/wrangler/doc/overview-summary.html)
3.2.8. Haskell
Hare [33]
Es un prototipo de herramienta para refactorizar programas escritos en
Haskell. Hare permite realizar refactorizaciones básicas como rename,
delete, promote level, etc. La aplicación corre una interfaz gráfica ami-
gable.
3.2.9. Resumen
Puede verse cómo en los últimos años se ha incrementado la cantidad
de herramientas de desarrollo que facilitan la aplicación de refactorización
de código fuente. Básicamente existen tres variantes. La primera como plug-
in adosable a un entorno de desarrollo. La segunda formando parte de un
entorno integrado de desarrollo (IDE). La tercera, como una aplicación stand-
alone. Las dos primeras variantes son las más encontradas. Cabe destacar que
si bien la cantidad de herramientas de refactorización son numerosas, esta
técnica es muy reciente y es de esperar que las herramientas evolucionen en
un número aun mayor.
36
dentro del código fuente de la aplicación [38]. Ésta es sólo una parte del
complejo proceso que se requiere en la refactorización de modelos. Desde el
punto de vista de la refactorización, los modelos UML son aquellos candidatos
más apetecibles para ser refactorizados. Cabe destacar que existen varios
trabajos realizados en esta dirección. Desde la perspectiva de los modelos de
comportamiento, no es sencillo poder probar que los cambios ejercidos por
una refactorización preservan el comportamiento del modelo. Existen pocos
trabajos hechos sobre refactorización de diagramas de estados, por ejemplo.
37
Extract superaspect.
38
Capı́tulo 4
Refactorización de Código
Estructurado
39
ceptos como el de Cohesión y Acoplamiento reforzados por Constantine [14],
conocidos como los principios de la modularidad.
4.2.1. C
Éste es considerado uno de los lenguajes más importantes dentro de la
historia de los lenguajes de programación. C es un lenguaje de programación
de propósito general desarrollado entre 1969 y 1973 por Dennis Ritchie, in-
vestigador de los Laboratorios Bell, para el sistema operativo Unix.
40
diseño fue orientado para ser un lenguaje eficiente, con un núcleo relativa-
mente pequeño que además estaba provisto de bibliotecas que manejaban
archivos y cálculos matemáticos.
4.2.2. FORTRAN
El 15 de octubre de 1956 fue publicado el primer borrador de la especi-
ficación de The IBM Mathematical Formula Translating System [4], este
lenguaje de programación nació con un conjunto de 32 instrucciones, la may-
or parte de ellas para controlar los dispositivos de entrada/salida (READ
DRUM, PUNCH).
Esta primera versión de FORTRAN no estaba preparada para soportar pro-
gramación de tipo procedural y sólo podı́an definirse arrays de 1, 2 ó 3 dimen-
siones de sólo dos tipos de datos: enteros (fixed point) o de punto flotante
(floating point). Admitı́a la declaración implı́cita de tipos de variable, las
comenzadas en i, j, k, l, m o n eran de tipo entero y las de punto flotante
comenzaban con cualquier otro carácter. No admitı́a la conversión implı́cita
de tipos de datos, es decir, no podı́an usarse variables enteras y de punto
flotante en una misma expresión, si bien la conversión estaba permitida.
FORTRAN II fue la versión posterior, liberada en 1958. Entre algunas de las
caracterı́sticas nuevas que FORTRAN II poseı́a se encuentran:
CALL y RETURN.
COMMON.
41
compilaba; éstas fueron eliminadas en la versión de FORTRAN IV en 1961.
Gracias a la gradual relevancia obtenida por este lenguaje de programación,
hacia 1966 la American Starndadr Association (en la actualidad ANSI) con-
formó un comité que redactó la primera versión del estándar de FORTRAN
conocida como FORTRAN 66. El mismo se basa principalmente en FOR-
TRAN IV. En 1978 y debido a la popularidad adquirida por el lenguaje y
a las modificaciones que introdujeron algunos fabricantes de compiladores,
la ANSI se vio obligada a hacer una revisión del estándar. En abril de 1978
fue publicada una nueva versión llamada FORTRAN 77 [19]. Esta versión se
convertirı́a en el dialecto de FORTRAN más utilizado a lo largo de unos 30
años.
Hacia 1992, con la aparición de la programación orientada a objetos, el
estándar de FORTRAN se somete a una nueva revisión, que concluye con
la publicación del estándar denominado FORTRAN 95 [20].
Cabe destacar que en la revisión de 1992 no se elimina ninguna caracterı́sti-
ca respecto de la versión anterior (en el Appendix B.1 se indica: The list of
deleted features in this standard is empty.”). La última revisión del estándar
es la de FORTRAN 2003 en la cual se introdujeron todas las propiedades de
la programación orientada a objetos como el polimorfismo, la herencia, etc.
FORTRAN es posiblemente el lenguaje con mayor bagaje histórico entre los
lenguajes de programación.
4.2.3. COBOL
Podrı́a decirse que éste es el lenguaje de programación más conocido por
la personas que trabajan en ambientes de procesamiento de datos. Su nombre
es una abreviatura de COmmon Business-Oriented Language, que fue con-
struido principalmente para implementar sistemas fuertemente relacionados
con el ámbito financiero, económico y administrativo. En mayo de 1959 fue
creada la comisión CODASYL, conformada por el Departamento de Defensa
de los Estados Unidos, por fabricantes de hardware y por usuarios.
42
funcionalidad. En 1968 surge la primera versión ANSI de COBOL llama-
da COBOL ANSI-68, con revisiones posteriores COBOL ANSI-74, COBOL
ANSI-85 posiblemente la versión más utilizada de este lenguaje de progra-
mación y una última revisión en el año 2002 llamada COBOL ANSI-2002. A
partir del año 2007 se está preparando una nueva revisión del lenguaje.
43
b Delete unused parameter
c Delete a function
a Rename variable
b Rename constant
c Rename user-defined type
d Rename structure field
e Rename function
f Replace the type of a program entity
g Contract variable scope
h Extend variable scope
i Replace value with constant
j Replace expression with variable
k Convert variable to pointer
l Convert pointer to direct variable access
m Convert global variable into parameter
n Reorder function arguments
4. Complex refactorings:
44
#define XMAX 100
#define YMAX 100
#define TRUE 1
#define FALSE 0
#include <stdio.h>
typedef struct {
float x;
float y;
} Point;
typedef struct {
Point pt1;
Point pt2;
} Rectangle;
Point middle;
void main() {
45
Rectangle sc;
float x1, x2;
scanf("Enter upper left x coordinate: %f", x1);
scanf("Enter upper left y coordinate: %f", x2);
sc.pt1 = make_pt(x1, x2);
if (x1 < (XMAX-10) && x2 < (YMAX-10)) {
float x1, x2;
scanf("Enter lower right x coordinate: %f", x1);
scanf("Enter lower right y coordinate: %f", x2);
sc.pt2 = make_pt(x1, x2);
}
else
sc.pt2 = make_pt(XMAX, YMAX);
middle = middle_point(&sc);
}
Después de aplicar:
46
Point lower_right;
} Rectangle;
Point middle;
47
}
48
4.5. Refactorización de Código Fuente Estruc-
turado en FORTRAN
A pesar de ser un lenguaje de programación con casi unos 50 años de
vida con cientos de miles de lı́neas de código escritas, y además uno de los
lenguajes más utilizados para cómputo paralelo y de altas prestaciones [46] y
uno de los lenguajes más evolucionados desde la fecha de su creación hasta el
dı́a de hoy, FORTRAN cuenta con un muy escaso desarrollo de herramientas
y técnicas de refactorización.
Éstas son dos posibles formas de escribir el mismo ciclo Do-Loop en FOR-
TRAN 90/95, la primera forma pertenece al estándar de FORTRAN 77 [19]
y la segunda la versión corregida o revisada de FORTRAN 90/95 (ambas
válidas para este último). Por ende, en un programa escrito en FORTRAN
90 [20] podemos encontrar la misma estructura de control escrita en dos for-
matos distintos, esto si bien permite la compatibilidad de versionado entre
los distintos estándares del lenguaje, por otro lado hace más compleja la
comprensión y la claridad del código fuente.
Una caracterı́stica que poseen las dos versiones de F77 y F90 en los loops
son los llamados Shared Do loops Terminations, en este caso se recomien-
da eliminarlos por las formas más estructuradas de escribir, que es con los
correspondientes END-DO [58]:
49
DO 101 k=1,l
DO 101 i = 1,imax
X(i,k)=temp(i,k)-h25e2
Y(I,k)=x(i,k) * x(I,k)
101 CONTINUE
DO k=1,l
DO i = 1,imax
X(i,k)=temp(i,k)-h25e2
Y(I,k)=x(i,k) * x(I,k)
END DO
END DO
Otro caso interesante de estudio sobre las caracterı́sticas del código fuente
de FORTRAN lo encontramos en los operadores lógicos. A partir de la versión
de FORTRAN 90 [20] es posible escribir de dos formas los operadores lógicos:
50
IF (X .GT. 0) THEN
IF (X .GE. Y) THEN
WRITE(*,*) ’X ES POSITIVO Y X >= Y’
ELSE
WRITE(*,*) ’X ES POSITIVO PERO, X < Y’
ENDIF
ELSEIF (X .LT. 0) THEN
WRITE(*,*) ’X ES NEGATIVO’
ELSE
WRITE(*,*) ’X ES CERO’
ENDIF
IF (X > 0) THEN
IF (X >=0 Y) THEN
WRITE(*,*) ’X ES POSITIVO Y X >= Y’
ELSE
WRITE(*,*) ’X ES POSITIVO PERO, X < Y’
ENDIF
ELSEIF (X < 0) THEN
WRITE(*,*) ’X ES NEGATIVO’
ELSE
WRITE(*,*) ’X ES CERO’
ENDIF
Código fuente escrito en el formato F90 [20] (ambos válidos para F90).
Cabe además destacar que se han hecho trabajos de grado que han de-
mostrado que la aplicación de ciertos cambios al código fuente de programas
escritos en FORTRAN mejoran, además, otras caracterı́sticas del mismo co-
mo por ejemplo la performance. En este trabajo se llega a medir una variación
en el rendimiento de ciertas rutinas de la aplicación de hasta un 22,94 %, cam-
biando el código fuente escrito a la notación matricial donde podı́a realizarse
el cambio[51][58] .
51
últimas versiones se han introducido algunas de las refactorizaciones descrip-
tas en este apartado. Una de las razones de la importancia de este punto,
se basa en las caracterı́sticas de los programadores FORTRAN, si bien un
entorno gráfico proporciona claridad, usabilidad, comprensibilidad, etc. es
cierto que, además, los programadores de este lenguaje están muy acostum-
brados a entornos de tipo consola, en los cuales el formato de la herramienta
a utilizar cambia radicalmente.
Por otro lado, existen muy pocos trabajos que apliquen técnicas de refac-
torización dentro de la programación estructurada orientados a áreas más
especı́ficas, como por ejemplo la High Performance o la Programación en
Paralelo. Este es un campo dentro de las técnicas de refactorización de códi-
go estructurado en el cual no se han hecho muchos trabajos sobre el tema,
un muy buen punto de partida para futuras investigaciones.
52
Capı́tulo 5
Conclusiones
Se han enumerado los motivos principales por los que un sistema de soft-
ware necesita apoyarse en técnicas que permitan mejorar el producto, medi-
ante la aplicación de pequeños cambios en forma paulatina.
53
hasta la edición de este trabajo, que proveen técnicas automatizadas para la
realización de estas transformaciones.
54
refactorización y de los lı́mites de aplicabilidad de la misma dentro del cam-
po de la ingenierı́a de software. Asimismo es importante determinar cuáles
son los lı́mites dentro de los que una serie de transformaciones pueden ser
llamadas refactorizaciones o no. Además es necesario formalizar los concep-
tos dentro de la definición de refactoring donde aun hoy existen opiniones
controversiales de cuándo una determinada transformación es o no una refac-
torización.
55
Bibliografı́a
[4] J. Backus. The history of Fortran I, II, and III. ACM SIGPLAN Notices,
13(8):165–180, 1978.
[7] Corrado Böhm and Giuseppe Jacopini. Flow diagrams, turing machines
and languages with only two formation rules. Commun. ACM, 9(5):366–
371, 1966.
[8] F.P. Brooks. No silver bullet: Essence and accidents of software engi-
neering. IEEE computer, 20(4):10–19, 1987.
56
[11] R. Canning. Rejuvenate your old systems. EDP Analyzer, 22(3):1–16,
1984.
[12] N. Chapin, J.E. Hale, K.M. Khan, J.F. Ramil, and W.G. Tan. Types
of software evolution and software maintenance. Journal of Software
Maintenance and Evolution: Research and Practice, 13(1), 2001.
[13] E.J. Chikofsky and J.H. Cross. Reverse engineering and design recovery:
A taxonomy. IEEE software, 7(1):13–17, 1990.
[17] J.M. Favre. Languages evolve too! changing the software time scale.
In Proceedings of the Eighth International Workshop on Principles of
Software Evolution (IWPSE), Washington, DC, USA, IEEE Computer
Society, pages 33–44, 2005.
[18] B. Foote and J. Yoder. Big ball of mud. Pattern languages of program
design, 4(654-692):99, 2000.
57
[24] A. Garrido and R. Johnson. Refactoring C with conditional compilation.
In 18th IEEE Int. Conf. on Automated Software Engineering, 2003.
[31] M.M. Lehman et al. Programs, life cycles, and laws of software evolution.
Proceedings of the IEEE, 68(9):1060–1076, 1980.
[32] M.M. Lehman, J.F. Ramil, P.D. Wernick, D.E. Perry, and W.M. Turs-
ki. Metrics and laws of software evolution-the nineties view. In 4th
International Software Metrics Symposium (METRICS’97), 1997.
[33] H. Li, C. Reinke, and S. Thompson. Tool support for refactoring func-
tional programs. In Proceedings of the 2003 ACM SIGPLAN workshop
on Haskell, pages 27–38. ACM New York, NY, USA, 2003.
[35] R.C. Linger, B.I. Witt, and HD Mills. Structured Programming; Theory
and Practice the Systems Programming Series. Addison-Wesley Long-
man Publishing Co., Inc. Boston, MA, USA, 1979.
[36] Michael J. Lyons. Salvaging your software asset: (tools based main-
tenance). In AFIPS ’81: Proceedings of the May 4-7, 1981, national
computer conference, pages 337–341, New York, NY, USA, 1981. ACM.
58
[37] Bill McCloskey and Eric Brewer. Astec: a new approach to refactoring
c. SIGSOFT Softw. Eng. Notes, 30(5):21–30, 2005.
[38] T. Mens, G. Taentzer, and D. Muller. Challenges in model refactor-
ing. In Proc. 1st Workshop on Refactoring Tools, University of Berlin,
volume 98, 2007.
[39] T. Mens and T. Tourwé. A survey of software refactoring. IEEE Trans-
actions on software engineering, 30(2):126–139, 2004.
[40] M.P. Monteiro and J.M. Fernandes. Towards a catalog of aspect-
oriented refactorings. In Proceedings of the 4th international conference
on Aspect-oriented software development, page 122. ACM, 2005.
[41] HW Morgan. Evolution of a software maintenance tool. In Proceedings
of the 2nd Natwnal Conference EDP Software Maintenance, pages 268–
278, 1984.
[42] M.C. Ohlsson, A. Von Mayrhauser, B. McGuire, and C. Wohlin. Code
decay analysis of legacy software through successive releases. In Proc.
IEEE Aerospace Conf, pages 69–81. Citeseer, 1999.
[43] L. Olsina, A. Garrido, G. Rossi, D. Distante, and G. Canfora. Web Ap-
plication evaluation and refactoring: A Quality-Oriented improvement
approach. Journal of Web Engineering, 7(4):258–280, 2008.
[44] W.F. Opdyke. Refactoring object-oriented frameworks. PhD thesis, Cite-
seer, 1992.
[45] W.F. Opdyke and R.E. Johnson. Refactoring: An aid in designing appli-
cation frameworks and evolving object-oriented systems. In Proceedings
of Symposium on Object-Oriented Programming Emphasizing Practical
Applications (SOOPPA), 1990.
[46] Jeffrey Overbey, Spiros Xanthos, Ralph Johnson, and Brian Foote.
Refactorings for fortran and high-performance computing. In SE-HPCS
’05: Proceedings of the second international workshop on Software engi-
neering for high performance computing system applications, pages 37–
39, New York, NY, USA, 2005. ACM.
[47] J.L. Overbey, S. Negara, and R.E. Johnson. Refactoring and the evolu-
tion of Fortran. Urbana, 51:61801.
[48] J. Peng. Semi-Automated Refactoring Applied to the C Programming
Language.
59
[49] D. Pigott. An interactive historical roster of computer languages. hopl.
murdoch. edu. au, last visited: March, 2005.
60
Índice de figuras
61