Diseño e Implementación en Delphi del Caso de Posicionamiento 2D Jordi Juan García Joaquín Díaz Maíquez Facultad de Informática - Universidad Politécnica de Valencia email: [email protected], [email protected] Resumen En este documento abarcamos la aplicación de la metodología orientada a objetos en el diseño y en la implementación del caso de posicionamiento 2D, ampliamente resuelto mediante técnicas de análisis y diseño estructurado. Para ello, haremos uso del lenguaje Delphi, que es una extensión del Object Pascal, en la implementación del sistema. En cuanto al diseño, propondremos un modelo de objetos que especificaremos mediante la herramienta Rational Rose. Por último, comentaremos las ventajas e inconvenientes que conlleva la aplicación de esta metodología, orientando la explicación a la elaboración de sistemas no complejos, como es el caso que nos ocupa. 1. Introducción “La Ingeniería de la Programación se define como la disciplina tecnológica relacionada con la producción sistemática y el mantenimiento de productos software que son desarrollados y modificados en el tiempo previsto y dentro de los costes estimados.” [1] Partiendo de esta definición, definimos el concepto de método en ingeniería de la programación como un conjunto ordenado de pasos para obtener un resultado específico, mientras que metodología es el estudio de una familia de métodos. A lo largo del documento vamos a hacer hincapié en el uso de la metodología orientada a objetos de cara a la realización del diseño y la implementación del caso de posicionamiento 2D enunciado en [1] (págs. 193-194), mientras que el método elegido para la elaboración del sistema será UML [2]. La metodología orientada a objetos establece cómo abordar de un modo sistemático la construcción de software, y está centrada en el análisis y diseño, que son las fases del proceso de producción de software donde se acomete el modelado del sistema. Además, en estas fases describimos el problema y la solución mediante una serie de modelos. Esta metodología se puede concebir desde dos perspectivas dimensionales de distinta naturaleza: Tecnológica: conceptos, notación y herramientas usadas para el modelado Proceso: conjunto de pasos a realizar y resultados obtenidos en cada paso En cuanto a nuestra inclinación por UML como método para la especificación del sistema, además de por ser un método estándar y ampliamente difundido en la comunidad científica, debemos tener en cuenta las siguientes características: 1 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia es un método totalmente apropiado en el contexto de desarrollo en el que estamos introducidos, ya que aporta facilidades para la reingeniería, nuevo software, prototipado o reutilización cubre el ciclo de vida en un grado muy amplio, abarcando el análisis, diseño, implementación, testing, etc. En los métodos orientados a objetos la descomposición del sistema se basa en los objetos o clases de objetos que se descubren en el dominio del problema. Problema Representación del dominio del problema Representación del dominio de la solución Figura 1. Relación entre las fases de análisis y diseño. Los objetivos del análisis son los siguientes: Comprender el problema que el sistema software debe resolver Decidir lo que el sistema debe hacer Asegurar que el sistema satisface las necesidades de los usuarios y definir criterios de aceptación Proporcionar una base para el desarrollo del sistema En cuanto al diseño del sistema, distinguimos tres etapas, que son el diseño del sistema, el diseño de objetos y el diseño de la persistencia. En el diseño del sistema se produce una descomposición del modelo de objetos en subsistemas, y una elección de la arquitectura para conectar dichos subsistemas. En el diseño de objetos, modelizamos el dominio de la solución, lo cual incluye las clases del modelo de análisis con, posiblemente, algunas modificaciones más, tales como: Clases de la interface: relacionadas con la interface de usuario, representan la visión del usuario de las clases del modelo conceptual Clases de la aplicación: son los objetos que comienzan la aplicación y que controlan la secuenciación de funciones, es decir, secuencian las llamadas a las funciones que están dentro del diseño de objetos, eligiendo un orden de dichas funciones según la acción a realizar 2 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia Clases base/utilidades: son componentes que son independientes de la aplicación considerada, como por ejemplo, colecciones, estructuras de datos predefinidas, etc. En definitiva, las clases propias del diseño son aquellas que no tienen una correspondencia directa con las clases de análisis, y entre ellas se encuentran el acceso a las bases de datos o las estructuras de datos, clases de la interface de usuario, etc. Clases semánticas Dominio del Problema Clases Base/Utilidades Clases de la Aplicación Clases de la Interface Dominio de la solución Figura 2. Clases del problema y de la solución Por último, comentar que en el diseño de la persistencia se trabajan detalles relativos a que el sistema tenga la capacidad necesaria para poder trabajar frente a una base de datos relacional, y para ello las clases se transforman en tablas y las relaciones entre clases se representan en el modelo relacional mediante claves ajenas. 2. Diseño del Sistema En este apartado vamos a especificar conceptualmente el sistema que estamos resolviendo, y para ello procederemos a la elaboración de un diagrama de clases que capture y reproduzca fielmente el propósito del caso de posicionamiento 2D. El diagrama de clases refleja la estructura estática del sistema, y es la herramienta principal de la mayor parte de los métodos OO, ya que contiene clases relacionadas con otras clases, mediante asociaciones, ordenadas en jerarquías de agregación y de generalización/especialización. Cuando sea conveniente, se pueden utilizar también diagramas que contengan objetos, entendidos como una entidad de programación con dos componentes; por una parte está el estado del objeto, que contiene la información que puede almacenar el objeto y que puede variar con respecto al tiempo, y por otra el comportamiento del objeto, que es el conjunto de acciones que puede realizar. 3 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia Cada objeto posee una interfaz que contiene los servicios que ofrece al mundo exterior. Además, en un lenguaje orientado a objetos, con ocultación de información, no se puede acceder libremente a los campos de un objeto. La mayor parte de los sistemas orientados a objetos distinguen entre la descripción de un objeto y el objeto en sí. Como muchos objetos similares pueden ser descritos por una misma definición o esquema general, a esta definición o descripción se le llama clase. Una clase en el diagrama de clases es la descripción de un grupo de objetos con estructura, comportamiento y relaciones similares. Realmente se trata de una abstracción, ya que un objeto es una manifestación concreta de esa abstracción. A continuación presentamos el diagrama de clases del sistema que estamos desarrollando: En este diagrama están expresadas las clases semánticas, es decir, las clases que definen las reglas del negocio que forman parte del proceso del sistema que estamos modelando. De igual forma, como se ha comentado antes, existen las clases de interface, de la aplicación y las clases relativas a la persistencia de los datos, aunque para estos casos no hay estándares en cuanto al modelado propiamente dicho se refiere. Podemos observar la figura central de la clase Mapa, la cual tiene una perspectiva global del sistema y desde la cual, estableciendo contextos navegacionales, podemos navegar a 4 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia cualquier información que se encuentre en el sistema, es decir, que desde la clase Mapa accedemos a cualquier otra clase que se halle presente en el sistema. En términos más cercanos a la jerga del problema que estamos considerando, podemos decir, siempre teniendo en cuenta el modelo que acabamos de presentar, que un mapa está formado por 400 celdas, las cuales forman una matriz 20x20. Además, asociado a un mapa tenemos una ruta. Por otra parte, tenemos rutas que están asociadas a un mapa, dichas rutas pueden ser reales o estimadas. Cada ruta está formada por uno o más avances, los cuales están asociados a una posición. Esta sería la descripción general de lo que estamos modelando. Si echamos un vistazo a los atributos, obtenemos nueva información de la realidad que estamos modelando. De este modo, un mapa tiene asociada una ruta real y una ruta estimada; a una celda la caracterizamos por su marca (una celda marcada formará parte de la ruta, estos aspectos ya los veremos en implementación); un avance está formado por una dirección y por unos pasos; y una posición tiene una coordenada X y una coordenada Y. Hasta aquí tenemos toda la información del sistema que podemos extraer del modelo atendiendo a la parte estática, pero si nos fijamos en las operaciones obtendremos información de la parte dinámica o de comportamiento del sistema. Así, vemos que desde el mapa podemos validar la dirección y los pasos del avance, calcular la dirección estimada de la ruta estimada, unir los puntos que forman parte de la ruta real, unir los puntos que forman parte de la ruta estimada, o imprimir el mapa por pantalla. De una celda podemos saber si está marcada y cuál es su marca, de una ruta real podemos calcular la nueva posición después de que se haya producido un avance, de una ruta estimada podemos calcular las nuevas coordenadas que se estiman, mientras que de un avance y de una posición podemos obtener información sobre los atributos de la clase. Con la información estática y de comportamiento del sistema, poco a poco vamos comprendiendo y acercándonos más a la propia naturaleza del sistema de información que estamos modelando. Es decir, que en este punto ya hemos abarcado, dentro de la fase de diseño, el diseño del sistema y el diseño de objetos. Ahora sólo nos queda por cumplimentar el diseño de la persistencia. El diseño de la persistencia trata sobre la ubicación de los datos que va a necesitar el sistema, tanto para consultas como para almacenamiento o manipulación de los mismos. En estos casos, lo aconsejable y razonable es utilizar una base de datos relacional para almacenar dichos datos. Hemos escogido una tecnología relacional para la base de datos por ser la que más asentada se encuentra en el mercado en este momento, aunque también podríamos haber hecho uso de una tecnología objeto-relacional. Debido a la mínima complejidad del sistema que estamos desarrollando, la información a almacenar va a ser muy escasa, ya que en términos prácticos sólo necesitamos guardarnos la información relativa a las posiciones que forman parte de la ruta que posteriormente podremos visualizar. Si así lo queremos, también podemos almacenar la dirección y el número de pasos de cada avance vinculado a una posición; de esta manera podremos extraer estadísticas de la ruta. 5 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia Con todo lo comentado, podemos extraer como conclusión que necesitamos almacenar información de las posiciones y de los avances. Ello nos haría pensar en la elaboración de dos tablas, una correspondiente a la clase Posición y otra para la clase Avance, pero como la relación entre ambas clases es una asociación uno a uno, podemos fusionar toda esta información en una única tabla que conglomere los atributos de dichas clases. En pocas palabras, con sólo una tabla garantizamos la persistencia del sistema de información. Por último, sólo queda comentar que como cada tupla que forma parte de la tabla debe estar perfectamente identificada, nos vemos en la obligación de añadir un nuevo campo de la tupla, que es un código identificador precisamente de esa tupla. De esta manera, podemos utilizar este campo como la clave primaria de la tabla que estamos diseñando. De este modo, cada tupla de nuestra tabla Ruta está compuesta por los siguientes campos: - identificador de avance dirección del avance número de pasos del avance coordenada X asociada al avance coordenada Y asociada al avance Con todos estos detalles expuestos, ya sólo nos queda por hablar de la implementación del sistema. 3. Implementación De cara a la implementación del sistema, hemos optado por el lenguaje Delphi, que no es más que una extensión del Object Pascal. Por ello, Delphi soporta los conceptos fundamentales de la programación orientada a objetos: clases, herencia y polimorfismo. Una clase es un tipo de datos definido por el usuario que contiene: un estado (representación) y un comportamiento (operaciones). Las clases las utiliza el programador para introducir nuevos tipos de datos en el sistema. Un objeto es una instancia de una clase, o una variable del tipo de datos definido por la clase. Aquí ponemos como ejemplo la clase Avance: type TAvance = Class private direccion : string; // dirección del avance pasos : integer; // pasos del avance posicion : TPosicion; // posición del mapa asociado al avance public constructor crear(d : string; p : integer); procedure crearPosicion(x, y : integer); function obtenerDireccion : string; function obtenerPasos : integer; function obtenerX : integer; // coordX de la posición asociada function obtenerY : integer; // coordY de la posición asociada 6 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia procedure destruir; end; Delphi utiliza un modelo de referencias para ubicar los objetos en memoria, es decir, las variables de tipo clase contienen una referencia a un objeto de tipo class. Los objetos se crean y se destruyen utilizando métodos especiales llamados constructores y destructores. Ejemplo del constructor de la clase Avance: constructor TAvance.crear(d: string; p : integer); begin direccion := d; pasos := p; end; Cuando un constructor se invoca se producen las siguientes acciones: - reserva de espacio en el montículo (heap) para la instancia inicialización de los atributos del objeto ejecución del código del constructor finalmente, se devuelve una referencia al nuevo objeto Los destructores sirven para destruir objetos, produciéndose las siguientes acciones: - se ejecuta el código situado dentro del destructor se libera la memoria donde estaba almacenado el objeto En cuanto a la herencia, Delphi dispone de herencia simple y se declara de forma explícita. En nuestra aplicación utilizamos la herencia en las clases Real y Estimada, las cuales heredan de la clase Ruta. A continuación ponemos un ejemplo de uso de la herencia, para ello presentamos la definición de la clase Ruta y de la clase Real: TRuta = Class protected avance : array [0..MaxAvances] of TAvance; // avances de la ruta numAvances : integer; public constructor crear; virtual; function obtenerAvances : integer; function obtenerX(indice : integer) : integer;//coordX del avance i-esimo function obtenerY(indice : integer) : integer;//coordY del avance i-esimo procedure destruir; end; 7 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia TReal = Class (TRuta) public constructor crear; override; procedure calcularNuevaPosicion(pos : TPosicion; dir : string; pasos, id integer); procedure obtenerRuta; end; : Delphi proporciona dos mecanismos de ocultación de información: unidad de compilación y clase. Unit Unidad; Interface { características públicas de la unidad de compilación} Implementation { implementación de características públicas + privadas } begin end. Ello posibilita que podamos definir una clase del sistema por unidad, facilitando la modularidad y el encapsulamiento de la información. En cuanto a las interfaces de usuario, principalmente hemos diseñado las siguientes: una inicial que le ofrece al usuario las distintas opciones presentes en el programa otra para la introducción de la ruta otra para la visualización de la ruta y una última para la visualización de las estadísticas de la ruta Aquí tenemos una muestra de la interfaz inicial del sistema: A continuación mostramos un ejemplo de la interfaz de visualización de la ruta: 8 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia Por último, mostramos la interfaz de estadísticas, que accede directamente a la base de datos: 4. Conclusiones 9 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia La aplicación de un lenguaje visual a la hora de implementar un sistema software dota al producto final de un entorno muy agradable y amigable, lo cual produce un impacto grande en el usuario que está utilizando el producto. Ahora bien, detrás de ese aspecto impecable que deja a las aplicaciones, un lenguaje visual está compuesto por jerarquías muy amplias de clases, ya que hay multitud de eventos, lo cual desemboca en un indeseado aumento de las transacciones debido a la complejidad de la interfaz de usuario. Es decir, que al realizar una programación dirigida por eventos, la dificultad de implementación aumenta, ya que no sólo tenemos que prestar atención a la lógica interna del producto y asegurarnos que implementa correctamente las reglas del negocio, si no que además tenemos que prestar atención a detalles como la interfaz de usuario y a accesos a bases de datos, en lo que se conoce como una arquitectura de 3 capas. En los sistemas de información de complejidad mínima, como es el caso que nos ocupa, se obtiene una mayor eficiencia utilizando un lenguaje de 3ª generación, el cual utiliza ficheros planos para acceder a la información y no hace uso de bases de datos; y además no se implementa interfaz gráfica alguna. Desde este punto de vista, usar un lenguaje de este tipo consume muchos menos recursos que el uso de un lenguaje visual. Además, la aplicación de la metodología orientada a objetos en este sistema tampoco es la óptima en cuanto al consumo de memoria se refiere. Con orientación a objetos también aumenta el consumo de recursos de una manera notable. Por poner un ejemplo, en nuestro sistema, sólo con inicializar el mapa, se cargan en memoria 20x20 = 400 objetos de tipo celda, los cuales en una metodología estructurada serían fácilmente implementables en una estructura sencilla, tal como puede ser el vector. Como conclusión final, resaltar la importancia de aplicar una metodología orientada a objetos en el sentido de que dota de una mayor trazabilidad a las diferentes fases que forman parte del proceso de producción de software, y nos acerca la ingeniería del software a una verdadera actividad de ingeniería. Pero también es cierto que el esfuerzo realizado a lo largo de todo el proceso es enorme, limitando de esta manera el tiempo de entrega del producto final, por lo que es conveniente aplicar dicho proceso a sistemas de información con una complejidad lo suficientemente elevada que nos permita justificar que el esfuerzo empleado no ha sido en vano. 5. Referencias [1] Molina A., Letelier P., Sánchez P., Sánchez J., Metodología y Tecnología de la Programación, Servicio de Publicaciones UPV-97.498, 1997. [2] Rational Software Corporation, The Unified Modeling Language Notation Guide v.1.3. [http://www.rational.com], 2000. [3] www.dsic.upv.es/~uml. Un curso en español de Análisis y Diseño Orientado a Objetos con UML. [4] Teixeira, F., Programación en Delphi 4, Ed. Prentice-Hall, 1998. 10 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia 11 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia