Anda di halaman 1dari 14

Programación Modular. ETSIT. 1o C.

Apuntes del profesor Juan Falgueras.


Curso 2005
21 de febrero de 2005

1
Ingenierı́a del software

Contenido
1. Ingenierı́a del software 1
1.1. Desarrollo actual de proyectos de software . . . . . . . . . . . . . . . . . . . . . . . 2
1.2. Ciclo de vida del software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2.1. Modelos orientados hacia la especificación . . . . . . . . . . . . . . . . . . . 4
1.2.2. Modelos de desarrollo evolutivos . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2.3. Modelos iterativos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2.4. Transformaciones formales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2.5. Desarrollo aséptico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2.6. Aplicabilidad de cada modelo . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3. Fundamentos del diseño del software . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.1. Diseño por encapsulado y ocultamiento . . . . . . . . . . . . . . . . . . . . 11
1.3.2. Modularidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3.3. TADs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.3.4. POO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.3.5. Abstracción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3.6. Ocultación de información . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3.7. Independencia funcional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3.8. Cohesión . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3.9. Acoplamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4. Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

1. Ingenierı́a del software


Objetivos del tema:
Presentar al estudiante la problemática del desarrollo de las aplicaciones de software.
Conocer el lenguaje general usado y las principales técnicas que históricamente se han
ido cimentando especialmente respecto al desarrollo de grandes aplicaciones; ver muchos
de los mitos ya desaparecidos.
Convencer al estudiante de la importancia de la reusabilidad del código en el desarrollo
de software.
Dar al estudiante criterios de validación de los módulos constitutivos de los programas,
de sus caracterı́sticas y oportunidad.
Introducir a las técnicas modernas de modularización, y programación orientada a ob-
jetos.
Se trata éste de un tema más bien teórico en el que trataremos de comprender los grandes
problemas que envuelven el complejo mundo del desarrollo de las enormes aplicaciones que se
están imponiendo.
Con la presentación del Ciclo de Vida y las variantes históricas que se han desarrollado,
trataremos de entender la necesaria organización que debe existir tras los grupos más o menos
grandes de desarrollo. Ası́ se presentan los papeles más importantes a cubrir en la organización
1.1 Desarrollo actual de proyectos de software 2

análisis
especificación
diseño
implementación
mantenimiento

Figura 1: Ciclo de vida en cascada.

de grupos de trabajo para resolver la compleja e inmensa maquinaria de relojerı́a que es una
gran aplicación de software. Las correctas costumbres en programación. La poca duración de
las aplicaciones de software por su insuficiente flexibilidad para adaptarse a las continuamente
nuevas necesidades de los usuarios y el alto costo de su desarrollo nos deben hacer ver la gran
importancia de seguir buenas técnicas de gestión de software.

1.1. Desarrollo actual de proyectos de software


Para plantear la temática de la Ingenierı́a del Software es preciso entender:
¿qué son las especificaciones y de qué forma se pueden dar?, formales, algebraicas, por medio
de modelos, etc.;

por otro lado, ¿qué es el diseño?, caracterı́sticas (top-down, modularidad, diseño orientado
a objetos);
las técnicas de implementación concretas (portabilidad, control de excepciones, reutilizabi-
lidad), verificación (empı́rica y formal)
y, finalmente, en el Ciclo de Vida primitivo (ver Fig. 1), podemos ver la serie temporal inicial de
que sitúa esquemas generales de trabajo en cuanto a documentación, estilo, etcétera, dentro del
entorno de trabajo a seguir.
Una de las mejores referencias históricas al ciclo de vida del software es la de Yourdon (en
[You88], o [YC79]); los tiempos empleados en cada etapa y la misión de las herramientas CASE
se pueden ver en el clásico [Fis88].
Aunque no la única, una de las propiedades más importantes que garantizan una efi-
ciente construcción de software es la reusabilidad.
En términos generales se puede llegar a decir que la pérdidad de reusa-
bilidad en informática es su pérdida de valor.

Dentro de un ciclo de vida se enumeran y definen las caracterı́sticas que hacen a un software
de calidad (Fig. 2).
La modularidad inicialmente y sobre ella, a un nivel de abstracción más alto, la programa-
ción orientada a objetos, son hoy dı́a imprescindibles para cualquier proyecto de ingenierı́a. Para
entender esto, tenemos que entender cómo la programación es un proceso de ingenierı́a en el que
cada uno de nosotros es parte dentro de un grupo de trabajo1 .
En adelante se hará hincapié en la realización de programas mediante módulos especificados
formalmente en su totalidad, con interfaces de uso perfectamente documentadas. Las caracterı́sticas
que formalmente debe ofrecer este interfaz lo han de convertir en un conjunto coherente, completo
1 Con respecto a la modularidad en concreto, es recomendable la lectura complementaria del artı́culo de Barbara
Liskov [Lis81] en la que se desarrolla un ejemplo completo de un programa formateador de textos en lenguaje CLU.
1.1 Desarrollo actual de proyectos de software 3

Cualidades del Software

Corrección
Fiabilidad
Conveniencia al usuario
Adecuado
Aprendible
Robusto
Mantenibilidad
Legibilidad
Expandibilidad
Comprobabilidad
Eficiencia
Portabilidad

Figura 2: Caracterı́sticas deseables del software

y no redundante de procedimientos, tipos, etcétera, que cubran la finalidad del módulo en el nivel
de abstracción planteado2 .
Como ejemplo sencillo de esta jerarquización de niveles que aparecen tanto en relación con
las estructuras de datos como con las de control podemos ver la diagramación de flujos de datos
que, al contrario que los diagramas de estructuras, están bastante unificados en su presentación
y simbologı́a. En un diagrama de flujo de datos en distintos niveles, desde el nivel “cero” que se
refiere a las entidades que intervienen, a niveles inferiores de detalle, de miniespecificaciones.
Se clasificarán los componentes de software desde el punto de vista de su finalidad y de
las propiedades de su implementación. A lo largo del curso se va a trabajar frecuentemente con
diferentes implementaciones de TADs. Estas implementaciones necesitarán ser caracterizadas por
sus propiedades respecto a diversos conceptos: acotación, concurrencia, recolección de memoria no
usado, etc.
Para poder reutilizar los módulos y objetos se usan distintos mecanismos y recursos que
permiten la su abstracción: genericidad, instanciación, tipos de parámetros genéricos, librerı́as y
sublibrerı́as; lo que repercute en la composición de grupos de trabajo, etc.
En este sentido los lenguajes de programación han ido evolucionando y adoptando estos
criterios en mayor o menor grado dependiendo de su finalidad: C, Pascal, Modula2, Ada, C++,
etc., fueron precursores de la programación orientada a objetos, como la de SmallTalk, C++, Eiffel
etc., hoy presente en todos los lenguajes de desarrollo3 .
2 Es muy importante definir desde un principio lo que se entiende por “nivel de abstracción”. Esto puede ser

relacionado con el ciclo de vida del software, desde un nivel de especificaciones a niveles de detalle en las mi-
niespecificaciones. También puede ser asociado en el desarrollo “top-down”, al nivel de detalle de las operaciones,
vistas en primera aproximación, como sentencias generales que en sucesivas aproximaciones se van a ir refiriendo a
instrucciones a “bajo nivel”
3 Una lectura complementaria que introduce al concepto de programación orientada a objetos es [Boo86], donde,

con la sintaxis de paquetes de Ada, se presentan los conceptos básicos de programación orientada a objetos.
1.2 Ciclo de vida del software 4

1.2. Ciclo de vida del software


El desarrollo de cualquier sistema de software, incluso el de sistemas triviales, es una actividad
estructurada. Se dan varios pasos, desde que el sistema es diseñado y programado hasta que es
validado. A esta secuencia de actividades, incluyendo sus entradas y salidas, es a lo que se denomina
proceso de software, desarrollo de software, y en su conjunto, y a veces indistinguiblemente,
el ciclo de vida del software. Cada organización sigue su propio proceso de software, pero estos
métodos particulares suelen seguir a procesos de software más abstractos y generales: los modelos
de desarrollo de software. Un modelo de desarrollo de software es una representación abstracta
de las actividades y documentos a realizar en el desarrollo de software. Dependiendo del nivel
de detalle, el modelo puede también mostrar los papeles responsables de estas actividades, las
herramientas que se usan para desarrollarlas, los tipos de comunicación entre las actividades y los
papeles y situaciones excepcionales a considerar como parte de los procesos.
El desarrollo del software es una actividad muy compleja, que demanda una gran actividad
intelectual y puede exigir gran creatividad a los participantes del mismo.

1.2.1. Modelos orientados hacia la especificación


Entre los años 50 y 60 el desarrollo del software fue un proceso muy informal alejado de otras
metodologı́as seguidas en procesos de ingenierı́a. Usualmente se seguı́an descripciones informales
de las necesidades a programar. Conforme se iban ampliando las necesidades de software esta
carencia de modelos y estructura fue haciéndose más y más costosa. Basándose en otros procesos
de ingenierı́a las organizaciones fueron adoptando procesos de desarrollo para el software más
estructurados. Ası́ se definieron actividades delimitadas de especificación, diseño y desarrollo con
tiempos intermedios de separación entre ellas, en los cuales se suponı́an acabadas las actividades
de las etapas anteriores.
La primera discusión pública acerca de este “ciclo de vida” del software se debe a Royce, en
1970. Hoy dı́a se denomina a este modelo de desarrollo de cascada. Este modelo consta de varias
etapas (Fig. 3):
Documentos de
requisitos
Definición de
requisitos Especificación del
diseño del sistema
Diseño del software
y del sistema Programas del
sistema
Implementación y
prueba de unidades Sistema
realizado
Integración y prueba
del sistema

Mantenimiento

Figura 3: Modelo en cascada de desarrollo de software

1. Definición de requisitos. Se definen los servicios a prestar y las restricciones a cumplir.


2. Diseño del software y del sistema. Se identifican los subsistemas y la estructura global del
sistema. Dependiendo de la envergadura de la organización se podrá llegar a mayor deta-
lles o a descripciones abstractas. Se pueden seguir métodos de diseño estructurado para el
desarrollo del diseño del software.
3. Implementación y prueba de unidades. Se desarrollan individualmente los módulos que con-
forman el sistema en (uno o varios) lenguajes de programación elegidos. Se prueban los
1.2 Ciclo de vida del software 5

módulos por separado.


4. Integración y prueba del sistema. Se integran y prueban todos los módulos como un sistema
completo.
5. Mantenimiento. Se instala y pone en funcionamiento el sistema. Durante su tiempo de vida,
el software será modificado siguiendo los requisitos del usuario y reparando los fallos que se
van descubriendo.
Cada uno de estos puntos puede naturalmente ser detallado más y dar lugar a una descripción
más fina en forma también de cascadas.
Entre las muchas variantes surgidas de este ya bien asentado modelo están el modelo en V,
que resuelve en parte el problema de la simplicidad del modelo de cascada que sólo muestra una
salida por proceso y el hecho de que esta salida no puede ser reinsertada como parte de la entrada
de etapas anteriores.
Una modificación que permite la iteración en el modelo de cascada se muestra en la Figura 4,
es el modelo iterativo en cascada.
Documentos de
requisitos
Definición de
requisitos Especificación del
diseño del sistema
Diseño del software
y del sistema Programas del
cambios en sistema
los requisitos
Implementación y
prueba de unidades Sistema
cambios en realizado
el diseño Integración y prueba
del sistema
cambios en
el programa
Mantenimiento

Figura 4: Modelo en iterativo en cascada de desarrollo de software

1.2.2. Modelos de desarrollo evolutivos


Los documentos producidos al final de cada etapa pueden convertirse en obstáculos en tanto
en cuanto las sucesivas etapas no podrán empezar hasta que éstos no se acaben. En los modelos
evolutivos se produce un sistema rudimentario inicial que evoluciona según las necesidades del
cliente hasta cumplir con los requisitos últimos de éste. Al no requerir preespecificaciones detalladas
tampoco exige una costosa producción de documentación por etapas. Las etapas son:
1. Formulación de un esquema de los requisitos del sistema. Aunque no necesariamente ni
completa ni consistente sino tan sólo como guı́a para los programadores.
2. Desarrollo de un sistema, tan rápido como sea posible, basado en las especificaciones ante-
riores.
3. Evaluación y modificación del sistema según vayan ası́ especificándolo los propios usuarios.
El modelo evolutivo, basado en prototipos, es especialmente importante hoy dı́a en el desarrollo
de sistemas interactivos, dado la creciente importancia de este aspecto.
Dentro de los modelos evolutivos en general hay dos muy utilizados:
Prototipado de pruebas (Fig. 5). Su objetivo es ‘solamente’ el comprender los requisitos
reales del usuario. Una vez que el sistema prototipo permite esta comprensión, se deshace
del prototipo.
1.2 Ciclo de vida del software 6

Prototipado evolutivo (Fig. 6). Los prototipos sucesivos son modificados hasta constituir el
propio software que finalmente usará el cliente.

Esquema de Desarrollo Evaluación Especificación


requisitos de prototipo de prototipo de sistema

Desarrollo Validación de Entrega de


de software sistema sistema

Figura 5: Prototipado de pruebas desechables.

Especificación Construcción Entrega


abstracta de prototipo de prototipo

Propuesta Evalución
nuevos requ. de prototipo

Figura 6: Desarrollo mediante prototipados que evolucionan.

1.2.3. Modelos iterativos


Los modelos evolutivos aunque permiten la interacción entre las etapas del desarrollo, no
lo hacen de una manera, no muestran claramente los momentos. Dos modelos de desarrollo, el
incremental y el modelo en espiral son los más importantes de los modelos iterativos.

El modelo incremental sugerido por Mills, en 1980, divide el proceso en conjuntos de procesos
menores, que se identifican y resuelven por separado.
El el modelo incremental el cliente identifica y esquematiza los servicios esperados por el
sistema priorizándolos. Esta priorización es tenida en cuenta a la hora del desarrollo. De la es-
quematización y división surgen partes a ser resueltas por distintas partes del sistema. Una vez
que uno de los incrementos se ha completado y puesto en funcionamiento, el cliente puede usarlo
teniéndose ası́ en cuenta sus sugerencias tanto para mejorar esa parte como para reestructurar
y mejorar las demás. No es imprescindible utilizar el mismo proceso con cada incremento en el
desarrollo.
1.2 Ciclo de vida del software 7

Aunque las ventajas son evidentes, los inconvenientes también aparecen, como:
1. Identificación de los incrementos que deben ser relativamente pequeños (de no más de unas
20.000 lı́neas de código) y cubrir alguna funcionalidad, siendo difı́cil, en muchos casos asociar
requisitos del cliente con funcionalidades del sistema. Los requisitos, normalmente no son
independientes y la consecución de uno implica el desarrollo de varios.
2. Infraestructura necesaria Muchos sistemas exigen de la implantación de una infraestructura
común a varias partes del sistema. Esto dificulta aún más la independencia de las partes del
sistema.

3. Gestión de los contratos Ya que partes del sistema no se saben cuándo van a empezar, es
difı́cil llevar un sistema de contrataciones y organizar el trabajo del personal involucrado,
que usualmente debe fijarse con horarios y fechas desde el principio.

Definición del Priorización de Asignación de


esquema requisitos requisitos a
de requisitos incrementos

Diseño de la Desarrollo de
arquitectura servicios básicos
del sistema

Especificación de Desarrollo de Validación del


un incremento un incremento incremento
del sistema del sistema

NO

Integración del Validación del ¿Está completo


incremento sistema el sistema?

Entrega final

Figura 7: Modelo de desarrollo incremental

Este último aspecto se elimina en la variante de entrega incremental que sigue las primeras
etapas, pero no pospone las especificaciones de ninguna otra de manera que se puedan prever los
contratos y fechas de trabajo.

En el modelo en espiral cada parte se resuelve independientemente teniendo muy en cuenta


los costos y riesgos. Fue propuesto inicialmente por Boehm en 1988. Ve el desarrollo del proyecto
como una espiral, desde una concepción inicial, en el centro, hasta el desarrollo final del sistema.
Este modelo se caracteriza por permitir revisiones regulares del progreso logrado frente a objetivos
bien definidos de manera que no sufre de problemas usuales en los modelos de prototipos.
Este modelo está basado en una constate evaluación de riesgos. Antes de entrar en la siguiente
fase se debe tener una completa evaluación de los riesgos involucrados. Los riesgos se consideran
una falta de información de manera que para resolverlos es necesaria la recogida de información y
su análisis.
Cada fase se representa mediante una vuelta de espiral y cada vuelta pasa por cuatro etapas
(Fig. 8)
1.2 Ciclo de vida del software 8

1. Establecimiento de objetivos y restricciones de esa vuelta.


2. Fase de análisis de riesgos frente a los objetivos, con la posible actividad de resolución de
riesgos mediante construcción de prototipos, etc.
3. Fase de desarrollo, que puede acompañar a la del diseño, programación y actividades de
validación. Aquı́ podemos usar un modelo en cascada.
4. Fase de planificación, en la que se planea la siguiente iteración.

E
ide val
nt uac
ific ió
ac n d
ió e
Análisis rie n, r alte
es
ci e

sg es rn
ric d
on

de riesgos os olu at
st n
re ció

ció iva
y ina

n s,
de
os m

Análisis
tiv er
je et

de riesgos
ob D

Análisis Protot.
de riesgos operativo
Protot.
Prot. 3
Análisis
de riesg 2
Prot.
REVISIÓN 1
Sim
plan de ula cion
requisitos y es, m
Concepto de odelo
de ciclo de vida s, co
operaciones mpa
rativ
as
Requ. de
SW
plan de Validación Diseño Diseño
desarrollo requis. producto detallado
pl sig

código
an u
la

ifi ien

integración y test
ca te

diseño unidades
ci f

plan de pruebas n ón
ón as

v&v test ció cci


ica odu
de e

integración i f
test er pr
aceptación ,v e
servicio o llo el d
rr iv
sa e n
Deient
u
sig

Figura 8: Modelo en espiral de Boehm original. 1988.

Un tı́pico riesgo es la inadecuación de la interfaz de usuario, por ejemplo, al tipo de uso que se
quiere del sistema, por ejemplo en un sistema que pretende ser de tipo “walk up and use”, en el que
se requerirá una gran facilidad de manejo para todos. Aquı́ un fallo en la interfaz serı́a un desastre
para el sistema completo. Esto se resuelve en la etapa que corresponda mediante la construcción de
bocetos y prototipos parciales que habrán de testearse ampliamente antes de abordar su desarrollo.
Este modelo abarca a otros. Donde no hay un gran riesgo en la recogida de requisitos se
convierte en un sencillo modelo en cascada, mientras que en sistemas de más compleja defini-
ción de requisitos, como en los sistemas altamente interactivos, el sistema puede ser considerado
como un sistema evolutivo con las actividades de prototipado dominando y un tercer cuadrante
relativamente pequeño (ver Figura 8).
Las dos grandes dificultades de este modelo son
1. La dificultad del análisis de riesgos, que requiere personal con experiencia y altamente espe-
cializado.
2. Los problemas de contratación, ya que este modelo trata de evitar decisiones prematuras,
que son, por otro lado esenciales a la hora de prever fechas de contratación.
1.2 Ciclo de vida del software 9

Este modelo requiere de un alto grado de cercanı́a o confianza entre el cliente y los desarrolladores.

1.2.4. Transformaciones formales


En aquellos sistemas en los que el resultado debe seguir fielmente las especificaciones, como
por ejemplo, sistemas de seguridad, como el de control ferroviario, etc., el sistema de ciclo de
vida en cascada no es apropiado. Para estos sistemas ni siquiera el enfrentamiento del resultado
a una baterı́a de datos de prueba es suficiente, dado que estas pruebas demuestran tan sólo la
posibilidad de que existan errores, no su total ausencia. La única opción posible en estos casos
es la elaboración de una metodologı́a que matemáticamente demuestre la corrección del código
construido. Aunque este sistema no se haya muy extendido debido fundamentalmente a la aún
incapaz análisis y formalizaciones existentes, sı́ que se llega a emplear en algunos sistemas de
seguridad crı́ticos, en determinadas fases del desarrollo.

1.2.5. Desarrollo aséptico


El desarrollo en sala aséptica (Cleanroom process) se desarrolló en IBM a partir de trabajos
sobre programación estructurada de 1970 a partir de 1987 por Mills y Linger. Combina aspectos
del desarrollo incremental y el de transformaciones formales. Toma su nombre del usado para las
salas para la fabricación de semiconductores donde se trata de tener un ambiente absolutamente
exento de impurezas que pudieran introducirse en las obleas de silicio.
Las caracterı́sticas que lo definen son (Fig. 9):
1. Desarrollo formal del software. Es el aspecto más delicado de este modelo por carecerse,
como se ha dicho de técnicas formales suficientes para software medianamente complejo.
2. Desarrollo incremental. Esencial por el hecho de permitir la integración de partes formalmente
correctas, según las técnicas formales que lo permiten demostrar sólo cuando son pequeñas.
3. Prueba estadı́stica. La fiabilidad del software se evalúa según el número de fallos detectados
en el proceso de datos de muestra, según un modelo de Littlewood de 1990.
Este modelo parece confirmar en la práctica una alta fiabilidad de los resultados. Sin embargo exige
que los desarrolladores dominen técnicas de especificación y manipulación matemáticas, lo que es
muy costoso. Además aún no está muy claro cómo aplicarlo al desarrollo de interfaces de usuario,
ya que aún están muy verdes las formalizaciones del proceso de interacción persona-ordenador.

Requisitos
del sistema

Especificación Definición de Desarrollo Verificación Integración


formal incrementos del FORMAL de
del sistema de software sistema del código incrementos

Pruebas Pruebas
estadísticas al sistema
al diseño integrado

Figura 9: Proceso de habitación aséptica (Cleanroom process).


1.3 Fundamentos del diseño del software 10

1.2.6. Aplicabilidad de cada modelo


En resumen, se puede concluir que no existe un modelo ideal y la aplicabilidad de cada cual
depende del tipo de proyecto. Podemos resumir en una tabla los modelos vistos aquı́:
Modelo Aplicabilidad
Cascada Sistemas de especificaciones nı́tidas. Desarrollo sub-
contratado.
Prototipo Partes de sistemas grandes. Interfaces de usuario
difı́ciles de especificar. Software que requiere proto-
tipos para pruebas de mercado.
Evolutivo Sistemas interactivos de vida corta. Sistemas comer-
ciales pequeños o medianos dependientes de una base
de datos.
Incremental Grandes sistemas claramente particionables. Siste-
mas de bien conocidos requisitos de infraestructura
(sobre bases de datos, por ejemplo). Adecuados para
el desarrollo interno en empresas, ası́, sin problemas
de contratación.
Espiral Partes de sistemas pero con desarrolladores interco-
municados.
Formales Sistemas muy pequeños pero de seguridad crı́tica.
Aséptico Grandes sistemas particionables y de altas exigen-
cias de fiabilidad, no incluyendo interacción persona-
ordenador.

1.3. Fundamentos del diseño del software


Durante los años 60 el único método que se empleaba para el diseño de los programas era el de
los diagramas de flujo, principalmente en programación. En la década de los 70 se amplió a técnicas
de diagramación de flujo de datos (DFD) y diagramas de entidad-relación (ERD). Por entonces fue
cuando se empezaron a plantear las cuestiones de necesidad de desarrollo de software modular (en
trabajos de Parnas, en 1972) y basado en el uso de Tipos Abstractos de Datos (TADs, en especial
con los trabajos de Liskov en 1975). El concepto de módulo fue experimentado a finales de los 70
por Niklaus Wirth (en 1977) y hasta principios de los 80 dónde se uso como base de lenguajes
fundamentales como Smalltalk-80, Ada y Modula-2. Desde mediados de los 80 y durante los 90
ha habido una emergente necesidad hacia la programación orientada a objetos (POO). Lenguajes
como Ada 95, Modula-3, C++ (de Stroustrup, en 1986), Eiffel (Meyer, 1992), Smalltalk (Goldberg,
1989), Object Pascal (Tesler, 1985), Java, etc. y también lenguajes de gestión de bases datos como
Ontos, Gemstone, O2, Orion, ObjectStore, etc. utilizan este paradigma.
Tradicionalmente se han desarrollado técnicas en el diseño del software: top-down (t-d),
bottom-up (b-u), diagramas de flujo de datos (DFDs), diagramas de entidad relación
(DER) y máquinas de estado finitos (MEF).
Los enfoques de diseño top-down, bottom-up, DFDs, etc. se han fijado en las caracterı́sticas
funcionales de las aplicaciones. Históricamente están muy ligados a los lenguajes de programación
imperativos o procedurales como Fortran, Pascal o C ya que son estos lenguajes los que se definieron
con aquéllos enfoques.
El diseño basado en refinamientos sucesivos nos lleva a acercarnos a niveles de detalle en los
procesos en un enfoque top-down (t-d).
El enfoque bottom-up (b-u) aunque está también orientado al aspecto funcional del software
se concentra en la información y su uso. A partir de los datos reales que se deben manejar en la
aplicación, se identifican los aspectos comunes entre ellos y se sintetiza en un proceso ascendente
para conseguir un conjunto de funciones que cubran el acceso y proceso de aquellos datos. Se
encuentran pues, a partir de los datos, las tareas que los pueden gestionar.
Estos dos enfoques, b-u y t-d, resultan incompletos a la hora de determinar la corrección
respecto a especificaciones y son inadecuados en el diseño de sistemas interactivos ya que alejan
1.3 Fundamentos del diseño del software 11

el desarrollo de las funciones del sistemas de la interfaz que los usará. Son sin embargo enfoques
adecuados a problemas pequeños y bien definidos. Son además principios muy importantes en
muchos otros enfoques de diseño.
Los DFDs permiten el diseño atendiendo a los datos, a las entradas y salidas, caracterización
de los datos que deben llegar y salir y de los procesos que descritos sobre todo en función de la
manera de transformar esos datos.
Esta representación del sistema permite además la exploración de las funciones en detalle.
Mediante la jerarquización de los diagramas, hasta llegar a las miniespecificaciones.
Los DFDs son muy populares y aún hoy se usan dado su sencillez de interpretación.
Entre los defectos de los DFDs están su incapacidad para la representación de iteraciones
entre tareas. Son una notación semiformal e incompleta y deben ser complementados con otras
técnicas.
Los DER sirven para detallar las estructuras de datos y su interrelación complementando
ası́ la descripción más grosera de los DFDs. Los DER utilizan la interrelación para modelar las
asociaciones de información estáticas entre entidades. Éstas tendrán cardinalidades (uno-a-uno,
uno-a-muchos o muchos-a-muchos) y atributos, incluyéndose hoy en ellos relaciones de herencia.
Las MEF capturan los aspectos de control del sistema. Para ello establecen estados que re-
presentan puntos funcionales del diseño, representando con arcos etiquetados los diferentes valores
(en forma de frases) que causarı́an a aquél estado un cambio o transición a otro estado.

1.3.1. Diseño por encapsulado y ocultamiento


El diseño de software usando módulos y TADs está basado en conceptos como:
Separación de objetivos y modularidad. Permiten abordar grandes problemas. Facilitan su
modificación. Permiten la división del trabajo de desarrollo.
Abstracción e independencia de la representación. Al ocultarse los detalles se tiene una más
amplia perspectiva durante el desarrollo. Se pueden ejecutar cambios en el interior de la
estructura interna de cada componente sin afectar al resto de los módulos o TADs.
Incremental/anticipación de cambios. Permite la continua y necesaria mejora de los módu-
los/TADs.
Cohesión/acoplamiento. Un módulo es coherente si cada parte en él está orientada hacia un
objetivo claro, sencillo y bien definido. Antiguamente se decı́a que un procedimiento deberı́a
tener como máximo una página de largo (unas sesenta lı́neas). Si ası́ fuera, el sistema serı́a
juzgado como coherente. El acoplamiento significa interdependencia entre componentes. Es
considerado el complemento de la cohesión. Un sistema de bajo acoplamiento entre compo-
nentes, tiene asimismo poca interacción entre ellos, lo que a su vez los hace más fáciles de
controlar.

1.3.2. Modularidad
El concepto de módulo fue propuesto inicialmente por Parnas a principio de los 70 y fue imple-
mentado en lenguajes como Modula-2 y Ada. Su origen estuvo en el examen de programas reales
que mostraban soluciones de enfoque comunes independientemente del dominio de la aplicación.
Particularmente se veı́a que una estructura de datos dada mostraba siempre una compañı́a de fun-
ciones que permitı́an su acceso y posibilidades. En lenguajes como C esto se recogı́a organizando en
ficheros separados la estructura del programa. Los módulos formalizaron este proceso reconocien-
do la particionabilidad de los programas en unidades discretas con una interacción explı́citamente
representada y, por tanto, perfectamente definida. Individualmente cada unidad de programa en-
capsulaba la funcionalidad deseada para una tarea y ofrecı́a una interfaz para su cliente (otro
módulo) mientras ocultaba su implementación.
Los módulos ofrecı́an pues la posibilidad de encapsular la funcionalidad y permitir futuros
cambios.
1.3 Fundamentos del diseño del software 12

Desde muchos puntos de vista la modularidad reflejaba el enfoque top-down del refinamiento
por pasos sucesivos.
Los módulos encajaban bien con las descripciones de los DFDs y DER, siendo una técnica
orientada a los diseñadores de software más que a los usuarios finales de los programas.

1.3.3. TADs
Los TADs fueron propuestos inicialmente por Liskov para el lenguaje de programación CLU
a finales de los 70. Un TAD está caracterizado por una información almacenable y una serie de
procedimientos de acceso, modificación y recorrido, que reflejan todo su comportamiento externo.
La implementación privada de los TADs queda oculta al cliente del mismo, que es el propio
diseñador en otra parte del diseño.
En realidad los TADs no son una idea nueva como concepto ya que los tipos definidos por los
lenguajes de programación tienen más que ningún otro, comportamiento de TADs. Por ejemplo,
el tipo entero y las operaciones que lo permiten manejar (+, -, *, div y mod) nos abstraen del
mecanismo interno de su implementación.
Los TADs dan lugar a una programación más orientada a los datos y su uso. Para ello debemos:
Identificar las unidades de información principales.
Describir el propósito de cada unidad.
Definir las técnicas de manipulación para cada unidad.
Encapsular y ocultar los aspectos no definidos.
Claramente las ventajas del uso de los TADs son las mismas que la del uso de los módulos,
sin embargo, que estas técnicas son particulares para cada parte del proceso, los errores se pueden
arrastrar a todos ellos. Además la carencia de patrones y la falta de la herencia de caracterı́sticas
hacen que la construcción de TADs en un proyecto pueda dar lugar un alto grado de redundancia
de código. TADs que pueden ser semejantes pero sólo difieran en alguna pequeña caracterı́sti-
cas tendrán igualmente que ser implementados por separado con la repetición del código. Estas
carencias hacen de los TADs menos reutilizables.

1.3.4. POO
La transición hacia el diseño OO a partir de las especificaciones no es una actividad trivial.
No existen técnicas globales que permitan la transición de DER directamente hacia una POO.
Dado que los enfoques DFD y DER son en parte contrarios, su concreción en un lenguaje OO
es contradictorio. Es por esto que la mayorı́a de los lenguajes OO encierran su propio enfoque de
lo que es el proceso de diseño utilizando una unidad de encapsulamiento/abstracción llamada tipo
de objeto o clase, con un fuerte paralelismo con el concepto de TAD. La diferencia fundamental
con el TAD está en el concepto de herencia. La herencia permite la compartición controlada
de propiedades entre objetos/clases permitiendo ası́ el recoger tanto datos componentes como
operaciones admisibles desde el supertipo o superclase al subtipo o subclase.
La POO es adecuada porque:
Refuerza la modularidad.
Incrementa la productividad.
Controla la consistencia de la información.
Favorece la reusabilidad del software.
Facilita la evolución del software.
Aunque no hay un total acuerdo en cuanto a la terminologı́a respeto al diseño OO, podemos
describir los siguientes conceptos comunes:
1.3 Fundamentos del diseño del software 13

Tipo objeto/clase: sirve para modelar las caracterı́sticas (en forma de información recogible)
y el comportamiento (métodos utilizables) para una aplicación.
Información: tipos privados de un TO/clase. Representa su estado interno caracterizando la
instancia.
Método: procedimiento requerido para una acción particular contra los datos privados del
TO/clase.
Herencia: compartición controlada de la información/métodos entre TO/clases entendién-
dose esta compartición como una herencia de más TO/clases más generales a otros más
particulares, subclases, que repiten todos o parte de la composición del ancestro, substitu-
yendo, probablemente algunos de sus métodos/datos, y añadiendo o eliminando otros. Pero
siempre tomando como punto de partida el conjunto de propiedades de la superclase.
Instancia: Concreción en un TO/clase de una información y métodos.
Mensaje: Acción, llamada a método, que puede ser lanzada por la propia instancia sobre
sı́ misma o otras instancias de otros.

1.3.5. Abstracción
La abstracción es una técnica de desarrollo muy potente que permite ignorar los detalles y
utilizar tan sólo los elementos, simplificadamente, menos farragosos, de un nivel más abstracto en
el que sólo nos interesan caracterı́sticas dadas del módulo o componente de software.
La abstracción en el desarrollo del software se consigue mediente la independización de los
detalles en bloques no visibles.

1.3.6. Ocultación de información


La ocultación de la información permite la abstracción de detalles ası́ como la privacidad del
desarrollo y también la seguridad de acceso.
La ocultación de la información exige la creación de módulos aislados y el aislamiento de los
módulos exige su independencia funcional.

1.3.7. Independencia funcional


Es una necesidad para varias de las caracterı́sticas antes mencionadas: la reutilización de ele-
mentos implica manejar elementos realmente independientes, ya que en otro caso, la complicación
añadida por los módulos dependientes los hace menos útiles ni interesantes en distintos proyectos
o partes distintas del mismo.
La independencia funcional facilita la ocultación de la información al no revelar ningún detalle
de su mecanismo a ningún otro módulo.

1.3.8. Cohesión
La cohesión es la cualidad más importante para hacer que los módulos sean independientes
ya que representa el hilo conductor que une internamente las piezas de un módulo. Si este hilo es
único y sencillo todas piezas del módulo encontrarán los elementos necesarios para su funciona-
miento dentro del propio módulo. Si existen varios la multiplicidad implicará mayor dependencia
de módulos externos ası́ como una más complicada idea de su funcionamiento.

1.3.9. Acoplamiento
El acoplamiento entre módulos surge de la falta de coherencia interna de los mismos o su
complicada definición. En general, sin embargo, es imposible de evitar totalmente siendo una ca-
racterı́stica natural un acoplamiento controlado entre los módulos. Esta dependencia controlada se
1.4 Referencias 14

consigue estableciendo técnicas de comunicación e intercambio de datos/control entre los módulos.


Los parámetros que se envı́an en una llamada a otra función son parte de este acoplamiento. El
fan in o abanico de parámetros de entrada de una función o módulo deberı́a ser pequeño (no más
de tres parámetros) ası́ como el fan out o abanico de datos de salida, esperados, del mismo. Sin
embargo es este acoplamiento controlado el que permite hacer con los módulos distintas opera-
ciones y desvelar el comportamiento de los mismos con distintos datos o situaciones. Un módulo
sin datos de entrada tendrı́a siempre el mismo comportamiento y por lo tanto no tendrı́a ningún
interés ni uso.

1.4. Referencias
Textos fundamentales, traducidos y asequibles son los de [Pre93] y [Som96]

Referencias
[Boo86] Grady Booch. Object-oriented development. IEEE Transactions on Software Enginee-
ring, 12(2):211–221, February 1986.
[Fis88] Alan S. Fisher. Case. Using Software Development Tools. John Wiley & Sons, 1988.
[Lis81] Barbara Liskov. Modular program construction using abstractions. Technical report,
MIT. Dept. of Elect. Eng. and Comp. Sci., Cambridge, Mass. 02139/USA, March 1981.
Interesante y sencillo de leer, este artı́culo basa un ejemplo desarrollado en CLU en la
abstracción y stepwise refinement de Dijstra y Wirth. El ejemplo es un detenido desarrollo
de un formateador de texto.
[Pre93] Roger S. Pressman. Ingenierı́a del Software. Un enfoque práctico. McGraw-Hill, 1993.
Ya va por la cuarta edición. Referencia obligada para todos los programadores. Ofrece
una visión global y muy completa de todos los problemas y modelos de la programación
de sistemas. Puede resultar un poco superficial en algunos terrenos debido naturalmente
al espacio limitado del texto. Extensa bibliografı́a.
[Som96] Ian Sommerville. Software Engineering. Addison-Wesley, 5th edition, 1996. Clásico
introductorio sobre la problemática general de la Ingenierı́a del Software. Más breve y
con menos bibliografı́a.
[YC79] Edward Yourdon and Larry L. Constantine. Structured Design. Fundamentals of a Dis-
cipline of Computer Program and Systems Design. Yourdon Press, 1979.
[You88] Edward Yourdon. Managing the System Life Cycle. Prentice-Hall, second edition, 1988.

Juan Falgueras
Dpto. Lenguajes y Ciencias de la Computación
Universidad de Málaga
Despacho 3.2.32

Anda mungkin juga menyukai