Sei sulla pagina 1di 50

Unidad

1
DIPLOMATURA EN PROGRAMACION JAVA
Capítulo 1
Diplomatura en Programación Java

Capítulo 1 - Fundamentos de Clases y Objetos


Conceptos fundacionales: ¿cómo se llegaron a crear las clases y
los objetos?
La mejor forma de entender una tecnología es siempre saber su historia, aunque sea
parcialmente, para comprender lo que motivó su creación. Esto permite comprender no sólo las
causa que la motivaron sino también cómo utilizarla correctamente. Sin embargo, entrar en todos
los detalles históricos es largo y seguramente aburrido para quien quiere aprender un tema
tecnológico, por lo tanto se expondrá un breve resumen interpretativo de su evolución.

Estructuras de Datos

Vectores
Desde que se comenzaron a utilizar vectores, siempre se buscó agrupar los datos bajo un mismo
nombre que definiera a un conjunto de ellos. De esta manera, un vector es un conjunto de datos
del mismo tipo (por ejemplo, entero) agrupados con un único nombre que define a dicho vector.
De esta manera, si se declara en un programa un vector de 8 enteros con los primeros ocho
números naturales, una representación de cómo se distribuye en la memoria lo muestra la Figura
1-1.

Figura 1-1: Distribución de un vector en memoria

Los números se almacenan en forma continua uno al lado del otro y el nombre del vector
representa la dirección en donde comienzan a almacenarse los elementos. Los lenguajes
determinan la cantidad de bytes que se reserva para cada elemento del vector en base a su
declaración. En este caso se utilizó un tipo de datos entero. Suponiendo que para el lenguaje en
particular, un entero tiene 4 bytes (32 bits), el vector ocuparía 32 bytes de memoria (256 bits). La
forma de encontrar en memoria al vector es a través de la dirección de memoria en el que
comienza. Si se quiere un elemento en particular, por ejemplo el tercero, basta con desplazarse al
tercer lugar, es decir, moverse al tercer entero dentro del vector. Esto se hace de la siguiente
manera:

1. Si se quiere el primer elemento, sumar 0 bytes a la dirección donde empieza el vector.


2. Si se quiere el segundo elemento, sumar 4 bytes (un entero) a la dirección donde empieza
el vector (pasarse el primer elemento para leer el segundo).
3. Si se quiere el tercer elemento, sumar 8 bytes (dos enteros) a la dirección donde empieza
el vector (pasarse el segundo elemento para leer el tercero).
4. Etc …

Lic. Marcelo F. Samia


1
Diplomatura en Programación Java

Un ejemplo de utilización es colocar doce valores enteros dentro de un vector que representa las
veces que usó un auto una persona en cada uno de los 12 meses. Así cada elemento es un mes y el
valor que almacena es la cantidad de veces que usó el auto. El nombre del vector podría ser, por
ejemplo, usoDelAutoPorJuan y el vector sería como el que muestra la figura:

Figura 1-2: Representación en un vector del uso de un auto

El uso de esta manera de un vector permite hacer una abstracción del uso de la información para
que un programa interprete los datos de la siguiente manera:

Juan usó el auto según la Tabla 1-1.

Tabla 1-1: Interpretación de los datos en el vector


Mes Cantidad de veces

Enero 10

Febrero 6

Marzo 12

Abril 11

Mayo 3

Junio 22

Julio 6

Agosto 15

Septiembre 21

Octubre 11

Noviembre 30

Diciembre 33

Claramente se establece una relación entre el nombre del vector y la información que contiene
cada uno de sus elementos, por lo tanto este “agrupamiento” de datos tiene un valor agregado
conceptual, la posición del elemento indica el número de mes que se “asocia” a las veces que se
utilizó el auto.

Lic. Marcelo F. Samia


2
Diplomatura en Programación Java

Estructuras de datos
Una vez agrupados datos de un mismo tipo como se hizo en el vector, el siguiente desafío es
agrupar datos de diferentes tipos con el mismo fin, dar un valor agregado conceptual al
“agrupamiento”. Muchos lenguajes de programación resolvieron esta cuestión incorporando
estructuras de datos, las cuales siguen el mismo precepto que el vector, salvo que para cada
elemento ahora debe definirse el tipo de datos que es. Cada lenguaje define estas estructuras
según su gramática particular, pero en todos los casos, las estructuras de datos son modelos que
definen un nuevo tipo de datos. Es decir, una estructura se define para declarar variables del tipo
de la estructura.

Para no caer en un lenguaje en particular, se utiliza pseudocódigo para mostrar una declaración
tipo, según el siguiente formato:

ESTRUCTURA Nombre

DECLARACIONES DE VARIABLES

FIN ESTRUCTURA

ESTRUCTURA Nombre VARIABLE_ESTRUCTURA

Notar que no se tiene una variable en memoria hasta que se la declara explícitamente, como se
hace al final de la declaración y que al igual que en el vector, el nombre de la estructura
representa el lugar de memoria en donde se almacena la misma, pero a diferencia de este, cada
vez que se quiera acceder a un elemento de la estructura, se deberá desplazar la dirección tantos
bytes como mida el elemento en particular

Ejemplo

ESTRUCTURA Persona

CADENA nombre

CADENA apellido

ENTERO edad

FIN ESTRUCTURA

ESTRUCTURA Persona variablePersona

Notar que el uso de la abstracción en una estructura de datos es mayor que en el caso de un
vector. En estas se agrupan datos más genéricos que en el caso del vector y tiene mayor
flexibilidad para realizar asociaciones conceptuales entre el nombre de la variable del tipo
estructura y su contenido. Esto quiere decir que se pueden crear “modelos” de conceptos más
complejos que en el caso del vector. De esta manera, se puede modelar, por ejemplo, los datos

Lic. Marcelo F. Samia


3
Diplomatura en Programación Java

que pertenecen a una Persona, un Auto, etc., porque dichos conceptos tienen datos de diferente
tipo que lo describen (por ejemplo, en el caso de una persona, el nombre, apellido, D.N.I, etc.). Se
concluye entonces que una estructura de datos puede “modelar” los datos de “entidades
complejas” que un vector no puede hacer al tener todos sus elementos “del mismo tipo”.

Otro punto importante a tener en cuenta es que se pueden declarar tantas variables del tipo de
la estructura como se necesiten. La declaración de una estructura define un nuevo tipo de datos
(por ejemplo, como si fuera un entero o un punto flotante) y por definición se pueden declarar
tantas variables como se deseen de un determinado tipo de datos. La importancia de este hecho
radica en qué si bien la estructura puede modelar, por ejemplo, los datos de una Persona, existen
muchas de ellas en particular y cada una posee su conjunto exclusivo de datos, por lo tanto se
deben tener tantas variables como “entidades” se trabajen con la estructura de datos.

Uso de variables definidas por una estructura de datos


Una vez definida la estructura de datos y declarada una o más variables de su tipo, es necesario
acceder a las variables declaradas dentro de la estructura de datos para manejar su contenido en
particular. Una notación adoptada por muchos lenguajes de programación es la notación de
punto. Del ejemplo anterior, se pueden definir una serie de asignaciones de la siguiente manera:

variablePersona.nombre = “Martín”
variablePersona.apellido = “García”
variablePersona.edad = 33

Se debe tener en cuenta que una variable que se encuentra declarada dentro de otra de tipo
estructura es básicamente una variable, con lo que tiene todas sus propiedades: se pueden
asignar y recuperar valores, se pueden retornar desde procedimientos o funciones y pueden ser
sus parámetros.

Se pueden extender algunos conceptos de la siguiente forma:

Una estructura de datos se puede utilizar para realizar una abstracción de una entidad
Las variables dentro de la estructura de datos son los atributos de dicha entidad

Así, en el ejemplo, la entidad es Persona, y sus atributos son nombre, apellido y edad.

Si la persona cumple años, se debe cambiar el atributo edad y almacenar, por ejemplo, 34 en lugar
de 33. Este hecho demuestra el siguiente importante enunciado:

Los valores que almacena una determinada entidad, definen el estado de la misma

Por lo tanto, las variables declaradas dentro de una estructura son sus atributos y los valores que
almacenan definen su estado.

Lic. Marcelo F. Samia


4
Diplomatura en Programación Java

Ampliando las estructuras de datos


Las entidades representadas mediante estructuras de datos son un gran paso en la dirección de
abstraer elementos de un programa mediante la agrupación de los atributos que pertenecen a
dicha entidad. Sin embargo, esto significa que lo único que se está teniendo en cuenta son los
datos que se definen para una determinada entidad y no los procedimientos o funciones que
operan con dichos datos.

Tomando un ejemplo sencillo, es válido suponer querer realizar una función o procedimiento que
verifique que la edad que se le asigna a una persona está en un rango entre 0 y 120 años y pasarle
como parámetro una variable de tipo estructura que tenga en su interior declarada otra que
almacena el dato requerido (como la edad de una Persona). Con lo que se definió hasta el
momento, dicho procedimiento o función debe ser una parte independiente del programa, pero
opera con datos específicos de la estructura, es más, opera tan sólo con los almacenados en una
variable declarada dentro de la estructura. Por lo tanto, una asignación incorrecta de los valores
podría causar errores inesperados si estos no son los propios de la estructura (por ejemplo, por
error se pone el valor de la altura de la persona en la variable que corresponde a la edad).

Otro punto importante es que estas funciones o procedimientos sirven como servicios que la
entidad brinda para su utilización (por ejemplo, en este caso, el servicio es “no equivocarse al
asignar una determinada edad”). Una conclusión importante derivada de esto es el siguiente
enunciado:

Las entidades poseen atributos que definen su estado y servicios mediante los cuales se
comunican con otras entidades

Se puede concluir entonces que sería provechoso que dichos procedimientos o funciones
estuvieran incluidos dentro de la estructura y no en una parte independiente del código que se
utiliza y la única forma de acceder a los valores almacenados sea a través de ellos.

Para declarar un elemento dentro de una estructura, es fundamental conocer el tipo de datos para
saber cuántos bytes de memoria se deben reservar para almacenar la información, pero ¿cuántos
bytes de memoria hay que reservar si se va a colocar dentro de una estructura una función o
procedimiento? En realidad, no es necesario saber el tamaño de una función o procedimiento para
colocarlo dentro de una estructura, basta con saber en qué lugar de la memoria se encuentra el
mismo y guardar una referencia a ese espacio. Además, las direcciones de memoria en un
computador son siempre del mismo tamaño ya que este lo fija el bus de direcciones. Por lo tanto,
un lenguaje “sabe” el tamaño de una dirección de memoria para una determinada plataforma de
trabajo donde se intenta crear un programa. Esto permite definir tamaños fijos dentro de la
estructura de datos para indicar cuales son las direcciones de los procedimientos o funciones que
operan con los datos declarados dentro de la estructura.

Lic. Marcelo F. Samia


5
Diplomatura en Programación Java

¿Cómo trabaja un programa en memoria?


Todo programa en memoria sigue un formato conceptual de cuatro regiones, determinadas por
los registros del procesador que gestionan los datos almacenados en ellas, donde se almacena
información en la memoria RAM. Estas cuatro regiones son:

Heap (Amontonamiento): todo programa tiene asignado un espacio de memoria RAM


para su ejecución. Este espacio lo determina el sistema operativo sobre el cuál se ejecuta
el programa. Este a la vez gestiona dentro de este espacio las otras tres áreas que lo
componen. Sin embargo, si el programa no utiliza todo el espacio que le asigna el sistema
operativo queda un lugar sin usar al cual tiene acceso. Los lenguajes de programación
permiten el acceso a dicho lugar de la RAM mediante un gestor dinámico de memoria,
esto quiere decir, el programa durante su ejecución puede reservar espacios aleatorios de
la memoria que le asignó el sistema operativo para usarla. Como la solicitud del espacio de
memoria es aleatorio y depende de que sea solicitada durante la ejecución, la memoria se
asigna en el primer espacio libre que se encuentra y los diferentes espacios asignados se
van amontonando según se van solicitando (de ahí su nombre, Heap)
Stack (Pila): cada vez que se invoca una función o procedimiento, primero se reserva en la
zona de la RAM asignada al Stack una porción de memoria para almacenar en ella los
parámetros y variables locales que usará éste durante su ejecución. Cuando el
procedimiento o función termina, este espacio de memoria reservado previamente se
libera para que otro del mismo tipo pueda reclamar dicho espacio. Como un método
puede invocar a otro, y este a su vez a otro y así sucesivamente, los espacios de memoria
se conceden apilando los requerimientos y liberándolos según van terminando (de ahí su
nombre).
Memoria Estática: cuando un programa utiliza datos que deben conservarse a lo largo de
toda la ejecución del mismo, se deben guardar en un área de memoria que permanezca
inalterable. Cómo esto determina que ese espacio se mantenga igual a lo largo de toda la
ejecución, no puede variar dinámicamente como en el caso del Stack, por eso este lugar se
maneja en un bloque separado de RAM
Zona de Texto: es el lugar de memoria donde se encuentran las instrucciones de un
programa. Dentro de la zona de texto están almacenados las funciones o procedimientos
que pertenecen a un programa y cada una está diferenciada por un punto de entrada.
Dicho punto de entrada es un desplazamiento (offset) calculado desde el comienzo del
área de la RAM asignada a la Zona de Texto

El diagrama de bloque de la Figura 1-3 muestra cómo queda conformada lógicamente la memoria
RAM para la ejecución de un programa.

Lic. Marcelo F. Samia


6
Diplomatura en Programación Java

Figura 1-3: Diagrama de bloques de un programa en memoria

Creación de Instancias
Cada vez que se declara una variable del tipo de una estructura se crea una instancia y cada
instancia puede tener su propio estado porque cada nueva variable se almacena en un lugar
diferente de la memoria. Entonces, cabe la siguiente pregunta ¿Cómo encuentra cada instancia
diferente los atributos que definen su estado?

Es obvio que de alguna manera hay que tener una referencia al lugar de memoria que se debe
utilizar. Estas referencias se resuelven mediante el uso del nombre de la variable y la notación de
punto cuando se acceden a los atributos, pero ¿cómo sabe un servicio cuáles son los atributos
sobre los cuales operar? La solución lógica es pasarle cada vez que se invoca al servicio la dirección
de memoria en donde se encuentran los atributos.

Como esta es una tarea repetitiva y promueve errores de programación si los programadores
debieran hacerlo cada vez que invocan a un servicio, los lenguajes de programación resuelven el
tema “tras bambalinas” y pasan por defecto esta referencia en cada invocación.

Para los lenguajes orientados a objetos las estructuras se denominan clases y las variables del tipo
de la estructura se denominan objetos. Por lo tanto un objeto se obtiene como consecuencia de
crear una instancia de una clase y tiene todas las propiedades de las variables.

Lic. Marcelo F. Samia


7
Diplomatura en Programación Java

Los atributos de un objeto se denominan variables de instancia y las funciones o procedimientos


definidos en la clase se denominan servicios, métodos o funciones de instancia. Las variables
locales o parámetros definidos dentro de los servicios no pertenecen a la estructura o clase, por lo
tanto no son variables de instancia sino que se las denomina variables locales al método, porque
sólo tienen validez dentro de él.

Definiciones
Para empezar a separar conceptos y clarificarlos, este es el punto donde las definiciones empiezan
a ser necesarias. Las mismas comienzan con la realización de sistemas y van siendo cada vez más
específicas hasta llegar a los mismos componentes que pertenecen al desarrollo de un programa,
por lo tanto debemos establecer una diferencia clara entre “sistema” y “programa”:

Programa: Un programa es simplemente un grupo de instrucciones que la computadora


debe seguir para transformar datos, por lo tanto su objetivo está bien definido y cambia
poco o nada con el transcurso del tiempo.
Sistema: Es un conjunto de soluciones que se deben brindar para un determinado
problema o funcionalidad. Puede estar compuesto de ninguno, uno o varios programas ya
que un sistema puede ser tanto manual como informático. Los sistemas siempre
evolucionan con el tiempo porque las funcionalidades o problemas también lo hacen.

Otro concepto importante para comprender en este momento es el de “análisis de un sistema”. La


razón es simple, no se puede resolver algo que no se comprende y para hacerlo se debe “analizar”.
Por lo tanto se define:

Análisis de un sistema: comprender lo que el mismo realiza y cómo lo hace usando


cualquier técnica que lo permita.

Para desarrollar un sistema se debe realizar una determinada planificación de manera de


racionalizar los esfuerzos que implica la creación del mismo y enmarcar los recursos utilizados para
lograrlo.

Proyecto: Un proyecto es una planificación que consiste en un conjunto de actividades


que se encuentran interrelacionadas y coordinadas. En nuestro caso, un proyecto
informático se compone de las acciones que se toman para desarrollar un sistema.

Con estos conceptos en mente, lo próximo es entender cuáles son los elementos que permiten
construir un proyecto informático en un lenguaje orientado a objetos.

Clase: es una construcción que se utiliza como un modelo (o plantilla) para crear objetos
de ese tipo. Define un nuevo tipo de datos creado por el usuario (programador) que es
justamente el de la clase. A este modelo se lo denomina también abstracción del objeto
que representa.
Miembros de una Clase: son los atributos y servicios declarados dentro de la clase.

Lic. Marcelo F. Samia


8
Diplomatura en Programación Java

Objeto: es la unidad que en tiempo de ejecución realiza las tareas de un programa y se


define mediante la creación de una instancia de una determinada clase.
Variables de Instancia o Atributos: son las variables declaradas dentro de una clase. No se
almacena espacio de memoria para ellas hasta que no se cree una instancia de la clase (de
ahí su nombre).
Servicios: son los procedimientos o funciones declarados dentro de una clase. Muchos
lenguajes los denominan como método o función miembro.
Variables locales: son las variables declaradas como parámetros de los servicios o dentro
de los mismos. Sólo se las puede acceder dentro del método en dónde se las declara, por
lo cual no son variables de instancia.
Módulo: es una unidad de programación. Muchos lenguajes de programación establecen
que un módulo es una clase. Sin embargo, como los módulos se comunican entre sí
mediante el acceso a sus atributos o servicios, este concepto se suele extender en otros
lenguajes a un conjunto de clases que interactúan con otros módulos (como es el caso de
las librerías de enlace dinámico – dll, dynamic link library – utilizadas por los sistemas
operativos). En otras palabras, es una definición que se puede aplicar a muchos conceptos
porque indica un agrupamiento de elementos usados como unidad (inclusive puede ser un
subsistema en sí mismo).

Ingeniería de software
Cuando se quiere desarrollar software, se necesita alguna “técnica” para hacerlo que nos guie por
el camino correcto respecto de las dificultades que se pueden encontrar en el desarrollo de un
proyecto. A las mencionadas técnicas se las llamó disciplinas. Cuando se tuvo un conjunto de las
mismas se las denominó sub disciplinas y se las definió como los componentes del proceso
sistemático del desarrollo de software para que sea tanto sistemático (se posee un sistema para
llevarlo a cabo) como cuantificable (se lo puede medir para, fundamentalmente, la toma de
decisiones. Un ejemplo de esto es el tiempo de desarrollo).

Existen muchas definiciones que se pueden ajustar muy a la descripción de lo que significa
ingeniería de software, por lo tanto utilizaré un conjunto de ellas, formuladas por prestigiosos
autores, extraído de Wikipedia en https://es.wikipedia.org/wiki/Ingenier%C3%ADa_de_software y
son las siguientes:

• La ingeniería de software es el estudio de los principios y metodologías para el desarrollo y


mantenimiento de sistemas software (Zelkovitz, 1978).
• La ingeniería de software es la aplicación práctica del conocimiento científico al diseño y
construcción de programas de computadora y a la documentación asociada requerida
para desarrollar, operar y mantenerlos. Se conoce también como desarrollo de software o
producción de software (Bohem, 1976).

Lic. Marcelo F. Samia


9
Diplomatura en Programación Java

• La ingeniería de software trata del establecimiento de los principios y métodos de la


ingeniería a fin de obtener software de modo rentable, que sea fiable y trabaje en
máquinas reales (Bauer, 1972).
• La ingeniería de software es la aplicación de un enfoque sistemático, disciplinado y
cuantificable al desarrollo, operación, y mantenimiento del software (IEEE Standard
Glossary of Software Engineering Terminology).

Sin embargo, sólo a efectos de ser más claro que preciso, llamaremos ingeniería de software a
todo lo que está incluido en el proceso de creación del mismo.

Ciclo de vida iterativo e incremental de los proyectos


Los proyectos pueden desarrollarse utilizando una aproximación iterativa e incremental. Esta es la
forma en la cual se desarrollan los proyectos modernos.

Una iteración es un paso en el ciclo de vida de todo el proyecto y resulta en un incremento de


dicho proyecto. Los incrementos se logran cumpliendo cuatro fases. Una vez realizadas las mismas
se reitera el ciclo.

Algo que es muy conocido en el lenguaje popular es el concepto de “versión de un sistema o


producto de software. Una versión se logra a través de cumplir una cierta cantidad de iteraciones
(una o varias) luego de las cuales el proyecto se considera en condiciones para presentarlo a aquel
que lo recibirá.

La Figura 1-4 muestra el comportamiento iterativo del ciclo de vida de un proyecto.

Primera
Iteración

Segunda
Iteración

Figura 1-4: Ciclo de vida Iterativo de un proyecto

Un incremento se refiere al crecimiento, en términos del resultado final general de todo el


proyecto. La sugerencia es siempre es que en lugar de atacar el problema en un solo paso, se itere

Lic. Marcelo F. Samia


10
Diplomatura en Programación Java

a través de un ciclo y se produzcan actualizaciones incrementales. Cada incremento se construye


sobre el otro, mejorando y corrigiendo los incrementos previos.

Fases principales del ciclo de vida iterativo e incremental


El ciclo de vida del desarrollo consiste en las siguientes cuatro fases:

• Concepción
• Elaboración
• Construcción
• Transición

La Figura 1-5 muestra las fases principales de un ciclo de vida iterativo e incremental y como se
relacionan con los incrementos.

Elaboración Concepción
Primera
Iteración

Segunda
Iteración

Construcción Transición

Figura 1-5: Fases del ciclo de vida iterativo de un proyecto

En la Figura 1-6 se puede ver como las distintas fases afectan las etapas de un proyecto. Las
siguientes, son las iteraciones de cada etapa del ciclo de vida de un proyecto y sus respectivas
fases.

Lic. Marcelo F. Samia


11
Diplomatura en Programación Java

Concepción Elaboración Construcción Transición

Requerimientos

Análisis

Diseño

Implementación

Verificación

Iteración

Tiempo

Figura 1-6: Las Fases en las etapas de un proyecto

Nota: se debe tener en cuenta que las áreas sólidas indican la carga de actividad para cada
etapa en cada iteración y que es una guía simplemente y puede variar de proyecto a proyecto
dependiendo exclusivamente de los requerimientos que cada uno tenga. Cuando se completa
una iteración en cada etapa, implica un incremento.

Información relevada (Iteración 1 – fase de concepción –


requerimientos)
La información relevada es aquella a partir de la cual se comienza a analizar cuáles son las
abstracciones principales. Por lo general se encuentra en forma de una serie de párrafos que se
obtienen al tratar de entender el problema a resolver y que se obtiene de un cliente, interesado o
definición que indican en forma narrativa sus necesidades de solución. Por ejemplo, cuando un
profesor dicta un problema a los alumnos en una clase, el enunciado pasa a ser la información
relevada.
Por lo general la información de este tipo no sigue el orden que suele tener el enunciado de un
problema que dicta un profesor sino que viene en un formato no secuencial, desordenado y
confuso. También parte de ella se puede descartar si no es relevante a la solución que se desea
obtener.

A la simplificación de la información relevada se la denomina extracción de requisitos y ordena en


forma sencilla las necesidades de solución planteadas en la información relevada. Cuando el
conjunto de requerimientos se ordena en un enunciado claro y conciso, sin redundancias ni
perdida de información de necesidades a resolver, se lo llama enunciado de un problema, al igual
que el dictado por un profesor a sus alumnos.

Lic. Marcelo F. Samia


12
Diplomatura en Programación Java

Ejemplo de relevamiento
La biblioteca Municipal desea realizar un sistema para administrar la gestión de los libros que
presta al público general y a sus socios registrados. La información relevada de distintas fuentes se
encuentra a continuación:

Para comenzar, se quiere tener un pequeño control de cómo se arman los puestos de
lectura, a los que se les llama puesto de trabajo. Los puestos se dividen en informáticos y
de lectura. Los primeros tienen un escritorio con una sola silla y los segundos un escritorio
con cuatro. Algunos escritorios tienen asignados una PC de escritorio mientras que otros
sólo se usan con notebooks que se proveen cuando se las solicita ya que se debe ser socio
de la biblioteca para tener acceso a los recursos informáticos. Por el momento se cuenta
tan sólo con 20 máquinas pero en el futuro habrá más y se quiere empezar la realización
de un sistema que controle los recursos con los que cuenta la biblioteca. Actualmente,
sólo interesa indicar como se arman los puestos y que recursos fueron asignados. Cada
recurso posee un número de identificación para reconocerlo. Los libros y las
computadoras se asignan a los lectores, no a los puestos de trabajo.

Para las necesidades actuales, en lo que refiere a los escritorios con computadoras o
notebooks prestadas, sólo se pretende saber que socios las están utilizando

La biblioteca atiende a dos tipos de personas: el público en general que se presenta para
leer en el salón y los socios. Cuando cualquiera de estos dos tipos de personas accede al
salón, la biblioteca los considera lectores más allá de su situación administrativa. Los
socios adquieren su condición en un sistema independiente en el cual les entregan un
carnet de acreditación. Los libros se pueden entregar para leer en el salón o en el domicilio
en caso de ser socios, pero el público en general sólo los puede leer en el salón. Cuando
los libros se entregan para leer en el domicilio del socio tiene una fecha de devolución. Los
socios sólo pueden retirar un libro para su domicilio si previamente realizaron una
reservación o cuando lo solicita en el mismo salón y se encuentra disponible. Pueden
existir muchas copias de un mismo libro y todos los mismos son físicos ya que la biblioteca
no maneja libros en formato electrónico.

Cuando los socios crean una reserva se la considera activa. Si el socio posteriormente por
alguna razón desea dar de baja la reserva, la única operación que se realiza es poner a la
misma como inactiva. Esto brinda la posibilidad que en un futuro se puedan reactivar las
reservas aunque en este momento no es un requerimiento para la primera versión de la
solución. Por otro lado, cuando el socio retira el libro, la reserva se considera inactiva pero
se marca para indicar que el o los libros en ella se encuentran prestados.

Nunca se entregan dos copias de un mismo libro a un lector, sea socio o público. Esto se da
tanto para el caso en el cual el libro se presta para el domicilio de un socio o cuando se
entrega a un lector que se encuentre en el salón.

Lic. Marcelo F. Samia


13
Diplomatura en Programación Java

Por el momento no se pretende llevar un control sobre la cantidad de copias que se


entregan y se debe suponer que siempre hay una cantidad suficiente de las mismas.

Tampoco se desea crear una interfaz gráfica para interaccionar con el sistema, sólo
controlar que la funcionalidad se lleva a cabo correctamente para diseñar adecuadamente
como se presentará la información usando el tiempo que se genera mientras se realiza
este desarrollo.

La información que se debe mostrar en pantalla para verificar el funcionamiento del


desarrollo se debe hacer mediante una simulación que permita ver:

1. Los puestos de trabajo del salón de lectura


2. Los lectores y sus libros que se encuentran en el salón de lectura
3. Los lectores de cada libro
4. Los libros reservados
5. Libros que se encuentran prestados y el estado de las reservas
6. Los socios que están usando computadoras y cuáles son

Enunciado de un problema o sentencia del problema.


El enunciado de un problema es lo que un sistema va a proporcionar como suma de
funcionalidades cuando se encuentre la solución del mismo. Para enunciar un problema, se debe
utilizar información relevada y en base a ella generar lo que se denomina “sentencia del
problema”, la cual es una descripción breve y concisa de la información relevada y el problema a
resolver.

Atención: no se deberá perder información al enunciar el problema, sino por el contrario, se


debe incluir toda la misma pero evitando redundancias.
Además, se debe tener en cuenta que la sentencia de un problema por lo general es una
composición de acciones que se deben realizar para solucionar la problemática planteada
mediante la creación de un sistema (también se puede utilizar para solucionar un simple
programa, pero no es lo que estamos tratando).

Ejemplo

Nota: la denominación “sentencia del problema” es un nombre histórico y se respeta como tal.
En la actualidad se lo podría llamar “enumeración de funcionalidades a resolver” y tal vez sería
más adecuado. Sin embargo, como es una terminología instalada, se lo sigue llamando de esta
manera.

Se enuncia el problema en base al relevamiento expuesto como ejemplo anteriormente.

Lic. Marcelo F. Samia


14
Diplomatura en Programación Java

Enunciado del problema (Iteración 1 – fase de concepción – requerimientos)

Enumeración de funcionalidades a resolver


1. La biblioteca brinda servicios a dos tipos de personas: socios y público en general.
2. Se denomina lector al que accede al salón, sea socio o no.
3. Crear un control de cómo se arman los puestos de lectura, a los que se les llama puesto de
trabajo.
4. Dividir los puestos de trabajo en informáticos y de lectura.
5. Los puestos de trabajo informáticos tienen un escritorio, una silla y algunos se usan con PC
de escritorio mientras que otros se usan con notebooks.
6. El número de computadoras está limitado a 20 por el momento
7. Gestionar la asignación de elementos de la biblioteca para su funcionamiento para el
armado de puestos de trabajo.
8. Cada elemento de trabajo posee un número de identificación
9. Los libros y las computadoras se asignan a los lectores, no a los puestos de trabajo.
10. Las PC y notebooks sólo se prestan a los socios y se debe saber quiénes las están usando
11. Los libros se entregan para leer en el salón o en el domicilio. Esto último es válido sólo
para los socios y tiene asociada una fecha de devolución.
12. Los préstamos de libro se hacen con o sin reservación previa en el momento. No se tiene
en cuenta la disponibilidad y se supone que siempre hay libros para realizar la operación.
13. La biblioteca sólo maneja libros físicos, no electrónicos.
14. Las reservas se marcan como activas o inactivas. Si la inactividad es porque se concretó un
préstamo, se marca como prestados en la misma reserva.
15. Nunca se entregan dos copias de un mismo libro a un lector o en un préstamo.
16. No se pretende llevar un control sobre la cantidad de copias que se entregan y se debe
suponer que siempre hay una cantidad suficiente de las mismas.
17. No se desea crear una interfaz gráfica para interaccionar con el sistema, sólo controlar que
la funcionalidad se lleva a cabo correctamente para diseñar adecuadamente como se
presentará la información.
18. La información que se debe mostrar en pantalla para verificar el funcionamiento del
desarrollo se debe hacer mediante una simulación que permita ver:
a. Los puestos de trabajo del salón de lectura
b. Los lectores y sus libros que se encuentran en el salón de lectura
c. Los lectores de cada libro
d. Los libros reservados
e. Libros que se encuentran prestados y el estado de las reservas
f. Los socios que están usando computadoras y cuáles son

Delimitar la solución
Cada vez que se realiza un análisis de un problema es importante determinar cuáles son los límites
de la solución. Es muy fácil cuando se crean modelos concluir que otros objetos se pueden

Lic. Marcelo F. Samia


15
Diplomatura en Programación Java

modelar a partir de las abstracciones principales. De alguna manera hay que establecer donde se
debe parar y hay que tener presente en todo momento dichas limitaciones, mientras se analiza o
se diseña una clase.

No siempre es claro cómo realizar este trabajo. Sin embargo, el uso las definiciones anteriores
ayudan a manejar esta complejidad lo que permite establecer dónde está contenida la solución
buscada.

Los desarrolladores siempre buscan solucionar funcionalidades, lo que nos lleva a la creación de
sistemas compuestos de uno o varios programas mediante el análisis del mismo. Estos pueden
basarse en un sistema manual o crear uno nuevo.

Es entonces fundamental encontrar dónde se “ubica” el sistema comparado con otros posibles,
cuáles son las tareas que se tienen que realizar para desarrollarlo y hasta dónde llega cada una de
las soluciones brindadas. Para determinar todo esto se debe comprender el significado de tres
definiciones fundamentales:

• Dominio
• Contexto
• Alcance

Para explicar estos conceptos se utilizarán nombres y definiciones derivadas de la teoría de


conjuntos (sólo los nombres, no se preocupe).

Dominio de un problema
Es el universo donde se encuentran todas las posibles soluciones de un determinado
problema.

Un ejemplo puede ayudar a comprender correctamente la definición. Supongamos que debemos


realizar un sistema contable. Su dominio estará determinado por todos los sistemas contables que
se pueden realizar con sus diferentes variaciones.

¿Cuál es la importancia de manejar este concepto? Bueno, sirve nada más y nada menos que para
solicitar ayuda. Comprendiendo el dominio se pueden consultar soluciones similares para resolver
dificultades que se encuentren al desarrollar un sistema. También se puede consultar a personas
que sean idóneas por conocer la problemática a resolver (a estos se le suele denominar expertos
de dominio). Se puede buscar bibliografía del tema, etc.

En ejemplo del sistema contable a resolver, comprender el dominio permite que le podamos hacer
consultas, por ejemplo, a un contador. Sin embargo, ¿se puede preguntar algo sin saber cómo
hacerlo? La respuesta es simple, no. Para saber que preguntar, se debe entender el dominio en el
que se encuentra la solución. En palabras simples, no le puedo preguntar a un contador como se
realiza un circuito eléctrico porque estoy en otro dominio.

Lic. Marcelo F. Samia


16
Diplomatura en Programación Java

También se puede ver un sistema similar para entender como resuelve cierta funcionalidad. En
este caso, el “experto del domino” que se consulta es un sistema y no una persona.

Es importante tener en cuenta que el “experto” pertenece al dominio, motivo por el cual puede no
estar involucrado directamente con el sistema a desarrollar ya que pertenece al universo de todas
las soluciones posibles.

Otro punto importante para aclarar es que los dominios no son necesariamente estáticos, sino
más bien todo lo contrario. En el ejemplo del contador, supongamos que se dictamina una nueva
ley para llevar la contabilidad. Esto implica una variación en el dominio que seguramente
repercute en todo lo realizado.

Ejemplo
Establecimiento del dominio del proyecto para la biblioteca.

Dominio (Iteración 1 – fase de elaboración – análisis)


Gestión de préstamos de libros y puestos de trabajo en las bibliotecas con manejo de socios y
público en general.

Contexto de un problema
Es el subconjunto dentro del universo definido por el dominio que determina la solución del
sistema a realizar.

Una vez determinado el dominio de un sistema el próximo paso es encontrar dentro de todas las
posibles soluciones la que se ajusta al sistema a desarrollar. En otras palabras, se debe encontrar
la solución que se adecue al problema a resolver estableciendo el límite en cual dicha solución es
válida. En palabras sencillas, resolver sólo lo necesario y nada en exceso.

Muchas veces estas limitaciones se establecen como una lista de lo que la solución hace y lo que
no. Al conjunto de elementos que pertenece a dicha lista se lo denomina contexto de un
problema.

En un ejemplo anterior, se modela como una Persona come una Fruta. En la abstracción creada no
se tiene en cuenta todas las cosas que puede comer una persona o de cuantas formas diferentes
se puede “dejar comer” una fruta. Estas limitaciones pueden no ser muy claras durante el análisis
pero si no se pierde de vista el contexto que se define para la solución del problema, se sabe
exactamente donde terminar el análisis para no modelar más de lo que el problema requiere para
su solución.

Retomando el ejemplo del sistema contable, si la solución buscada es un sistema que mantenga
las cuentas, pero que no realice el balance porque el mismo lo desarrolla un contador en su
estudio profesional, el desarrollo del balance está fuera de contexto.

Lic. Marcelo F. Samia


17
Diplomatura en Programación Java

El contexto de un problema no es estático y puede variar a medida que avanza el análisis (por
ejemplo, se contrata a un nuevo contador y este no realiza el balance en su estudio y el sistema
ahora deberá resolverlo – por eso se dice que los sistemas evolucionan). Mientras se determinan
que elementos son parte de la solución o no, se va extendiendo la lista que pertenece al contexto.
Cabe destacar, que en algunos casos, los menos, el sistema se reduce en lugar de crecer, es decir,
se requiere menos funcionalidad del mismo. Vamos a avanzar con el caso en el cual el sistema
crece sólo para favorecer una comprensión más simple del concepto.

Como el problema que resolverá la solución lo determina el contexto de la misma, muchas veces
se denomina al contexto como dominio de la solución. Sin embargo, vale la pena aclarar que para
que el contexto coincida con el dominio debe resolver todos los sistemas posibles que se pueden
crear en dicho universo, lo cual es prácticamente imposible ya que el mismo universo puede
evolucionar y variar (este es el problema que enfrentan las soluciones llamadas “paquetes
cerrados de software" porque siempre hay algún contexto de solución que no estará incluido).

Podemos concluir entonces que el dominio de la solución es la suma de los contextos particulares
de las diferentes soluciones que se realizaron para resolver el problema de dominio.

En el análisis y diseño orientado a objetos se suele llamar a un problema (sistema) a resolver


problema de negocio, ya que por lo general la información relevada es para solucionar un
problema de ese estilo y particular. Hoy en día se utilizan estas palabras para englobar el
enunciado de cualquier tipo de problema, más allá si es de un negocio en particular, científico, etc.

¿Cuál es la importancia de manejar este concepto? Cuando se establece correctamente el


contexto se determina en qué cosas hay que trabajar y cuáles no. Esto es fundamental para no
desarrollar soluciones no requeridas lo cual tienen consecuencias directas sobre cómo evoluciona
un desarrollo. También afecta directamente en los tiempos estimados para crear una solución, lo
cual impacta en los costos, los cuales muchas veces determinan el fracaso o éxito de un proyecto
de desarrollo.

Ejemplo (Iteración 1 – fase de elaboración – análisis)


Determinar el contexto del sistema de la biblioteca

Contexto
1. Gestión del armado de los puestos de trabajo
2. Gestión de público en general que ingresa a la biblioteca para leer en el salón
3. Gestión de socios para lectura y acceso a computadoras en el salón
4. Manejo de socios y público en general como lectores cuando acceden al salón
5. Gestión de socios para reservas y préstamos de libros
6. Administración de libros físicos
7. Las salidas se producen a través de la consola mediante simulaciones de uso del sistema

Lic. Marcelo F. Samia


18
Diplomatura en Programación Java

Alcance de una solución


El alcance de un sistema es la suma de las soluciones funcionales que presta y las que no.
Esto implica que es un subconjunto del contexto delimitado por las funcionalidades a crear
dentro del mismo.

En palabras sencillas, una vez que se determina que se va a realizar dentro de un contexto, el
alcance determina hasta donde se llega en la implementación de dicha funcionalidad. Si existe una
funcionalidad dentro del contexto, se debe decidir si se realiza total o parcialmente, inclusive, si no
se la desarrolla.

En el caso del ejemplo del sistema contable, que el sistema no realice balances es una
funcionalidad que se determina como parte del contexto. Sin embargo, en ese mismo contexto se
indica que se deben manejar las cuentas y el alcance puede establecer que se manejarán las
cuentas sin realizar los “mayores” de las mismas (los mayores es una forma de agrupamiento de
valores que asumen las diferentes cuentas). Si bien se cumple el requisito de manejar las cuentas
que el contexto especificó, el alcance determina cómo se van a manejar estableciendo que se va a
incluir y que no como parte de la solución.

Nota: En diferentes técnicas de análisis y desarrollo orientado a objetos a la suma del


enunciado del problema, el contexto y el alcance se la denomina “lista de requerimientos”. Sin
embargo se opta por usar el enunciado del problema, el contexto y el alcance por separado
porque es más simple para evitar errores debido al análisis o por omisión.

Ejemplo (Iteración 1 – fase de elaboración – análisis)


Tabla 1-2: Análisis de funcionalidades del proyecto
Funcionalidades de la solución
Contexto Se realizará No se realizará
Armado de puestos de trabajo Control sobre los puestos de
con distintos tipos de sillas, trabajo
escritorio y computadoras
Gestión del armado de los
puestos de trabajo Identificación de sillas, Control sobre el
escritorios y computadoras mantenimiento, baja o
reemplazo de sillas escritorios o
computadoras
Gestión del público Control y seguimiento del
Gestión de público en general público general
que ingresa a la biblioteca para
leer en el salón Asignación de libros al público Seguimiento y control sobre los
libros
Gestión de socios para lectura y Entrega de libros y Seguimiento y control sobre los
acceso a computadoras en el computadoras libros y las computadoras
salón

Lic. Marcelo F. Samia


19
Diplomatura en Programación Java

Funcionalidades de la solución
Manejo de socios y público en Creación de lectores de salón Asignación de lectores a
general como lectores cuando puestos de trabajo
acceden al salón Asignación de computadoras Control sobre las asignaciones
Creación y activación de Control de reservas duplicadas
reservas y que no sean más de
5
Desactivación de reservas Cualquier gestión de reservas
marcando las mismas desactivadas
Creación de préstamos y que Seguimiento y control de
Gestión de socios para reservas
no sean más de 5 préstamos
y préstamos de libros
Asignación de préstamos
marcando la reserva
Asignación de fechas de Verificación o gestión de fechas
reserva
Asignación de fechas de Verificación o gestión de fechas
préstamo
Entrega de libros para el salón
Administración de libros físicos
Entrega de libros a préstamo
Las salidas se producen a través Creación de datos para simular Validaciones de asignaciones de
de la consola mediante el funcionamiento datos
simulaciones de uso del Creación de salidas por consola
sistema

Visibilidad en las Clases


Una clase es algo más que una simple estructura. En los ejemplos expuestos anteriormente se
trataron los servicios como agentes internos que cumplen una función específica, como validar un
ingreso de información. Sin embargo es claro que se necesita definir de forma estricta que se
puede acceder desde adentro de la misma clase o desde fuera de ella. En otras palabras, definir
cuáles servicios son internos (como por ejemplo validar) y cuales son externos (como conocer el
estado de un objeto por medio de sus atributos).

Si se accede a los atributos de un objeto sin ningún control, se permite que cualquier código que
accede a un objeto modifique el valor que almacena y esto puede derivar en errores. Si se utiliza
como ejemplo una clase del tipo Persona igual a la estructura de datos previamente definida, se
puede dar el caso que a la variable edad se le asigne un valor que no lo controla el servicio que
valida que las edades estén dentro del rango de 0 a 120, con lo cual el atributo almacena un valor
que es inconsistente con el diseño de la clase, causando una anomalía en tiempo de ejecución.

Se hace evidente entonces que deben existir controles de acceso a los elementos (variables de
instancia y métodos) que componen una clase. En los lenguajes de programación esto se define
mediante una técnica llamada visibilidad. La visibilidad especifica el alcance de una variable, es
decir, los lugares dentro del código en los cuales es válido su acceso (por eso muchas veces se

Lic. Marcelo F. Samia


20
Diplomatura en Programación Java

utilizan los términos indistintamente – visibilidad o alcance de una variable). Cuando una variable
sale del alcance es porque pierde su visibilidad y no puede ser invocada.

Principio del iceberg: ocultamiento de la información


Para poder dominar como una clase se comunica con otra hay que utilizar diseño de la misma. La
razón es simple: la forma en que se declaran los elementos que pertenecen a una clase se rigen
por la visibilidad definida en los mismos. Esto implica que la comunicación se establecerá por el
desarrollo de algún medio de acceso que se declare.

Una primera definición para realizar es la diferencia entre los miembros que son accesibles desde
fuera de la clase cuando se crea una instancia de ella (objeto) y los que no:

Las clases definen miembros públicos y privados. Los primeros son accesibles desde fuera
de la clase por cualquier código que lo requiera. Los segundos sólo se pueden acceder
desde dentro de la clase, por lo tanto tiene su visibilidad circunscripta a la misma.

Se denomina interfaz de la clase a todo miembro público, y es la definición que establece como se
acceden sus elementos. Si se piensa en una interfaz, bien se podría decir que la clase consta de
ciertos elementos internos que se comunicarán a través de esta con otras clases, actuando como
un canal que controla dicha comunicación. Lo que se quiere señalar con esto es que, los
elementos privados de un módulo no deben ser accesibles desde afuera de este por ningún otro,
salvo por medio de la interfaz definida para hacerlo, que es la parte pública del mismo.

Resumiendo, el principio se puede reformular como:

En cada módulo debe existir una división entre sus componentes en secciones que sean
públicas y privadas de manera que toda información acerca del mismo sea privada a éste,
a no ser que se especifique como pública explícitamente.

Si se alteran los elementos privados de un módulo, pero su interfaz se mantiene constante, la


interacción con otros módulos no variará ya que estos acceden mediante ellas, evitando que los
cambios se propaguen a lo largo del código sin control.

Para asegurarse de cumplir el principio de ocultamiento de la información, se deben


declarar privados todos los atributos de una clase para que los mismos sean invariables.
Sólo pueden ser públicos aquellos atributos que sean CONSTANTES

Para clarificar el principio, se puede pensar en una clase que posee un vector interno que
almacena números enteros y un servicio que permite realizar una búsqueda sobre el vector para
acceder a cada uno de sus elementos.

Como interfaz se puede brindar un servicio que busque un determinado elemento y retorne el
índice del vector (la posición) del elemento. Si se cambia el elemento del vector, mientras se lleva
a cabo la búsqueda, del valor almacenado que es justamente el que se deseaba hallar, el servicio

Lic. Marcelo F. Samia


21
Diplomatura en Programación Java

retornará que encontró un valor que ya no está almacenado en el vector porque otro código lo
accedió y lo cambió sin que se pueda realizar ninguna acción de control previa. Esto es, se cambia
un valor almacenado sin que un servicio propio del objeto registre el acceso a la variable de
instancia (el elemento del vector) y pueda realizar alguna acción en consecuencia. Si por el
contrario, el acceso a la variable de instancia se realiza mediante un servicio, este puede verificar
que otro servicio de la clase no esté accediendo al elemento y la búsqueda no retornará un valor
erróneo o viceversa, que no se realice una búsqueda mientras este en proceso un cambio de valor.

Se suele llamar a este principio "del iceberg" puesto que la interfaz de la clase, que es lo que se ve
desde afuera del módulo, es la punta del iceberg, mientras que los elementos privados, que son
por lo general el grueso de la implementación, se encuentran ocultos al mundo exterior del
módulo.

La importancia de este principio radica en el control que permite del flujo de datos hacia y desde
la clase, además de los servicios brindados por esta. Respecto de los mencionados servicios que
brinda, al estar oculta la forma en que los lleva a cabo, la comunicación con la clase estará
garantizada a través de su parte pública, ocultando detalles y uso no deseado de los componentes
del módulo (clase) que se encuentren en la parte privada.

Para acceder a los atributos de la clase se utilizan métodos especiales diseñados para tal fin
llamados “de acceso” y “de mutación” (en inglés, accessors y mutators). Estos métodos por un
estándar “de facto” en la industria se nombran antecediendo la palabra “get” al nombre del
atributo para los primeros y lo mismo con la palabra “set” para los segundos. De esta manera, si se
tiene el atributo “nombre” el método de acceso se lo llama getNombre() mientras que el de
mutación se denomina setNombre(). El primero sirve para retornar el valor que almacena el
atributo mientras que el segundo sirve para modificar el valor que almacena.

Además, en una situación en la que un método cumple una funcionalidad similar pero se lo quiere
diferenciar, se lo hace fácilmente cambiándole el nombre. En el ejemplo anterior podría ser
obtenerNombre().

Encapsulado
Siguiendo el ejemplo enunciado, ¿qué pasa si el servicio que realiza la verificación del rango de
valores del atributo edad de la clase Persona es una interfaz de la clase? Como la verificación se
hace sobre los atributos dentro de un objeto del tipo Persona, puede dejar a los mismo en una
condición inconsistente, es decir, se puede cometer el error de invocar la verificación usándola
como un servicio diferente a como se pensó originalmente. Supongamos que la verificación recibe
como parámetro el índice del elemento que debe verificar y cierto código ajeno a la clase
confunde ese parámetro con el valor que se debe verificar en la validación. El código tratará de
acceder a un elemento que probablemente no exista causando un error.

Para evitar este tipo de situaciones, se debe diseñar un servicio interno de la clase que sea
utilizado sólo por los miembros de esta y que acceda a los atributos privados de la misma. Esto

Lic. Marcelo F. Samia


22
Diplomatura en Programación Java

permite mantener el control de la prestación de servicios de manera que sólo se utilicen para los
fines que fueron creados.

Como se mencionó anteriormente para los atributos, existe una técnica utilizada por los lenguajes
de programación que limita el acceso y alcance de las variables llamado visibilidad. Esta se puede
aplicar de manera análoga a los servicios para que se accedan sólo desde el interior de la clase. Por
lo tanto, el servicio interno sólo se invocará desde otros elementos de la clase y su
comportamiento estará restringido a la visibilidad de la clase en la que está definido.

Cuando una clase tiene definido un servicio interno, esto es, una función o procedimiento
con visibilidad privada, se define un comportamiento encapsulado dentro del objeto en
tiempo de ejecución. Para que el comportamiento del servicio sea correcto, los atributos
deben estar ocultos de manera que un cambio en los mismos no provoque un error al
ejecutarlo.

Encapsular significa limitar la situación al entorno al que pertenece, en este caso, la clase. Por lo
tanto, para que se cumpla correctamente el encapsulamiento se debe cumplir las siguientes reglas
sencillas al mismo tiempo:

• Los atributos deben ser privados


• El comportamiento definido para la clase debe estar limitado a la misma y los servicios que
ofrezca a través de los métodos públicos deben entregar resultados. Dicho
comportamiento, si se define en un método privado, se denomina “encapsulado” porque
su ejecución se realiza desde dentro de la clase. Si produce un resultado, este se deberá
entregar a un método público para que sea el encargado de la comunicación (por eso
estos métodos se denominan interfaces) y nunca retronarlo directamente.
• Un servicio se encuentra encapsulado si y sólo si los atributos que utiliza son privados para
que ninguna asignación de valor sea externa a la clase.
• Un método se encuentra encapsulado si y sólo si los atributos a los que accede cumplen
con el principio de ocultamiento de la información.

¿Cómo se determinan las operaciones que realiza un objeto? Porque se deben pensar en los
servicios que presta el objeto, directa o indirectamente. Por ejemplo, en un vaso se puede
servir líquido, por lo tanto presta el servicio de recibir el líquido que se sirve en él. Sin
embargo, no se puede interaccionar con la forma en la cual contiene el líquido, ya que este es
un servicio interno, pero el servicio que presta al permitir que lo sirva en él seguramente
invocará a dicho servicio interno. Podemos afirmar que el primero es un servicio en la interfaz
del objeto mientras que el segundo está encapsulado. O sea, el primero se brinda
directamente mientras que el segundo lo hace indirectamente. Las operaciones que realiza un
objeto son los servicios que brinda el mismo.

¿Qué pasa si el vaso se rompe? En ese caso, el objeto no se usa para lo que fue diseñado y sus
servicios, tanto directos como indirectos deben manejar una situación anómala (la rotura del
Lic.vaso). Esto
Marcelo es lo que genera las condiciones y el manejo de errores en un desarrollo.
F. Samia
23
Diplomatura en Programación Java

Descubriendo los objetos


Todos los enunciados que se vienen haciendo hasta el momento encontraron su motivación en las
limitaciones que existían en la programación tradicional o estructurada.

En los lenguajes tradicionales, la programación se basa en funciones y procedimientos,


prevaleciendo éstos sobre los datos que manejan.

Si prevalecen las funciones, la solución será hacer tan importantes a los datos como a las
operaciones que se realizan con ellos, agruparlos dentro de un módulo y que las operaciones sean
los servicios antes explicados.

A partir de esta afirmación, las cosas se complican, porque normalmente se pensaba en los datos
sólo como elementos a transformar por diferentes procesos.

Además, no se pueden pensar a los datos como entidades aisladas, puesto que los mismos
transformados por ciertos procesos pueden generar nuevos datos de los que se alimente el
sistema.

La respuesta al dilema se encuentra en poder unir bajo una misma estructura tanto a los datos
como a las operaciones que manejan a los mismos. Cuando las transformaciones sufridas a través
de procesos generan nuevos datos, pero estos están representados como atributos dentro de una
entidad, sus modificaciones provocan sólo cambios de estado dentro de los objetos a los que
pertenecen.

Por lo tanto, la clave del diseño de la programación orientada a objetos radica en detectar los
objetos que sirven para la solución del problema en particular que se aborda.

Todo objeto está representado de forma natural en el lenguaje por medio de los sustantivos. Por
ejemplo, tomando la frase “Juan come una manzana” se pueden detectar los objetos separando
los sustantivos y analizando la frase. De esta manera los sustantivos son:

Juan
Manzana

La frase tiene una sola acción a analizar:

Come

Esta información permite un primer análisis. Existen dos objetos, Juan y manzana, y una
operación, comer. Como se puede apreciar en la frase, los objetos se detectan en tiempo de
ejecución (Juan come - ahora - una manzana). A dichos objetos se los denomina candidatos
porque se debe corroborar que se puede generar una abstracción única a partir de ellos. Por
ejemplo, si dos objetos candidatos son sinónimos, ambos tendrán como abstracción a la misma
clase.

Lic. Marcelo F. Samia


24
Diplomatura en Programación Java

Una vez detectados, se debe crear una abstracción de ellos (o sea, una clase). Se puede realizar la
siguiente abstracción para representar al objeto:

Juan es una instancia de la clase Persona

Al realizar semejante afirmación se está indicando que si se genera una clase que se llame
Persona, los atributos y servicios definidos dentro de ella pueden representar perfectamente a un
objeto como Juan cuando se cree una instancia de la misma. Análogamente, se puede crear una
abstracción de manzana por medio de la clase Fruta.

Sin embargo, se puede extraer aún más información de la frase analizada. Queda por ver qué pasa
con la acción que se define en ella. Las acciones en el mundo de la programación orientada a
objetos se representan como servicios que los diferentes objetos ofrecen en tiempo de ejecución.
Por lo tanto se debe definir que objeto tiene la responsabilidad de ofrecer el servicio comer.

Este último razonamiento nos permite crear la siguiente definición:

Responsabilidad de un objeto: es el conjunto de servicios que debe prestar un objeto

Por lo tanto, la determinación de responsabilidades es un punto crucial en el diseño de clases


como abstracciones de objetos a crear.

Esto puede inducir a errores de razonamiento. Si no se es cuidadoso y se plantea bien a que objeto
pertenece la responsabilidad del servicio en dichos términos, se puede caer en la tentación de
deducir que el mismo pertenece a Juan “porque es Juan el que come”. Esto es un error. Juan
puede comer la manzana porque la manzana tiene el servicio que permite a Juan comerla. Por lo
tanto, la responsabilidad del servicio recae sobre el objeto manzana. Cuando se genera una
abstracción de la misma por medio de la clase Fruta, se puede asegurar que Fruta posee un
servicio que es “dejarseComer” y que el mismo pertenece a la interfaz de la clase. En otras
palabras, el objeto “manzana” posee los elementos que permiten determinar en tiempo de
ejecución si es posible comerla.

Sin embargo, Juan también posee un servicio, que puede ser interno o externo, que recibe un
parámetro del tipo fruta e invoca a través de su método público “dejarseComer” el servicio de una
instancia en particular, en este caso, manzana

Resumiendo, de una simple frase se pudo analizar la siguiente información para diseñar las
abstracciones:

Existen dos abstracciones, las clases Persona y Fruta


La clase Fruta tiene un servicio público que es dejarseComer
La clase Persona tiene un servicio público o privado que es comer

Manteniendo esto último presente se puede definir:

Lic. Marcelo F. Samia


25
Diplomatura en Programación Java

Los objetos pueden invocar métodos públicos de otros objetos para llevar a cabo
aquellos servicios que son sus responsabilidades

Todavía se puede sacar algunas conclusiones más para realizar un buen modelo por medio de la
clase. Cuando se obtiene la abstracción, se puede inferir cuales son los atributos que la misma
posee. En el caso de persona se puede determinar rápidamente sin miedo a cometer un error, que
se debe incluir entre sus atributos nombre y apellido. En particular, el objeto analizado, Juan,
guarda en el atributo nombre este valor y define así su estado. No confundir el nombre de la
instancia del objeto con el valor del atributo. En este caso en particular, el nombre de la instancia
coincide con el valor que asume el atributo nombre en tiempo de ejecución.

Abstracciones principales
En el ejemplo anterior rápidamente se encontró en la frase analizada dos objetos candidatos.
Cuando se detectan objetos rápidamente en una frase es porque los mismos son los más
importantes o destacados, ya que puede haber muchos otros objetos que se determinen cuando
se profundice el análisis, por medio de obtener más información o porque descubrimos que
ciertos atributos de los objetos deben tratarse como objetos en sí mismo.

En el ejemplo se determinó que las abstracciones eran Persona y Fruta y como fueron las primeras
en detectarse se las denomina abstracciones principales. En el caso de la primera se puede
determinar la necesidad de un atributo que se llame dirección. Sin embargo un análisis más
minucioso revela que el atributo puede tener servicios en sí mismo, por ejemplo uno que permita
realizar cambios de dirección. Cuando un atributo se detecta como un posible objeto se lo
denomina objeto derivado y a su modelado como abstracción derivada.

Crear una lista de objetos candidatos


Determinar en base a la sentencia del problema y teniendo en cuenta el contexto del mismo, los
objetos candidatos detectados en ella. Para esto, subrayar todos los sustantivos que se
encuentren en el enunciado del problema y armar una lista con ellos. Estos conformarán los
objetos candidatos y a partir de ellos se crearán las abstracciones principales.

Una vez desarrollada la lista, se debe analizar cada entrada en la misma y decidir cuál se descarta y
cuál no. Para esto se suele colocar otra entrada en donde se indica si el objeto está Activo o no. En
otra columna se debe agregar la justificación de la decisión para consultas futuras.

Estas listas no tienen un formato específico pero un buen modelo propuesto es el de la Tabla 1-3.

Tabla 1-3: Modelo de lista de objetos candidatos


Objetos Candidatos Descripción Estado Motivo Abstracción
nombre explicación de que es el Activo si es parte de una Explicación nombre
objeto y que hace abstracción principal del estado
Descartado si se deja de
lado por algún motivo

Lic. Marcelo F. Samia


26
Diplomatura en Programación Java

Los motivos principales para descartar un posible objeto candidato pueden ser porque: es un
atributo de otra clase, es un sinónimo de dominio, está fuera de contexto, dominio o alcance.

Nota: un sinónimo de dominio es aquel que se usa indistintamente en un determinado


contexto o dominio para un mismo concepto aunque no sean realmente sinónimos fuera de
este. Por ejemplo, Persona es un sinónimo de dominio tanto para Público como para Socio
porque en el relevamiento se pueden intercambiar el uso de estas palabras, aunque no sean
estrictamente sinónimos fuera del contexto o dominio.

Nota: la falta de acentos en los nombres de las abstracciones es intencional. Si bien en UML se
pueden asignar nombres con acentos, no es una buena práctica. La razón reside en que
algunos compiladores no manejan muy bien los caracteres acentuados o los específicos de un
lenguaje, como la “ñ” del español. Por esta razón es una buena práctica evitar cualquier
acento o letra específica del lenguaje y se pueden ver nombres escritos mal a propósito para
evitar este problema, como poner anio en lugar de año. De esta manera se evitan errores que
se puedan producir a causa de una mala interpretación del carácter por parte del compilador
que son sumamente difíciles de encontrar.

Ejemplo
Creación de la lista de objetos candidatos y análisis de los mismos para descubrir las abstracciones
principales

¿Cuál es el criterio para decidir si un objeto está dentro del alcance del desarrollo a realizar?
Cuando un objeto presta servicios (tiene operaciones) necesarias para el desarrollo se debe
considerar como candidato y crear una abstracción a partir de él.

Ejemplo de lista de objetos candidatos (Iteración 1 – fase de elaboración – análisis)


Para confeccionar la lista, se toma el enunciado del problema y se resaltan de alguna forma, todos
los sustantivos que se encuentren.

Enumeración de funcionalidades a resolver


1. La biblioteca brinda servicios a dos tipos de personas: socios y público en general.
2. Se denomina lector al que accede al salón, sea socio o no.
3. Crear un control de cómo se arman los puestos de lectura, a los que se les llama puesto de
trabajo.
4. Dividir los puestos de trabajo en informáticos y de lectura.
5. Los puestos de trabajo informáticos tienen un escritorio, una silla y algunos se usan con PC
de escritorio mientras que otros se usan con notebooks.
6. El número de computadoras está limitado a 20 por el momento

Lic. Marcelo F. Samia


27
Diplomatura en Programación Java

7. Gestionar la asignación de elementos de la biblioteca para su funcionamiento para el


armado de puestos de trabajo.
8. Cada elemento de trabajo posee un número de identificación
9. Los libros y las computadoras se asignan a los lectores, no a los puestos de trabajo.
10. Las PC y notebooks sólo se prestan a los socios y se debe saber quiénes las están usando
11. Los libros se entregan para leer en el salón o en el domicilio. Esto último es válido sólo
para los socios y tiene asociada una fecha de devolución.
12. Los préstamos de libro se hacen con o sin reservación previa en el momento. No se tiene
en cuenta la disponibilidad y se supone que siempre hay libros para realizar la operación.
13. La biblioteca sólo maneja libros físicos, no electrónicos.
14. Las reservas se marcan como activas o inactivas. Si la inactividad es porque se concretó un
préstamo, se marca como prestados en la misma reserva.
15. Nunca se entregan dos copias de un mismo libro a un lector o en un préstamo.
16. No se pretende llevar un control sobre la cantidad de copias que se entregan y se debe
suponer que siempre hay una cantidad suficiente de las mismas.
17. No se desea crear una interfaz gráfica para interaccionar con el sistema, sólo controlar que
la funcionalidad se lleva a cabo correctamente para diseñar adecuadamente como se
presentará la información.
18. La información que se debe mostrar en pantalla para verificar el funcionamiento del
desarrollo se debe hacer mediante una simulación que permita ver:
a. Los puestos de trabajo del salón de lectura
b. Los lectores y sus libros que se encuentran en el salón de lectura
c. Los lectores de cada libro
d. Los libros reservados
e. Libros que se encuentran prestados y el estado de las reservas
f. Los socios que están usando computadoras y cuáles son

Con la lista de objetos candidatos encontrados se arma la Tabla 1-4 para analizarlos y descubrir las
abstracciones principales.

Tabla 1-4: Objetos candidatos del sistema para la biblioteca


Objetos Candidatos Descripción Estado Motivo Abstracción
puestos de trabajo Sitios de lectura y uso Activo Dentro del alcance PuestoDeTrabajo
de computadoras
escritorio Escritorio Activo Dentro del alcance Escritorio
silla Silla Activo Dentro del alcance Silla
PC Computadora de Descartado Atributo de
escritorio computadora
notebooks Notebook Descartado Atributo de
computadora
computadoras Computadora Activo Dentro del alcance Computadora

Lic. Marcelo F. Samia


28
Diplomatura en Programación Java

Objetos Candidatos Descripción Estado Motivo Abstracción


elementos de la Sillas, escritorios, Descartado Sinónimo de
biblioteca libros, etc … dominio para silla
escritorio, libro
etc.
elemento de trabajo Sillas, escritorios, Descartado Sinónimo de
libros, etc … dominio para silla
escritorio, libro
etc.
número de Número que identifica Descartado Atributo de cada
identificación un elemento de elemento de
trabajo de la trabajo
biblioteca
biblioteca Institución que realiza Activo Dentro del alcance Biblioteca
las operaciones y
contiene a los
elementos de trabajo
personas Persona física Descartado Sinónimo de
dominio de
Persona y Socio
socios Socio de la biblioteca Activo Dentro del alcance Socio
público en general Persona en la Activo Dentro del alcance Publico
biblioteca que no es
socio y quiere utilizar
sus servicios
lector Toda persona que usa Activo Dentro del alcance Lector
el salón de lectura
salón Lugar donde se leen Activo Dentro del alcance Salon
los libros que entrega
la biblioteca
puestos de lectura e Puestos de trabajo en Descartado Sinónimo de
informáticos el salón dominio de puesto
de trabajo
libros Libros físicos que Activo Dentro del alcance Libro
entrega la biblioteca
domicilio Residencia del socio Activo Dentro del alcance Direccion
fecha de devolución Fecha en un Activo Dentro del alcance Calendario
calendario
préstamos de libro Grupo de libros Activo Dentro del alcance Prestamo
entregados al socio
por la biblioteca.
reservación Reserva de libros Descartado Sinónimo de
dominio de
Reserva
operación Préstamo, reserva o Descartado Sinónimo de
retiro de libro para el dominio de

Lic. Marcelo F. Samia


29
Diplomatura en Programación Java

Objetos Candidatos Descripción Estado Motivo Abstracción


salón Reserva, préstamo
o retiro de libros
libros físicos Libros físicos que Descartado Sinónimo de
entrega la biblioteca dominio de Libro
libros electrónicos Libros en formato Descartado Fuera de contexto
electrónico
reservas Reserva de libros Activo Dentro del alcance Reserva
reservas activas Reserva en curso Descartado Atributo de
Reserva
reservas inactivas Reserva que no está Descartado Atributo de
en curso Reserva
prestados Préstamo de libro Descartado Sinónimo de
dominio de
copias Copia de libro Descartado Atributo de Libro
interfaz gráfica Interfaz gráfica para la Descartado Fuera del alcance
presentación de datos
e interacción con el
usuario
sistema Este desarrollo Descartado Fuera de contexto
información Datos elaborados por Descartado Fuera de contexto
el sistema en
desarrollo
pantalla Salida por consola Activo Dentro del alcance Consola
desarrollo Este desarrollo Descartado Fuera de contexto
simulación Emulación del Activo Dentro del alcance BibliotecaTest
funcionamiento de
este desarrollo
libros reservados Libros que se Descartado Atributo de
encuentran Reserva
reservados
Libros que se Libros en posesión del Descartado Atributo de
encuentran prestados socio Préstamo

Diagramas UML para las clases

Las clases tienen una representación gráfica en un lenguaje universal de modelado llamado UML
(Universal Modelling Language).

Las clases se representan en un rectángulo con tres divisiones en su interior, como muestra la
Figura 1-7.

Lic. Marcelo F. Samia


30
Diplomatura en Programación Java

Figura 1-7: Formato UML para una clase

En la primera división se coloca el nombre de la clase


En la segunda división se coloca los atributos de la clase
En la tercera división se colocan los servicios de la clase

Dejando de lado la división que lleva el nombre de la clase, las otras dos son opcionales y pueden
no estar presentes en el diagrama, ya sea una o ambas. Sin embargo, por una cuestión de claridad
visual, se recomienda usar todas las divisiones aunque alguna de ellas esté vacía.

Los diagramas de clases se utilizan tanto para el análisis como para el diseño, por lo cual es normal
que dependiendo de la etapa del análisis en la que se encuentre, una de las divisiones opcionales
o ambas esté vacías. Como ejemplo, se puede observar la Figura 1-8.

Figura 1-8: Una clase representada en UML

En el diagrama se modela una clase que se llama Ejemplo, que posee dos atributos, y dos servicios.
A continuación se explica la forma de leer las declaraciones que tienen los miembros.

Para los atributos

Visibilidad: en este caso pueden ser públicas, privadas o protegidas (las visibilidades más
comunes en los lenguajes de programación aunque no las únicas). Si un atributo es público
se representa con el símbolo +, si es privado con – y si es protegido con #. En el ejemplo
tanto atributo1 como atributo2 tienen visibilidad privada
Nombre: el nombre que se le asigna a la variable de instancia. En este caso, las variables
de instancias se llaman atributo1 y atributo2
Tipo: es el tipo de variable definida. Para el caso del ejemplo, atributo1 es un int y
atributo2 es un double. La declaración del tipo de variable va siempre a continuación del
símbolo “:”.

Para los servicios

Visibilidad: en este caso pueden ser públicos, privados o protegidos (las visibilidades más
comunes en los lenguajes de programación aunque no las únicas). Si un servicio es público

Lic. Marcelo F. Samia


31
Diplomatura en Programación Java

se representa con el símbolo +, si es privado con – y si es protegido con #. La declaración


de visibilidad es igual que para el caso de los atributos
Lista de parámetros: se declaran entre paréntesis separados por comas con el mismo
formato de los atributos pero sin incluir la visibilidad. Según el lenguaje a utilizar, pueden
agregarse declaraciones propias de estos, como la palabra “in” que se puede apreciar en
el gráfico, aunque este es opcional.
Nombre: el nombre que se le asigna al método. En este caso, los que muestra el diagrama
son servicio1 y servicio2.
Tipo del valor retornado: es el tipo de datos que retorna el método (en caso que retorne
un valor). Para el ejemplo, servicio1 retorna un byte y tiene dos parámetros. En el caso de
servicio2 no retorna valor ni recibe parámetros. La declaración del tipo de valor retornado
va siempre a continuación del símbolo “:”.

También se puede modelar gráficamente un objeto o instancia de una clase. Utilizando el ejemplo
de la clase Persona y la instancia Juan, se conoce para dicho caso tanto el nombre de la clase como
el del objeto y el diagrama es como el que se muestra en la Figura 1-9

Figura 1-9: Modelado de un objeto con nombre de instancia en UML

Pero si se debe modelar una instancia de una clase que todavía no tiene asignado un nombre, se lo
puede hacer como muestra la Figura 1-10

Figura 1-10: Modelado de un objeto sin nombre de instancia en UML

Ejemplo

Lic. Marcelo F. Samia


32
Diplomatura en Programación Java

En este ejemplo se comienzan a analizar cómo modelar las abstracciones principales. Por lo
general, un analista con experiencia lo hace mientras elabora el diagrama. Por motivos didácticos
se presentará una tabla por cada abstracción antes de crear el diagrama en particular de cada
clase para que el lector pueda comprender la justificación de su diseño. Cabe destacar que en esta
fase del ciclo de vida se suelen solapar el análisis y el diseño. Para establecer una delimitación,

Nota importante: Ante un mismo enunciado de problema, se pueden elaborar múltiples


diseños diferentes que cumplan el mismo objetivo. El presentado es tan sólo uno posible.

podemos afirmar que mientras no se establecen los detalles de cómo estarán conformados los
atributos y los métodos, se está llevando a cabo un análisis, mientras que cuando se detalla cómo
están conformados, se está diseñando. La explicación en cada tabla sirve para verificar en el
enunciado del problema como se concluye la necesidad de cada uno de los componentes de la
abstracción. Se puede revisar cada una teniendo a mano el enunciado para corroborar la
necesidad de cada una.

Análisis de las abstracciones principales (Iteración 1 – fase de elaboración – análisis y diseño)


Cuando se crean las primeras abstracciones se establecen los servicios y atributos de las mismas.
Es muy común descartar algunos de estos cuando se refina el análisis o el diseño, como así
también cambiar los tipos de datos, parámetros o valores retornados. En la iteración 1 se transita
entre las fases de concepción y elaboración porque se está comprendiendo mejor el problema y se
empieza a elaborar una solución.

Puesto de trabajo
Esta clase representa un recurso de la biblioteca. Es normal cuando se representa un recurso o una
entidad (mucha veces ambas palabras se usan como sinónimos en diferentes contextos) que
tengan pocos servicios y el grueso de la clase sea para el manejo de atributos bajo el principio de
ocultamiento de la información. Sin embargo, suelen ser clases que tiene declarados muchos
atributos los cuales en tiempo de ejecución representan el “estado del objeto” (los valores de las
variables que almacena un objeto).

Tabla 1-5: Atributos de PuestoDeTrabajo


Atributo Explicación
informatica Almacena si es un puesto informático

Tabla 1-6: Métodos de PuestoDeTrabajo


Método Explicación
getDetalles Retorna una cadena de caracteres con los
valores que almacenan los atributos

PuestoDeTrabaj o

- informati ca: boolean = false

Lic. Marcelo F. Samia + getDetall es(): String


+ 33 boolean
isInformatica():

Figura 1-11: Diagrama de la clase PuestoDeTrabajo


Diplomatura en Programación Java

Escritorio
Esta clase representa un recurso o entidad.

Tabla 1-7: Atributos de Escritorio


Atributos Explicación
id Identificador
descripcion Descripción del escritorio
informatica Si el escritorio es de informática o no
longitud Largo
anchura Ancho
altura Alto
cantidadDeAsientosPosibles Número de asientos que se le pueden agregar

Tabla 1-8: Métodos de Escritorio


Método Explicación
getDetalles Retorna una cadena de caracteres con los valores que almacenan los
atributos

Escritorio

- altura: doubl e
- anchura: double
- cantidadDeAsientosPosibles: int
- descripcion: String
- id: String
- informatica: boolean
- longitud: double

+ getAltura(): double
+ getAnchura(): double
+ getCantidadDeAsientosPosibles(): int
+ getDescripcion(): String
+ getDetalles(): String
+ getId(): String
+ getLongitud(): double
+ isInformatica(): boolean
+ setAltura(double): void
+ setAnchura(double): void
+ setCantidadDeAsientosPosibles(int): void
+ setDescripcion(String): void
+ setId(String): void
+ setInformatica(boolean): void
+ setLongitud(double): voi d

Figura 1-12: Diagrama de la clase Escritorio

Lic. Marcelo F. Samia


34
Diplomatura en Programación Java

Silla
Esta clase representa un recurso o entidad.

Tabla 1-9: Atributos de Silla


Atributos Explicación
id Identificador
descripcion Descripción de la silla
informatica Si la silla es de informática o no

Tabla 1-10: Métodos de Silla


Método Explicación
getDetalles Retorna una cadena de caracteres con los
valores que almacenan los atributos

Silla

- descripcion: Stri ng
- id: String
- informati ca: boolean

+ getDescri pcion(): String


+ getDetall es(): String
+ getId(): String
+ isInformatica(): boolean
+ setDescripcion(String): void
+ setId(String): voi d
+ setInformatica(boolean): void

Figura 1-13: Diagrama de la clase Silla

Computadora
Esta clase representa un recurso o entidad.

Tabla 1-11: Atributos de Computadora


Atributos Explicación
id Identificador
notebook Si es notebook o no
procesador Procesador que posee
velocidadProcesador Velocidad del procesador
memoria Cantidad de memoria
velocidadMemoria Velocidad de la memoria
descripcion Descripción de la computadora

Tabla 1-12: Métodos de Computadora


Métodos Explicación

Lic. Marcelo F. Samia


35
Diplomatura en Programación Java

getDetalles Retorna una cadena de caracteres con los valores


que almacenan los atributos

Computadora

- descri pcion: Stri ng


- id: String
- memoria: String
- notebook: boolean
- procesador: String
- velocidadMemoria: String
- velocidadProcesador: String

+ getDescripcion(): String
+ getDetalles(): String
+ getId(): Stri ng
+ getMemori a(): String
+ getProcesador(): String
+ getVelocidadMemori a(): String
+ getVelocidadProcesador(): String
+ isNotebook(): boolean
+ setDescripcion(String): void
+ setId(String): voi d
+ setMemoria(Stri ng): void
+ setNotebook(boolean): void
+ setProcesador(String): void
+ setVelocidadMemoria(String): void
+ setVelocidadProcesador(String): void

Figura 1-14: Diagrama de la clase Computadora

Biblioteca
No se encontraron atributos en esta abstracción, sin embargo esta clase tiene la particular función
de representar las acciones principales de la biblioteca y “encamina” hacia los objetos que se
necesitan para cumplir la acción los requerimientos de servicios que estos poseen.

Tabla 1-13: Métodos de Biblioteca


Métodos Explicación
creaReservaDelSocio Crea una reserva para un socio
obtenerLitaLectoresEnElSalon Obtiene todos los lectores en el salón
agregarLibroEnReservaExistente Incorpora un libro a una reserva ya existente
entregarLibroAlPublicoParaElSalon Entrega de libro al público
agregarPuestoDeTrabajoAlSalon Incorpora un puesto de trabajo de lectura en el salón
entregarLibroAlSocioParaElSalon Entrega un libro al socio para el salón
agregarPuestoDeTrabajoInformaticoAlSalon Incorpora un puesto de trabajo informático en el salón
asignaComputadoraAlSocio Asignación de computadora para los socios
creaPrestamoBasadoEnLaReserva Hace efectiva una reserva convirtiéndola en préstamo a
un socio

Lic. Marcelo F. Samia


36
Diplomatura en Programación Java

Biblioteca

+ agregarLibroEnReservaExistente(): void
+ agregarPrestado(): void
+ agregarPuestoDeTrabajoAlSalon(): void
+ agregarPuestoDeTrabajoInformaticoAlSalon(): void
+ creaPrestamoBasadoEnLaReserva(): void
+ creaReservaDelSocio(): void
+ obtenerLitaLectoresEnElSalon(): void

Figura 1-15: Diagrama de la clase Biblioteca

Socio
Esta clase es claramente una entidad y es importante desde el punto de vista que será el receptor
de la funcionalidad que se desarrolle. Notar que los servicios suelen ser simples porque la
funcionalidad principal la resuelven los objetos que invocan a éste.

Tabla 1-14: Atributos de Socio


Atributos Explicación
nombre Nombre del socio
segundoNombre Segundo nombre del socio
apellido Apellido del socio
dni Dni del socio
email Email del socio
tel Teléfono del socio
celular Celular del socio

Tabla 1-15: Métodos de Socio


Abstracción Métodos Explicación
getDetalles Retorna una cadena de caracteres con los
valores que almacenan los atributos
cantidadDeReservas Reservas que posee el socio
Socio obtieneReserva Agrega una reserva al socio
obtenerLibrosUsadosPorSocioEnElSalon Los libros que tiene asignados el socio.
cantidadDePrestamos Préstamos que posee el socio
obtienePrestamo Agrega un préstamo al socio

Lic. Marcelo F. Samia


37
Diplomatura en Programación Java

Socio

- apell ido: String


- celul ar: String
- dni: String
- emai l: String
- nombre: String
- segundoNombre: String
- tel: String

+ canti dadDePrestamos(): int


+ canti dadDeReservas(): int
+ getApellido(): String
+ getCelular(): String
+ getDetalles(): String
+ getDni(): String
+ getEmail(): String
+ getNombre(): String
+ getSegundoNombre(): String
+ getT el(): String
+ obtenerLi brosUsadosPorSocioEnEl Salon(): void
+ obtienePrestamo(Prestamo): void
+ obtieneReserva(Reserva): void
+ setApellido(String): void
+ setCelular(String): void
+ setDni(String): void
+ setEmail(String): void
+ setNombre(Stri ng): void
+ setSegundoNombre(String): void
+ setTel(String): void

Figura 1-16: Diagrama de la clase Socio

Publico
Esta clase es claramente una entidad y es importante desde el punto de vista que será el receptor
de la funcionalidad que se desarrolle.

Tabla 1-16: Atributos de Público


Atributos Explicación
nombre Nombre del público
segundoNombre Segundo nombre del público
apellido Apellido o del público
dni Dni del público
email Email del público
tel Teléfono del público
celular Celular del público

Tabla 1-17: Métodos de Público


Métodos Explicación
getDetalles Retorna una cadena de caracteres con los valores
que almacenan los atributos

Lic. Marcelo F. Samia


38
Diplomatura en Programación Java

Publico

- apelli do: String


- celular: Stri ng
- dni: String
- email : String
- nombre: String
- segundoNombre: String
- tel: String

+ getApellido(): String
+ getCelular(): String
+ getDetalles(): Stri ng
+ getDni(): String
+ getEmail(): String
+ getNombre(): Stri ng
+ getSegundoNombre(): String
+ getTel(): String
+ setApellido(String): voi d
+ setCel ular(String): void
+ setDni (String): void
+ setEmail(String): void
+ setNombre(String): void
+ setSegundoNombre(String): void
+ setTel (String): void

Figura 1-17: Diagrama de la clase Publico

Lector
No se encontraron métodos en esta abstracción, pero tiene sentido porque es una clase que
representa como trata administrativamente la biblioteca a sus dos entidades principales: el socio y
el público en general. Se podría haber considerado un sinónimo de dominio pero esto sería
incorrecto ya que los lectores sólo lo son para el salón de lectura y los socios tienen la posibilidad
adicional de retirar libros a préstamos, lo cual no se ajusta a la definición utilizada de “lector”. Esta
abstracción sólo la podremos resolver correctamente al final cuando se exponga el concepto de
interfaces. Por el momento se la considerará una clase más que claramente es independiente de
otras abstracciones.

Tabla 1-18: Atributo de Lector


Atributos Explicación
esSocio Verdadero si es socio

Lic. Marcelo F. Samia


39
Diplomatura en Programación Java

Lector

+ esSocio: boolean = false

+ getDetalles(): String
+ isEsSocio(): boolean

Figura 1-18: Diagrama de la clase Lector

Salon
No se encontraron atributos en esta abstracción. Esto tiene como explicación que la clase sólo
representa la funcionalidad que cumple el salón para la biblioteca y los servicios expuestos
brindan principalmente dicha información.

Tabla 1-19: Métodos de Salon


Métodos Explicación
agregarPuestoDeTrabajo Incorpora el puesto de lectura al salón
agregarPuestoDeTrabajoInformatico Incorpora el puesto informático al salón
getListaPuestosDeTrabajo Obtiene la lista de puestos de trabajo
getListaLectores Obtiene la lista de lectores
agregarLector Incorpora un lector

Salon

+ agregarLector(): void
+ agregarPuestoDeTrabajo(): void
+ agregarPuestoDeTrabajoInformatico(): void
+ getListaLectores(): void
+ getListaPuestosDeTrabajo(): void

Figura 1-19: Diagrama de la clase Salon

Libro
Esta clase es una entidad principal puesto que es el motivo sobre el cual gira todo el desarrollo.

Tabla 1-20: Atributos de Libro


Atributos Explicación
titulo Título del Libro
autor Autor del Libro
editorial Editorial del Libro
genero Genero del Libro
cantidad Cantidad del Libro
isbn Isbn del Libro

Lic. Marcelo F. Samia


40
Diplomatura en Programación Java

Tabla 1-21: Métodos de Libro


Métodos Explicación
getDetalles Retorna una cadena de caracteres con los valores que almacenan los
atributos
agregarReserva Registra la incorporación del libro a una reserva
getReservasDelibro Retorna todas las reservas en las que está el libro
agregarPrestamo Registra la incorporación del libro a un préstamo
getPrestamosDelLibro Retorna todos las préstamos en los que está el libro

Libro

- autor: String
- cantidad: int
- editorial: String
- genero: String
- isbn: String
- titulo: String

+ agregarPrestamo(): void
+ agregarReserva(): void
+ asignarPublico(): void
+ asignarSocio(): void
+ getAutor(): String
+ getCantidad(): int
+ getDetalles(): String
+ getEditorial(): String
+ getGenero(): String
+ getIsbn(): String
+ getPrestamosDelLibro(): void
+ getReservasDelibro(): void
+ getTitulo(): String
+ obtenerPublicoQueEstanUsandoEsteLibroEnElSalon(): void
+ obtenerSociosQueEstanUsandoEsteLibroEnElSalon(): void
+ setAutor(String): void
+ setCantidad(int): void
+ setEditorial(String): void
+ setGenero(String): void
+ setIsbn(String): void
+ setTitulo(String): void

Figura 1-20: Diagrama de la clase Libro

Direccion
Esta clase se desarrolló independiente porque es brinda servicios para el proyecto
independientemente de donde se la use. Por ejemplo, no es lo mismo hablar de la dirección de un
socio que del público ya que el primero tiene libros que pertenecen a la biblioteca en su domicilio.
Por supuesto que es una decisión de diseño cuestionable y muchos lo pueden ver como un simple
atributo.

Tabla 1-22: Atributos de Direccion


Atributos Explicación
esAvenida calle común o avenida

Lic. Marcelo F. Samia


41
Diplomatura en Programación Java

nombreCalle nombre completo de la calle


Nro número de la casa o departamento
esDepartamento es departamento o no
Piso número del piso
Dpto. departamento del piso

Tabla 1-23: Método de Direccion


Métodos Explicación
cambiaDireccion Permite actualizar la dirección

Direccion

- dpto: String
- esAvenida: bool ean
- esDepartamento: boolean
- nombreCal le: String
- nro: int
- piso: int

+ cambiaDireccion(bool ean, String, int, boolean, int, String): void


+ getDpto(): String
+ getNombreCalle(): String
+ getNro(): int
+ getPi so(): i nt
+ isEsAvenida(): boolean
+ isEsDepartamento(): boolean
+ setDpto(String): void
+ setEsAveni da(boolean): voi d
+ setEsDepartamento(boolean): void
+ setNombreCalle(String): void
+ setNro(int): void
+ setPiso(int): void

Figura 1-21: Diagrama de la clase Direccion

Calendario
Se diseñó esta abstracción de forma independiente usando el mismo criterio que con la clase
Direccion

Tabla 1-24: Atributos de Calendario


Atributos Explicación
fechaInicio Fecha de inicio para reserva o préstamo
fechaFin Fecha de finalización para reserva o préstamo

Tabla 1-25: Método de Calendario


Métodos Explicación
getDetalles Retorna una cadena de caracteres con los
valores que almacenan los atributos

Lic. Marcelo F. Samia


42
Diplomatura en Programación Java

Calendario

- fechaFin: String
- fechaIni cio: String

+ getDetal les(): String


+ getFechaFin(): String
+ getFechaInicio(): String
+ setFechaFin(String): void
+ setFechaInicio(String): void

Figura 1-22: Diagrama de la clase Calendario

Prestamo
Representa la actividad de la biblioteca al prestar un libro al socio.

Tabla 1-26: Atributo de Prestamo


Atributos Explicación
id Identificador

Tabla 1-27: Método de Prestamo


Métodos Explicación
getDetalles Retorna una cadena de caracteres con
los valores que almacenan los atributos

Prestamo

- id: int

+ getDetalles(): String
+ getId(): int

Figura 1-23: Diagrama de la clase Prestamo

Reserva
Representa la actividad de reservar libros que puede realizar un socio

Tabla 1-28: Atributos de Reserva


Atributos Explicación
id Identificador
activa Verdadero si está activa la reserva
prestado Verdadero si está inactiva la reserva

Tabla 1-29: Método de Reserva


Métodos Explicación

Lic. Marcelo F. Samia


43
Diplomatura en Programación Java

getDetalles Retorna una cadena de caracteres con


los valores que almacenan los atributos

Reserv a

- activa: boolean
- id: int
- prestado: bool ean

+ getDetall es(): String


+ getId(): int
+ isActiva(): boolean
+ isPrestado(): boolean
+ setActiva(bool ean): void
+ setPrestado(boolean): void

Figura 1-24: Diagrama de la clase Reserva

BibliotecaTest
Esta clase se diseña para probar las funcionalidades requeridas por el desarrollo. Más adelante se
explica el concepto de simulación en los proyectos modernos de desarrollo informático. En este
caso, en lugar de usar una herramienta diseñada con este fin, se creó esta clase para que cumpla
la misma funcionalidad: usar un conjunto de datos fijos que simulan la interacción con el sistema.

Tabla 1-30: Métodos de Biblioteca


Métodos Explicación
agregaPuestosDeTrabajo Agrega los puestos de trabajo en el salón de
lectura
librosPedidosPorElPublico Libros que pide el público para el salón
librosPedidosPorSocios Libros que piden los socios para el salón
reservasDeSocios Reservas realizadas por los socios
agregarLibrosEnReservasExistentes Incorporar libros a Reservas que ya existen
creaPrestamoBasadoEnLasDosPrimerasReservas Crear préstamos en base a las dos primeras
reservas de la biblioteca
sociosQueSolicitaronComputadoras Socios que pidieron usar computadoras

BibliotecaTest

+ agregaPuestosDeTrabajo(): void
+ agregarLibrosEnReservasExistentes(): void
+ creaPrestamoBasadoEnLasDosPrimerasReservas(): void
+ l ibrosPedidosPorElPublico(): void
+ l ibrosPedidosPorSocios(): voi d
+ reservasDeSocios(): void
+ sociosQueSolicitaronComputadoras(): void

Figura 1-25: Diagrama de la clase BibliotecaTest

Lic. Marcelo F. Samia


44
Diplomatura en Programación Java

¿Qué es una simulación (Mock)?


Las simulaciones se utilizan para efectuar operaciones que imitan el comportamiento de un
sistema en ejecución. La idea en general es evitar cualquier dependencia externa que pueda tener
el sistema, incluyendo los ingresos de datos por parte de un usuario, que pueda tener mediante
datos fijos pre establecidos para emular el funcionamiento de las distintas partes que lo
componen. De esta manera, se logra una primera evaluación de la correcta funcionalidad de un
sistema.

Existen muchas maneras de realizar simulaciones y muchas soluciones de software que se pueden
incorporar a un desarrollo en forma de API (Application Program Interface) para llevarlas a cabo.
Sin embargo, se puede lograr el mismo fin con clases sencillas diseñadas por el usuario y esta es la
solución que se utiliza en este desarrollo. El motivo es incorporar la menor cantidad de conceptos
nuevos fuera de los que se centran en las herramientas de la programación orientada a objetos
pero sin dejar de conocer la forma moderna de trabajar.

Paquetes en UML
Utilizando la definición que brinda Wikipedia:

Un diagrama de paquetes en el Lenguaje Unificado de Modelado (UML) representa las


dependencias entre los paquetes que componen un modelo. Es decir, muestra cómo un
sistema está dividido en agrupaciones lógicas y las dependencias entre esas agrupaciones.

Dado que normalmente un paquete está pensado como un directorio, los diagramas de
paquetes suministran una descomposición de la jerarquía lógica de un sistema.

Los paquetes están normalmente organizados para maximizar la coherencia interna dentro
de cada paquete y minimizar el acoplamiento externo entre los paquetes. Con estas líneas
maestras sobre la mesa, los paquetes son buenos elementos de gestión. Cada paquete
puede asignarse a un individuo o a un equipo, y las dependencias entre ellos pueden
indicar el orden de desarrollo requerido.

Esta definición es “casi” correcta. Se deben modificar algunos conceptos para que quede una
definición mejor ajustada a la realidad.

Primero, es necesario aclarar un término, acoplamiento, el cual indica el nivel de dependencia


entre dos elementos, sean cuales fueran.

Una vez comprendido esto, la definición tiene un error bastante grave. Los paquetes definen
“espacios de nombres” mediante los cuales realizan los mencionados agrupamientos. Está bien
hacer la analogía con los directorios porque permite una imagen lógica del funcionamiento
jerárquico que es análogo al de los espacios de nombre, pero sin lugar a dudas, lo más importante
es el hecho de ser un espacio de nombres porque no crea una dependencia con ningún lenguaje
en particular que lo use de esta manera exactamente. Por lo tanto, como digo siempre, es bueno

Lic. Marcelo F. Samia


45
Diplomatura en Programación Java

buscar cosas en Internet porque ayudan, pero no se debe confiar ciegamente en lo que se
encuentra, se debe verificar siempre.

Sin embargo, la noción de jerarquía como si fueran directorios ayudan a comprender dos
conceptos importantes: el gráfico en forma de carpeta y las líneas de dependencia que indican
cuando un paquete depende de otro

Paquete

Figura 1-26: Diagrama UML de un paquete

Ejemplo
Un diseño posible de la jerarquía de los espacios de nombre para el sistema de biblioteca se
muestra en la Figura 1-27.

Lic. Marcelo F. Samia


46
Diplomatura en Programación Java

Paquete por defecto

entidades

gestion prestamos

(from gesti on)

reserv as

recursos

(from gesti on)

salidas

test

(from gesti on)

Figura 1-27: Jerarquía de paquetes UML

Notar que el agrupamiento de clases se realizó siguiendo “cierta lógica”, de manera que el nombre
del paquete indique su contenido y aísle las clases en él de otras. La mayor ventaja de esto es que
los espacios de nombres en sí mismos definen una visibilidad y permite que si dos clases se llaman
igual pero están en diferentes espacios de nombre, una declaración no colisione con la otra y sea
posible y permite claridad en la estructura del proyecto a realizar.

Sin embargo, este no es el modo usual en el que se muestran los paquetes y sub paquetes en UML
sino como gráficos de carpeta que muestran sus contenidos, lo cual incluye clases y sub paquetes.

Lic. Marcelo F. Samia


47
Diplomatura en Programación Java

Ejemplo (Iteración 1 – fase de elaboración – análisis y diseño)


Diseño de estructura de paquetes para el sistema de biblioteca

entidades

+ Publico
+ Socio

gestion

+ Bibl ioteca prestamos

+ Calendario + Prestamo
+ Direccion
+ GestionBiblioteca
+ Lector
+ prestamos (from gestion)
+ reservas
+ salidas
reserv as

recursos + Reserva

+ Computadora
+ Escritorio
+ Libro
(from gestion)
+ PuestoDeTrabajo
+ Salon
+ Silla
salidas

+ Consola
test

+ BibliotecaTest

(from gestion)

Figura 1-28: Representación de paquetes UML usado por la mayoría de herramientas de diseño

Se pueden observar los sub paquetes contenidos y las clases dentro de cada paquete según el
diseño que se elaboró del mismo.

Lic. Marcelo F. Samia


48
Diplomatura en Programación Java

Ejercicios

Los temas de los que tratan los ejercicios de este módulo son los siguientes:

Creación de abstracciones usando UML


Enunciado del problema de negocio
Delimitación del dominio, contexto y alcance
Detección de objetos candidatos
Abstracciones Principales

Lic. Marcelo F. Samia


49