Ciclo de de Desarrollo de Software PDF
Ciclo de de Desarrollo de Software PDF
Ciclo de de Desarrollo de Software PDF
Guadalupe Ibargüengoitia G.
Hanna Oktaba
Amparo López Gaona
Contenido
Introducción
Capítulo 1 Ciclo de desarrollo de software
1.1 Introducción al ciclo de vida del software
1.2 Definición de Ingeniería de Software
1.3 Software, su naturaleza y características
1.4 Principios de la Ingeniería de Software
1.5 Proceso de software
1.6 Ciclo de desarrollo de software
1.7 Lenguaje de Modelado Unificado UML
Capítulo 3 Análisis
3.1 Introducción al Análisis
3.2 Vista estática.
3.2.1 Diagrama de clases
3.3 Vista dinámica.
3.3.1 Diagramas de secuencia
3.3.2 Diagramas de estados
Capítulo 4 Diseño
4.1 Introducción al Diseño
4.1.1 Principios del diseño
4.2 Arquitectura de software
4.2.1 Diagrama de paquetes
4.2.2 Diagrama de distribución
4.3 Construcción de componentes
4.4 Diseño de la base de datos
4.4.1 Conversión del diagrama de clases al modelo de datos de una base de
datos relacional
Capítulo 5 Construcción
5.1 Diseño detallado de clases
5.2 Estándares de codificación
5.3 Revisión de código y programación entre pares
5.4 Pruebas unitarias
5.4.1 Pruebas caja blanca
5.4.2 Pruebas caja negra
Introducción
Los productos de software apoyan gran cantidad de las actividades humanas. Estos
productos responden a las necesidades de personas, empresas, organizaciones, etc. Los
defectos en sistemas de software pueden causar daños no solamente económicos sino
también de vidas humanas. Por lo tanto, la forma en que se desarrolle el software para
cumplir con las necesidades de sus usuarios y para evitar el mayor número de defectos, es
de vital importancia.
El objetivo de este Material para los Estudiantes es enseñar las prácticas básicas de
Ingeniería de Software para la concepción y desarrollo de software. Las notas describen las
principales fases de un ciclo de desarrollo y las técnicas básicas que sirvan de guía a los
alumnos que construyen estos productos de software por primera vez. El material está
dirigido principalmente a los estudiantes de licenciaturas, que ya saben programar en un
lenguaje orientado a objetos.
En el capítulo 4, se presentan varias técnicas para hacer el diseño del software que
comprende desde la arquitectura hasta el diseño de la base de datos.
El capítulo 5 habla de diseño detallado para la construcción del software y de las pruebas
unitarias.
El presente Material para los Estudiantes ha sido elaborado bajo el convenio 19403-1688-
29-XI-06 entre Microsoft y la Facultad de Ciencias de la UNAM y está acompañado con el
Material para el maestro, ambos en su versión preliminar.
Capítulo 1
Ciclo de desarrollo de software
Los productos de software tienen un ciclo de vida que consta de dos etapas:
Etapa de concepción y desarrollo
– Alguien define las necesidades que deberá cubrir el software.
– Se analiza y diseña el producto que las cumplirá
– Se construye y prueba el producto
Etapa de operación, mantenimiento y retiro
– Se pone en operación
– Se va modificando y mejorando
– Eventualmente se deshecha
Las personas que construyen estos productos de software se llaman Ingenieros de Software.
Se entiende por software al código generado por programas, escritos en algún lenguaje de
programación, que resuelve un problema. El software no es sólo el código, sino también
“los documentos asociados y la configuración de datos que se requieren para que esos
programas funcionen correctamente” [Sommerville] y puedan ser mantenidos.
El software es un nuevo tipo de producto que no se parece a ningún otro artefacto que sea
tangible como puentes, casas, teléfonos, etc. El software tiene una naturaleza diferente, por
lo que es necesario entenderla.
Definir cuales son las características de calidad que debe tener un producto de software no
es fácil, pues depende de a quién se le pregunte: al cliente, al analista, al desarrollador, el
que hará el mantenimiento, etc. Las características mas reconocidas son las siguientes:
• Funcionalidad (Functinality): si se comporta de acuerdo a las especificaciones de las
funciones que debe ejecutar.
• Confiabilidad (Reliability): si el usuario puede depender de él y si se comporta
"razonablemente" aún en circunstancias no anticipadas en la especificación de
requerimientos.
• Usable (Usability): Si el usuario lo encuentra fácil de entender, aprender y usar.
• Eficiente (Efficiency): si usa sus recursos adecuadamente y proporciona un desempeño
adecuado.
• Mantenible (Maintainability): Si es fácil hacerle modificaciones tales como
correcciones, mejoras o adaptaciones.
• Portable (Portability): Si es posible correrlo en diversos ambientes o plataformas.
• Reusable: Si se pueden usar partes o todo para el desarrollo de un nuevo producto.
• Interoperable: Si puede coexistir y cooperar con otros sistemas.
•
La Ingeniería de Software es relativamente reciente, por lo que no está tan madura como
otras ramas de la Ingeniería. Sin embargo, existen algunos principios ya validados por la
experiencia.
Proceso de Software
1..*
Fase
1..*
Producto Actividad Rol
1..* 1..*
Un Proceso de software está compuesto por fases y debe incluir al menos una fase. Las
fases están compuestas de al menos una actividad, que tiene asociado uno o varios
productos y uno o varios roles. Un rol es responsable de al menos una actividad.
• Las Fases constituyen pasos significativos del proceso de software. Tienen un objetivo
dentro del desarrollo. Para cada fase se identifican: los roles, actividades y productos
que son necesarios cabo para cumplir el objetivo de la fase.
• Actividades definen las acciones que se llevan a cabo en el desarrollo del software y
utilizan y/o generan los productos.
• Productos son las entradas y salidas de las actividades. Pueden ser documentos,
diagramas de diseño, código, planes de pruebas, reportes, manuales de usuario, o
conjuntos de ellos.
• Roles son los responsables por llevar a cabo las actividades del proceso.
En estas notas nos abocamos solo a la etapa de desarrollo de software que representa el
inicio del ciclo de vida . En la etapa de desarrollo se usará tecnología orientada a objetos
para hacer la construcción del software. El proceso de desarrollo del software está basado
en el Proceso Unificado [Jacobson], que está guiado por los casos de uso y es iterativo e
incremental.
• Guiado por los casos de uso:
– Un caso de uso es una funcionalidad del sistema que proporciona al usuario
un valor o servicio. Un usuario es una persona o un sistema que interactúa
con el software. Por lo que los casos de uso guían el desarrollo del software
para que cumpla con las necesidades del usuario.
• Iterativo e incremental
– Una iteración es la ejecución de todos los pasos del ciclo de desarrollo. Un
Incremento es la evolución que va teniendo el producto a lo largo del
tiempo. En el desarrollo se escogen algunos casos de uso iniciales para una
iteración y en versiones posteriores del software se incrementa
incorporando otros casos de uso. Las iteraciones se deben planear y
controlar.
El Lenguaje de Modelado Unificado (UML por sus siglas en inglés) [Booch] es el estándar
de la OMG (Object Management Group) para el modelado orientado a objetos y será la
herramienta de modelado en el curso por las siguientes razones:
- Provee de un lenguaje de modelado expresivo y visual.
- Es independiente de lenguajes de programación y los procesos de desarrollo.
- Cubre los requerimientos de modelado de los sistemas actuales, por ejemplo, sistemas
concurrentes y distribuidos.
- Está enfocado a proporcionar un lenguaje de modelado estándar y no a un proceso
estándar.
A lo largo del ciclo de desarrollo de software que usaremos, se irán construyendo diversos
diagramas de UML.
Referencias bibliográficas
• Booch G., Rumbaugh J., Jacobson I. The Unified Modeling Languaje. Users guide.
Addison Wesley 1999.
• Ghezzi C., Jazayeri M., Mandrioli D. Fundamentals fo Software Engineering. Prentice
Hall 1991.
• IEEE Standard Glossary of Software Engineering Terminology, std610.12-1990.
• Jacobson I., Booch G., Rumbaugh J. The Unified Software Development Process.
Addison Wesley 1999.
• Oktaba H., Ibargüengoitia G. “Software Processes Modeled with Objects: Static View”,
Computación y Sistemas, Iberoamerican Journal of Computer Science, CIC-IPN,
México, 1, 4 (1998), p.228-238.
• Pressman R.S. Ingeniería del Software. Un enfoque práctico. McGraw Hill.
• Sommerville I. Ingeniería de Software 6ª edición. Addison wesley 2002.
• SWEBOK. Guide to the Software Engineering Body of Knowlwdge. Trial version
Mayo 2001. www.swebok.org
Capítulo 2
Especificación de requerimientos
La mayor parte de las veces, el cliente no tiene claro qué es lo que realmente necesita. Es el
desarrollador el responsable de ayudar al cliente a entender y expresar sus necesidades para
que el software las pueda satisfacer. Para identificar los requerimientos se consultan a los
interesados a través de varias técnicas [Tomayco] como son:
• Hacer entrevistas.
• Aplicar cuestionarios.
• Observar a los futuros usuarios al realizar las tareas que apoyará el software.
• Revisar documentos o sistemas ya existentes que se pretenden mejorar.
El cliente expresa de manera oral sus necesidades sobre el software que desea se le
construya. Escribir un texto, entre el cliente y el desarrollador, que defina el problema, es
una buena práctica que permite poner en blanco y negro las necesidades del software y
ayuda al cliente a precisarlas. Por lo que la entrada inicial al proceso de desarrollo de
software es escribir en un texto la Definición del problema.
Coad [Coad] propone una serie de estrategias al redactar ese texto para ayudar a aclarar el
objetivo del software. Una de ellas es escribir una frase del tipo “para ayudar a” o “para
apoyar a” que permiten saber el tipo de usuarios que tendrá el software y para qué se usará.
Otra estrategia que propone es que el desarrollador “se dé una vuelta por el ambiente de
trabajo donde se usará el software”, esto permite ver a los usuarios y el tipo de cosas que
necesitan que el sistema haga para apoyarlos en su trabajo diario. Una estrategia más,
indica que “se haga una lista de características o cualidades” que deberá tener el software,
la que se puede escribir en orden de importancia.
En el texto de la figura 2.1 se muestra una definición del problema para construir un
sistema para una bolsa de trabajo en internet. En él se aplican dos de las estrategias
propuestas por Coad, usar la frase “para apoyar a” y “hacer una lista de características”.
Bolsa de trabajo
Se desarrollará un sistema de bolsa de trabajo que apoye a desempleados y a empresas.
Este sistema podrá ser usado por desempleados que están en busca de algún empleo y
por empresas que estén en busca de empleados para ocupar una vacante.
Los desempleados podrán ver las vacantes disponibles sin tener que registrarse, pero si
el desempleado quiere postularse para una vacante tendrá que registrarse forzosamente.
Las empresas podrán publicar sus vacantes por medio de un contacto, el cual será el
responsable de los datos de la empresa, la empresa podrá revisar quién se registró para
ocupar la vacante publicada. La empresa podrá contactarlo después de revisar su
solicitud y el currículo del desempleado.
3. Las empresas tendrán que tener una clave de usuario y una contraseña para
poder ver los postulados para su vacante.
5. Las empresas sólo podrán ver a los desempleados que se registraron para sus
vacantes.
7. El sistema deberá de ser fácil de usar por algún usuario aún sin tener ningún tipo
de capacitación para usar el sistema.
Glosario de términos
La definición del problema es difícil pues el del cliente usa los términos relacionados con el
problema y el técnico el lenguaje de los desarrolladores. Para que se puedan comunicar más
fácilmente todos los involucrados, se recomienda construir un glosario de términos que
establece un vocabulario común.
GLOSARIO DE TÉRMINOS
Actor: Es una entidad que interacciona con el sistema para obtener un resultado.
Puede ser una persona, otro sistema, un dispositivo, etc.
Bolsa de Trabajo: En este caso, es la concentración de información acerca de
empresas que tienen puestos disponibles (vacantes) y de personas que tienen la
necesidad de conseguir un empleo.
Caso de uso: Es la descripción de un conjunto de secuencias de acciones que un
sistema lleva a cabo para regresar un resultado observable a un actor.
Contraseña: Clave de seguridad que se le asigna a un usuario.
Desempleado: Persona que no tiene trabajo y está en busca de un empleo.
Empresa: Organización que tiene la necesidad de contratar a personas con
capacidades especificas para su correcto funcionamiento.
Nombre de usuario: Identificación del usuario para poder acceder al sistema.
Vacante: Puesto disponible para ser ocupado por un desempleado por parte de una
empresa.
Visitante: Persona que abre las páginas del sistema y revisa la información que se
presenta en este sitio Web, la información la podrá ver sin tener que registrar sus datos.
Los requerimientos deben formularse de forma clara, precisa y no ambigua. Para eso
pueden usarse varias técnicas al mismo tiempo: el lenguaje natural, que es claro para el
cliente pero ambiguo; el modelado gráfico, que es mas claro para el desarrollador y no es
ambiguo, pero puede no ser claro para el cliente; prototipo de interfaz de usuario, útil para
ambos pues es una representación visual de lo que hará el software.
Los casos de uso proporcionan una manera incremental y modular de describir software.
Definen como utilizan el software sus usuarios. El conjunto de casos de uso conforma el
modelo de casos de uso que describe el comportamiento general del sistema. Los casos de
uso proporcionan una representación que puede ser fácilmente comprendida por todos los
interesados. Se representan gráficamente con Diagramas de caso de uso de UML.
Consultar
vacante
Actor. Es algo externo al software que intercambia información con el sistema, puede ser
un usuario u otro sistema. El objetivo de un actor es completar una funcionalidad con el
software para obtener un valor o servicio. Se representa con una figura humana con el
nombre del actor en singular. Los sistemas externos con los que interacciona el software
que se está desarrollando también son actores. Un caso de uso puede proporcionar un valor
a uno o más actores. En el ejemplo del sistema para la Bolsa de Trabajo, un actor es el
Desempleado.
Desempleado
Alcance del sistema. Representa la frontera del sistema y contiene los casos de uso que se
realizan en cada ciclo de desarrollo. Se representa por un rectángulo que incluye los casos
de uso dentro del alcance del sistema.
Diagrama de casos de uso. Un diagrama de casos de uso incluye los actores identificados,
los casos de uso para cada actor y el alcance del sistema. En el diagrama general se ponen
las funcionalidades o casos de uso más generales que posteriormente se detallan en
diagramas en los que se desglosa cada funcionalidad. Este diagrama general tiene por
objetivo mostrar de forma gráfica y clara las funcionalidades del sistema por lo que deberá
ser simple, para mostrar a golpe de vista el alcance. Se recomienda que siempre se incluya
un caso de uso para entrar al sistema y uno de salir de los actores. El diagrama general se
discute con el cliente y los usuarios del software.
En la figura 2.3 se muestra el diagrama general de casos de uso del sistema de la Bolsa de
trabajo. En este diagrama se aprecian 8 casos de uso generales para 3 actores que
posteriormente se detallarán. El alcance del sistema está encuadrado en el rectángulo. Este
diagrama permite entender la funcionalidad general del sistema y su alcance.
Una vez identificados los principales casos de uso para cada actor, se describe en detalle
cada uno. La plantilla que se propone para esta descripción es:
Actor: Visitante
Descripción: Un Visitante entra al sistema para consultar las vacantes que están
disponibles.
Precondiciones:
Usuario Sistema
Paso Acción Paso Acción Excepción
1 El usuario da clic en el 2 Muestra la pantalla de Todas E1
vínculo Ver Vacantes. las Vacantes.
3 Selecciona la Vacante de
la cual desea ver los
datos a más detalle.
4 Da clic en el botón Ver 5 Se muestra la pantalla de E1,E2
Detalle de Vacante con los
datos de la vacante
seleccionada.
Id Nombre Acción
E1 La conexión con la base de datos Se manda un mensaje de error, el cual indica
no esta establecida o se que los datos no se pueden mostrar debido a que
interrumpió. no hay conexión con la base de datos.
E2 No se ha seleccionado ninguna No hace nada.
vacante
Poscondiciones:
En resumen, se debe cuidar que exista coincidencia entre el detalle de los casos de uso y el
prototipo. Deben coincidir:
• Las opciones del menú y los casos de uso
• Los nombres de las pantallas
• Los nombres de los botones
1. El sistema debe de ser fácil de usar, además deberá tener una interfaz gráfica
agradable y con colores suaves para no dañar en algún sentido visual al usuario.
2. El funcionamiento del sistema deberá estar activo las 24 horas del día y los 365 días
del año.
Confiabilidad
3. Este sistema deberá de tener una alta confiabilidad e integridad con los datos de los
usuarios.
4. Para poder modificar, dar de alta o eliminar datos, el usuario debe de proporcionar
al sistema un nombre de usuario y una contraseña.
Eficiencia
5. La velocidad para mostrarle los datos al usuario debe de ser considerable, lo cual
implica que la pagina no debe de contener imágenes muy pesadas que haga que el
sistema se retarde.
Restricciones de diseño y construcción
6. El sistema de software será construido para funcionar en ambiente Web.
7. El sistema deberá estar codificado en lenguaje de programación C#.
8. La base de datos del sistema de software deberá estar construida con el manejador
de bases de datos SQL-server 2000.
9. Para el desarrollo de este sistema se utilizarán las siguientes herramientas
a. Star UML para modelado del sistema.
b. Visual Studio 2003 (C#) para la codificación.
c. Microsoft Word para hacer la documentación.
d. ASP.NET para el desarrollo del sitio web.
e. SQL-Server para la creación de la Base de Datos.
f. Internet Information Server para la configuración del sitio Web.
Referencias bibliográficas
• Booch G., J. Rumbaugh, I. Jacobson. The Unified Modeling Language User Guide.
Addison-Wesley. 1999
• Coad P. at. al. Object Models, Strategies, Patterns and Applications. Yourdon Press
Computing Series, Prentice Hall. 1995
• SWEBOK. Guide to the Software Engineering Body of Knowlwdge. Trial version
Mayo 2001. www.swebok.org
• Tomayko J. E., Hazzan O. Human Aspects of Software Engineering. Charles River
Media, Computer Engineering Series. 2004.
Capítulo 3
Análisis
El trabajo en el análisis es construir el modelo del análisis que consiste en identificar los
elementos con los que se construirá el sistema y estructurarlos de tal forma que conformen
una primera versión de la arquitectura del sistema. En el caso del análisis orientado a
objetos los elementos del modelo serán clases.
Para documentar los resultados del análisis orientado a objetos se construyen dos vistas: la
vista estática, formada por diagramas de clase que representan los elementos estructurales
y sus relaciones; y la vista dinámica con las interacciones de los objetos de esas clases que
se modela con diagramas de secuencia.
Estos tres estereotipos están definidos por UML para facilitar la identificación de las clases
del sistema que se incluyen en los diagramas de clases, que forman la vista estática del
modelo del análisis.
Los diagramas de clases se usan para modelar gráficamente la vista estática del software.
Describen los tipos de objetos que son importantes para modelar un sistema y cómo se
relacionan [Arlow]. Contienen los siguientes elementos:
Desempleado
Nombre
Dirección
Teléfono
Email
Curriculum
Alta()
Modificar()
Consultar Datos()
Eliminar()
Postularse vacante()
• Relación muestra la dependencia entre dos o más clases. Los tipos principales de
relaciones entre clases son: asociación, agregación y generalización.
• Asociación es una relación estructural que describe ligas entre objetos de las clases.
Se representa por una línea que conecta a las clases asociadas. Esta liga puede tener
adornos como la multiplicidad que denota cuántos objetos de una clase pueden estar
relacionados con objetos de la otra.
Vacante
Nombre
Desempleado Requisitos
Nombre Sueldo
Dirección HoraInicio
Teléfono HoraFin
Email Descripción
Curriculum 1..*
1..* Alta()
Alta() Modificar()
Modificar() ConsultarDatos()
Consultar Datos() Eñliminar()
Eliminar()
Postularse vacante()
Esta asociación entre las clases Desempleado y Vacante indica que uno o mas
Desempleados pueden postularse para una o más Vacantes.
• Agregación es un tipo de asociación que denota que los objetos de una clase B
forman parte de un objeto de otra clase A. O sea que una clase A está compuesta por
objetos de la clase B. Se denota por una línea con un rombo del lado de la clase
compuesta, un ejemplo de este tipo de relación, es un libro que está compuesto por
varias páginas.
ClaseA
1
*
ClaseB
• Generalización relaciona a una clase general o abstracta que comparte sus atributos
y operaciones con clases que los especializan. Las subclases heredan todos los
atributos y operaciones de la superclase. La relación entre la clase general y sus
especializaciones se denota por una línea con un triángulo del lado de la general. Un
ejemplo de esta relación es una figura geométrica que puede especializarse en un
triángulo, cuadrado, círculo, etc. A todas estas figuras se les puede medir el
perímetro, el área pero cada una tiene su forma de calcularse.
ClaseGeneral
Clase
Identificación de clases
Para identificar las clases, se analiza cada caso de uso para imaginar qué clases se necesitan
de cada estereotipo. Se recomienda iniciar por la identificación de las clases de control.
Una técnica para identificar las clases son las tarjetas CRC [Beck, Cunningham]. Las
tarjetas CRC (Clase-Responsabilidad-Colaboración) se usan para determinar tanto las
clases como sus responsabilidades. Para cada responsabilidad se busca la colaboración con
otras clases y así se identifican nuevas clases. Estas tarjetas tienen la forma:
Nombre de clase
Responsabilidad Colaboración
Durante este proceso se van refinando y corrigiendo las tarjetas. Cuando ya se tiene un
conjunto de tarjetas para la realización de todos los casos de uso, se construye el diagrama
de clases a partir de éstas.
1. Para cada tarjeta se crea una clase en el diagrama, con el mismo nombre, en singular y
empezando con mayúscula.
2. Por cada responsabilidad de la clase, se define el método correspondiente, nombrado
como verbo en infinitivo y en minúsculas.
3. Para cada colaboración entre clases, se dibuja una relación de asociación entre ambas
clases.
Al analizar todos los casos de uso, se puede construir uno o varios diagramas de clases de
control para los casos de uso con las clases que son indispensables.
Clases de Interfaz.
Una vez teniendo las clases de control, se identifican las clases de interfaz de usuario. Para
encontrarlas, se revisa el prototipo de interfaz de usuario creado en la fase de
Especificación de requerimientos y se dibuja una clase para cada pantalla. Las clases de
interfaz se podrán implementar con diversas tecnologías como serán ventanas, código html,
jsp, etc. que se decidirán en el diseño.
Clases de Interfaz
Clases de Entidad.
Para identificar las clases de Entidad, se escogen las clases de control cuyos atributos deben
ser guardados. Para cada una de estas clases, se dibuja una clase de tipo entidad, que se
encargue de resguardar estos atributos en una base de datos o un archivo.
• Objetos son instancias de las clases. Se representan por un rectángulo con el nombre
subrayado de la clase a la que pertenecen. En el diagrama, cada objeto tiene una línea
vertical que representa su línea de tiempo que avanza de arriba – abajo.
:vacante
• Mensajes que son enviados de un objeto fuente a otro receptor a través del tiempo.
Representa la invocación del método del objeto receptor. Se modela como una línea con
la flecha del objeto fuente al receptor con el nombre del método sobre la línea el cual
puede o no contener los parámetros del método.
:Vacante :VacanteDB :
BufferedWriter
guardar()
Visi tante
Para cada flujo normal y alternativo de eventos en los casos de uso, se construye un
diagrama de secuencia. Estos diagramas representan la vista dinámica de los casos de uso
especificados en los requerimientos. Para su construcción se parte del detalle de los casos
de uso.
Por cada flujo de un caso de uso se identifican las clases de cada tipo necesarias para su
realización y se crea un diagrama de secuencia de la siguiente manera:
1. Se representa al actor que corresponde al caso de uso poniéndolo arriba en el extremo
izquierdo del diagrama.
2. El actor inicia las acciones del caso de uso enviando un mensaje a un objeto de una
clase de interfaz identificada para este flujo.
3. Enseguida se pone uno o mas objetos de clases de control y si es necesario, uno o mas
objetos de entidad.
4. Cada mensaje entre objetos aparece como una flecha dirigida del objeto solicitante al
objeto receptor, etiquetado con el nombre del método correspondiente.
5. Para visualizar el orden temporal del envío de los mensajes, la flecha de un mensaje
posterior se dibuja un poco mas abajo que la del mensaje anterior.
Es común que al hacer los diagramas de secuencia surjan nuevas clases y métodos no
identificados durante la construcción de los diagramas de clase. Por lo tanto, una vez
terminados los diagramas de secuencia para todos los casos de uso, se revisa la consistencia
entre ambos los diagramas de clase y de secuencia. Se modifican los diagramas de clases
según lo encontrado durante la construcción de los diagramas de secuencia.
Los cambios en los diagramas, significan que se está entendiendo mejor el problema y el
proceso se avanza de manera iterativa en la construcción de la solución computacional.
Para modelar el cambio de estados de entidades del sistema, que es otro aspecto de la vista
dinámica, se usan los diagramas de estados de UML.
Un diagrama de estados modela una máquina de estados finitos o autómata, que enfatiza el
flujo de control de un estado a otro. Es una gráfica con nodos que representan estados y
arcos dirigidos que representan transiciones entre los estados a causa de eventos. Los
elementos de estos diagramas son:
Principal
• Una transición modela el cambio de estado a causa de un evento. Se representa por una
flecha que va de un estado a otro. La flecha se puede etiquetar con el nombre del
evento.
• El estado final que se denota por un círculo con un punto negro en el centro. Puede
haber varios estados finales o ninguno.
Para construir el diagrama de estados, que modela la navegación, se parte del prototipo de
interfaz de usuario construido en la fase de Especificación de requerimientos. Las pantallas
se representan por estados y los eventos, que ocasionan el cambio de un estado a otro, por
las transiciones entre estados.
Otro uso de los diagramas de estado, es modelar el orden válido de ejecución de casos de
uso. Por ejemplo, el caso de uso de “Autentificar al usuario” que debe realizarse antes de
cualquier otro caso de uso. Para modelar el orden válido de ejecución de los casos de uso,
se parte del diagrama general de casos de uso. Cada caso de uso se modela como un estado
y el paso de un caso de uso a otro a consecuencia de un evento, se modela por una
transición.
Referencias bibliográficas
• Arlow J., Neustadt I. UML2 and the Unified Process. Practical Object-Oriented
Analysis and Design. 2a edición. Addison Wesley 2005.
• Beck K., Cunningham W., SIGPLAN Notices October 1989, vol. 24 (10).
• Rumbaugh J., Jacobson I., Booch G. “The Unified Software Development Process”.
Addison Wesley 1999.
Capítulo 4
Diseño
Diseñar para el cambio. Como se indicó en los principios de la Ingeniería del software, el
software cambia constantemente, por lo que es fundamental anticiparse a los cambios. Esto
significa que el diseño debe ser flexible para permitir cambios con relativa facilidad.
Diseñar para facilitar el uso del software. Es importante diseñar teniendo en mente a los
usuarios del software y sus aptitudes. Considerar algunos escenarios del uso del software,
puede ayudar en la identificación de los componentes que deberá tener.
Diseñar para facilitar la prueba. Este principio está enfocado en el desarrollador que
probará el sistema. Se identifican los componentes del sistema como unidades que se
puedan probar sin necesidad de incluir a otros componentes.
Para apoyar la aplicación estos principios del diseño, se tienen dos medidas que ayudan a
estructurar e identificar los componentes:
Los principios del diseño pueden usarse como criterios para evaluar los diseños. Es
importante aclarar que no existe El buen diseño.
Una capa es una abstracción que toma el resultado de la capa inferior, efectúa su función y
entrega ese resultado a la capa superior. La regla en este modelo es que cada capa se
comunica solamente con las capas adyacentes.
Una vez definida la arquitectura del producto de software, se representa con diagramas de
paquetes de UML.
Un paquete se representa con una carpeta con su nombre. Los paquetes pueden contener
otros paquetes, clases, interfaces, código html, etc. Los elementos de cada paquete deben
tener una alta cohesión y bajo acoplamiento con los elementos de otros paquetes.
Asociación (se representa por una línea continua). Establece una relación entre dos
paquetes que requieren de los servicios uno del otro. Esta relación es bidireccional.
Generalización (se representa por una línea continua con triángulo transparente que apunta
hacia el paquete más general). Un paquete representa los aspectos más generales y otro los
especializa, es la relación de herencia.
Realización (se representa por una línea punteada con triangulo transparente que apunta
hacia el paquete que va a ser realizada por otro). Es un contrato que promete que un
paquete va a ser implementado por otro.
La arquitectura de 3 capas se representa por paquetes que son una refinación de las capas
del Análisis:
• Capa de Presentación. Esta capa puede contener uno o varios paquetes que
contengan la interfaz de usuario. Por ejemplo, el paquete de la interfaz en el
servidor y el paquete con la interfaz del cliente. Los paquetes de la capa de
Presentación tienen el sufijo IH.
• Capa de Lógica de la aplicación. En general, esta capa contiene varios paquetes,
uno para cada funcionalidad del sistema. Estos paquetes pueden tener relaciones de
dependencia, asociación o generalización.
• Capa de Almacenamiento. En este paquete puede estar la base de datos o archivos
en uno o más paquetes.
Las relaciones entre estos tres paquetes serán de asociación del paquete de nivel inferior
(Almacenamiento), al intermedio (Lógica de la aplicación) y de éste al superior
(Presentación).
En la figura 4.1 se muestra un diagrama con las 3 capas de la arquitectura. Los paquetes de
la capa de Presentación son DesempleadosIH, VacantesIH y EmpresaIH. Los siguientes
paquetes pertenecen a la capa de Lógica de la aplicación, las relaciones que se muestran
entre estos paquetes son dependencias. Por ejemplo el Paquete Postulaciones depende de
Vacantes y de Desempleado. El paquete de Base de Datos contiene la capa del
Almacenamiento.
Los elementos de estos diagramas son: los nodos y las conexiones entre ellos.
Las conexiones son relaciones que representan las comunicaciones entre los nodos. Pueden
etiquetarse con un protocolo de comunicación.
En la figura 4.2 se muestran los nodos de un sistema en web. La conexión entre servidor y
el cliente es por el protocolo http.
Un componente es como una caja negra con un comportamiento bien definido que
encapsula una cierta parte del diseño y que proporciona interfaces para interaccionar con él.
Los componentes tienen interfaces de entrada que especifican lo que se debe proporcionar
para su ejecución e interfaces de salida que especifican lo que entregan al ejecutarse.
Pueden contener otros componentes relacionados entre sí por dependencias. Hay varios
tipos de componentes:[Arlow]
• Subsistemas que son formas de descomponer sistemas grandes en unidades
jerárquicas
• De construcción, definen un conjunto de cosas para organizar la construcción.
• De entidad, son componentes persistentes que representan algún concepto que debe
almacenarse.
La estructura de una base de datos relacional es muy sencilla, pero esta sencillez dificulta el
proceso de representar objetos completos.
Cada clase del diagrama de clases se convierte en el esquema de una tabla en la base de
datos relacional (figura 4.4). Se puede utilizar el mismo nombre de la clase para la tabla,
aunque se acostumbra que ese nombre esté en plural. Esta tabla tendrá como campos los
atributos de la clase, es decir, cada atributo se convierte en una columna de la tabla.
UML podría traducirse como un VARCHAR (254) en SQL. Para tipos enumerados, y sobre
todo si no se tienen dominios, se puede crear una tabla para el tipo y poner los valores en
ella, pues de esta forma se podría adicionar nuevos valores cuando se requiera. Una
sugerencia de transformación es la siguiente:
En la creación de tablas no hay nada con respecto a las operaciones, sin embargo existe la
posibilidad de representar conducta en el esquema a través de procedimientos almacenados.
Conversión de interfaces.
Conversión de asociaciones.
Una base de datos relacional contiene tablas, no asociaciones, por lo que las asociaciones
deben integrarse a las tablas a través de columnas especiales. En la conversión de una
asociación binaria a un esquema relacional se debe utilizar el concepto de llave externa.
Una llave externa, es un conjunto de columnas cuyo valor debe estar en la llave primaria de
la tabla con la que se está conectando.
En el ejemplo de la figura 4.6, se está especificando que una empresa coloca de 1 a varias
vacantes, y que cada vacante es colocada por una y sólo una empresa.
Notar en la figura 4.7, que en la tabla Empresas se define nombre como llave primaria
(PK) y en la tabla Vacantes se tiene nombreE como llave externa (FK) con lo cual se
especifica que nombreE debe ser el nombre de alguna empresa en la tabla Empresas y si
es el mismo ambas tuplas están relacionadas. En cada vacante sólo hay una nombreE, es
decir cada vacante es colocada por una empresa. Como el nombre de empresa se puede
repetir en la llave externa se tiene que cada empresa puede colocar más de una vacante.
Se crea una tabla para cada clase en la jerarquía de herencia, incluyendo las clases
abstractas, después se crean las llaves externas para cada relación de generalización. Si la
llave primaria de la superclase consta de varias columnas, se deben crear esas mismas
columnas en cada subclase.
Tomando como ejemplo la jerarquía de herencia mostrada en la figura 4.12 se tienen las
tres tablas mostradas en la figura 4.13. En tabla usuarios se tiene como llave primaria un
identificador para cada usuario, éste se utiliza como llave externa en cada una de las tablas
que representa a cada una de las subclases.
Lo importante en la conversión del modelo de datos UML al esquema relacional es ser muy
sistemático en el método. Si se entiende como mapear cada concepto UML en conceptos
relacionales es posible representar fácilmente la mayoría de los aspectos del modelo.
Referencias bibliográficas
• Arlow J., Neustadt I. UML2 and the Unified Process. Practical Object-Oriented
Analysis and Design. 2a edición. Addison Wesley 2005.
• Booch G., Rumbaugh J., Jacobson I. “The Unified Modeling Languaje. Users guide”.
Addison Wesley 1999.
• Humphrey Watts S., “Introduction to Team Software Process”, SEI Series in Software
Engineering, Addison Wesley, 2000.
• Jacobson I., Booch G., Rumbaugh J. “The Unified Software Development Process”.
Addison Wesley 1999.
• Pressman
Capítulo 5
Construcción
El detalle de las clases de control incluye: nombres y tipos de todos los atributos, para los
métodos se especifican los parámetros con sus tipos y el tipo del valor de retorno. Si algún
método requiere para su implementación de un algoritmo más complejo, éste se especifica
en seudo-código. La Figura 5.1. muestra un ejemplo de diseño detallado de una clase.
En los paquetes se incluyen las clases necesarias del ambiente de programación o las
bibliotecas disponibles para la construcción de las clases.
integridad entre los diagramas y el código, por lo que los cambios en uno se reflejan en los
otros.
Por ejemplo, un estándar de comentario de encabezado de una clase puede pedir que éste
contenga los siguientes elementos: el propósito de la clase, sus autores, la fecha de
creación, su versión actual y referencias cruzadas a otras clases o archivos.
Una alternativa para generar el código y leerlo a la vez por dos personas, es la
programación entre pares [Beck]. La idea principal de la programación entre pares es que
el código se escribe entre dos personas sentadas frente de una sola máquina. Un miembro
de la pareja tiene el control sobre el teclado y el ratón y es el que está codificando. La otra
persona lee lo que se va escribiendo, analiza el código, revisa la lógica y la sintaxis, y
comenta posibles alternativas y errores a su pareja. Este trabajo es dinámico, los roles
dentro de la pareja pueden cambiar constantemente.
Con esta práctica se hacen revisiones constantes al código pues quien no tiene el control del
teclado, está leyéndolo en cuanto se teclea y detecta errores que sería difícil y tardado de
encontrar posteriormente.
Aunque aparentemente con la programación entre pares se avanza mas lento, la práctica ha
demostrado que esto no necesariamente es verdad y que el código que se obtiene está mas
libre de errores lo que hace que tenga mejor calidad.
Las clases se prueban a través de la invocación de sus métodos. Para probar los métodos de
una clase se definen casos de prueba. Un caso de prueba de un método consiste en definir
un conjunto representativo de valores para los parámetros del método y el valor del
resultado esperado para ese conjunto. Para cada método se pueden definir uno o más casos
de prueba según la complejidad del método.
Para hacer las pruebas unitarias de clases cada ingeniero define su Plan de las pruebas
unitarias para las clases que está construyendo.
En el Plan de pruebas unitarias se define: las clases que se probarán, los métodos y los
casos de prueba para cada método. Una forma de especificar este plan es hacer una tabla
con 4 columnas:
• La clase que se probará.
• Método a probar.
• Los casos de prueba con los conjuntos de valores para los parámetros para cada
método.
• El resultado esperado de cada caso de prueba.
Para realizar la prueba unitaria de una clase, se crea un objeto de esa clase. Se invoca cada
método a probar con los parámetros definidos en sus casos de prueba. Si el resultado
obtenido coincide con el esperado, el método pasa esa prueba. Si no coincide, se revisa el
código del método para encontrar la causa del defecto y corregirlo. Se vuelve a aplicar el
mismo caso de prueba hasta que pase. Cuando una clase pasa todas las pruebas definidas en
el Plan de pruebas unitarias, es aceptada.
Para definir los casos de prueba se usan dos técnicas: las de caja blanca (transparente) y
las de caja negra. En las pruebas de caja blanca se toma en cuenta la estructura del código
de un método y se busca que durante las pruebas cada instrucción se ejecute al menos una
vez. Las de caja negra, consideran al código del método como un todo oculto, verificando
que para cada conjunto de valores de los parámetros se obtenga el resultado esperado.
A continuación se explican en que consisten ambos tipos de prueba y algunas técnicas para
planear ese tipo de pruebas.
Las pruebas de caja blanca también se conocen como pruebas estructurales. Se revisa la
estructura lógica de la unidad a probar tratando de definir casos de prueba que permiten
ejecutar por lo menos una vez, cada una de las instrucciones del método.
Una técnica que se usa como guía para saber cuántos casos de prueba se deben definir para
recorrer todas las instrucciones de la unidad por lo menos una vez, es la complejidad
ciclomática de McCabe. La complejidad ciclomática se define como el número de
condiciones encontradas en el código más 1. Una condición es un punto de decisión, como
por ejemplo if, while, for, etc.
Para planear las pruebas de caja blanca usando la complejidad ciclomática se determina el
número de casos de prueba necesarios usando la fórmula de la complejidad ciclomática.
Según este número, se definen los casos de prueba como conjuntos de valores de las
variables, que permitan recorrer las diferentes trayectorias del código. Para cada condición,
se eligen valores de las variables para que sea en una ocasión verdadera y en otra falsa. Para
cada conjunto de valores se define el resultado esperado.
Este tipo de prueba, también conocida como prueba funcional, revisa que la unidad cumpla
con la funcionalidad esperada sin considerar el detalle del código. Para definir los casos de
prueba, se establecen los posibles resultados esperados de la unidad y se identifican los
conjuntos de valores de los parámetros, para que se generen estos resultados.
Una técnica para diseñar los casos de prueba de caja negra son las Tablas de decisión. Las
tablas de decisión ayudan a describir combinaciones de datos de entrada que generan
diferentes salidas.
Resultados esperados: Las dos secciones de abajo especifican los resultados esperados
para las combinaciones de valores de las condiciones de entrada. Se marca con X que
resultado se espera para cada posible combinación de valores de los parámetros.
El Plan de pruebas unitarias de caja negra, creado a partir de la tabla de decisión, es una
tabla que tiene como casos de prueba la combinación de condiciones de valores cierto y
falso para los parámetros de entrada y los resultados esperados. En la figura 5.6 se muestra
el Plan de pruebas para la tabla de decisiones.
Las tablas de decisión es una técnica que se puede emplear durante el desarrollo del
software, en diferentes etapas, cuando hay combinaciones de condiciones para ayudar en la
toma de decisiones.
Para efectuar las pruebas unitarias, se recomienda primero ejecutar los casos de prueba de
caja negra. Posteriormente se agregan otros casos de prueba que permitan revisar la
estructura, según la técnica de caja blanca.
Muchas veces al querer probar una operación o método requiere de otros que no están
disponibles. Para simular su comportamiento se declaran métodos sustitutos llamados
Stubs. Los sustitutos no hacen nada excepto regresar el valor esperado, por lo que se puede
programar una pequeña interfaz por el cual el programador simula que se invocó el método
y que eventualmente proporciona el resultado esperado.
Referencias bibliográficas
Capítulo 6
Integración y prueba del sistema
Para hacer la integración, se usa como guía el diseño arquitectónico, y se asegura que se
tienen todos los componentes definidos en el diseño en la última versión aprobada.
Para definir el orden de integración de los elementos del sistema, se puede seguir alguna de
estas estrategias [Binder]
• Estrategia de paquetes. La idea es hacer las integraciones según los paquetes del
diseño. Por ejemplo, se integran todos los elementos del paquete de interfaz de usuario
para un actor.
• Estrategia por funcionalidad o casos de uso. La idea es integrar los paquetes de las
tres capas que corresponden a la realización de un caso de uso. Se puede hacerlo para
varios casos de uso en paralelo, cuando no hay dependencia entre ellos.
No existe una estrategia adecuada para todos los sistemas, decidir cuál usar es decisión del
proyecto y el nivel de diseño efectuado.
El elemento del paquete que no dependa de otros, es el primero que se integra. En el caso
de las clases, una clase depende de otra si invoca alguno de sus métodos. Bajo esta regla, se
puede crear una gráfica de dependencias entre clases que sirve de guía para definir el orden
de integración.
Al integrar los componentes se identifican los métodos que se invocan entre clases. Estos
métodos deben ejecutarse para comprobar que el paso de parámetros y los resultados
devueltos son los adecuados.
Como es muy difícil probar al cien por ciento todos los aspectos del sistema, se debe
planear a qué se le dará prioridad. Por ejemplo, se puede decidir primero asegurar que
cumple con sus funciones, luego evaluar la usabilidad, posteriormente comprobar el
sistema bajo condiciones de estrés y medir el desempeño.
Al probar el sistema se debe comprobar que cumplan con los requerimientos y asegurar que
todas las funcionalidades están cubiertas.
Una técnica para documentar lo que se quiere probar son las tablas cruzadas. Una tabla
cruzada contiene en los renglones los requerimientos y en las columnas los componentes
del sistema. En el interior de la tabla se pone “X” si el requerimiento “i” está cubierto en el
componente “j” para indicar en qué componentes están cubiertos los requerimientos.
De esta manera se tiene una lista de comprobación de que se están cumpliendo todos los
requerimientos, pues ningún renglón deberá estar vacío, lo que indica que al menos algún
componente del sistema cubre ese requerimiento.
Por otro lado, al revisar las columnas ninguna estará en blanco, lo que significa que los
componente cooperan con al menos un requerimiento.
Esta tabla documenta qué componentes cubren a qué requerimientos, lo que es útil para
mantener el sistema al hacer cambios a los requerimientos.
Efectuadas las pruebas, se corrigen los defectos encontrados. Se vuelven a aplicar pruebas,
conocidas como pruebas de regresión. Las pruebas de regresión sirven para detectar
defectos al hacer cambios a componentes ya probados. Al iniciar un nuevo ciclo de
desarrollo, se generan nuevos componentes o se modifican los que se tenían para incluir
nuevas funcionalidades o características. Esos componentes pueden ocasionar fallas en lo
que ya funcionaba por efectos laterales o nuevas interacciones.
6.3 Manuales
Al construir un sistema, siguiendo el ciclo de desarrollo, se ha generando la documentación
del sistema para los desarrolladores en siguientes ciclos o para el mantenimiento. Sin
embargo, generalmente se requiere de manuales para otros involucrados en el sistema,
principalmente sus usuarios.
• Los manuales deberán estar escritos en el lenguaje del lector a quien está dirigido.
Manual de usuario
Este manual debe contener información que permita usar el sistema. Es un documento
electrónico o impreso que describe la forma de uso del software, organizado con base a la
interfaz de usuario. El contenido debe incluir:
• Cómo se entra, qué aparece en la interfaz, qué se espera en cada opción o campo,
qué responderá el sistema, cómo resolver problemas a la hora de la ejecución.
Este manual también podría contener información sobre la instalación que pueda ser útil al
usuario.
Se aplican pruebas de usuario a cada manual para asegurarse que la escritura es clara,
precisa, completa y entendible.
Referencias bibliográficas