GUIA 1 POO Unipanamericana
GUIA 1 POO Unipanamericana
Ingeniería de Software.
Modelo Conceptual.
1. Presentación
El ejercicio para esta guía es aplicar en el proyecto de cada grupo de manera que
puedan con solvencia realizar las siguientes acciones:
2. Profundización.
Página 1 de 32
como es la ingeniería, que es la confianza del cliente.
En general, todos los problemas se pueden dividir en estos tres aspectos. Por una
parte, se debe identificar lo que el cliente espera de la solución. Esto se denomina un
requerimiento funcional. En el caso de la programación, un requerimiento funcional
hace referencia a un servicio que el programa debe proveer al usuario. El segundo
aspecto que conforma un problema es el mundo o contexto en el que ocurre el
problema. Si alguien va a escribir un programa para una empresa, no le basta con
entender la funcionalidad que éste debe tener, sino que debe entender algunas cosas
de la estructura y funcionamiento de la empresa. Por ejemplo, si hay un
requerimiento funcional de calcular el salario de un empleado, la descripción del
problema debe incluir las normas de la empresa para calcular un salario. El tercer
aspecto que hay que considerar al definir un problema son los requerimientos no
funcionales, que corresponden a las restricciones o condiciones que impone el
cliente al programa que se le va a construir.
Fíjese que estos últimos se utilizan para limitar las soluciones posibles. En el caso
del programa de una empresa, una restricción podría ser el tiempo de entrega del
programa, o la cantidad de usuarios simultáneos que lo deben poder utilizar.
EJEMPLO
Objetivo: Identificar los aspectos que hacen parte de un problema.
Evidencias:
Página 2 de 32
TAREA 1:
Objetivo: Identificar los aspectos que forman parte de un problema.
El problema: un banco quiere crear un programa para manejar sus cajeros automáticos. Dicho
programa sólo debe permitir retirar dinero y consultar el saldo de una cuenta. Identifique y discuta
los aspectos que constituyen el problema. Si el enunciado no es explícito con respecto a algún
punto, intente imaginar la manera de completarlo.
Especificación del problema
Cliente
Usuario
Requerimiento Funcional
Requerimiento NO Funcional
Desde el programa se debe poder realizar las siguientes operaciones: (1) calcular la
edad actual del empleado, (2) calcular la antigüedad en la empresa, (3) calcular las
prestaciones a las que tiene derecho en la empresa, (4) cambiar el salario del
empleado, y (5) cambiar el empleado.
Página 3 de 32
Caso de Estudio Nº 2: Un Simulador Bancario
Una de las actividades más comunes en el mundo financiero es la realización de
simulaciones que permitan a los clientes saber el rendimiento de sus productos a
través del tiempo, contemplando diferentes escenarios y posibles situaciones que se
presenten.
El saldo total de la cuenta es la suma de lo que el cliente tiene en cada uno de dichos
productos. En la cuenta corriente, el cliente puede depositar o retirar dinero. Su
principal característica es que no recibe ningún interés por el dinero que se encuentre
allí depositado. En la cuenta de ahorros, el cliente recibe un interés mensual del 0,6%
sobre el saldo. Cuando el cliente abre un CDT, define la cantidad de dinero que
quiere invertir y negocia con el banco el interés mensual que va a recibir. A diferencia
de la cuenta corriente o la cuenta de ahorros, en un CDT no se puede consignar ni
retirar dinero.
La única operación posible es cerrarlo, en cuyo caso, el dinero y sus intereses pasan
a la cuenta corriente. Se quiere que el programa permita a una persona simular el
manejo de sus productos bancarios, dándole las facilidades de: (1) hacer las
operaciones necesarias sobre los productos que conforman la cuenta, y (2) avanzar
mes por mes en el tiempo, para que el cliente pueda ver el resultado de sus
movimientos bancarios y el rendimiento de sus inversiones.
Página 4 de 32
- Con el botón marcado como "Avanzar mes" el usuario puede avanzar un mes
en la simulación y ver los resultados de sus inversiones.
- Con los seis botones de la parte derecha de la ventana, el usuario puede
simular el manejo que va a hacer de los productos que forman parte de su
cuenta bancaria.
- En la parte media de la ventana, aparecen el saldo que tiene en cada producto
y el interés que está ganando en cada caso.
Página 5 de 32
- Con los tres botones de la izquierda, el usuario puede cambiar los puntos que
definen el triángulo, el color de las líneas y el color del fondo.
- En la zona marcada como "Medidas en pixeles", el usuario puede ver el
perímetro, el área y la altura del triángulo (en píxeles).
- En la parte derecha aparece dibujado el triángulo descrito por sus tres puntos.
- Un identificador y un nombre.
- Un resumen de la operación.
- Las entradas (datos) que debe dar el usuario para que el programa pueda
realizar la operación.
- El resultado esperado de la operación. Hay tres tipos posibles de resultado en
un requerimiento funcional: (1) una modificación de un valor en el mundo del
problema, (2) el cálculo de un valor, o (3) una mezcla de los dos anteriores.
EJEMPLO
Objetivo: Ilustrar la manera de documentar los requerimientos funcionales de un
problema.
Solución: En este ejemplo se documenta uno de los requerimientos funcionales del
caso de estudio del empleado. Para esto se describen los cuatro elementos que lo
componen.
Página 6 de 32
Para determinar si algo es o no un requerimiento funcional, es conveniente hacerse
tres preguntas:
- ¿Poder realizar esta operación es una de las razones por las cuales el cliente
necesita construir un programa? Esto descarta todas las opciones que están
relacionadas con el manejo de la interfaz ("poder cambiar el tamaño de la
ventana", por ejemplo) y todos los requerimientos no funcionales, que no
corresponden a operaciones sino a restricciones.
- ¿La operación no es ambigua? La idea es descartar que haya más de una
interpretación posible de la operación.
- ¿La operación tiene un comienzo y un fin? Hay que descartar las operaciones
que implican una responsabilidad continua (por ejemplo, "mantener
actualizada la información del empleado") y tratar de buscar operaciones
puntuales que correspondan a acciones que puedan ser hechas por el
usuario.
Página 7 de 32
Evidencias:
TAREA 2:
Objetivo: Crear habilidad en la identificación y especificación de requerimientos funcionales. Para el
caso de estudio 2, un simulador bancario, identifique y especifique tres requerimientos funcionales.
Requerimiento Funcional 1
Nombre
Resumen
Entradas
Resultado
Requerimiento Funcional 2
Nombre
Resumen
Entradas
Resultado
Requerimiento Funcional 3
Nombre
Resumen
Entradas
Página 8 de 32
Resultado
TAREA 3
Objetivo: Crear habilidad en la identificación y especificación de requerimientos funcionales.
Para el caso de estudio 3, un programa para manejar un triángulo, identifique y especifique tres
requerimientos funcionales.
Requerimiento Funcional 1
Nombre
Resumen
Entradas
Resultado
Requerimiento Funcional 2
Nombre
Resumen
Entradas
Resultado
Página 9 de 32
Requerimiento Funcional 3
Nombre
Resumen
Entradas
Resultado
Este modelo será utilizado en la etapa de diseño para definir los elementos básicos
del programa. Esta actividad está basada en un proceso de "observación" del mundo
del problema, puesto que los elementos que allí aparecen ya existen y nuestro
objetivo no es opinar sobre ellos (o proponer cambiarlos), sino simplemente
identificarlos y describirlos para que esta información sea utilizada más adelante.
Página 10 de 32
Para expresar el modelo del mundo utilizaremos la sintaxis definida en el diagrama
de clases del lenguaje de modelos UML (Unified Modeling Language). Dicho
lenguaje es un estándar definido por una organización llamada OMG (Object
Management Group) y utilizado por una gran cantidad de empresas en el mundo
para expresar sus modelos.
Para el primer caso de estudio, hay dos entidades en el mundo del problema: la clase
Empleado y la clase Fecha. Esta última se emplea para representar el concepto de
fecha de nacimiento y fecha de ingreso a la empresa. Si lee con detenimiento el
enunciado del caso, se podrá dar cuenta de que éstos son los únicos elementos del
mundo del problema que se mencionan. Lo demás corresponde a características de
dichas entidades (el nombre, el apellido, etc.) o a requerimientos funcionales.
EJEMPLO
Objetivo: Ilustrar la manera de identificar las entidades (llamadas también clases) del
mundo del problema.
En este ejemplo se identifican las entidades que forman parte del mundo del
problema para el caso 2 de este nivel: un simulador bancario.
Página 11 de 32
TAREA 4:
Objetivo: Identificar las entidades del mundo para el caso de estudio 3: un programa que maneje
un triángulo.
Lea el enunciado del caso y trate de guiarse por los sustantivos para identificar las entidades del
mundo del problema.
SOLUCIÓN
Página 12 de 32
Punto de reflexión: ¿Qué pasa si no identificamos bien las entidades del mundo?
Punto de reflexión: ¿Cómo decidir si se trata efectivamente de una entidad y no sólo de una
característica de una entidad ya identificada?
En el lenguaje UML, una clase se dibuja como un cuadrado con tres zonas (ver
ejemplo 5): la primera de ellas con el nombre de la clase y, la segunda, con los
atributos de la misma. El uso de la tercera zona la veremos más adelante, en la
etapa de diseño.
EJEMPLO
Objetivo: Mostrar la manera de identificar y modelar los atributos de una clase.
Página 13 de 32
Clase: Fecha
Página 14 de 32
Con las tres características anteriores queda completamente definida una fecha. Esa
es la pregunta que nos debemos hacer cuando estamos en esta etapa: ¿es
necesaria más información para describir la entidad que estamos representando? Si
encontramos una característica cuyos valores posibles no son simples, como
números, cadenas de caracteres, o una lista de valores, nos debemos preguntar si
dicha característica no es más bien otra entidad que no identificamos en la etapa
anterior. Si es el caso, simplemente la debemos agregar.
Es importante que antes de agregar un atributo a una clase, verifiquemos que dicha
característica forma parte del problema que se quiere resolver. Podríamos pensar,
por ejemplo, que la ciudad en la que nació el empleado es uno de sus atributos.
¿Cómo saber si lo debemos o no agregar? La respuesta es que hay que mirar los
requerimientos funcionales y ver si dicha característica es utilizada o referenciada
desde alguno de ellos.
TAREA 5:
Página 15 de 32
Para cada una de las cuatro entidades identificadas en el caso de estudio del simulador bancario,
identifique los atributos, sus valores posibles, y escriba la clase en UML. No incluya las relaciones
que puedan existir entre las clases, ya que eso lo haremos en la siguiente etapa del análisis. Por
ahora trate de identificar las características de las entidades que son importantes para los
requerimientos funcionales.
SOLUCIÓN
Clase: SimuladorBancario
ATRIBUTO VALORES POSIBLES
Diagrama UML:
Clase: CuentaCorriente
ATRIBUTO VALORES POSIBLES
Diagrama UML:
Página 16 de 32
Clase: CuentaAhorros
ATRIBUTO VALORES POSIBLES
Diagrama UML:
Clase: CDT
ATRIBUTO VALORES POSIBLES
Diagrama UML:
Página 17 de 32
Las Relaciones entre las Entidades
En esta actividad, debemos tratar de identificar las relaciones que existen entre las
distintas entidades (objetos) del mundo y asignarles un nombre. Las relaciones se
representan en UML como flechas que unen las cajas de las clases (ver figura abajo)
y se denominan usualmente asociaciones. El diagrama de clases en el cual se
incluye la representación de todas las entidades y las relaciones que existen entre
ellas se conoce como el modelo conceptual, porque explica la estructura y las
relaciones de los elementos del mundo del problema.
El modelo presentado en la figura dice que hay dos entidades en el mundo (llamadas
Clase1 y Clase2), y que existe una relación entre ellas. También explica que para la
Clase1, la Clase2 representa algo que puede ser descrito con el nombre que se
coloca al final de la asociación. La selección de dicho nombre es fundamental para la
claridad del diagrama.
Es posible tener varias relaciones entre dos clases, y por eso es importante
seleccionar bien el nombre de cada asociación. En la figura abajo se muestran las
asociaciones entre las clases del caso de estudio del empleado y del caso de estudio
del triángulo. En los dos casos existe más de una asociación entre las clases, cada
una de las cuales modela una característica diferente.
Página 18 de 32
Caso de Estudio del Empleado:
- La primera asociación dice que un empleado tiene una fecha de nacimiento y
que esta fecha es una entidad del mundo, representada por la clase Fecha.
- La segunda asociación hace lo mismo con la fecha de ingreso del empleado a
la empresa.
- La dirección de la fecha indica la entidad que "contiene" a la otra. El empleado
tiene una fecha, pero la fecha no tiene un empleado.
EJEMPLO
Objetivo: Presentar el diagrama de clases, como una manera de mostrar el modelo
de una realidad.
A continuación se muestra el diagrama de clases del modelo del mundo, para el caso
Página 19 de 32
del simulador bancario.
Definición de atributos
Cada lenguaje de programación cuenta con un conjunto de tipos de datos a través de
los cuales el programador puede representar los atributos de una clase. En este nivel
nos vamos a concentrar en dos tipos simples de datos: los enteros (tipo int), que
permiten modelar características cuyos valores posibles son los valores numéricos
de tipo entero (por ejemplo, el día en la clase Fecha), y los reales (tipo double), que
permiten representar valores numéricos de tipo real (por ejemplo, el interés de una
cuenta de ahorros). También vamos a estudiar un tipo de datos para manejar las
cadenas de caracteres (tipo String), que permite representar dentro de una clase una
característica como el nombre de una persona o una dirección. En los siguientes
niveles, iremos introduciendo nuevos tipos de datos a medida que los vayamos
necesitando. En Java, en el momento de declarar un atributo, es necesario declarar
el tipo de datos al cual corresponde, utilizando la sintaxis que se ilustra en el ejemplo
que se muestra a continuación:
Página 20 de 32
- Inicialmente se declaran los atributos nombre y apellido, de tipo String
(cadenas de caracteres).
- Los atributos se declaran como privados ( private ) para evitar su manipulación
desde fuera de la clase.
- El atributo salario se declara de tipo double, puesto que es un valor real.
- Con las tres declaraciones que aparecen en el ejemplo, el computador
entiende que cualquier objeto de la clase Empleado debe tener valores para
esas tres características.
- Sólo quedó pendiente por decidir el tipo del atributo genero, que no
corresponde a ninguno de los tipos vistos; eso lo haremos más adelante.
Para modelar el atributo "genero", debemos utilizar alguno de los tipos de datos con
los que cuenta el lenguaje. Lo mejor en este caso es utilizar un atributo de tipo entero
y usar la convención de que si dicho atributo tiene el valor 1 se está representando
un empleado con género masculino y, si es 2, un empleado con género femenino.
Este proceso de asociar valores enteros y una convención para interpretarlos es algo
que se hace cada vez que los valores posibles de un atributo no corresponden
directamente con los de algún tipo de datos. Fíjese que una cosa es el valor que
usamos (que es arbitrario) y otra la interpretación que hacemos de ese valor.
Página 21 de 32
representar los valores posibles, es importante agregar un comentario en la
declaración del mismo, explicando la interpretación que se debe dar a cada valor. En
el ejemplo, decidimos representar con un 1 el valor masculino, y con un 2 el valor
femenino.
En el diagrama de clases de UML, por su parte, usamos una sintaxis similar para
mostrar los atributos. En la figura de abajo aparece la manera en que se incluyen los
atributos y su tipo en el caso de estudio del empleado. Dependiendo de la
herramienta que se utilice para definir el diagrama de clases, es posible que la
sintaxis varíe levemente.
Lo único que nos falta incluir en el código Java es la declaración de las asociaciones.
Para esto, vamos a utilizar una sintaxis similar a la presentada anteriormente
utilizando el nombre de la asociación como nombre del atributo y el nombre de la
clase como su tipo, tal como se presenta en el siguiente fragmento de código:
Las asociaciones hacia la clase Fecha las declaramos como hicimos con el resto de
atributos, usando el nombre de la asociación como nombre del atributo. El tipo de la
asociación es el nombre de la clase hacia la cual está dirigida la flecha en el
diagrama de clases. El orden de declaración de los atributos no es importante.
Página 22 de 32
TAREA 6:
Objetivo: Crear habilidad en la definición de los tipos de datos para representar las características
de una clase.
Escriba en Java y en UML las declaraciones de los atributos (y las asociaciones) para las cinco clases
del caso de estudio del simulador bancario.
SOLUCIÓN
Declaración en java Descripción de la clase en UML
Simulador Bancario
CuentaCorriente
CuentaAhorros
CDT
Definición de métodos
Después de haber definido los atributos de las clases en Java, sigue el turno para lo
que hemos llamado métodos o comportamientos de los objetos. Se podría decir que
en los métodos están "los algoritmos" de la clase, y cada uno de estos pretende
resolver un problema puntual, dentro del contexto del problema global que se quiere
resolver.
Página 23 de 32
También se puede ver un método como un servicio que la clase debe prestar a las
demás clases del modelo (o a ella misma si es el caso), para que ellas puedan
resolver sus respectivos problemas. Un método está compuesto por cuatro
elementos:
Típicamente, una clase tiene entre cinco y veinte métodos (aunque hay casos en los
que tiene decenas de ellos), cada uno capaz de resolver un problema puntual de la
clase a la cual pertenece. Dicho problema siempre está relacionado con la
información que contiene la clase. Piense en una clase como la responsable de
manejar la información que sus objetos tienen en sus atributos, y los métodos como
el medio para hacerlo. En el cuerpo de un método se explica entonces la forma de
utilizar los valores de los atributos para calcular alguna información o la forma de
modificarlos si es el caso.
EJEMPLO
Objetivo: Mostrar la sintaxis que se usa en Java para declarar un método. Usamos
para esto el caso de estudio del empleado, con tres métodos sin cuerpo, suponiendo
que cada uno debe resolver el problema que ahí mismo se describe. La declaración
que aquí se muestra hace parte de la declaración de la clase (los métodos van
después de la declaración de los atributos).
SOLUCIÓN
public void cambiarSalario( double pNuevoSalario)
{
// Aquí va el cuerpo del método
}
Nombre: cambiarSalario
Página 24 de 32
Parámetros: pNuevoSalario de tipo real. Si no se entrega este valor como parámetro
es imposible cambiar el salario del empleado. Note que al definir un parámetro se
debe dar un nombre al valor que se espera y un tipo.
Retorno: ninguno ( void ) puesto que el objetivo del método no es calcular ningún
valor, sino modificar el valor de un atributo del empleado.
Descripción: cambia el salario del empleado, asignándole el valor que se entrega
como parámetro.
Nombre: darSalario
Parámetros: ninguno, puesto que con la información que ya tienen los objetos de la
clase Empleado es posible resolver el problema.
Retorno: el salario actual del empleado, de tipo real. En la signatura sólo se dice el
tipo de datos que se va a retornar, pero no se dice cómo se retornará.
Descripción: retorna el salario actual del empleado.
TAREA 7:
Objetivo: Definir el cuarto método para que sea definido.
En este caso, a partir de la descripción, debe determinar los parámetros, el retorno y la signatura
del método.
SOLUCIÓN
Nombre: aumentarSalario
Parámetros:
Retorno:
Página 25 de 32
Descripción: aumenta el salario del empleado en un porcentaje
que corresponde a la inflación anual del país.
Signatura:
Por ahora, supongamos que la clase tiene ya definidos los métodos que necesita
para poder resolver la parte del problema que le corresponde y trabajemos en el
cuerpo de ellos. En el diagrama de clases de UML, se utiliza la tercera zona de la
caja de una clase para poner las signaturas de los métodos, tal como se ilustra en la
figura:
Supongamos que la clase tiene ya definidos los métodos que necesita para poder
resolver la parte del problema que le corresponde y trabajemos en el cuerpo de ellos.
En el diagrama de clases de UML, se utiliza la tercera zona de la caja de una clase
para poner las signaturas de los métodos, tal como se ilustra en la figura abajo:
TAREA 8:
Objetivo: Escribir y entender en Java la signatura de algunos métodos del caso de estudio del
simulador bancario.
Complete la siguiente información, ya sea escribiendo la signatura del método que se describe, o
interpretando la signatura que se da. Todos los métodos de esta tarea son de la clase
CuentaAhorros.
Nombre: darSaldo
Parámetros: ninguno.
Retorno: valor de tipo real.
Página 26 de 32
Descripción: retorna el saldo de la cuenta de ahorros.
Signatura del Método:
Nombre: retirarValor
Parámetros: valor de tipo entero, que indica el monto que se quiere retirar de la cuenta
de ahorros.
Retorno: ninguno.
Descripción: retira de la cuenta de ahorros el valor que se entrega como parámetro.
Signatura del Método:
Nombre: darInteresMensual
Parámetros: ninguno.
Retorno: valor de tipo real.
Descripción: retorna el interés mensual que paga una cuenta de ahorros.
Signatura del Método:
Nombre: actualizarSaldoPorPasoMes
Parámetros: ninguno.
Retorno: ninguno.
Descripción: actualiza el saldo de la cuenta de ahorros simulando que acaba de
transcurrir un mes y que se deben agregar los correspondientes intereses ganados.
Signatura del Método:
Puesto que la clase Empleado no tiene acceso directo a los atributos de la clase
Fecha, debe llamar el método de dicha clase que presta ese servicio (o que sabe
resolver ese problema puntual).
EJEMPLO
Objetivo: Se necesita saber el año de ingreso a la empresa.
SOLUCIÓN
Página 27 de 32
- Invocamos el método darAnio( ) sobre el objeto de la clase Fecha que
representa la fecha de ingreso.
- Para pedir un servicio a través de un método, debemos dar el nombre de la
asociación, el nombre del método que queremos usar y un valor para cada
uno de los parámetros que hay en su signatura (ninguno en este caso).
- El resultado de la llamada del método lo guardamos en una variable llamada
valor, de tipo entero.
De la misma manera que un objeto puede invocar un método de otro objeto con el
cual tiene una asociación, también puede, dentro de uno de sus métodos, invocar
otro método de su misma clase. ¿Para qué puede servir eso? Suponga que tiene un
método cuyo problema se vería simplificado si utiliza la respuesta que calcula otro
método.
Página 28 de 32
Suponga que queremos calcular el monto de los impuestos que debe pagar el
empleado en un año. Los impuestos se calculan como el 19,5% del total de salarios
recibidos en un año. Si ya tenemos un método que calcula el valor total del salario
anual, ¿por qué no lo utilizamos como parte de la solución? Eso nos va a permitir
disminuir la complejidad del problema puntual del método, porque nos podemos
concentrar en la parte que "nos falta" para resolverlo.
Para invocar un método sobre el mismo objeto, basta con utilizar su nombre sin
necesidad de explicar sobre cuál objeto queremos hacer la llamada. Por defecto se
hace sobre él mismo.
Note que utilizamos una variable ( total ) como parte del cuerpo del método. Una
variable se utiliza para almacenar valores intermedios dentro del cuerpo de un
método.
Una variable debe tener un nombre y un tipo, y sólo puede utilizarse dentro del
método dentro del cual fue declarada. En el siguiente capítulo volveremos a tratar el
tema de las variables.
EJEMPLO
Objetivo: Ilustrar la construcción de los métodos de una clase.
Para el caso de estudio del simulador bancario, en este ejemplo se muestra el código
de algunos métodos, en donde se pueden apreciar los distintos tipos de instrucción
que hemos visto hasta ahora.
Página 29 de 32
Declaración de los atributos de la clase que representa la cuenta bancaria. Note de
nuevo la manera en que se declaran las relaciones con otras clases (como atributos,
cuyo nombre corresponde al nombre de la asociación).
Para depositar en la cuenta corriente un valor que llega como parámetro, la cuenta
bancaria pide dicho servicio al objeto que representa la cuenta corriente, usando la
asociación que hay entre los dos y el método consignarMonto() de la clase
CuentaCorriente.
Página 30 de 32
Para calcular y retornar el saldo total de la cuenta bancaria, el método pide a cada
uno de los productos que la componen que calcule su valor actual. Luego, suma
dichos valores y los retorna como el resultado. Fíjese que una expresión puede estar
separada en varias líneas, mientras no aparezca el símbolo ";" de final de una
instrucción. Para calcular el valor presente del CDT se le debe pasar como parámetro
el mes en el que va la simulación.
TAREA 9:
Objetivo: Escribir el cuerpo de algunos métodos simples.
Escriba el cuerpo de los métodos de la clase CuentaBancaria (caso de estudio 2) cuya signatura
aparece a continuación. Utilice los nombres de los atributos que aparecen en la declaración de la
clase. Suponga que existen los métodos que necesite en las clases CuentaCorriente, CuentaAhorros
y CDT.
Página 31 de 32
}
3. BIBLIOGRAFÍA
Villalobos, S., Casallas, J. A., Villalobos, R. J. A., & Casallas, R. (2006). Fundamentos de
programación: aprendizaje activo basado en casos: un enfoque moderno usando Java,
UML, Objetos y Eclipse (No. Sirsi) i9789702608462).
Página 32 de 32