Ciclo de desarrollo de un programa


Definición de Problema: Se definen los problemas por los que tiene que pasar para poder dar el resultado. Se crea una una lista de cosas que queremos que haga nuestro programa. Lo normal es que recopilemos dicha lista hablando con todas las personas que podamos: usuarios de nuestro programa, expertos en el tema de que trata el programa, etc, etc.

EJEMPLO:
Suponiendo que quiero hacer un programa para jugar al ajedrez.

Normalmente la gente con la que hablemos nos dará los requisitos de una forma vaga y desordenada. Es labor nuestra ordenarlos (por temas, por dificultad, por importancia para los usuarios, etc) y asegurarnos de que son claros.
Para asegurarnos de que un requisito es claro, debemos saber qué persona lo ha propuesto y por qué lo ha propuesto, qué es lo que cree exactamente que vamos a hacer en nuestro programa cuando nos ha dicho ese requisito.
Por ejemplo, unos cuantos requisitos para nuestro programa de ajedrez pueden ser:
  • Que avise de los jaques
  • Que el movimiento de las piezas del tablero sea suave
  • Que tarde menos de 30 segundos en "pensar" un movimiento
  • Si el usuario no sabe qué mover, que pueda pedirle ayuda al ordenador.
  • Que pueda aprender aperturas que se le introduzcan.
  • Que guarde las partidas en una base de datos

y ahora toca aclararlos. ¿Qué es avisar de los jaques? ¿un pitido? ¿un texto "jaque" en algún sitio de la pantalla? ¿una voz que diga "jaque"? ¿Debe avisar también cuando el usuario es el que da jaque al ordenador? ...

E incluso ordenarlos. ¿Cuales son los más importantes para los usuarios? Los menos importantes se podrían dejar para el final o darles menos importancia, dedicarles menos tiempo que a los importantes. ¿Cuales son más difíciles de hacer?. Quizás debamos dedicarnos a ellos primero, para saber si vamos a ser capaces de hacerlos, o vamos a tener que dejar el programa a medias, después de haber trabajado unos meses en él. Podríamos empezar a negociar antes con el cliente para cambiar dicho requisito por otro.




Análisis de los problemas y su viabilidad: recopilar, examinar y formular los requisitos del cliente y examinar cualquier restricción que se pueda aplicar. Durante el análisis vamos a definir más claramente qué es lo que va a hacer nuestro programa. Debemos hacer varias cosas principalmente:

Identificar actores.
En lenguaje UML, actores son los usuarios y cualesquiera otros sistemas con los que se pueda comunicar nuestro programa. En nuestro programa de ajedrez, un actor sería el usuario que va a jugar al ajedrez. Le llamaremos "jugador". También se indicaba como requisito que pueda aprender aperturas. La persona que le va a enseñar aperturas a nuestro programa podría ser otro actor, al que podemos llamar "maestro". Una misma persona puede ser varios actores. Por ejemplo si alguien compra nuestro programa de ajedrez, a veces puede jugar y otras veces puede enseñarle aperturas. Es la misma persona, pero el papel que desempeña en cada caso es distinto.

Identificar casos de uso.
Un caso de uso es algo que un actor quiera hacer con nuestro sistema. Por ejemplo, un caso de uso para un "jugador" es "jugar una partida". Está claro que el jugador quiere nuestro programa para jugar una partida de ajedrez. Otro posible caso de uso es "análisis de un tablero". El "jugador" pone las piezas en determinada posición y quiere que el ordenador le dé una lista de posibles movimientos, etc, etc. En resumen, debemos obtener una lista de cosas que los actores van a querer hacer con nuestro sistema. Deben ser cosas grandes y no meternos en los detalles. "Mover una pieza" no sería un caso de uso, sino una parte de "jugar una partida".


CasosUso.gif




Detallar casos de uso.
En un texto vamos poniendo varios puntos. En cada punto ponemos sentencias del estilo "el usuario hace tal cosa y el programa hace tal otra". Es decir, explicamos por escrito, desde el punto de vista del usuario, qué es lo que tiene que hacer y qué es lo que va a hacer el ordenador. Por ejemplo, para "jugar una partida"
  • El usuario indica que quiere jugar una partida. El programa le pregunta el color de las piezas con las que quiere jugar
  • El usuario elige el color. El programa le dibuja el tablero con las piezas colocadas en la posición inicial. Las piezas del usuario en la parte inferior de la pantalla. Si el programa tiene blancas, piensa y realiza el primer movimiento.
  • El usuario mueve su pieza. El programa comprueba que el movimiento es correcto, piensa y realiza su propio movimiento.
  • Se repite el paso anterior hasta llegar a jaque mate o tablas.
En el caso de uso se detalla una situación normal, sin fallos ni situaciones raras. Al final debería ponerse una pequeña lista con los posibles fallos o situaciones anómales.
  • Si el movimiento del ordenador pone en jaque al usuario, el ordenador avisa del jaque
  • Si el usuario intenta un movimiento incorrecto, el ordenador avisa y deja al usuario que vuelva a intentarlo
Advertir que en ningún caso nos hemos metido a detallar cómo va a hacer algo nuestro programa, sólamente qué es lo que va a hacer.
Siguiendo los esquemas UML, podemos incluso hacer por cada caso de uso un diagrama de secuencia en el que los objetos implicados son el actor (el "jugador") y nuestro programa, sin meternos dentro de él.
También en este paso podemos ir empezando a pensar en cómo van a ser las pantallas de la interface de usuario, de nuestro programa.

Diagrama de clases del negocio
Es un diagrama de clases de objetos que tienen sentido para el usuario. En el caso del ajedrez los objetos serían del estilo "tablero", "pieza blanca", "torre blanca", "jugador", "cronómetro", "partida", "torneo" etc. Nunca "lista de piezas", "array de casillas", etc. También se presentan las relaciones entre ellos, como "las piezas están en el tablero", "la torre blanca es una pieza blanca", etc.
Este diagrama a este nivel tiene dos utilidades:
  • Asegurar que los que saben del tema y los que hacen el programa están hablando de lo mismo.
  • Servir de base para el diseño detallado orientado a objetos.
Cuando el tema es más complejo o menos conocido que una partida de ajedrez, es posible que el informático que programa no tenga muy claros muchos de los conceptos que tiene que manejar. No sabe qué es un asiento contable, un balance, si hay relación entre ellos, etc.
Es por eso importante hacer un diagrama de este tipo, en conjunto con un experto o con el cliente, para asegurar que no hay malentendidos.



Negocio.gif




Diseño general: Aquí ya empezamos a pensar en cómo vamos a hacer las cosas.

En el diseño preliminar tratamos de establecer la arquitectura de nuestro programa. La arquitectura es un esquema de en qué módulos/paquetes vamos a dividir nuestro programa, qué librerías. Si el programa es suficientemente grande, quizás vaya en varios ejecutables, una arquitectura cliente/servidor, etc.
Viendo los casos de usos, deberíamos ver qué cosas podemos hacer comunes o como librerias aparte, que podamos reutilizar. Por ejemplo, en nuestro caso del juego de ajedrez, podríamos hacer los siguientes paquetes:
  • Paquete de ajedrez. Un paquete que sea capaz de jugar al ajedrez, pero sin ningún tipo de relación con las pantallas. Si es una clase, tendría métodos del estilo "Poner_Piezas_Posición_Inicial()", "Mover_Pieza()", "Dame_Siguiente_Movimiento()", etc, etc. Sólo con este paquete, seríamos capaces de jugar al ajedrez, o de instanciar dos paquetes y hacer que jueguen entre ellos, o jugar en red, etc.
  • Interface con el usuario. Un paquete con el dibujo del tablero, las piezas, recoger los movimientos del usuario etc.
Dentro de estos paquetes, podemos ir pensando más subpaquetes, etc.
En este punto y con los casos de uso en general, debemos tener cuidado. Según una crítica generalizada a los casos de uso, estos llevan a un diseño funcional y no a uno orientado a objetos. Debemos tratar de pensar en objetos y almacenarlos juntos en la misma librería cuando estén muy relacionados entre sí, no en funciones. Por ello es buena idea tratar de agrupar las clases del diagrama de clases del negocio en paquetes y tratar de desarrollar la arquitectura a partir de ellas.
Es importante en este paso definir las interfaces y relaciones entre paquetes. Para ello puede servir de ayuda hacer los diagramas de secuencia de los casos de uso mostrando los actores, los paquetes y los mensajes entre ellos. Según vayan creciendo los diagramas de secuencia por aquello de ir entrando en detalles, podremos ir extrayendo subcasos de uso, como "mover pieza", "elegir color", etc.
Secuencia.gif



Algoritmo:
Un algoritmo es un un metodo para resolver un problema mediente una serie de pasos!"

El algoritmo se puede representar por medio de dos formas :

Pseudo código
Diagrama de flujo

Pseudocódigo o diagrama de flujo (algoritmo): Este es en realidad el primer paso que se debe de seguir pues generalmente ya se tiene definido el problema. En esta etapa es donde se determinan los pasos o instrucciones a seguir y el orden lógico de su ejecución para darle una eficiente solución al problema. Aquí es donde radica toda la dificultad para solucionar un problema por computador; el resto de las etapas básicamente se circunscriben a la adaptación para que un computador determinado ejecute los pasos o instrucciones planteados en el seudocódigo y se obtengas los resultados esperados.



Es la representación grafica del algoritmo; según la ANSI consta de una simbologia , que tiene los siguientes significados:


algo.jpg


DISEÑO PRELIMINAR/DISEÑO DETALLADO


Aquí ya empezamos a pensar en cómo vamos a hacer las cosas.

Tratamos de definir la arquitectura del juego, es decir: los modulos o paquetes en los que se va a dividir el programa.
Viendo los casos de usos, deberíamos ver qué cosas podemos hacer comunes o como librerias aparte, que podamos reutilizar. Por ejemplo, en nuestro caso del juego de ajedrez, podríamos hacer los siguientes paquetes:
  • Paquete de ajedrez. Un paquete que sea capaz de jugar al ajedrez, pero sin ningún tipo de relación con las pantallas. Si es una clase, tendría métodos del estilo "Poner_Piezas_Posición_Inicial()", "Mover_Pieza()", "Dame_Siguiente_Movimiento()", etc, etc. Sólo con este paquete, seríamos capaces de jugar al ajedrez, o de instanciar dos paquetes y hacer que jueguen entre ellos, o jugar en red, etc.
  • Interface con el usuario. Un paquete con el dibujo del tablero, las piezas, recoger los movimientos del usuario etc.

Dentro de estos paquetes, podemos ir pensando más subpaquetes, etc.

En el diseño detallado ya se entra a nivel de clases y métodos. Por cada paquete que hayamos extraido en el paso anterior y siguiendo siempre los casos de uso, debemos ir detallando las clases que vamos a implementar y los métodos que van a tener. Detallamos aun más los casos de uso y las interfaces de las clases.

IMPLEMENTACIÓN Y PRUEBAS

Pues a ello. Hay muchas cosas que se podrían contar aquí, pero no son de diseño.
De las pruebas podemos decir que hay que escribir los "casos de prueba". Básicamente son como la descripción de los casos de uso, pero indicando datos concretos que el operador va a introducir y qué resultados exactos debe dar nuestro programa.

Documentación
Este paso es muy importante por que guardamos la historia de como se creo el programa paso a paso, ayuda a la facil utilizacion del programa por parte del usuario.

Por ejemplo se guardaran las reglas, los movimientos permitidos etc. etc. los algoritmos que se llevaran a cabo para respetar todo esto.

Mantenimiento.
El mantenimiento del software es la modificación de un producto software después de la entrega para corregir fallos, para mejorar el rendimiento u otros atributos, o para adaptar el producto a un entorno modificado.
Por ejemplo.
En nuestro juego de ajedrez ya entregado, se recibe una queja de un mal movimiento en alguna ficha, o cualquier fallo que pudiera tener el programa.
Entonces el programa se revisa para poder arreglar los problemas.









Fuentes:
http://www.chuidiang.com/ood/metodologia/metodologia.php
http://cnx.org/content/m17404/latest/