El contexto en el que se ha desarrollado el software está
fuertemente ligado a la evolución de los sistemas informáticos. Un mejor
rendimiento del hardware, una reducción del tamaño y un costo más bajo, han
dado lugar a sistemas informáticos más sofisticados.
La evolución del software dentro del contexto de las áreas
de aplicación de los sistemas basados en computadoras, puede verse de la
siguiente manera :
Lo normal era que el hardware
fuera de propósito general. Por otra parte, el software se diseñaba a medida
para cada aplicación y tenía una distribución relativamente pequeña. La mayoría
del software se desarrollaba y era utilizado por la misma persona u
organización. La misma persona lo escribía, lo ejecutaba y, si fallaba, lo
depuraba.
Debido a este entorno
personalizado del software, el diseño era un proceso implícito,
realizado en la mente de alguien, y la documentación normalmente no existía.
La segunda era en la evolución de los sistemas de
computadoras se extiende desde la mitad de la década de los 60 hasta finales de
los setenta. La multiprogramación y los sistemas multiusuarios introdujeron
nuevos conceptos de interacción hombre máquina. Las técnicas interactivas
abrieron un nuevo mundo de aplicaciones y nuevos niveles de sofisticación del
hardware y del software. Los sistemas de tiempo real podían recoger, analizar y
transformar datos de múltiples fuentes, controlando así los procesos y
produciendo salidas en milisegundos en lugar de en minutos. Los avances en los
dispositivos de almacenamiento en línea condujeron a la primera generación de
sistemas de gestión de bases de datos.
Otra característica fue el
establecimiento del software como producto y la llegada de las “casas
de software”.
Conforme crecía el número de
sistemas, comenzaron a extenderse las bibliotecas de software de computadora.
Se desarrollaban proyectos en los que se producían programas de decenas de
miles de sentencias fuente. Todos esos programas (todas esas sentencias
fuentes) tenían que ser corregidos cuando se detectaban fallos, modificados
cuando cambiaban los requisitos de los usuarios o adaptados a nuevos
dispositivos que se hubieran incorporado. Estas actividades se llamaron mantenimiento
del software. El esfuerzo gastado en el mantenimiento comenzó a absorber recursos
en una medida alarmante. Había comenzado una “crisis del software”.
La tercera era en la evolución de los sistemas de
computadoras comenzó a mediado de los setenta y llega hasta el momento actual.
El procesamiento distribuido (múltiples computadoras, cada una ejecutando
funciones concurrentemente y comunicándose con alguna otra) incrementó
notablemente la complejidad de los sistemas informáticos. Las redes de área
local y de área global, las comunicaciones digitales de alto ancho de banda y
la creciente demanda de acceso “instantáneo” a los datos, pusieron una fuerte
presión sobre los desarrolladores del software.
En esta era se produce la llegada
de los microprocesadores y las computadoras personales.
Las computadoras personales han
sido el catalizador del gran crecimiento de muchas compañías de software. Estas
compañías venden decenas y centenares de copias de sus productos de software.
La cuarta era de la Evolución software de computadora
está comenzando ahora. Las tecnologías orientadas a objetos están comenzando a
ser utilizadas en muchas áreas de aplicación. Las técnicas de cuarta generación
para el desarrollo de software ya están cambiando la forma en que algunos
segmentos de la comunidad informática construyen los programas. Los sistemas
expertos y el software de inteligencia artificial se han trasladado del
laboratorio a las aplicaciones prácticas. El software de redes neuronales
artificiales ha abierto excitantes posibilidades para el reconocimiento de
formas y habilidades de procesamiento de información al estilo de como lo hacen
los humanos.
Conforme transitamos por la
cuarta era, continúan intensificándose los problemas asociados con el software
de computadoras :
La sofisticación del hardware ha dejado desfasada nuestra capacidad de
construir software que pueda explotar el potencial del hardware.
Nuestra capacidad de construir nuevos programas no puede dar abasto a la
demanda de nuevos programas.
Nuestra capacidad de mantener los programas existentes está amenazada
por el mal diseño y el uso de recursos inadecuados.
Los principios básicos de la
Ingeniería de Software
En los primeros días de la
informática, la programación se veía como un “arte”. Existían pocos métodos
formales, y pocas personas los usaban. El programador aprendía normalmente su
oficio mediante prueba y error.
Hoy, la distribución de costos en
el desarrollo de sistemas informáticos ha cambiado drásticamente. El software,
en lugar del hardware, es normalmente el elemento principal del costo.
Los problemas existentes en el
desarrollo de software no va a desaparecer rápidamente. Las soluciones que se
van elaborando tienden a asistir prácticamente al desarrollador de software, y
mejorar la calidad del software.
Mediante la combinación de métodos completos
para todas las fases de desarrollo de software, mejores herramientas para
automatizar estos métodos, bloques de construcción más potentes para
la implementación del software, mejores técnicas para la garantía de
calidad del software y una filosofía predominante para la
coordinación, control y gestión, puede conseguirse una disciplina para el
desarrollo del software : Ingeniería del software.
Una definición :
“El establecimiento y uso de
principios de ingeniería robustos, orientados a obtener software económico que
sea fiable y funcione de manera eficiente sobre máquinas reales.” (Fritz Bauer)
La ingeniería de software cubre
tres elementos claves :
Métodos
Herramientas, y
Procedimientos
que facilitan al gestor controlar
el proceso de desarrollo de software y suministrar las bases para construir
software de alta calidad de una forma productiva.
Los métodos indican
“cómo” construir técnicamente el software. Estos métodos abarcan tareas que
incluyen : planificación y estimación de proyectos, análisis de los
requisitos del sistema y del software, diseño de estructuras de datos,
arquitectura de programas y procedimientos algorítmicos, codificación, prueba y
mantenimiento.
Las herramientas suministran
un soporte automático o semiautomático para los métodos. Cuando se integran las
herramientas de forma que la información creada por una herramienta pueda ser
usada por otra, se establece un sistema de soporte llamada Ingeniería de
Software Asistida por Computadora (CASE).
Los procedimientos son
el pegamento que junta los métodos y las herramientas, y facilita un desarrollo
racional y oportuno. Definen la secuencia en la que se aplican los métodos, las
entregas (documentos, informes, formas, etc.) que se requieren, los controles
para asegurar la calidad y coordinar los cambios, y las directrices que ayudan
a los gestores de software a evaluar el progreso.
La complejidad de los problemas
No todos los sistemas de software
son complejos. En particular las aplicaciones que son especificadas,
construidas, mantenidas, y usadas por la misma persona, no pueden considerarse
problemas complejos. Estos sistemas tienden a tener propósitos limitados y un
ciclo de vida muy corto. Estas aplicaciones generalmente son más tediosas que
difícil de desarrollar, y en consecuencia aprender cómo se diseñan no es de
nuestro interés.
Las aplicaciones de mayor
envergadura (las que presentan comportamiento variado, mantienen la integridad
de cientos de transacciones de registro de información, control de tráfico,
etc.), son esencialmente complejas.
Esta complejidad es, en general,
imposible de ser comprendida en su totalidad por una sola persona. Por esto se
deben considerar formas disciplinadas para manejar la complejidad.
“La complejidad del software es
una propiedad esencial, no una cuestión accidental” (Brooks). En general la
complejidad deriva de
cuatro elementos :
La complejidad del dominio del
problema,
La dificultad para administrar el
proceso de desarrollo,
La posible flexibilidad del
software, y
Los problemas de caracterizar el
comportamiento de sistemas discretos.
La complejidad del dominio del
problema
Los problemas que se intenta
resolver en software frecuentemente involucran elementos de complejidad, tales
como requerimientos que compiten entre sí, o contradictorios. A la complejidad
propia del problema hay que agregarle las que surgen de requerimientos no
funcionales, tales como usabilidad, performance, costo, continuidad en el
tiempo, y confiabilidad.
Otro aspecto de la complejidad
surge por el problema de comunicación entre los usuarios y los
desarrolladores : los usuarios generalmente encuentran muy difícil dar en
forma precisa sus necesidades de manera que los desarrolladores puedan
entenderlas. En algunos casos extremos los usuarios pueden tener sólo una vaga
idea de lo que desean. Los usuarios y desarrolladores tienen diferentes
perspectivas de la naturaleza de la solución. En realidad, aún si los usuarios
tienen perfecto conocimiento de sus necesidades, los desarrolladores tienen
pocos instrumentos para capturar en forma precisa estos requerimientos. La
manera común de expresar los requerimientos es con texto, acompañados por
algunos diagramas. Estos documentos son difíciles de comprender, son abiertos a
interpretación variada, y frecuentemente contienen elementos que son de diseño
en vez de requerimientos esenciales.
Otra complicación adicional es
que los requerimientos de un sistema frecuentemente cambian durante su
desarrollo.
La dificultad de administrar el proceso de desarrollo
Hoy en día es habitual encontrar
sistemas cuyo tamaño se mide en cientos de miles, y aún millones, de líneas de
código. Ninguna persona puede entender tales sistemas en forma completa. Si
estos sistemas son descompuestos de alguna manera significativa, nos podemos
encontrar con cientos o miles de módulos separados. Esto hace que se utilicen
grupos de desarrollo, e idealmente tan pequeño como sea posible. Más
desarrolladores significa más complejidad de comunicación y de aquí más dificultad
de coordinación, y en particular si el grupo está geográficamente disperso. Con
un grupo de desarrollo, la clave del desafío de administración es siempre
mantener una unidad e integridad de diseño.
La posible flexibilidad del software
En la industria del software
existen muy pocos estándares para la construcción de código. Cada desarrollador
puede construir de manera diferente una solución para un mismo problema.
El desarrollo de software
continua como un negocio de labor intensiva.
Los problemas de caracterizar el
comportamiento de sistemas discretos
En aplicaciones grandes, puede
haber cientos y aún miles de variables así como también más de un hilo de
control. El conjunto completo de estas variables, sus valores actuales, las
direcciones actuales y las pilas de llamada de cada proceso dentro del sistema
constituyen el estado presente de la aplicación. El software es ejecutado sobre
computadoras digitales, y por lo tanto constituyen un sistema con estados
discretos. Los sistemas discretos tienen una cantidad finita de estados
posibles, en grandes sistemas estos tienen una explosión combinatoria haciendo
este número muy grande.
Los sistemas tienden a ser
diseñados con una separación de intereses, para que el comportamiento de una
parte del sistema tenga un impacto mínimo sobre el comportamiento de otra. Sin
embargo cada evento externo al sistema tiene el potencial de colocar a este en
un nuevo estado, y de esta manera el pasaje de estado a estado no es siempre
determinístico. En algunas circunstancias, un evento externo puede corromper el
estado de un sistema, porque sus diseñadores fallaron al tomar en cuenta
ciertas interacciones entre eventos. En sistemas discretos todos los eventos
externos pueden afectar cualquier parte del estado interno del sistema. Esta es
la motivación primaria para un testeo vigoroso del sistema, pero
excepto para sistemas triviales, el testeo exhaustivo es imposible. Debido a
que no se cuenta con herramientas matemáticas o la capacidad intelectual para
modelar el comportamiento completo de grandes sistemas, deben establecerse
niveles aceptables para asegurar su validez.
Los cinco atributos de un sistema Complejo
Hay cinco atributos comunes a
todo sistema complejo (Simon, Ando, y Courtois) :
“Frecuentemente, la complejidad toma la forma de una jerarquía, por lo
cual un sistema complejo está compuesto de subsistemas interrelacionados que
tienen a la vez sus propios subsistemas, hasta que algún nivel menor de
componentes elementales es alcanzado.”
La estructura jerárquica es un
factor importante que permite entender, describir, y ver un sistema y sus
partes.
“La elección de qué componentes en un sistema son primitivas es
relativamente arbitrario y depende del observador del sistema.”
“Las vinculaciones internas de las componentes son generalmente más
fuertes que las vinculaciones entre los componentes. Esto tiende a separar la
dinámica de alta frecuencia de las componentes - involucrando la estructura
interna de las componentes - de la dinámica de baja frecuencia - involucrando
la interacción entre las componentes.”
Esta diferencia entre interacción
interna y externa de las componentes proveen una clara diferenciación de
intereses entre las diferentes partes del sistema, haciendo posible estudiar
cada parte en forma aislada.
“Los sistemas jerárquicos están generalmente compuestos de solamente
pocas clases de subsistemas diferentes en varias combinaciones y órdenes.”
Los sistemas complejos tienen
patrones comunes. Estos patrones pueden requerir el reuso de pequeñas o grandes
componentes.
“Un sistema complejo que trabaja, invariablemente ha evolucionado de un
sistema simple que trabajaba... Un sistema complejo diseñado de la nada nunca
trabajará, y no puede ser `emparchado' para hacer que trabaje. Se debe empezar
nuevamente, comenzando con un sistema simple que trabaje.”
Diseño de software
La evolución del diseño de
software, como parte del proceso de desarrollo de software, es un proceso
continuo que se ha ido produciendo durante las últimas tres décadas. Los
primeros trabajos sobre diseño se centraron sobre los criterios para el
desarrollo de programas modulares y los métodos para mejorar la arquitectura
del software de una manera descendente. Los aspectos procedimentales de la
definición del diseño evolucionaron hacia una filosofía denominada programación
estructurada. Posteriores trabajos propusieron métodos para la traducción del
flujo de datos o de la estructura de los datos, en una definición de diseño.
Nuevos enfoques para el diseño proponen un métodoorientado a objetos para
la obtención del diseño.
Cada metodología de diseño de
software introduce heurísticas y notaciones propias, así como una visión algo
particular de lo que caracteriza a la calidad del diseño. Sin
embargo, todas las metodologías tienen varias características comunes :
Un mecanismo para la traducción de la representación del campo
de información en una representación de diseño ;
Una notación para representar los componentes funcionales y
sus interfaces ;
Heurísticas para el
refinamiento y la partición, y
Criterios para la valoración de la calidad.
Diseño puede definirse
como :
“Proceso iterativo de tomar un
modelo lógico de un sistema junto con un conjunto de objetivos fuertemente
establecidos para este sistema y producir las especificaciones de un sistema
físico que satisfaga estos objetivos.” (Gane - Sarson).
“Actividad por la cual un
relevamiento de datos y funciones de un sistema (modelo esencial) se traduce en
un plan de implementación. El modelo es volcado en una tecnología determinada”.
“...el proceso de aplicar
distintas técnicas y principios con el propósito de definir un dispositivo,
proceso o sistema con los suficientes detalles como para permitir su
realización física.” (E. Taylor)
Objetivos del Diseño
El objetivo más importante
es :
entregar las funciones requeridas
por el usuario (Satisfaga una especificación funcional dada).
Pero además para lograr esto
deben considerarse los aspectos de :
Rendimiento : cuán rápido permitirá el diseño realizar el trabajo
dado un recurso particular de hardware. Es decir que contemple las limitaciones
del medio donde será implementado el sistema, y alcance los requerimientos de
performance y uso de recursos.
Control : protección contra errores humanos, máquinas defectuosas,
o daños intencionales.
Cambiabilidad : facilidad con la cual el diseño permite
modificar el sistema.
Generalmente estos tres factores
trabajan unos contra otros : un sistema con muchos controles tenderá a
degradar su rendimiento, un sistema diseñado para un alto rendimiento solo
podrá ser cambiado con dificultad, etc..
Además deberá
Satisfacer criterios de diseño
sobre la forma interna y externa del producto obtenido.
Satisfacer restricciones sobre el
proceso de diseño en sí mismo, tales como su tiempo o costo, o las herramientas
disponibles para hacer el diseño.