UNIVERSIDAD AUTóNOMA METROPOLITANA
UNIDAD IZTAPALAPA
DIVISIÓN DE CIENCIAS
BASICAS
E INGENIERIATíTU LO
LENGUAJE DE ESPECIFICACIóN ENACT:
Su uso en el diseiio de programas orientados a objetos
PRESENTADO POR
ALTAIR HAZEL MARROQUíN CRUZ
ASESORADO POR
DR. JOHN CHARLES GODDARD CLOSE
PARA OBTENER EL TíTULO DE
-
LICENCIADO EN COMPUTACIóNA TODOS AQUELLOS QUE ME AYUDARON YAPOYARON A SER LO QUE AHORA SOY
iNDlCE
INTRODUCCI~N OBJETIVOS
INGENIERíA DE SOFTWARE
LENGUAJE DE ESPECIFICACIóN ENACT PROGRAMACIóN ORIENTADA A OBJETOS CONSTRUCCIóN DE PROTOTIPOS
ENACT
1.CAPíTULO
I
DESCRIPCIóN DEL MÉTODO
61 . I .DIFERENCIAS CON EL DESARROLLO TRADICIONAL 7
1.2.EJEMPLIFICANDO EL MÉTODO 9
1.2.1 .ESPECIFICACIóN EN ENACT 11
I .2.2.lMPLEMENTAClóN EN C++ 14
2.CAPíTULO
II
DESCRIPCIóN DEL PROBLEMA
202.1.DESCRIPClÓN DE LAS NECESIDADES DE UN SISTEMA
BIBLIOTECARIO 20
2.2.ORGANIZAClÓN ACTUAL 21
2.3.PROBLEMAS 23
3.CAPiTULO 111
DESARROLLO DEL SISTEMA
263.1 .ANÁLISIS Y DISEÑO DEL SISTEMA BIBLIOTECARIO 26 3.2.MODELO EN ENACT 33
3.3.IMPLEMENTAClóN EN C++ 44
3.4.CONCLUSIONES 59
APÉNDICES
SINTÁXIS EN ENACT
DIAGRAMAS Y DESCRIPCIóN DE TÉRMINOS C++
61 61 66 68
I'.. No debes confundir la escala con el destino.. "
c. c.
P.OBJETIVOS
En la computación como en otras ramas de la ciencias los avances tecnológicos se suceden vertiginosamente, se debe estar al tanto de las nuevas ideas. El estudio tanto de la filosofía de la programación orientada a objetos convinada con la utilización de un lenguaje de especificación durante el desarrollo de un sistema son
los
principales objetivos de este proyecto.INGENIERíA DE SOFTWARE
Actualmente se demandan sistemas más confiables por lo que se plantea la necesidad de utilizar una metodología que comprenda todas las etapas del ciclo de vida del software.
de software en la siguiente figura.
Podemos ver las partes principales que integran el desarrollo
-
DISENO ... : + ...
Fig. 1 Ciclo de vida del Software
ANALISIS
En esta etapa es cuando debemos entender
los
requerimientos del cliente, precisando la información que se va a abarcar, como va a seractualizada y consultada.
DISEÑO
El diseño se refiere a la identificación de los componentes de la programación (funciones, flujos de datos y almacenamiento) especificando la relación entre ellos, la estructura de la programación y manteniendo un registro de las decisiones.
Aquí decidimos como la información deseada va a ser organizada y procesada por la computadora, escogiendo la plataforma de implementación, cuyas características se tomarán en consideración en el diseño de estructuras de datos y algoritmos que usará el sistema.
IMPLEMENTACI~N
La fase de implementación viene después cuando el análisis y el diseño ha determinado suficientemente la descripción precisa del código requerido. Construimos componentes de código compuestas de subrutinas que son probadas individualmente y luego en conjunto. Consecuentemente descubrimos errores ó inadecuaciones en el código que corregimos. Por otro lado también se encuentran inadecuaciones en el diseño, corregir esto es más caro, debido a que los cambios requeridos pueden afectar componentes que ya han sido considerados completos.
Metodologías Tradicionales
Herramientas utilizadas durante la fase del Análisis
Diagramas E-R,
Descomposición Funcional,
Diagrama de dependencia entre los procesos,
Diseño
Diagrama de flujo de datos, Tablas de estructura,
Diagramas de Acción (Algoritmos)
Implementación COBOL, PL/I, C
Manejadores de bases de datos como: ORACLE, FOXPRO, INFORMIX, etc.
Cuadro1
PROGRAMACIóN ORIENTADA A OBJETOS
El software una vez desarrollado tiene que tener la habilidad de estar abierto a futuros cambios. Los métodos orientados a objetos es una alternativa que permiten ésta flexibilidad.
En la programación convencional, los datos asumen cualquier estructura y los procesos hacen de los datos lo que el programador desee.
En el mundo orientado a objetos, las estructuras se relacionan con los objetos y sólo pueden ser utilizadas mediante los métodos diseñados para ese tipo de objeto, es decir, el procesamiento de los datos se centra en los tipos de objetos cuya estructura de datos sólo pueda controlarse mediante los métodos de la clase del objeto.
Cada objeto lleva a cabo una función específica e independiente de los demás objetos. Responde a mensajes, sin saber la razón del envío de éstos ni las consecuencias de su acción.
Las técnicas orientadas a objetos modifican el punto de vista de los analistas de sistemas de información acerca del mundo. En lugar de pensar en los procesos y su descomposición, piensan en objetos y su comportamiento, los Cuadros1 y 2 que muestran las herramientas utilizadas en las fases de desarrollo del software nos permiten ver este contraste.
Técnicas Orientadas a Objetos
Análisis y Diseño se basan en:
La identificación de Objetos y definición de clases Organización jerarquizada de clases
Reutilización de clases
Contrucción de marcos estructurales de aplicación a partir de librerías de clases
Implementación
Smalltalk, C++, ADA, etc
Cuadro2
Construcción
del prototipos
La contrucción de prototipos es una versión a pequeña escala del sistema, la idea es lograr una versión funcional lo más pronto posible para poder explorar opciones de diseño e implantación. Se utiliza para apoyar la confirmación de requisitos, no se ha utilizado mucho en la evaluación del software. Esto es debido a que mejor se modifica el sistema terminado para que cumpla con necesidades no planteadas ó no percibidas anteriormente antes que dar primero la oportunidad al usuario que comprenda, refine y complete sus necesidades y posteriormente se construya el sistema final. Construir el prototipo es caro si se le considera con los mismos estándares y términos que el sistema final. Sin embargo si se proyecta para demostrar los aspectos funcio- nales más que los no funcionales de un sistema, tendría un costo mucho menor que el sistema final.
Para sistemas pequeños puede ser apropiado presentar al usuario un sistema incompleto y después ampliarlo a medida que se descubran ó completen las necesidades reales, es decir partir del prototipo y evolucionar hasta el final, por otra parte se puede contruir el prototipo para identificar los problemas iniciales y, después de experimentar, se formula una especificación mejorada, se desecha y se construye el sistema final. La razón de este ultimo enfoque es que el desarrollo rápido es el principal objetivo de la contrucción de prototipos
Ventajas de utlizar un prototipo
-
Disminución de malentendidos entre desarrolladores de software y usuarios, al poder identificarlos a medida que se muestran las funciones del sitema-
Detectar servicios faltantes-
Identificar y redefinir los servicios difíciles de utilizar o confusos-
Disponer con rapidez de un sistema de trabajo, aunque limitado, para demos-
Se pueden encontrar inconsistencias en los requisitos ó pueden estar éstos-
El prototipo puede servir como especificación trar la viabilidad y utilidad de la aplicaciónincompletos
Especificación
abstracta de alto nivel para el diseñador
La especificación es la parte en la cual el diseño se expresa en una forma
Especificaciones operacionales
La función principal de las especificaciones operacionales es la de definir lo que el programa debe hacer en lugar de efectuar realmente las operaciones.
Si el lenguaje de especificación es ejecutable, la especificación no es más que otro programa, éstos imponen demandas muy fuertes a un sistema a tiempo
de ejecución y podrían ejecutarse con una lentitud cientos de veces mayor que los programas equivalentes.
El desarrollo de las especificaciones es un proceso iterativo; a medida que se desarrollan las especificaciones de las abstracciones de bajo nivel del sistema, pueden surgir errores en las especificaciones de nivel más alto y deben ser corregidas.
Un área muy importante de desarrollo de software, que parece ignorarse en la mayoría de los análisis sobre especificación del software, es la entrada y la salida. Los programas reales toman y producen información para su ambiente. Si una parte de cierto sistema es responsable de la entrada y la salida, también se debe especificar.
La razón de evitar las operaciones de E/S en la mayoría de los análisis sobre especificación formal es que resulta muy difícil establecer un modelo limpio de propósito general subyacente en los procesos de E/S. Esta dificultad resulta de que estos procesos deben actuar recíprocamente con el hardware subyacente, cuyo diseño a menudo no es elegante ni está especificado de manera formal. Sin embargo, incluso un modelo informal de operaciones de E/S es inútil cuando se construyen las especificaciones de diseño.
ENACT
Para permitirnos evaluar estas nuevas alternativas de arquitectura de software y entender mejor su comportamiento, antes de hacer ó emprender una larga implementación en lenguaje de alto nivel como lo es C++, se utiliza ENACT como lenguaje de modelado.
ENACT fue desarrollado en la Universidad de Southampton, Inglaterra por Peter Henderson del Departamento de Electrónica y Ciencias Computacionales, su libro “Object-Oriented Specification and Design with C++” en el cual se basó este trabajo puede ser consultado para una mejor referencia.
CAPíTULO I
DESCRIPCIóN DEL MÉTODO
Esta basado en seguir la programación orientada a objetos. Como ya señalamos anteriormente, los métodos orientados a objetos facilita la creación en el programa de un modelo del mundo real donde hay una directa relación entre el modelo abstracto de alto nivel y los componentes del mundo real. Cada entidad en el mundo real será representado por un solo objeto en la máquina.
Antes que nada hay que enteder los requerimientos, después viene la fase de Análisis, que va a estar constituida por la construcción de un modelo conceptual del mundo real para un sistema en la computadora. Así como el mundo real evoluciona, el modelo basado en la computadora evoluciona ó desarrolla para conservar el paso y registrar hechos relevantes. Esta fase empieza desde el momento de escoger objetos para modelar las entidades del mundo real. Dibujando diagramas-objeto para capturar algunas de las propiedades más abstractas de
los
objetos, creando una arquitectura paranuestro sistema que sea adecuada a nuestros propósitos, válida y hábil a desarrollar tanto como evolucionen o desarrollen nuestros requerimientos. Se utilizan diversos diagramas que actúan como referencia visual para la información.
Finalmente se enumeran los eventos que puedan alterar el estado de nuestro mundo, se puede entrar o no en detalles de las operaciones que correspondan a las acciones de la ocurrencia de dichos eventos dependiendo de la complejidad del sistema.
Como ya se mencionó los cambios en el diseño puede alcanzar a cada componente en el sistema, por lo que se necesitan métodos que pongan especial cuidado en las primeras fases del desarrollo.
En el Diseño se empiezan a considerar los requerimientos que la computadora contrariamente al mundo real, pone sobre nosotros y desarrollar una estrategia que nos permita ir probando las decisiones de diseño.
Muchas veces, los detalles del problema y los conceptos de la solución
sólo
se comprenden claramente a través del esfuerzo de expresarlos en el programa: aquí es donde adquiere importancia la elección del lenguaje de programación ya que para que un lenguaje sea considerado de aplicación general debe poseer ciertas características:
Ejecutarse en máquinas tradicionales
Coexistir con sistemas operativos y lenguajes tradicionales en términos de
Servir para todas la áreas de aplicación importantes eficiencia durante la ejecución
La elección del lenguaje de programación para la Implementación en este caso es C++.
C++ es una buena plataforma para varios estilos de programación, en particular apoya la abstracción de datos y la programación orientada a objetos. Está diseñado para apoyar la noción de programa como modelo de algunos aspectos de la realidad y la de clase como la representación concreta de un concepto de la aplicación. Además de ser muy difundido comercialmente.
DIFERENCIAS CON EL DESARROLLO TRADICIONAL
Métodos de Especificación
Una especificación formal en
la
Ingeniería de Software es el uso de conceptos matemáticos para dar una definición precisa a los componentes con los que será construido el software. El camino normal por el cual una especificación es organizada; es la vista de esos componentes como un TDA.Las operaciones aplicadas al TDA dan un significado preciso es decir qué es lo que el componente se supone hace, en lugar de cómo se supone lo hace.
Los métodos matemáticos formales constituyen los fundamentos de los profesionales en Ingeniería de Software, sin embargo los métodos usados están en una especie de state-of-the-art y tienden hacia esas bases teóricas.
-
El método algebraic0-
El método orientado al modeladoDos métodos formales de especificación populares son:
que tienen cierta relación con la programació funcional.
La ventaja derivada del empleo de especificaciones formales de los componentes del software es que dada una especificación formal y una
definición de la semántica del lenguaje de programación, puede demostrarse que un programa cumple con su especificación. Así se puede establecer la ausencia de ciertos tipos de errores de los programas, siempre y cuando la prueba sea correcta. Sin embargo no se obtiene nada que se pueda ejecutar en una máquina.
ESPEClFICAC16N ORIENTADA A OBJETOS
Se ha hecho referencia al código en Enact como especificación, como modelo, modelo en funcionamiento y/o como prototipo.
Su papel es servir como pseudocódigo para capturar detalles de nuestro diseño orientado a objetos y cuando este lo suficientemente completo pueda ser ejecutado, proporcionando un modelo en funcionamiento dandonos una retroalimentación anticipada de las consecuencias de las decisiones del diseño.
¿En qué sentido es una descripción en Enact una especificación y en qué sentido es diferente de los métodos tradicionales de especificación matemática? Enact es diferente de
los
lenguajes de especificación matemática en que permite la directa descripción de efectos secundarios, permite asignaciones. Soporta directamente la descripción de cambio de estado. Usa la noción de objeto como poseedor de estado. El objeto tiene identidad y estado, las operaciones aplicadas a éI pueden cambiar su estado sin cambiar su identidad. Además de poder ejecutarlo y ver su interpretación y cambios que se generen, en contraste con los modelos matemáticos con frecuencia no correnEl método orientado a objetos descrito modela el mundo real asociando objetos con entidades en el mundo real, en el mismo sentido los cambios en el mundo real son modelados por los cambios correspondientes en los objetos.
Después de entender el mundo real, podemos construir un modelo en funcionamiento con una muy directa relación con la realidad, por consiguiente
Enact sirve como una especificación.
Dado que se ha tomado el diseño orientado a objetos como el paradigma central, obviamente hay otras alternativas para la especificación orientada a objetos ó la construcción del modelo, por ejemplo Smalltalk que provee toda la funcionalidad de Enact y más, pero ¿porqué no usar C++ directamente como especificación y lenguaje de modelado?
Una de las causas es el tiempo dedicado a detalles que no son relevantes en las primeras decisiones de diseño
La inversión en detalles de diseño es difícil de abandonar cuando se requieren cambios en una decisión de alto nivel en el diseño.
El papel de Enact es simplemente proveer una base de conceptos para el desarrollo rápido de aplicaciones directamente en C++.
EJEMPLIFICANDO EL MÉTODO
El problema tomado para introducir tanto las ideas de la programación orientada a objetos y ejemplificar el método a seguir para el desarrollo de un sistema, consiste una situación que se presenta en cualquier oficina, archivar documentos
ANALISIS
Tenemos que los documentos deben estar almacenados en cierto orden. Para hacerlo habrá que clasificarlos de alguna manera, todos los que pertenecen a una sola persona los guardaremos en un folder ó carpeta, como tendremos muchos folders de las distintas personas de las que tenemos documentos los pondremos en gavetas ó cajones.
Una primera visión se encuentra en el siguiente diagrama E-R
FOLDER
nido en
Fig. 2 DIAGRAMA ENTIDAD-RELACIóN
Pero la idea es tratar de escoger objetos para modelar entidades del mundo real y tenemos ciertas propiedades y restricciones que queremos que nuestro sistema cumpla.
Propiedades
-
Existen documentos pertenecientes a una persona-
Documentos deben guardarse en folders-
Folders deben guardarse en gavetasConsideramos que el sistema archivará por orden alfabético
Escogiendo objetos para modelar las entidades del mundo real
I
FOLDER
Arredondo Arzate
Fig. 3 DIAGRAMA-OBJETO
El paso final es enumerar los eventos que afectan el estado del mundo:
-
Se necesita archivar documentos(en folders)-
Se necesita archivar folders (en gavetas)-
Buscar gaveta, folders y documentos-
Eliminar documetosDISEÑO
Procedemos a construir nuestro modelo del problema en Enact. Antes debemos conocer y definir ciertos conceptos utilizados. (Ver Apéndice II para más definiciones de conceptos)
SISTEMA ABSTRACTO
Es producto de la fase del análisis y el inicio de la fase de diseño. Es un camino para organizar
los
elementos que constituyen los métodos orientados asistema abstracto es una colección de clases(vistas como tipos de datos abstractos junto con el protocolo para su uso), cada clase tiene su propio protocolo, pero sólo algunas de las operaciones en ellas deben ser hechas visibles al usuario del sistema abstracto.
PROTOCOLO
El conjunto de operaciones que sobre una clase particular pueden realizarse, sirve también como la interface que el usuario tiene con un sistema abstracto.
Podemos definirlo en dos formas: La forma textual y la forma de diagrama. La forma textual es más apropiada para capturar las definiciones que envuelven al diseño.
La forma de diagrama da una vista mejor del sistema abstracto en general y las relaciones entre las distintas operaciones que se encuentran en él.(Ver apéndice II para ver detalles de los elementos que lo integran)
Ambas formas se complementan, aunque es conveniente acompañar la sintaxis del protocolo con una descripción al usuario de cómo entender las relaciones entre las operaciones.
Las operaciones que sobre los objetos identificados (Gaveta, Folder,
Documento)se realizan son prácticamente las mismas por lo que es conveniente utilizar aquí el concepto de herencia de la metodología 00, definir una clase base que llamaremos Almacen, en la que se definan dichas acciones y heredar éstas propiedades en común a las subclases como se muestra a continuación.
Fig. 4 DIAGRAMA HERENCIA
class Almacen Object. class Gaveta Almacen. class Folder Almacen.
11
". . . "
Tanto la colección de documentos como la colección de folders deben almacenarse en una colección de objetos de clase Set. La clase Set predefinida en Enact que tiene el constructor set() y un protocolo que tiene la habilidad de insertar y remover elementos del conjunto y determinar si un objeto es elemento o no del conjunto (Ver Apéndice I).
La especificación en Enact para Almacen se muestra a continuación.
class Almacen -e Object.
Almacen.guarda(objeto) :=self.miembros.insert(objeto). Almacen.remueve(objeto):=self.miembros.remove(objeto). Almacen.busca(identifi) :=self.miembros.locate(x::x=identifi).
...
La primera declaración introduce la clase Almacen, como subclase de la clase (predefinida en Enact) Object, la cual es raiz de todas las clases. No declaramos ningun constructor para esta clase pues no queremos crear instancias de ella, decimos entonces que es una clase abstracta.
La posteriores líneas son las tres operaciones que tienen en común los objetos, es decir los métodos que son como definiciones de funciones excepto que la clase de objeto a la cual se aplican es hecha aparente.
El Único objeto que no requiere heredar dichas operaciones es Documento, pues solo necesitamos crear instancias de esa clase.
class Documento c Object.
documento(nombre) := new Documento with dueño = nombre. Documento.archivar(afolder) := afolder.guarda(self).
Especificación en Enact de la clase Documento
La utilización del constructor nos crea instancias de la clase Documento con un Único atributo: dueño, que es el nombre de la persona a la que pertenece dicho documento. Es necesario tener folders para guardar los documentos en ellos lo cual se realiza con la operación
aDocumento.archivar(afolder)
que guarda un documento aDocumento en un folder determinado afolder. La aperación invoca a la operación guarda que folder heredada de Almacen para almacenar objetos en una colección.
Almacen.guarda(objeto):=self.miembros.insert(objeto).
Almacen.guarda(objeto):=self.miembros.insert(objeto).
sólo que debemos especificar a que tipo de almacen debemos guardar el objeto, en este caso el Documento por lo que se declara
afolder.guarda(self)
de Enact self se liga a él.
del hecho de que aceptamos como parámetro un folder, la palabra reservada
Igualmente para la clase Folder, nada más creamos instancias de la clase folders como una colección de documentos
class Folder Almacen.
folder() := new Folder with documentos = set(). Folder.archivar(agaveta) := agaveta.guarda(self).
Especificación en Enact de la clase Folder
...
...
La clase Gaveta es una colección de folders y no es necesario definir ninguna otra operación.
class Gaveta c Almacen.
gaveta() := new Gaveta with folders
=
set().Cuando sea necesario buscar cierto objeto ya sea un documento en un folder o un folder en una gaveta, se llama a la operación busca definida en Almacen, de las formas siguientes
aFolder.busca(aDocumento) aGaveta.busca(aFolder)
objetos que nos permite definir métodos genéricos.
Esto es una muestra de la gran fuerza de la programación orientada a
Finalmente llegamos a nuestro sistema abstracto de archivos
aDocumento := documento(). aFolder := folder(). aGaveta := gaveta(). aDocumento.archivar(aFolder). aFolder.archivar(aGaveta). afolder. busca(aDocumento). aGaveta.busca(aFolder)
Protocolo para el sistema abstracto de archivos
Podemos darnos cuenta que el código implementado en Enact para probar nuestro diseño es sumamente corto, posteriormente haremos una comparación con el código en C++ para comprobar ésta ventaja.
Ejemplo de uso del sistema
Acta := documento(). Titulo:= documento(). Certificado:=documento().
Portillo := folder(). LetraP := gaveta().
Acta.archivar(Portillo). Titulo.archivar(Portillo). Certificado.archivar(Portillo).
Portillo.documentos.members. %->(Certificado, Titulo, Acta)
Portillo.archivar(LetraP).
LetraP.folders.members. %->(Portillo)
Cuando el producto pasa del estado de diseño al de implementación, su codificación podría realizarse en casi cualquier lenguaje, no es escencial pero es deseable que el lenguaje de programación no dependa de mecanismos que no se puedan realizar de manera eficiente en una arquitectura tradicional. Todos los lenguajes de programación orientados a objetos tienene tres cosas en común:
objetos, polimorfsmo y herencia.
Se ha escogido C++, ya que por su versatilidad en cuanto al apoyo en una gran variedad de estilos de programación, entre ellas la programación orientada a objetos, y su proyección en los futuros sistemas de programación.
En C++ una clase introduce un nuevo tipo, define el espacio utilizado para representar valores de éste y determina las operaciones que son aplicables a las instancias de ese tipo.
Empezaremos por mostrar la definición de la clase Documento de nuestro sistema.
class Documento{ public:
char* nombre; Documento(char*); char *name();
1;
Ahora podemos declarar instancias de este tipo asumiendo que se van accesar vía apuntadores, de la siguiente forma:
Documento *Acta
que en realidad es un apuntador a una instancia de tipo Documento.
La clase Documento tiene 3 miembros, por default todos los miembros de una clase son privados a menos que se especifique
lo
contrario como en este caso que ponemos la palabra reservada public que indica que pueden serutilizadas por cualquier función.
La primera declaración es un miembro dato que registra el nombre ó identificador del documento.
Las siguientes son funciones miembro que corresponden al constructor y a un método.
C++ utiliza el mismo nombre para la clase y para su constructor.
Documento *Acta =new Documento("Acta");
En la declaración anterior se crea un apuntador a la instancia de tipo Documento y el constructor que le reserva espacio en memoria. En este caso el constructor necesita un parámetro de inicialización.
Cada miembro de la clase constituyen
los
atributos de una instancia de esa clase y son accesibles simplemente invocandolas, por ejemplo para Documento tenemos la siguiente manera de acceder alos
atributos de Acta que es unainstacia de tipo de la clase Documento.
Acta->nombre Acta->name()
Las definiciones de las funciones miembros de la clase Documento se
Todas las funciones miembros estan construidas por el nombre de la clase muestran a continuación
a la cual pertenecen en este caso el prefijo es Documento::
Documento::Documento(char* n){ nombre = n;
1
La declaración anterior es la manera de referir a la función constructora al tiempo de definición e inicializa la variable, se puede utilizar este estilo que es
equivalente a declarar
Documento::Documento(char* n):nombre(n)O
Como el constructor no realiza nada más que inicializar datos miembros el cuerpo de la función está vacío
char *Documento::name(){ return nombre;
1
Hay varios mecanismos que provee C++ para apoyar la programación
orientada a objetos. La Herencia es uno de ellos. Vamos a ilustrarlo con nuestro ejemplo. Tenemos ya una clase llamada Documento, de la cual podemos crear instancias. Como ya lo habiamos tratado en la fase de Diseño, tenemos otras
clases más, acordando definir una clase abstracta, Almacen que hereda propiedades comunes tanto a la clase Folder, como a la clase Gaveta
Tenemos entonces una jerarquía de clases Fig. 4
Almacen es la clase base y Folder y Gaveta las clases derivadas
class Almacen{ char *nombre; Set *elementos;
Almacen(char *);
char *Almacen::name(); void guarda(void *objeto); void remueve(void *objeto); Set *miembros();
virtual void busca(); protected:
public:
1;
No nos interesa construir instancias directamente de tipo Almacen, sólo de tipo Gaveta y Folder por lo que no lo declaramos public, pero no puede ser privado puesto que las clases derivadas no pueden acceder a éI así que necesitamos un nivel intermedio: protected. Protected significa ser inaccesible a los usuarios de la clase excepto por las clases derivadas
class Gaveta : public Almacen{ public:
Gaveta(char *);
1;
class Fo1der:public Almacen{ public:
Folder(char *);
1;
Analizando éstas definiciones
class Fo1der:public Almacen
indica que Folder es una clase derivada de la clase base Almacen y que hereda los miembros públicos de Almacen, aparte se define un nuevo miembro, un constructor para crear instancias. Similarmente para la clase Gaveta.
Almacen::Almacen(char *n):nombre(n),elementos(new Set()){}
Folder::Folder(char *n) :Almacen(n)O
Gaveta::Gaveta(char *n) : Almacen(n)O
Funciones constructoras para las 3 clases
17
Los constructores de las clases derivadas únicamente pasan sus
argumentos al constructor de Almacen. Tanto Folder como Gaveta heredan las funciones miembros de Almacen definidas a continuación
void Almacen::guarda(void *objeto){ elementos->insert(objeto);
1
Set* Almacen::miembros(){return elementos;}
void Almacen::remueve(void *objeto){ elementos->remove(objeto);
1
Es conveniente adoptar la convención de que los datos miembros sean privados y sólo puedan ser accesados por funciones miembros, por lo tanto se implementa para C++
lo
que en Enact era un simple atributochar *Almacen::name(){
1
return nombre;
La implementación de Almacén ha requerido el uso de una clase
En general una práctica normal cuando se desarrollan programas grandes
Para reusar una clase existente necesitamos conocer su protocolo, es
La recolección de cierto protocolo para una clase se hará en la medida que
Se puede crear una instancia de la clase Set usando el constructor
una vez creada podemos insertar y remover items del conjunto usando las
x-> insert(p)
predefinida en C++, Set. En el diseño también se utilizó.
en C++ es hacer uso de clases predefinidas en él.
decir, cómo construir instancias de esa clase y cómo acceder a ellas.
se usen las instancias de esa clase.
Set *x
=
new Set();siguientes llamadas
x-> remove(p)
con p un apuntador. Existen varias operaciones que se pueden utilizar con la clase Set, una de ellas es
x-> member(p) que necesitamos para saber si el apuntador p es un miembro del conjunto x. La función regresa un valor falso si el elemento no pertenece al conjunto y verdadero si lo contrario(si el elemento ha sido insertado y no ha sido removido), ver el Apéndice Ill para definiciones de éstas funciones.
virtual void Almacen:: busca(){
cout << '7nIntroduzca el nombre del documento a buscar\n";
cin >> nombre-obj;
Documento *objeto=(Documento *)this->miembros()
cout << objeto->nombre;
->locate(compara-nombre-doc);
1
Aparte de
los
beneficios de compartir partes en común de sus definiciones, dividir las clases en una jerarquía de tipos, trae consigo la ventaja de que tenemos un tipo que podemos usar para referirnos tanto a folders como a gavetasSi declaramos un apuntado de tipo
le podemos asignar tanto folders como gavetas, es decir ambas Almacen *a;
asignaciones son válidas a=&aFolder; a=&aGaveta; Si llamamos a la función
a->busca();
Dependiendo de cual de las asignaciones tome lugar, será buscada la
instancia correspondiente,debido al uso del mecanismo virtual. Es decir el camino en C++ para indicar que la implementación de una función o procedimiento en una clase es o puede ser responsabilidad de una subclase.
Hemos especificado que esa función miembro es virtual que significa que puede ser redefinida en una o más de las clases derivadas. Si la clase derivada tiene a la función redefinida, entonces cuando sea invacada a través del
apuntador se da preferencia a la redefinida, si no está redefinidad entonces tomará lugar la definición de la clase base.
Por último tenemos funciones globales utilizadas para inspeccionar
los
valores de atributos de instanciasint compara-nombre-doc(void *objeto){
return strcmp(((Documento *)objeto)->name(), ::nombre-obj)==O;
1
int compara-nombre-fol(void *objeto){
return strcmp(((Fo1der *)objeto)->name(), ::nombre-obj)==O;
1
19
y las funciones para imprimir en pantalla
void printDoc(void *aDoc){
cout << ((Documento *)aDoc)->name() << I'
1
void printFol(void *aFol){
cout << ((Folder *)aFol)->name() << ' I ;
1
Ejemplo de uso del sistema
Folder *Portillo=new Folder("Portillo"); //se crean apuntadores Gaveta *LetraP =new Gaveta("LetraP"); // a instancias
Portillo->guarda((void *)Acta); Portillo->guarda((void *)Titulo); Portillo->guarda((void *)Certificado);
//imprime los nombres de documentos guardados en el folder Portillo Portillo->miembros()->forEachDo(printDoc);
LetraP->guarda((void *)Portillo); cout << I' \n";
LetraP->miembros()->forEachDo(printFol); Portillo->busca();
CAPiTU LO
I I
DESCRIPCIóN DEL PROBLEMA
Objetivos
-
Realización del análisis y diseño de un sistema bibliotecario con las ideas de la programación orientada a objetos, desarrollando una especificación en el lenguaje ENACT.-
La automatización de algunos procesos en el funcionamiento de la bibliotecaLa fase de
ANALISIS
pretende obtener a partir de la especificación del problema del usuario una definición del sistema que va a desarrollarse. Identificar objetos así como los datos y procesos que son naturales para esos objetos(Construcción de un modelo), especificación de requisitos del sistema.Debido a la naturaleza repetitiva de algunas actividades bibliotecarias, ya sea adquisición, catalogación, preparación, encuadernación, fotocopiado, reparación de libros, etc. es conveniente la automatización de algunas tareas.
El sistema pretende dar servicio a dos tipos de usuarios:
a) El que realiza el control del sistema e introduce nueva información. b) El usuario ordinario de la biblioteca
Generalmente las funciones de una biblioteca son las siguientes: 1. Selección y adquisición de material, incluyendo libros, periódicos, revistas, etc.
2. Preparación y cuidado de material a través de procesos como catalogación, clasificación, encuadernación
Las características deseables en un sistema son:
O Reducción de trabajo esclavizante
Se espera que la computadora reduzca, no incremente la carga de trabajo. Sea rápida, e idealmente se adapte al tipo de operaciones repetitivas involucradas como son la compilación de listas ó producción de tarjetas para catálogos.
O Reducción de errores al introducir datos al sistema
O Consistencia con el sistema
0 Rapidez
información actualizada a través de reportes
ORGANIZACION ACTUAL
Detección de errores
Consultar archivos más rápido que una persona y proveer
Se ha tomado como base y fuente de información la Coordinación de Servicios Documentales de la Universidad Autónoma Metropolitana
-
lztapalapa que es la encargada de poner a disposición de
los
usuarios el material bibliográfico, hemerográfico y documental que sirve de apoyo al desarrollo académico. Dicha coordinación realiza las actividades de organización, búsqueda de materiales, adquisiciones, catalogación, clasificación y diseminación de la información a través de diferentes secciones.SECCIóN DE BIBLIOTECA
Cuenta con 100, O00 volúmenes y es la encargada de fijar
los
procedimientos necesarios para que
los
lectores tengan fácil acceso a 10s materiales del acervo general y colecciones especiales.SECCldN DE HEMEROTECA
Responsable de la adquisición, organización y control del material hemerográfico
La adquisición de material (Revistas y periódicos) se realiza por 3 formas: Canje, compra ó donación.
La organización y control del revistas se realiza a través de un catálogo CARDEX, ordenados por título y alfabéticamente. Los datos contenidos en éI son:
-
Título-
ISSN-
Periodicidad-
Editorial de la revista-
Volumen-
Número-
AñoEn
los
estantes están en el mismo orden que aparecen en CardexLos periódicos(La Jornada, Uno más uno, Excélsior, El Financiero, El Universal y el Diario Oficial) estan disponibles desde una fecha dos meses anteriores al mes que va corriendo hasta la fecha actual.
SECCIóN DE SISTEMAS BIBLIOTECARIOS
Se encarga de la búsqueda, localización y obtención de documentos a nivel nacional como internacional, además de proporcionar información bibliográfica especializada, en forma manual ó automatizada.
SECCIóN DE ADQUISICIONES
donación de los materiales bibliográficos.
Su actividad básica es la adquisición ya sea por compra, canje ó
SECCIóN DE
ANALISIS
BIBLIOGFlÁFICOadquieren para organizar los diferentes catálogos técnicos y de usuarios. Investiga, analiza, cataloga y clasifica los materiales que se
Préstamos
El proceso de registro es muy importante ya que muestra en donde se encuentra un libro cuando no está en los anaqueles y cuando se tiene que regresar. La manera en que se registra en la CSD es :
-
Tipo de usuario (Estudiante, profesor ó administrativo)-
Nombre-
Matrícula ó No. económico-
Autor-
Colocación-
No. de adquisición-
FirmaEl usuario llena una papeleta con los siguientes datos:
-
TítuloPROBLEMAS
La producción de ordenes para el comerciante(editoria1) con copias para uso interno en operaciones de los departamentos que conforman la biblioteca, puede ser un proceso tardado y monótono cuando no se utiliza la computadora
La preparación de una lista general de títulos en pedido ó proceso de ser catalogado, comunmente referida como la lista de información en proceso
Las cartas de reclamación de pedidos con un periodo específico de tiempo
El mantenimiento de todas las operaciones de contabilidad de relacionadas con
los
fondos de libros, incluyendo la producción para cada departamento académico declaraciones mensuales indicando el presupuesto de fondos para libros, gastosUna lista de los títulos nuevos en catálogo de distribución periódica a los usuarios de la biblioteca para el conocimiento del acervo del que pueden disponer.
No es escencial pero es deseable que el sistema contara con un chequeo automático de todo el material prestado por un usuario para verificar la fecha de salida de material y adeudos pendientes.
o
-! dg
m
n
w-
z
-0
u
w
3
m
m z
4
u
8
z
.O3
z:
m
w
n
4 k
i
2
"w
m
6' O
W u
CAPiTU LO
I I I
DESARROLLO DEL SISTEMA
“. . Todo el tiempo es presente eternamente por lo
todo el tiempo es nuestro..” The Passion
ANALISIS
DIAGRAMA ENTIDAD-RELACION
EDITORIAL
a
ESTUDIANTE
SISTEMAS ESCOLARES
contrata~l,+
es contratadoI
+
RECURSOS HUMANOS
DIAGRAMA DE CONTEXTO
papeleta sellada
BIBLIOTECAS
HUMANOS
inform.
B.D.
ESCOLARES
-
Papeleta Solicitud
material bibliográfico Notificación
domicilio
Fecha entrega material
>
,
o adeudo
or autor
-
or tema
ANTE EDITORIAL
DE
BIBLIOTECA
rocesados
-
A
ARCHIVO
A
Datos
libros-copia
libro
.
Dato5
ALJETA LIBRO
YA ADQUiRiDO F COPIA Ll6RO
E ACUERDO A
\ -
y
ONGRESOCATÁLOGO L E A L
...
... . ... ... ... ... ... . ... .
'NAllONAL UNION CATALOG
PEDIDOS
m
EDITORIAL
nuevo material
: : ~ ~ ~ ~ ~ : ~ ~ . ~ ~ ~ ? ~ ~ ~ ~ ~ ?
>:.:.:.x.:<.:.:.:.:.:.:.:.:.:.:.:.: ...
edido
EDITORIAL
n
BASES DE DATOS UTILIZADAS POR EL SISTEMA -ESTUDIANTES -PROFESORES -ADMINISTRATIVOS -LIBROS -REVISTAS -EDITORIALES -PEDIDOS
-USUARIOS EXTERNOS -CONVENIOS
-SUSCRIPCIONES -PRESTAMOS -DISTRIBUIDOR
LIBROS REVISTAS EDITORIALES
.Número de Adquisición .Título
.Autor .ISBN .Edición
.Número de copia .Colocación
.Clave-editorial
4SSN Clave-editorial
.Título .Nombre-editorial
.Año .Dirección
.Volumen .Teléfono
.Número
.Clave-suscripcion .Colocación
.Periodicidad
PEDIDOS SUSCRIPCIONES
.Número de pedido .Tipo-material .Fecha-pedido .Fecha-inicio
.Fecha-llegada .Fecha-fin
Cantidad .Clave-distribuidor .Descripción .Precio
.Precio .Clave-suscripcion
DISEÑO
En relación a los préstamos introducimos tres clases
PRÉSTAMO
L
tj
USUARIOt
I L
J U
Fig.5 Diagrama-Objeto
El acervo bibliográfico comprende distintos tipos de materiales no
sólo
libros, también hay revistas, periódico, etc. Tenemos entonces un ejemplo en donde podemos aplicar el concepto de herencia.
Definimos una clase base
class Material < Object.
y puesto que las principales transacciones en una biblioteca se presentan cuando una persona realiza las operaciones de préstamo y devolución de un
libro
Material.presta(aUsuario, fecha-actual, fecha-entrega):=
(aUsuario.num-libros() < aUsuario.max-libros then (self.prestador:=aUsuario; fecha-actual.suma-dias( 15,fecha-entrega);
Material.regresa(fecha-act):=(self.prestador.devolucion(self,fecha-act);
self.prestador:=nil;
self.fecha-entrega:=nil).
La primera operación implica registrar la asociación del libro a la persona y a su vez la necesidad de validar (Verifica que el usuario no exceda el limite en la cantidad de libros permitidos para prestamo)
Similarmente para la segunda operación registrar la devolución tanto en el conjunto de libros que tenga el usuario como en el libro
También necesitamos operaciones complementarias como saber
si
el libro se encuentra en la biblioteca ó está prestado, ó identificar al usuario que tiene prestado el libro, calcular el monto de la multa a pagarsi
se retrasa en devolver el libro.Material.enbiblioteca():= self.prestador=nil.
Material.calcula-multa(tot):=tot*l
Material.usuarioprestador():=self.prestador.clave_usuario.
A continuación se presentan las definiciones de las clases Libro y Revista que son las que en realidad se instancian y heredan las funciones y
procedimientos de la clase Material
class Libro < Material,
libro(clave-material,nombre,num-copia):= new Libro with prestador=nil with
numero-adquisicion=clave-material
with titulo=nombre with copia=num-copia with fecha-entrega=nil.
class Revista < Material.
revista(c1ave-material, nombre,periodo):= new Revista with suscrip=nil with issn=clave-material
with titulo=nombre
with periodicidad=periodo.
I
LIBRO
prestador1
USUARIO
I
BOOLEAN0I
Fig. 6 Representación del Protocolo para la clase Libro
El sistema de préstamo debe establecer una fecha límite de entrega, por
lo
que se crea otra clase que maneje todolo
relacionado a fechasreverse(x):=x=nil then nil else
append(reverse(t1 x), (hd x):()).
La función reverse no es propiamente de la clase Fecha, es simplemente una función auxiliar que se utiliza dentro de ella
class Fecha c Object.
fecha():= new Fecha with meses=bag() with valor=set().
Todas las operaciones realizadas se hacen sobre un conjunto, el atributo valor que contendrá 6 digitos, 2 referentes al día, 2 al mes y 2 al año
Fecha.inserta(anum):=self.valor.insert(anum).
inicializa una lista con el número máximo de días de cada mes
Fecha.guarda-valores():=(j:=l; i:=2; (¡<=I O loop
Fecha.saca-valor(n, lista):=(n=O then hd(lista) else self.saca-valor(n-1 ,tl(lista))).
Fecha.bisiesto(anio):=((anio mod 4) = O and ((anio mod 100) <> O)
or
(anio mod 400) = O).Fecha.calcula~dias():=(mes:=l;dias:=O;temp:=self.meses.members; (mes< (self.saca-valor(1 ,self.valor.members))
loop (dias:=dias+ hd(temp);mes:=mes+l;temp:=tl(temp)));
dias + self.saca~valor(2,self.valor.members)).
Fecha.restan-dias():=(self.saca-valor(1 ,self.valor.members)=2 and self.bisiesto(hd(self.valor.members))
then ((29-self.saca-valor(2,self.valor.members))+l)
self.saca-valor(1 ,self.valor.members) loop
self.saca-valor(2,self.valor.members) +I )).
else (mes:=l ;temp:=self.meses.members;mes<
(temp:=tl(temp);mes:=mes+l); hd(temp)
-
Fecha.limpia():=(self.valor.members<>nil loop self.valor.remove(hd(self.valor.members))).
Fecha.copia(lista,n):=(n>O then (self.valor.insert(hd(lista));
lista:=tl(lista);self.copia(lista,n-I))
else (self.valor.members:=reverse(self.valor.members))).
Fecha.suma-dias(avalor, aFecha):=((avalor >O loop (avalor >=aFecha.restan-dias() then
(avalor:=avalor-aFecha.restan-dias();
anio:=hd(aFecha.valor.members)+(aFecha.saca-valor(l ,aFecha.valor.members
)/A 2);
mes:=aFecha.saca-valor(1 ,aFecha.valor.members) mod 12 + 1 ; dia:= 1 ; aFecha.limpia();
aFecha. inserta(dia);aFecha. inserta(mes);aFecha.inserta(anio)) else
(dia:=aFecha.saca~valor(2,aFecha.valor.members)+ avalor; avalor:=O;anio:=aFecha.saca_valor(O,aFecha.valor.members);
mes:=aFecha.saca-valor(1 ,aFecha.valor.members);aFecha.limpia();aFecha.ins erta(dia);
aFecha. inserta(mes);aFecha. inserta(ani0)))
1).
Fecha.dias-entre-fechas(aFecha):=
((totl
:=self.calcula~dias());(tot2:=aFecha.calcula~dias());
(aniol :=hd(self.valor.members))=(anio2:=hd(aFecha.valor.members)) then (totl
-
else
((aniol-1900)/4>0 then
((totl:=totl+l46*((aniol-1900)/4)); aFecha.inserta(tot1));
(aniol-1900) mod 4 >O then
((totl :=tot1 +365*((aniol-I 900) mod 4)+1); aFecha.inserta(tot1));
(anio2-I 900)/4 >O then
((tot2:=tot2+146 * ((anio2-I 900)/4)); aFecha.inserta(tot2));
(anio2-1900) mod 4 > O then
((tot2:=tot2+365*((anio2-1900) mod 4)+1); aFecha.inserta(tot2)); totl -tot2)).
la clase Material se introduce y hace uso de la clase Usuario. Los usuarios de la biblioteca tanto0 estudiantes como empleados ya sean profesores ó
administrativos y externos(personas que no pertenecen propiamente a la institución) tiene diferentes consideraciones en cuanto a las condiciones de préstamo, así que sus características son similares pero no iguales que nos hacer volver a la utilización de herencia.
tot2)
En la Fig. 6 y en las definiciones de los procedimientos y/o funciones de
ESTUDIANTE EMPLEADO EXTERNO
FIG. 7 DIAGRAMA-HERENCIA
class Usuario Object.
Usuario.registro(aMaterial):=(self.libros.insert(aMaterial)).
Usuario.devolucion(aMaterial,fecha_actual):=(self.libros.remove(aMaterial); ((tot:=fecha-actual.dias-entre_fechas(aMaterial.fecha_entrega)) >O)then (self.multa:=self.multa+aMaterial.calcula~multa(tot))).
Usuario.num-libros():=self.libros.size(). Usuario.paga():=(self.multa:=O).
Cada una de las clases derivadas tienen su constructor por que son las que se necesitan instanciar, ya que la clase base unicamente contiene las funciones ó procedimientos generales
class Estudiante Usuario.
estudiante(aMatricula):= new Estudiante with libros=set() with clave-usuario=aMatricula
with max-libros = 5 with multa=O.
El empleado puede se Académico ó Administrativo por lo que se agrega el atributo tipo.
class Empleado Usuario.
empleado(aNumero-economicolatipo):= new Empleado with libros=set() with clave-usuario = aNumero-economico
with max-libros = 8 with tipo=atipo.
class Externo Usuario.
externo(aCve-personallatelefono, adirec):= new Externo with libros=set() with clave-usuario
=
aCve-personalwith direccion = adirec
class lnstitucion c Object.
institucion(nombre-biblioteca):= new lnstitucion
with nombre-inst = nombre-biblioteca with telefono
with personas = set().
La clase Institución tambien nos da cuenta de la información de aquellas intituciones con las que se tiene convenio de préstamo interbibliotecario.
La operación de préstamo es la actividad principal de la bibliotena, desde luego no es la única, también está la de Adquisiciones, la Hemeroteca, etc.
La Hemeroteca lleva el control de revistas, publicaciones, periódicos, etc., una parte sencilla de modelar es la de suscripciones.
class Suscripcion Event.
suscripcion(ini, termina,aPrompter,aDisplay ):= new Suscripcion with distribuidor=nil
with prompter=aPrompter with fecha-ini=ini
with fecha-fin=termina with display = aDisplay.
Esta vez la clase no se deriva directamente de la clase predefinida en Enact Object. Se deriva de la Clase Event, que esta en el archivo Userface.act que tiene que cargarse antes de correr el programa, ya que Enact no reconoce clases, funciones ó procedimientos que no han sido declarados antes de su uso, esta utileria tiene funciones que permiten capturar información por parte del usuario y desplegarla en pantalla, digamos que es una capa intermedia entre el sistema y el usuario Io que se llama interfaz.
la parte de interfaz, y aquí se utiliza como auxiliar (para más detalles de sus operaciones ver Apéndice 111).
No ahondaremos en detalles de eso ya que no se considera en el diseño
La clase Suscripción se apoya fuertemente en la clase Fecha, sus operaciones están estrechamente ligadas a cuándo empieza y termina una suscripción y el otro atributo aparte de los utilizado para lograr la conección sistema-usuario es el de distribuidor que es como un apuntador a una instancia de la Clase Distribuidor que declaramos más adelante y contiene información que se puede requerir.
Suscripcion.revisa_fecha(fecha_actual):=fecha_actual.dias_entre_fechas(self.fe cha-fin).
Suscripcion.renueva(inicio, termino):=(ini:=fecha(); ini.inserta(self.prompter.get("'Fecha de inicio dial')); ini.inserta(self.prompter.get("'Fecha de inicio mes")); ini.inserta(self.prompter.get("'Fecha de inicio año'')); fin:=fecha();fin.guarda-valores();
fin.inserta(self.prompter.get("'Fecha de terminacion dial')); fin.inserta(self.prompter.get("'Fecha de terminacion mes")); fin.inserta(self.prompter.get("'fecha de terminacion año")); self.fecha_ini:=ini;self.fecha_fin:=fin;
resp:=self.display.put("'El
distribudor seguirá siendo el mismo");resp=n then (clave_d:=self.prompter.get("'Clave del distribuidor");self.distribuidor.clave-dist:=clave-d)).
Suscripcion.realiza(aMaterial,
fecha-actual):=(aMaterial.suscrip=nil
then (ini:=fecha();ini.inserta(self.prompter.get("'Fecha de inicio dial'));ini.inserta(self.prornpter.get("'Fecha de inicio mes")); ini.inserta(self.prompter.get("'Fecha de inicio
año"));fin:=fecha();fin.guarda-valores();
fin.inserta(self.prompter.get("'Fecha de terminacion
dia"));fin.inserta(self.prompter.get("'Fecha de terminacion mes")); fin.inserta(self.prompter.get("'Fecha de terminacion año''));
self.fecha-ini:=ini; self.fecha-fin:=fin; aMaterial.suscrip:=self;
clave-dist:=self.prompter.get("'Clave del distribuidor"); aMaterial.suscrip.distribuidor:=distribuidor(clave-dist)) else (dias:=aMaterial.suscrip.revisa_fecha(fecha_actual); self.display.put("'Faltan(días)",dias);dias~=30 then
ren:=self.prompter.get("'¿Desea renovarla?"); ren=s then aMaterial.suscripcion.renueva() )).
Talvez el código sea un poco difícil de entender a primera vista pero si se ha tenido relación con LISP, será hará un poco familiar y fácil de manejar.
La sección de Adquisiciones maneja
lo
que se refiere a la compra de nuevo material. Se requiere entonces llevar un control de las solicitudes de los usuarios para la adquisición de nuevo material. Introducimos la siguiente clase que se complementa con la clase Archivo que se explica posteriormenteclass Pedido Object.
pedido(aClve_editorial,aCant,aDescrip,aPrecio,aClve-progr):= new Pedido with clave-editorial = aClve-editorial
with cantidad
=
aCant with descripcion = aDescrip with precio = apreciowith clave-programa =aClve-progr with numero-pedido.
Pedido.adquisiciones-total():=self.cantidad*self.precio.
Pero si para las suscripciones necesitamos un distribuidor y para los pedidos aparte también se necesitan tratar con Editoriales para conseguir precios menores o mayor rapidez de entrega, ambos son Proveedores por lo que aunque por el momento parezca inútil tener una clase base que los derive ya que no declaramos ninguna operación para ambos como podremos ver a continuación, la filosofía de la programación orientada a objetos persigue que los sistemas faciliten los cambios en el futuro, así que no importa que ahora se deje así.
class Proveedor<Object.
class Editorial Proveedor.
editorial(clave):= new Editorial with clave-edit=clave with nombre.
class Distribuidor Proveedor.
distribuidor(clave):= new Distribuidor with clave-dist=clave with nombre.
La siguiente clase se utiliza para realizar una simulación de la EntradaEalida con la que no cuenta el lenguaje de Especificación ENACT
class Archivo < Object.
archivo():=new Archivo with members=nil.
Archivo.put(aTextObject):=(self.members:=append(self.members,aTextObject:())
1.
Archivo.lee():=(result:=hd(self.members);self.members:=tl(self.members);result).
Lo Único que realiza es por medio de listas simular la escritura y lectura secuencia1 en disco para poder modelar el proceso de Solicitud de nuevo
material de los distintos departamentos de la Universidad. El hecho es que para reducir el manejo de papeleo los solicitantes por medio de un diskete
conteniendo la información pertinente facilitan el manejo de pedidos que unicamente se revisan y se confirman
cargaPedido(aArchivo, aBiblio):=
caracter:=aArchivo.lee();cantidad:=caracter; caracter:=aArchivo.lee();descripcion:=caracter; caracter:=aArchivo.lee(); precio:=caracter;
caracter: =aArchivo. lee();clave-programa:=caracter;
aBiblio.adquiere(pedido(clave_editorial,cantidad,descripcion,precio,clave_progr
caracter:=aArchivo.lee())).
(caracter:=aArchivo.lee();(caractero"':")loop(clave-editorial:=caracter;
ama));
El procedimiento anterior y la clase que se describe a continuación sirven para probar el modelado de las solicitudes de pedido de nuevo material
class Adquiere Object. adquiere(aBiblioteca):=
new Adquiere with biblioteca=aBiblioteca.
Adquiere.do(aArch):=cargaPedido(aArch, self.biblioteca). Adquiere.suscrip(aMaterial,aFecha,aSuscripcion):= aSuscripcion.realiza(aMaterial,aFecha).
Finalmente la clase principal que lleva la batuta y dispara los eventos de las otras clases es la clase Biblioteca
class Biblioteca Object.
biblioteca():=new Biblioteca with solicitudes=set().
Biblioteca.adquiere(aPedido):=self.solicitudes.insert(aPedido).
Biblioteca.presta(aUsuario,aMaterial, fecha-actual):=(fecha-entrega:=fecha(); fecha_entrega.copia(fecha-actual.valor.members,
fecha_actual.valor.size());fecha-entrega.guarda_valores(); aMaterial.presta(aUsuario, fecha-actual, fecha-entrega)).
Biblioteca.regresa(aUsuario,aMaterial,fech):= aMaterial.regresa(fech).
Cabe señalar que en el prototipo no se consideraron las cuestiones de persistencia de datos e interfaz ya que el fin perseguido es tratar una rápida especificación y modelado del funcionamiento interno, sin embargo es
IMPLEMENTACIÓN
En esta fase el código crece debido a que se tiene que ser más detallado en cuestiones que para el rápido desarrollo del prototipo no se consideran
Header del programa aparte de la utilerías de C, debe tener
# include "c:collect.h"
para la utilización de operaciones de conjuntos,
Cuyo código se puede ver con más detalle en el Apéndice Ill que sirve
y las constantes que se manejan a lo largo del programa #define MAX-LIB-EST 5
#define MAX-LIB-EMP 8 #define MAX-LIB-EXT 5
#define DIAS-PRESTAMO-NORMAL 8
#define DIA-MULTA 1.5
# define MAX-NOM-USUARIO 30
# define MAX-CLAVE-USUARIO 8 # define MAX-DIR-USUARIO 50 # define MAX-TEL-USUARIO 1 O # define MAX-INS-USUARIO 1
Lo que procede ahora es como hacer una traducción de lo que tenemos en el prototipo a la plataforma de implementación C++.
La clase Fecha particularmente es muy distinta a la codificada en Enact, debido a que se utilizan estructuras distintas. En este caso las características de la plataforma no sirvieron en el diseño de estructuras, pues Enact no cuenta con mucha variedad de estructuras de datos.
class Fecha{ date valor; int* max-dias;
Fecha();
date regresa-fecha(); void guarda-fecha(date); void inicializa-meses(); int bisiesto(int);
int calcula-dias(); int restan-dias(); void suma-dias(int); dias-entre-fechas();
Fecha* genera-fecha-entrega(int); public:
Los miembros de una clase pueden ser
Quiere decir privado, su nombre
sólo
puede ser utilizado por funciones-
private
miembro y amigas de la clase en la que se declara
-
protected
y amigas de la clase en que se declara y por funciones miembro y amigas de clases derivadas de esta clase
Protegido, su nombre no sólo puede ser utilizado por funciones miembro
-
publicSu nombre puede ser utilizado por cualquier función, es una variable pública
Todas estas formas de declarar los miembros de una clase es porque es conveniente precisar el modo en que se deben declarar las variables, se
recomienda que sea de tipo private el acceso a
los
datos debe estar restringido lo más posible para que no cualquiera pueda modificar o accesar y funcione como un TDA, por omisión en C++ los miembros de una clase son private a menos que se especifique lo contrariosimple interfaz(comunicaci6n entre ella y los demás). Es mejor hacer el acceso a ella exclusivamente a través de funciones miembros.
Si queremos que la clase se comporte como un TDA con una buena y
// Constructor Fecha::Fecha(){
max-dias=new int (1 3);
int Aux[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; memcpy(max-dias,Aux ,26);
1
como ya mencionamos si sus miembros 6 atributos son privadas, el código crece al tener que crear funciones para poder acceder a sus atributos como las funciones siguientes
date Fecha::regresa-fecha(){ return valor;
1
void Fecha::guarda-fecha(date dma){
1
valor=dma;
int Fecha::bisiesto(int anio){
return(ani0 % 4 == O && anio % 100 != O
11
anio % 400 ==O);
I
int Fecha::calcula-dias(){ int mes,total, dias;
mes=total=dias=O;
for (;mes toascii(valor.da-mon); mes++) dias+=max-dias[mes];
total=dias
+
toascii(valor.da-day);if(mes>2 && bisiesto(toascii(valor.da_year)))
return(tota1); total++;
1
int Fecha::restan-dias(){ int mes, dia;
if(valor.da-mon==2 && bisiesto(valor.da-year))
else{
return (29-(valor.da-day)+l);
mes=toascii(valor.da-mon); dia=toascii(valor.da-day); return (max-dias[mes]-dia+l );
1
I
void Fecha::suma-dias(int n){ int numero;
while(n
>O){
numero=restan-dias(); if (n >=numero){
n=n-restan-dias();
valor.da-year+=(valor.da-mon/l2);
valor.da-mon = valor.da-mon % 12 + 1 ; valor.da-day = 1 ;
I
else{
valor.da-day+=n; n=O;
I
1
int Fecha::dias-entre-fechas(){
int totl , tot2, year-fin, year-actual;
year-fin = valor.da-year; tot2 = calcula-dias();
Fecha* actual=new (Fecha); getdate(&(actual->valor));
year-actual= actual->valor.da-year; totl = actual->calcula-dias();
if (year-fin != year-actual){ if(year-actual-I 900/4 > O)
totl =tot1 + 146 * ((year-actual-l900)/4); if(year-actual-I 900%4 > O)
totl =tot1 + 365 * ((year-actual-I 900)%4)+1; if(year-fin-I 900/4 > O)
tot2=(tot2 + 146 * (year-fin-I 900)/4); if(year-fin-I 900%4 > O)
tot2=tot2 + 365 * ((year-fin-I 900)%4)+1;
I
return abs(tot1 -tot2);
1
Dentro de los procedimientos y/o funciones se pueden declarar variables locales como la variable hoy y aux del procedimiento que se muestra a
continuación
Fecha*
Fecha::genera-fecha-entrega(int
dias){ Fecha* hoy=new (Fecha);date aux;
getdate(&(aux));
hoy->guarda-fecha(aux); hoy->suma-dias(dias); return(hoy);
I
//"""""""""""""""""""""""""""""""""""""""""""""-
En
C++,
al igual que en Enact no se puede hacer referencia a una clase ó procedimiento si no se ha declarado previamente. En la clase Material, se utiliza a la clase Usuario por los que se debe declararclass Usuario;
antes de definir la clase Material de lo contrario no se reconocerá
class Material{
Fecha* fecha-entrega; char* titulo;
public:
Usuario* prestador;
Material(char* nombre-mat); Fecha* regresa-fecha-entrega();
void presta(Usuario* persona, int dias); void regresa();
int enbiblioteca();
float calcula-multa(int tiempo, float multa); virtual char* nombre-titulo();
1;
Ahora hay que definirla, debido a que las operaciones que realiza la clase Material hacer referencia a atributos de Usuario que no se conocen
11
""""""""""""""""""""""""""-
"- """"""""""- """""""""""class Usuario {
char nombre-usuario [MAX-NOM-USUARIO]; Set * material-prestado;
char clave-usuario [MAX-CLAVE-USUARIO]; char direccion-usuario [MAX-DIR-USUARIO]; char telefono-usuario [MAX-TEL-USUARIO]; char inscrito-usuario [MAX-INS-USUARIO]; int multa;
public:
int max-num-libros; int max-libros(); Set* libros(); int num-libros();
void registro(Material* );
void devolucion(Material* ); Usuario(char* , char*, int); char* Quien();