miércoles, 8 de diciembre de 2010 | By: Wynnie Calero

Reingenieria


      I.        Reingeniería de procesos de negocios

La Reingeniería de procesos de negocio, RPN (Business Process Reingineering, BPR2) va más allá del ámbito de las tecnologías de la información y de la ingeniería del software. Entre las muchas definiciones (la mayoría de ellas, algo abstractas) que se han sugerido para la RPN, se cuenta con una publicada en la revista Fortune: «. . .la búsqueda e implementación de cambios radicales en el proceso de negocios para lograr un avance significativo». Ahora bien ¿cómo se efectúa la búsqueda, y cómo se lleva a cabo la implementación? O lo que es más importante, ¿cómo podemos estar seguros de que el «cambio radical» que se sugiere va a dar lugar realmente a un «avance significativo» en lugar de conducimos a un caos organizativo?


Procesos de negocio

Un proceso de negocio es «un conjunto de tareas lógicamente relacionadas que se llevan a cabo para obtener un determinado resultado de negocio». Dentro del proceso de negocio, se combinan las personas, los equipos, los recursos materiales y los procedimientos de negocio con objeto de producir un resultado concreto. Entre los ejemplos de negocio se incluyen el diseño de un nuevo producto, la adquisición de servicios y suministros, la contratación de nuevos empleados o el pago a proveedores. Cada una requiere un conjunto de tareas y se basa en diversos recursos dentro del negocio. Cada proceso de negocio posee un cliente bien definido una persona o grupo que recibe el resultado (por ejemplo: una idea, un informe, un diseño, un producto) . Además, los procesos de negocio cruzan los límites organizativos. Requieren que distintos grupos de la organización participen en las «tareas lógicamente relacionadas » que definen el proceso. El negocio global se puede segmentar de la siguiente manera:

El negocio
Sistemas de negocio
Proceso de negocio
Subprocesos de negocio

Cada uno de los sistemas de negocios (también llamados función de negocios) están compuestos por uno o más procesos de negocio, y cada proceso de negocio está definido por un conjunto de subprocesos. La RPN se puede aplicar a cualquier nivel de la jerarquía, pero a medida que se amplía el ámbito de la RPN (esto es, a medida que se asciende dentro de la jerarquía) los riesgos asociados a la RPN crecen de forma dramática. Por esta razón, la mayor parte de los esfuerzos de la RPN se centran en procesos o subprocesos individuales.




Principios de reingeniería de procesos de negocio

En muchos aspectos, la RPN tiene un objetivo y un ámbito idéntico al proceso de la ingeniería de la información. Lo ideal sería que la RPN se produjera de forma descendente, comenzando por la identificación de los objetivos principales del negocio, y culminando con una especificación mucho más detallada de las tareas que definen un proceso específico de negocios. Hammer sugiere una serie de principios que nos guiarán por las actividades de la RPN cuando se comienza en el nivel superior (de negocios):

Organización en torno a los resultados, no en torno a las tareas. Hay muchas compañías que poseen actividades de negocio compartimentadas, de tal modo que no existe una Única persona (u organización) que tenga la responsabilidad (o el control) de un cierto resultado de negocio. En tales casos, resulta difícil determinar el estado del trabajo e incluso más difícil depurar los problemas de proceso cuando esto sucede. La RPN deberá diseñar procesos que eviten este problema.

Hay que hacer que quienes utilicen la salida del proceso lleven a cabo el proceso. El objetivo de esta recomendación es permitir que quienes necesiten las salidas del negocio controlen todas las variables que les permitan obtener esa salida de forma temporalmente adecuada. Cuanto menor sea el número de personas distintas implicadas en el proceso, más fácil será el camino hacia un resultado rápido.

Hay que incorporar el trabajo de procesamiento de información
al trabajo real que produce la información pura. A medida que la TI se distribuye, es posible localizar la mayor parte del procesamiento de información en el seno de la organización que produce los datos. Esto localiza el control, reduce el tiempo de comunicación y la potencia de computación se pone en manos de quienes tienen fuertes intereses en la información producida.

Hay que manipular recursos geográficamente dispersos como si estuviesen centralizados. Las comunicaciones basadas en computadoras se han sofisticado tanto que es posible situar grupos geográficamente dispersos en una misma «oficina virtual». Por ejemplo, en lugar de emplear tres turnos de ingeniería en una única localización, toda la compañía podrá tener un turno en Europa, un segundo turno en Norteamérica y un tercer turno en Asia. En todos los casos, los ingenieros trabajarán durante el día y se comunicarán empleando redes de un elevado ancho de banda.

Hay que enlazar las actividades paralelas en lugar de integrar sus resultados. Cuando se utilizan diferentes grupos de empleados para realizar tareas en paralelo, es esencial diseñar un proceso que exija una continuación en la comunicación y coordinación. En caso contrario, es seguro que se producirán problemas de integración.



Hay que poner e1 punto de decisión en el lugar donde se efectúa el trabajo, e incorporar el control al proceso. Dentro de la jerga del diseño del software, esto sugiere una estructura organizativa más uniforme y con menos factorización

Hay que capturar los datos una sola vez, en el lugar donde se producen. Los datos se deberán almacenar en computadoras, de tal modo que una vez recopilados no sea necesario volver a introducirlos nunca.

Todos y cada uno de los principios anteriores representan una visión dotalmente general» de la RPN. Una vez informados por estos principios, los planificadores de negocios y los diseñadores de procesos deberán empezar a procesar el nuevo diseño. En la sección siguiente, se examinará el proceso de RPN más detalladamente.


Un modelo RPN

Al igual que la mayoría de las actividades de ingeniería, la reingeniería de procesos de negocio es iterativa. Los objetivos de negocio, y los procesos que los logran, deberán adaptarse a un entorno de negocio cambiante. Por esta razón, no existe ni principio ni fin en la RPN -se trata de un proceso evolutivo. En la Figura 30.1 se representa un modelo de reingeniería de procesos de negocio. Este modelo define seis actividades:

Definición del negocio. Los objetivos de negocios se identifican en un contexto de cuatro controladores principales: reducción de costes, reducción de tiempos, mejora de calidad y desarrollo y potenciación del personal. Los objetivos se pueden definir en el nivel de negocios o para un componente específico del negocio.

Identificación de procesos. En esta actividad se identifican los procesos críticos para alcanzar los objetivos definidos en la definición del negocio, A continuación, pueden recibir prioridades en función de su importancia, necesidad de cambio, o cualquier otra forma que resulte adecuada para la actividad de reingeniería.






Evaluación de procesos. Los procesos existentes deberán analizarse y medirse exhaustivamente. Las tareas de procesos se identificarán; los costes y los tiempos consumidos por las tareas de proceso se anotarán cuidadosamente, y se aislarán los problemas de calidad y rendimiento.

Especificación y diseño de procesos. Basándose en la información obtenida durante las tres primeras actividades de la RPN, se prepararán casos prácticos para cada uno de los procesos que se tengan que rediseñar. Dentro del contexto de la RPN, los casos prácticos identifican un escenario que proporciona resultados a un cliente. Con el uso de casos prácticos como especificación del proceso, se diseña un nuevo conjunto de tareas para el proceso.

Creación de prototipos. Es preciso construir un prototipo del proceso de negocios rediseñado antes de integrarlo por completo en el negocio. Esta actividad «comprueba» el proceso para que sea posible efectuar refinamientos.

Refinamiento e instanciación. Basándose en la realimentación procedente del prototipo, se refina el proceso de negocio y después se instancia en el seno de un sistema de negocio.

En algunas ocasiones las actividades de RPN descritas anteriormente se utilizan junto con herramientas de análisis del flujo de trabajo. El objetivo de estas herramientas es construir un modelo del flujo de trabajo existente, en un esfuerzo por analizar mejor los procesos existentes. Además, para implementar las cuatro primeras actividades descritas en el modelo de procesos se pueden utilizar las técnicas de modelado que se asocian normalmente a las actividades de ingeniería de la información tales como la planificación de estrategias de información y el análisis de áreas de negocios.


Advertencias

Es muy frecuente que se exagere la importancia de un nuevo enfoque de negocio en este caso, la RPN como si fuese la panacea, para después criticarla con tanta severidad que pase a ser un desecho. A lo largo de los Últimos años, se ha debatido de forma exagerada acerca de la eficacia de la RPN (por ejemplo: [BLE93]y [DIC95]). En un resumen excelente del caso a favor y en contra de la RPN, Weisz (WEI95) expone su argumento de la manera siguiente:

Resulta tentador atacar a la RPN como si se tratase de otra reencarnación de la famosa bala de plata. Desde varios puntos de vista -pensamiento de sistemas, tratamiento de personal, simple historia- habría que predecir unos índices de fallos elevados para el concepto, índices que parecen ser confirmados por la evidencia empírica. Para muchas compañías parece que la bala de plata no da en el blanco. Para otras, sin embargo, el nuevo esfuerzo de la reingeniería ha tenido evidentemente su fruto...

La RPN puede funcionar, si es aplicada por personas motivadas y formadas, que reconozcan que el proceso de reingeniería es una actividad continua. Si la RPN se lleva a cabo de forma efectiva, los sistemas de información se integran mejor con los procesos de negocios. Dentro del contexto de una estrategia más amplia de negocios se puede examinar la reingeniería de aplicaciones más antiguas, y también se pueden establecer de forma inteligente las prioridades de reingeniería del software. Aunque la reingeniería de negocio sea una estrategia rechazada por una compañía, la reingeniería del software es algo que debe hacerse. Existen decenas de millares de sistemas heredados -aplicaciones cruciales para el éxito de negocios grandes y pequeños- que se ven afectados por una enorme necesidad de ser reconstruidos o rehechos en su totalidad.


  1. Reingeniería del software

Este escenario resulta sumamente conocido: Una aplicación ha dado servicio y ha cubierto las necesidades del negocio de una compañía durante diez o quince años. A lo largo de este tiempo, ha sido corregida, adaptada y mejorada muchas veces. Las personas se dedicaban a esta tarea con la mejor de sus intenciones, pero las prácticas de ingeniería del software buenas siempre se echaban a un lado (por la urgencia de otros problemas). Ahora la aplicación se ha vuelto inestable. Sigue funcionando, pero cada vez que intenta efectuar un cambio se producen efectos colaterales graves e inesperados. ¿Qué se puede hacer? La imposibilidad de mantener el software no es un problema nuevo. De hecho, el gran interés por la reingeniería del software ha sido generado por un «iceberg» de mantenimiento de software que lleva creciendo desde hace más de treinta años.




Mantenimiento del software

Hace casi treinta años, el mantenimiento del software se caracterizaba por ser como un «iceberg». Esperábamos que lo que era inmediatamente visible fuera de verdad lo que había, pero sabíamos que una enorme masa de posibles problemas y costes yacía por debajo de la superficie. A principios de los años 70, el iceberg de mantenimiento era lo suficientemente grande como para hundir un portaaviones. En la actualidad podría hundir toda la Armada.

El mantenimiento del software existente puede dar cuenta de más del 60 por 100 de las inversiones efectuadas por una organización de desarrollo, y ese porcentaje sigue ascendiendo a medida que se produce más software [HAN93]. Los lectores que tengan menos conocimientos en estos temas podrían preguntarse por qué se necesita tanto mantenimiento, y por qué se invierte tanto esfuerzo. Osborne y Chifosky ofrecen una respuesta parcial:

Gran parte del software del que dependemos en la actualidad tiene por término medio entre diez y quince años de antigüedad. Aun cuando estos programas se crearon empleando las mejores técnicas de diseño y codificación conocidas en su época (y la mayoría no lo fueron), se crearon cuando el tamaño de los programas y el espacio de almacenamiento eran las preocupaciones principales. A continuación, se trasladaron a las nuevas plataformas, se ajustaron para adecuarlos a cambios de máquina y de sistemas operativos y se mejoraron para satisfacer nuevas necesidades del usuario; y todo esto se hizo sin tener en cuenta la arquitectura global.

El resultado son unas estructuras muy mal diseñadas, una mala codificación, una lógica inadecuada, y una escasa documentación de los sistemas de software que ahora nos piden que mantengamos en marcha...

La naturaleza ubicua del cambio subyace en todos los tipos de trabajo del software. El cambio es algo inevitable cuando se construyen sistemas basados en computadoras; por tanto debemos desarrollar mecanismos para evaluar, controlar y realizar modificaciones.


Al leer los párrafos anteriores, un lector podría argumentar: <<. . .pero yo no invierto el 60 por 1 00 de mi tiempo corrigiendo errores de los programas que desarrollo>>. Por supuesto, el mantenimiento del software es algo que va mucho más allá de <<corregir errores>>E. l mantenimiento se puede definir describiendo las cuatro actividades que se emprenden cuando se publica un programa para su utilización. Tan sólo el 20 por 100 de nuestros esfuerzos de mantenimiento se invertirán «corregir errores». El 80 por 100 se dedicará a adaptar los sistemas existentes a los cambios de su entorno externo, a efectuar las mejoras solicitadas por los usuarios y a rehacer la ingeniería de las aplicaciones para su posterior utilización. Cuando se considera que el mantenimiento abarca todas estas actividades, es fácil ver por qué absorbe tanto esfuerzo.


Un modelo de proceso de reingeniería del software

La reingeniería requiere tiempo; conlleva un coste de dinero enorme y absorbe recursos que de otro modo podrían emplearse en preocupaciones más inmediatas. Por todas estas razones, la reingeniería no se lleva a cabo en unos pocos meses, ni siquiera en unos pocos años. La reingeniería de sistemas de información es una actividad que absorberá recursos de las tecnologías de la información durante muchos años. Esta es la razón por la cual toda organización necesita una estrategia pragmática para la reingeniería del software.

Una estrategia de trabajo también acompaña al modelo de procesos de reingeniería. Más adelante, en esta misma sección, se describirá este modelo, pero veamos en primer lugar algunos de los principios básicos.

La reingeniería es una tarea de reconstrucción, y se podrá comprender mejor la reingeniería de sistemas de información si tomamos en consideración una actividad análoga: la reconstrucción de una casa. Consideremos la situación siguiente:

Suponga que ha adquirido una casa en otro lugar. Nunca ha llegado a ver la finca realmente, pero la consiguió por un precio sorprendentemente reducido, advirtiéndosele que quizá fuera preciso reconstruirla en su totalidad. ¿Cómo se las arreglaría?

  • Antes de empezar a construir, sería razonable inspeccionar la casa. Para determinar si necesita una reconstrucción, usted (o un inspector profesional) creará una lista de criterios para que la inspección sea sistemática.
  • Antes de derribar y de construir toda la casa, asegúrese de que la estructura está en mal estado. Si la casa tiene una buena estructura, quizá sea posible remodelarla sin reconstruirla (con un coste muy inferior y en mucho menos tiempo).
  • Antes de empezar a reconstruir, asegúrese de que entiende la forma en que se construyó el original. Eche una ojeada por detrás de las paredes. Comprenda el cableado, la fontanería y los detalles internos de la estructura. Aunque vaya a eliminarlos todos, la idea que haya adquirido de ellos le servirán de mucho cuando empiece a construirla.
  • Si empieza a reconstruir, utilice tan solo los materiales más modernos y de mayor duración. Quizá ahora le cuesten un poquito más, pero le ayudarán a evitar un mantenimiento costoso y lento en fecha posterior. Si ha decidido reconstruir, tenga una actitud disciplinada.
  • Utilice prácticas que den como resultado una gran calidad -tanto hoy como en el futuro-.

Aunque los principios anteriores se centran en la reconstrucción de una casa, son aplicables igualmente a la reingeniería de sistemas y aplicaciones basados en computadoras.

Para implementar estos principios, se aplica un modelo de proceso de reingeniería del software que define las seis actividades mostradas en la Figura 30.2. En algunas ocasiones, estas actividades se producen de forma secuencial y lineal, pero esto no siempre es así. Por ejemplo, puede ser que la ingeniería inversa (la comprensión del funcionamiento interno de un programa) tenga que producirse antes de que pueda comenzar la reestructuración de documentos.

 El paradigma de la reingeniería mostrado en la figura es un modelo cíclico. Esto significa que cada una de las actividades presentadas como parte del paradigma puede repetirse en otras ocasiones. Para un ciclo en particular, el proceso puede terminar después de cualquiera de estas actividades.

Análisis de inventario. Todas las organizaciones de software deberán disponer de un inventario de todas sus aplicaciones. El inventario puede que no sea más que una hoja de cálculo con la información que proporciona una descripción detallada (por ejemplo: tamaño, edad, importancia para el negocio) de todas las aplicaciones activas.

Los candidatos a la reingeniería aparecen cuando se ordena esta información en función de su importancia para el negocio, longevidad, mantenibilidad actual y otros criterios localmente importantes. Es entonces cuando es posible asignar recursos a las aplicaciones candidatas para el trabajo de reingeniería.

Es importante destacar que el inventario deberá revisarse con regularidad. El estado de las aplicaciones (por ejemplo, la importancia con respecto al negocio) puede cambiar en función del tiempo y, como resultado, cambiarán también las prioridades para la reingeniería.






Reestructuración de documentos. Una documentación escasa es la marca de muchos sistemas heredados. ¿Qué se puede hacer al respecto?

Opción 1: La creación de documentación consume muchísimo tiempo. El sistema funciona, y ya nos apañaremos con lo que tengamos. En algunos casos, éste es el enfoque correcto. No es posible volver a crear la documentación para cientos de programas de computadoras. Si un programa es relativamente estático está llegando al final de vida útil, y no es probable que experimente muchos cambios: ideémoslo así!

Opción 2: Es preciso actualizar la documentación, pero se dispone de recursos limitados. Se utilizará un enfoque «del tipo documentar si se modifica». Quizá no sea necesario volver a documentar por completo la aplicación. Más bien se documentarán por completo aquellas partes del sistema que estén experimentando cambios en ese momento. La colección de documentos Útil y relevante irá evolucionando con el tiempo.

Opción 3: El sistema es fundamental para el negocio, y es preciso volver a documentarlo por completo. En este caso, un enfoque inteligente consiste en reducir la documentación al mínimo necesario

Todas y cada una de estas opciones son viables. Las organizaciones del software deberán seleccionar aquella que resulte más adecuada para cada caso.

Ingeniería inversa. El término «ingeniería inversa» tiene sus orígenes en el mundo del hardware. Una cierta compañía desensambla un producto de hardware competitivo en un esfuerzo por comprender los «secretos» del diseño y fabricación de su competidor. Estos secretos se podrán comprender más fácilmente si se obtuvieran las especificaciones de diseño y fabricación del mismo. Pero estos documentos son privados, y no están disponibles para la compañía que efectúa la ingeniería inversa. En esencia, una ingeniería inversa con éxito precede de una o más especificaciones de diseño y fabricación para el producto, mediante el examen de ejemplos reales de ese producto.

La ingeniería inversa del software es algo bastante similar. Sin embargo, en la mayoría de los casos, el programa del cual hay que hacer una ingeniería inversa no es el de un rival, sino, más bien, el propio trabajo de la compañía (con frecuencia efectuado hace muchos años). Los «secretos» que hay que comprender resultan incomprensibles porque nunca se llegó a desarrollar una especificación. Consiguientemente, la ingeniería inversa del software es el proceso de análisis de un programa con el fin de crear una representación de programa con un nivel de abstracción más elevado que el código fuente. La ingeniería inversa es un proceso de recuperación de diseño. Con las herramientas de la ingeniería inversa se extraerá del programa existente información del diseño arquitectónico y de proceso, e información de los datos.

Reestructuración del código. El tipo más común de reingeniería (en realidad, la aplicación del término reingeniería sería discutible en este caso) es la reestructuración del código. Algunos sistemas heredados tienen una arquitectura de programa relativamente sólida, pero los módulos individuales han sido codificados de una forma que hace difícil comprenderlos, comprobarlos y mantenerlos. En estos casos, se puede reestructurar el código ubicado dentro de los módulos sospechosos. Para llevar a cabo esta actividad, se analiza el código fuente mediante una herramienta de reestructuración, se indican las violaciones de las estructuras de programación estructurada, y entonces se reestructura el código (esto se puede hacer automáticamente). El código reestructurado resultante se revisa y se comprueba para asegurar que no se hayan introducido anomalías. Se actualiza la documentación interna del código.

Reestructuración de datos. Un programa que posea una estructura de datos débil será difícil de adaptar y de mejorar. De hecho, para muchas aplicaciones, la arquitectura de datos tiene más que ver con la viabilidad a largo plazo del programa que el propio código fuente. A diferencia de la reestructuración de código, que se produce en un nivel relativamente bajo de abstracción, la estructuración de datos es una actividad de reingeniería a gran escala. En la mayoría de los casos, la reestructuración de datos comienza por una actividad de ingeniería inversa. La arquitectura de datos actual se analiza minuciosamente y se definen los modelos de datos necesarios. Se identifican los objetos de datos y atributos y, a continuación, se revisan las estructuras de datos a efectos de calidad.

Cuando la estructura de datos es débil (por ejemplo, actualmente se implementan archivos planos, cuando un enfoque relaciona1 simplificaría muchísimo el procesamiento), se aplica una reingeniería a los datos. Dado que la arquitectura de datos tiene una gran influencia sobre la arquitectura del programa, y también sobre los algoritmos que lo pueblan, los cambios en datos darán lugar invariablemente a cambios o bien de arquitectura o bien de código.

Ingeniería directa (forward engineering). En un mundo ideal, las aplicaciones se reconstruyen utilizando un «motor de reingeniería» automatizado. En el motor se insertaría el programa viejo, que lo analizaría, Reestructuraría y después regeneraría la forma de exhibir los mejores aspectos de la calidad del software. Después de un espacio de tiempo corto, es probable que llegue a aparecer este «motor», pero los fabricantes de CASE han presentado herramientas que proporcionan un subconjunto limitado de estas capacidades y que se enfrentan con dominios de aplicaciones específicos (por ejemplo, aplicaciones que han sido implementadas empleando un sistema de bases de datos específico). Lo que es más importante, estas herramientas de reingeniería cada vez son más sofisticadas.

La ingeniería directa, que se denomina también renovación o reclamación, no solamente recupera la información de diseño de un software ya existente, sino que, además, utiliza esta información para alterar o reconstruir el sistema existente en un esfuerzo por mejorar su calidad global. En la mayoría de los casos, el software procedente de una reingeniería vuelve a implementar la funcionalidad del sistema existente, y añade además nuevas funciones y/o mejora el rendimiento global.

  1. Ingeniería inversa

La ingeniería inversa invoca una imagen de «ranura mágica». Se inserta un listado de código no estructurado y no documentado por la ranura, y por el otro lado sale la documentación completa del programa de computadora. Lamentablemente, la ranura mágica no existe. La ingeniería inversa puede extraer información de diseño del código fuente, pero el nivel de abstracción, la completitud de la documentación, el grado con el cual trabajan al mismo tiempo las herramientas y el analista humano, y la direccionalidad del proceso son sumamente variables.

El nivel de abstracción de un proceso de ingeniería inversa y las herramientas que se utilizan para realizarlo aluden a la sofisticación de la información de diseño que se puede extraer del código fuente. El nivel de abstracción ideal deberá ser lo más alto posible. Esto es, el proceso de ingeniería inversa deberá ser capaz de derivar sus representaciones de diseño de procedimientos (con un bajo nivel de abstracción); y la información de las estructuras de datos y de programas (un nivel de abstracción ligeramente más elevado); modelos de flujo de datos y de control (un nivel de abstracción relativamente alto); y modelos de entidades y de relaciones (un elevado nivel de abstracción). A medida que crece el nivel de abstracción se proporciona al ingeniero del software información que le permitirá comprender más fácilmente estos programas.

La completitud de un proceso de ingeniería inversa alude al nivel de detalle que se proporciona en un determinado nivel de abstracción. En la mayoría de los casos, la completitud decrece a medida que aumenta el nivel de abstracción. Por ejemplo, dado un listado del código fuente, es relativamente sencillo desarrolla una representación de diseño de procedimientos completa. También se pueden derivar representaciones sencillas del flujo de datos, pero es mucho más difícil desarrollar un conjunto completo de diagramas de flujo de datos o un diagrama de transición de estados.

La completitud mejora en proporción directa a la cantidad de análisis efectuado por la persona que está efectuando la ingeniería inversa. La interactividad alude al grado con el cual el ser humano se «integra» con las herramientas automatizadas para crear un proceso de ingeniería inversa efectivo. En la mayoría de los casos, a medida que crece el nivel de abstracción, la interactividad deberá incrementarse, o sino la completitud se verá reducida.

Si la direccionalidad del proceso de ingeniería inversa es monodireccional, toda la información extraída del código fuente se proporcionará a la ingeniería del software que podrá entonces utilizarla durante la actividad de mantenimiento. Si la direccionabilidad es bidireccional, entonces la información se suministrará a una herramienta de reingeniería que intentará reestructurar o regenerar el viejo programa.







El proceso de la ingeniería se representa en la Figura 30.3. Antes de que puedan comenzar las actividades de ingeniería inversa, el código fuente no estructurado («sucio») se reestructura para que solamente contenga construcciones de programación estnicturada3. Esto hace que el código fuente sea más fácil de leer, y es lo que proporciona la base para todas las actividades subsiguientes de ingeniería inversa.

El núcleo de la ingeniería inversa es una actividad denominada extracción de abstracciones. El ingeniero tiene que evaluar el viejo programa y a partir del código fuente (que no suele estar documentado) tiene que extraer una especificación significativa del procesamiento que se realiza, la interfaz de usuario que se aplica, y las estructuras de datos de programa o de base de datos que se utiliza.


Ingeniería inversa para comprender el procesamiento

La primera actividad real de la ingeniería inversa comienza con un intento de comprender y extraer después abstracciones de procedimientos representadas por el código fuente. Para comprender las abstracciones de procedimientos, se analiza el código en distintos niveles de abstracción: sistema, programa, componente, configuración y sentencia.


La funcionalidad general de todo el sistema de aplicaciones deberá ser algo perfectamente comprendido antes de que tenga lugar un trabajo de ingeniería inversa más detallado. Esto es lo que establece un contexto para un análisis posterior, y se proporcionan ideas generales acerca de los problemas de interoperabilidad entre aplicaciones dentro del sistema. Cada uno de los programas de que consta el sistema de aplicaciones representará una abstracción funcional con un elevado nivel de detalle. También se creará un diagrama de bloques como representación de la iteración entre estas abstracciones funcionales. Cada uno de los componentes efectúa una subfunción, y representa una abstracción definida de procedimientos. En cada componente se crea una narrativa de procesamiento. En algunas situaciones ya existen especificaciones de sistema, programa y componente. Cuando ocurre tal cosa, se revisan las especificaciones para preciar si se ajustan al código existente.

Todo se complica cuando se considera el código que reside en el interior del componente. El ingeniero busca las secciones de código que representan las configuraciones genéricas de procedimientos. En casi todos los componentes, existe una sección de código que prepara los datos para su procesamiento (dentro del componente), una sección diferente de código que efectúa el procesamiento y otra sección de código que prepara los resultados del procesamiento para exportarlos de ese componente. En el interior de cada una de estas secciones, se encuentran configuraciones más pequeñas.

Por ejemplo, suele producirse una verificación de los datos y una comprobación de los límites dentro de la sección de código que prepara los datos para su procesamiento. Para los sistemas grandes, la ingeniería inversa suele efectuarse mediante el uso de un enfoque semiautomatizado. Las herramientas CASE se utilizan para «analizar» la semántica del código existente. La salida de este proceso se pasa entonces a unas herramientas de reestructuración y de ingeniería directa que completarán el proceso de reingeniería.


Ingeniería inversa para comprender los datos


La ingeniería inversa de datos suele producirse a diferentes niveles de abstracción. En el nivel de programa, es frecuente que sea preciso realizar una ingeniería inversa de las estructuras de datos internas del programa, como parte del esfuerzo general de la reingeniería. En el nivel del sistema, es frecuente que se efectúe una reingeniería de las estructuras globales de datos (por ejemplo: archivos, bases de datos) para ajustarlas a los paradigmas nuevos de gestión de bases de datos (por ejemplo, la transferencia de archivos planos a unos sistemas de bases de datos relacionales u orientados a objetos). La ingeniería inversa de las estructuras de datos globales actuales establecen el escenario para la introducción de una nueva base de datos que abarque todo el sistema.



Estructuras de datos internas. Las técnicas de ingeniería inversa para datos de programa internos se centran en la definición de clases de objetos5. Esto se logra examinando el código del programa en un intento de agrupar variables de programa que estén relacionadas. En muchos casos, la organización de datos en el seno del código identifica los tipos abstractos de datos. Por ejemplo, las estructuras de registros, los archivos, las listas y otras estructuras de datos que suelen proporcionar una indicación inicial de las clases. Para la ingeniería inversa de clases, Breuer y Lano sugieren el enfoque siguiente:

  • Identificación de los indicadores y estructuras de datos locales dentro del programa que registran información importante acerca de las estructuras de datos globales (por ejemplo, archivos o bases de datos).
  • Definición de la relación entre indicadores y estructuras de datos locales y las estructuras de datos globales. Por ejemplo, se podrá activar un indicador cuando un archivo esté vacío; una estructura de datos local podrá servir como memoria intermedia de los cien últimos registros recogidos para una base de datos central.
  • Para toda variable (dentro de un programa) que represente una matriz o archivo, la construcción de un listado de todas las variables que tengan una relación lógica con ella.

Estos pasos hacen posible que el ingeniero del software identifique las clases del programa que interactúan con las estructuras de datos globales.

Estructuras de bases de datos. Independientemente de su organización lógica y de su estructura física, las bases de datos permiten definir objetos de datos, y apoyan los métodos de establecer relaciones entre objetos. Por tanto, la reingeniería de un esquema de bases de datos para formar otro exige comprender los objetos ya existentes y sus relaciones.

Para definir el modelo de datos existente como precursor para una reingeniería que producirá un nuevo modelo de base de datos se pueden emplear los pasos siguientes:

Construcción de un modelo de objetos inicial. Las claves definidas como parte del modelo se podrán conseguir mediante la revisión de registros de una base de datos de archivos planos o de tablas de un esquema relacional. Los elementos de esos registros o tablas pasarán a ser atributos de una clase.

Determinación de los candidatos a claves. Los atributos se examinan para determinar si se van a utilizar o no para señalar a otro registro o tabla. Aquellos que sirvan como punteros pasarán a ser candidatos a claves.

Refinamiento de las clases provisionales. Se determina si ciertas clases similares pueden o no combinarse dentro de una Única clase.

Definición de las generalizaciones. Para determinar si se debe o no construir una jerarquía de clases con una clase de generalización como precursor de todos sus descendentes se examinan las clases que pueden tener muchos atributos similares.
Descubrimiento de las asociaciones. Mediante el uso de técnicas análogas al enfoque de CRC se establecen las asociaciones entre clases.

Una vez que se conoce la información definida en los pasos anteriores, se pueden aplicar una serie de transformaciones para hacer corresponder la estructura de la vieja base de datos con una nueva estructura de base de datos.

Ingeniería inversa de interfaces de uso

Las IGUs sofisticadas se van volviendo de rigor para los productos basados en computadoras y para los sistemas de todo tipo. Por tanto el nuevo desarrollo de interfaces de usuario ha pasado a ser uno de los tipos más comunes de las actividades de reingeniería. Ahora bien, antes de que se pueda reconstruir una interfaz de usuario, deberá tener lugar una actividad de ingeniería inversa.

Para comprender totalmente una interfaz de usuario ya existente (IU), es preciso especificar la estructura y comportamiento de la interfaz. Merlo y sus colaboradores sugieren tres preguntas básicas a las cuales hay que responder cuando comienza la ingeniería inversa de la IU:

¿Cuáles son las acciones básicas que deberá procesar la interfaz, por ejemplo, acciones de teclado y clics de ratón?
¿Cuál es la descripción compacta de la respuesta de comportamiento del sistema a estas acciones?
¿Qué queremos decir con «sustitución», o más exactamente, qué concepto de equivalencia de interfaces es relevante en este caso?

La notación de modelado de comportamiento puede proporcionar una forma de desarrollar las respuestas de las dos primeras preguntas indicadas anteriormente. Gran parte de la información necesaria para crear un modelo de comportamiento se puede obtener mediante la observación de la manifestación externa de la interfaz existente. Ahora bien, es preciso extraer del código la información adicional necesaria para crear el modelo de comportamiento.

Es importante indicar que una IGU de sustitución puede que no refleje la interfaz antigua de forma exacta (de hecho, puede ser totalmente diferente). Con frecuencia, merece la pena desarrollar metáforas de interacción nuevas. Por ejemplo, una solicitud de IU antigua en la que un usuario proporcione un superior (del 1 a 10) para encoger o agrandar una imagen gráfica. Es posible que una IGU diseñada utilice una barra de imágenes y un ratón para realizar la misma función.








  1. Reestructuración

La reestructuración del software modifica el código fuente y/o los datos en un intento de adecuar10 a futuros cambios. En general, la reestructuración no modifica la arquitectura global del programa. Tiende a centrarse en los detalles de diseño de módulos individuales y en estructuras de datos locales definidas dentro de los módulos. Si el esfuerzo de la reestructuración se extiende más allá de los límites de los módulos y abarca la arquitectura del software, la reestructuración pasa a ser ingeniería directa.

Arnold define un cierto número de beneficios que se pueden lograr cuando se reestructura el software:

  • Programas de mayor calidad con mejor documentación y menos complejidad, y ajustados a las prácticas y estándares de la ingeniería del software moderna.
  • Reduce la frustración entre ingenieros del software que deban trabajar con el programa, mejorando por tanto la productividad y haciendo más sencillo el aprendizaje.
  • Reduce el esfuerzo requerido para llevar a cabo las actividades de mantenimiento.
  • Hace que el software sea más sencillo de comprobar y de depurar.

La reestructuración se produce cuando la arquitectura básica de la aplicación es sólida, aun cuando sus interioridades técnicas necesiten un retoque. Comienza cuando existen partes considerables del software que son Útiles todavía, y solamente existe un subconjunto de todos los módulos y datos que requieren una extensa modificación.


Reestructuración del código

La reestructuración del código se lleva a cabo para conseguir un diseño que produzca la misma función pero con mayor calidad que el programa original. En general, las técnicas de reestructuración del código (por ejemplo, las técnicas de simplificación lógica de Warnier) modelan la lógica del programa empleando álgebra Booleana, y a continuación aplican una serie de reglas de transformación que dan lugar a una lógica reestructurada. El objetivo es tomar el código de forma de «plato de espaguetis» y derivar un diseño de procedimientos que se ajuste a la filosofía de la programación estructurada.

Se han propuesto también otras técnicas de reestructuración que puedan utilizarse con herramientas de reingeniería. Por ejemplo, Chot y Acacchi sugieren la creación de un diagrama de intercambio de recursos que diseña cada uno de los módulos de programa y los recursos (tipos de datos, procedimientos y variables) que se intercambian en este y otros módulos. Mediante la creación de representaciones del flujo de recursos, la arquitectura del programa se puede reestructurar para lograr el acoplamiento mínimo entre los módulos.

Reestructuración de los datos

Antes de que pueda comenzar la reestructuración de datos, es preciso llevar a cabo una ingeniería inversa, llamada análisis del código fuente. En primer lugar se evaluarán todas las sentencias del lenguaje de programación con definiciones de datos, descripciones de archivos, de E/S, y descripciones de interfaz. El objetivo es extraer elementos y objetos de datos, para obtener información acerca del flujo de datos, así como comprender las estructuras de datos ya existentes que se hayan implementado. Esta actividad a veces se denomina análisis de datos.

Una vez finalizado el análisis de datos, comienza el rediseño de datos. En su forma más sencilla se emplea un paso de estandarización de rediseño de datos que clarifica las definiciones de datos para lograr una consistencia entre nombres de objetos de datos, o entre formatos de registros físicos en el seno de la estructura de datos o formato de archivos existentes.

Otra forma de rediseño, denominada racionalización de nombres de datos, garantiza que todas las convenciones de denominación de datos se ajusten a los estándares locales, y que se eliminen las irregularidades a medida que los datos fluyen por el sistema.

Cuando la reestructuración sobrepasa la estandarización y la racionalización, se efectúan modificaciones físicas en las estructuras de datos ya existentes con objeto de hacer que el diseño de datos sea más efectivo. Esto puede significar una conversión de un formato de archivo a otro, o, en algunos casos, una conversión de un tipo de base de datos a otra.


  1. Ingeniería directa (forward engineering)

Un programa que posea flujo de control es el equivalente gráfico de un plato de espaguetis con «módulos», es decir con 2.000 sentencias de longitud; con pocas líneas de comentarios útiles en 290.000 sentencias de código fuente, y sin ninguna otra documentación que se deba modificar para ajustarle a los requisitos de cambios del usuario. Se puede decir que disponemos de las opciones siguientes:

    • La posibilidad de esforzarse por efectuar una modificación tras otra, luchando con el diseño implícito y con el código fuente para implementar los cambios necesarios.
    • La posibilidad de intentar comprender el funcionamiento interno más amplio del programa en un esfuerzo por hacer que las modificaciones sean más efectivas.
    • La posibilidad de rediseñar, recodificar y comprobar aquellas partes del software que requieran modificaciones, aplicando un enfoque de ingeniería del software a todos los segmentos revisados.
    • La posibilidad de rediseñar, recodificar y comprobar el programa en su totalidad, utilizando herramientas CASE (herramientas de reingeniería) que servirán para comprender el diseño actual.

No existe una Única opción «correcta». Las circunstancias pueden imponer la primera opción, aun cuando las otras sean las preferidas.

En lugar de esperar a que se reciba una solicitud de mantenimiento, la organización de desarrollo o de soporte utilizará los resultados del análisis de inventario para seleccionar el programa (1) que continúe utilizándose durante un número determinado de años, (2) que se esté utilizando con éxito en la actualidad, y (3) que tenga probabilidades de sufrir grandes modificaciones o mejoras en un futuro próximo.

Entonces, se aplicarán las opciones 2, 3 ó 4 anteriores. Este enfoque de mantenimiento preventivo fue introducido por Miller [MIL811 con el nombre de «reajuste estructurado». Definía este concepto como «la aplicación de las metodologías de hoy a los sistemas de ayer para prestar apoyo a los requisitos del mañana».

A primera vista, la sugerencia de volver a desarrollar un gran programa cuando ya existe una versión operativa puede parecer más bien extravagante. Sin embargo, antes de pasar a emitir un juicio, considérense los puntos siguientes:

  • El coste de mantener una línea de código fuente puede estar entre veinte y cuarenta veces por encima del coste del desarrollo inicial de esa línea.
  • El rediseño de la arquitectura del software (del programa y/o de las estructuras de datos) empleando conceptos de diseño modernos puede facilitar mucho el mantenimiento futuro.
  • Dado que ya existe un prototipo del software, la productividad de desarrollo deberá ser mucho más elevada que la media.
  • En la actualidad, el usuario ya tiene experiencia con el software. Por tanto, los nuevos requisitos y la dirección del cambio se podrán estimarse con mucha más facilidad.
  • Las herramientas CASE para la reingeniería automatizarán algunas partes del trabajo.
  • Cuando finalice el mantenimiento preventivo, se dispondrá de una configuración completa del software (documentos, programas y datos).

Cuando una organización de desarrollo de software vende el software como un producto, el mantenimiento preventivo se ve como «nuevas versiones» del programa. Un gran desarrollador de software local (por ejemplo, un grupo de desarrollo de software de sistemas para una compañía de productos de un consumidor de gran volumen) puede tener entre 500 y 2.000 programas de producción dentro de su dominio de responsabilidad. Se podrán asignar prioridades a estos programas según su importancia, y a continuación se revisarán esos programas como los candidatos para el mantenimiento preventivo.

El proceso de ingeniería del software aplica principios, conceptos y métodos de ingeniería del software para volver a crear las aplicaciones existentes. En la mayoría de los casos, la ingeniería directa no se limita a crear un equivalente moderno de un programa anterior, sino que más bien se integran los nuevos requisitos y las nuevas tecnologías en ese esfuerzo de volver a aplicar reingeniería. El programa que se ha vuelto a desarrollar amplía las capacidades de la aplicación anterior.


Ingeniería directa para arquitecturas cliente/servidor

A lo largo de la última década, muchas aplicaciones de grandes computadoras han sufrido un proceso de reingeniería para adaptarlas a arquitecturas cliente-servidor (C/S). En esencia, los recursos de computación centralizados (incluyendo el software) se distribuyen entre muchas plataformas cliente. Aunque se puede diseñar toda una gama de entornos distribuidos distintos, la aplicación típica de computadora central que sufre un proceso de reingeniería para adoptar una arquitectura cliente/servidor posee las características siguientes:

  • La funcionalidad de la aplicación migra hacia todas las computadoras cliente.
  • Se implementan nuevas interfaces IGU en los centros clientes.
  • Las funciones de bases de datos se le asignan al servidor.
  • La funcionalidad especializada (por ejemplo, los análisis de computación intensiva) pueden permanecer en el centro del servidor.
  • Los nuevos requisitos de comunicaciones, seguridad, archivado y control deberán establecerse tanto en el centro cliente, como en el centro servidor.


Es importante tener en cuenta que la migración desde computadoras centrales a un proceso C/S requiere tanto una reingeniería del negocio como una reingeniería del software. Además, es preciso establecer una «infraestructura de red de empresa».

La reingeniería de aplicaciones C/S comienza con un análisis exhaustivo del entorno de negocios que abarca la computadora central existente. Se pueden identificar tres capas de abstracción- (Fig. 30.4). La base de datos se encuentra en los cimientos de la arquitectura cliente/servidor, y gestiona las transacciones y consultas que proceden de las aplicaciones de servidor. Sin embargo, estas transacciones y consultas tienen que ser controladas en el contexto de un conjunto de reglas de negocio (definidas por un proceso de negocio ya existente o que ha experimentado una reingeniería). Las aplicaciones de cliente proporcionan la funcionalidad deseada para la comunidad de usuarios. Las funciones del sistema de gestión de bases de datos ya existente y la arquitectura de datos de la base de datos existente deberán sufrir un proceso de ingeniería inversa como precedente para el rediseño de la capa de fundamento de la base de datos. En algunos casos, se crea un nuevo modelo de datos.
En todos los casos, la base de datos C/S sufre un proceso de reingeniería para asegurar que las transacciones se ejecutan consistentemente; para asegurar que todas las actualizaciones se efectúen únicamente por usuarios autorizados; para asegurar que se impongan las reglas de negocios fundamentales (por ejemplo, antes de borrar el registro de un proveedor, el servidor se asegura de que no exista ningún registro pendiente, contrato o comunicación para ese proveedor); para asegurar que se puedan admitir las consultas de forma eficaz; y para asegurar que se ha establecido una capacidad completa de archivado.







La capa de reglas de negocios representa el software residente tanto en el cliente como en el servidor. Este software lleva a cabo las tareas de control y coordinación para asegurar que las transacciones y consultas entre la aplicación cliente y la base de datos se ajusten a los procesos de negocios establecidos.

La capa de aplicación del cliente implementa las funciones de negocios requeridas por grupos específicos de usuarios finales. En muchos casos, se segmenta una aplicación de computadora central en un cierto número de aplicaciones más pequeñas, sometidas a reingeniería, y adecuadas para su funcionamiento de sobremesa. La comunicación entre aplicaciones de sobremesa (cuando es necesaria) será controlada por la capa de reglas de negocios.



Ingeniería directa para arquitecturas orientada a objetos

La ingeniería del software orientada a objetos se ha transformado en el paradigma opcional de desarrollo para muchas organizaciones de software. Sin embargo, ¿qué sucede con las aplicaciones existentes que se desarrollaron empleando métodos convencionales? En algunos casos, la respuesta consiste en dejar estas aplicaciones tal y como eran. Pero en otros casos, es preciso aplicar una reingeniería a las viejas aplicaciones para que se puedan integrar fácilmente en grandes sistemas orientados a objetos.

La reingeniería del software convencional para producir una implementación orientada a objetos hace uso de muchas de las mismas técnicas descritas en la Cuarta Parte de este libro. En primer lugar, se hace una ingeniería inversa del software existente para que sea posible crear los modelos adecuados de datos, funcional y de comportamiento. Si el sistema que se aplica a la reingeniería extiende la funcionalidad o comportamiento de la aplicación original, se crean casos prácticos. Los modelos de datos creados durante la ingeniería inversa se utilizan entonces junto con un modelado CRC para establecer la base para la definición de clases. Las jerarquías de clases, los modelos de relaciones entre objetos, los modelos de comportamiento de objetos, y los subsistemas se definen a continuación, y comienza el diseño orientado a objetos.

A medida que la ingeniería directa orientada a objetos pasa del análisis hasta el diseño, se podrá invocar el modelo de proceso de ISBC. Si la aplicación existente se encuentra con un dominio ya ha sido popularizada por muchas aplicaciones orientadas a objetos, es probable que exista una biblioteca robusta de componentes y que se pueda utilizar durante la ingeniería directa. Para aquellas clases que sean preciso construir partiendo de cero, quizá sea posible reutilizar algoritmos y estructuras de datos procedentes de la aplicación convencional ya existente. Sin embargo, es preciso volver a diseñarlos para ajustarse a la arquitectura orientada a objetos.


Ingeniería directa para interfaces de usuario

Cuando las aplicaciones migran desde la computadora central a la computadora de sobremesa, los usuarios ya no están dispuestos a admitir unas interfaces de usuarios arcanas basadas en caracteres. De hecho, una parte significativa de todos los esfuerzos invertidos en la transición desde la computación de computadora central hasta la arquitectura cliente/servidor se pueden reinvertir en la reingeniería de las interfaces de usuario de la aplicación cliente.

Merlo y colaboradores sugieren el modelo de usuario? siguiente para la reingeniería de interfaces de usuario:

Comprender la interfaz original y los datos que se trasladan entre ella y el resto de la aplicación. El objetivo es comprender la forma en que los demás elementos del programa interactúan con el código existente que implementa la interfaz. Si se ha de desarrollar una nueva IGU, entonces el flujo de datos entre la IGU y el resto del programa deberá ser consecuente con los datos que en la actualidad fluyen entre la interfaz basada en caracteres y el programa.

Remodelar el comportamiento implícito en interfaz existente para formar una serie de abstracciones que tengan sentido en el contexto de una IGU. Aunque el modelo de interacción pueda ser radicalmente distinto, el comportamiento de negocios mostrado por los usuarios de la interfaz nueva y vieja (cuando se consideran en función del escenario de utilización) deberán seguir siendo los mismos. La interfaz diseñada deberá seguir permitiendo que el usuario muestre el comportamiento de negocios adecuado. Por ejemplo, cuando se efectúa una consulta en una base de datos, es posible que, para especificar la consulta, la interfaz vieja necesite una serie larga de órdenes basadas en textos. La IGU sometida a reingeniería puede hacer que la consulta sea más eficiente, reduciéndola a una pequeña secuencia de selecciones con el ratón, pero la intención y el contenido de la consulta deberán permanecer intactos.

Introducir mejoras que hagan que el modo de interacción sea más eficiente. Los fallos ergonómicos de la interfaz existente se estudian y se corrigen en el diseño de la IGU nueva.

Construir e integrar la IGU nueva. La existencia de bibliotecas de clases y de herramientas de cuarta generación puede reducir el esfuerzo requerido para construir la IGU de forma significativa. Sin embargo, la integración con el software de aplicación ya existente puede llevar más tiempo. Para asegurarse de que la IGU no propague unos efectos adversos al resto de la aplicación es preciso tener cuidado.


  1. La economía de la reingeniería

En un mundo perfecto, todo programa que no se pudiera mantener se retiraría inmediatamente, para ser sustituido por unas aplicaciones de alta calidad, fabricadas mediante reingeniería y desarrolladas empleando las prácticas de la ingeniería del software modernas. Sin embargo, vivimos en un mundo de recursos limitados. La reingeniería consume recursos que se pueden utilizar para otros propósitos de negocio. Consiguientemente, antes de que una organización intente efectuar una reingeniería de la aplicación existente, deberá llevar a cabo un análisis de costes y beneficios. Sneed ha propuesto un modelo de análisis de costes y beneficios para la reingeniería. Se definen nueve parámetros:

P1 = coste de mantenimiento anual actual para una aplicación;
P2 = coste de operación anual de una aplicación;
P3 = valor de negocios anual actual de una aplicación;
P4 = coste de mantenimiento anual predicho después de la reingeniería;
P5 =coste de operaciones anual predicho después de la reingeniería;
P6 =valor de negocio actual predicho después de la reingeniería;
P7 =costes de reingeniería estimados;
P8 =fecha estimada de reingeniería;
P9 = factor de riesgo de la reingeniería (P9 = 1,0 es el valor nominal);
L = vida esperada del sistema.

El coste asociado al mantenimiento continuado de una aplicación candidata (esto es, si no se realiza la reingeniería) se puede definir como:

Cmant = [P3 - (P1+P2)] X L (30.1)

Los costes asociados con la reingeniería se definen empleando la relación siguiente:

Creing= [P6- (P4+P5)] x (L P8) - (P7 x P9)] (30.2)

Empleando los costes presentados en las ecuaciones (30.1) y (30.2), los beneficios globales de la reingeniería se pueden calcular en la forma siguiente:

Beneficio y coste = Creing- Cmant (30.3)

El análisis de costes y beneficios presentados en las ecuaciones anteriores se puede llevar a cabo para todas aquellas aplicaciones de alta prioridad que se hayan identificado durante un análisis de inventario. Aquellas aplicaciones que muestren el mayor beneficio en relación con los costes podrán destinarse a la reingeniería, mientras que las demás podrán ser propuestas hasta que se disponga de más recursos.



Bibliografía:

Pressman .S. Roger. Ingeniería de Software. Un enfoque practico. Editorial McGraw-Hill V Edición. Pág. 541-554














0 comentarios:

Publicar un comentario