Índice
1.1 Análisis y Diseño Orientado a Objetos. ... 3
Visión general de la orientación a objetos... 3
Orientación a Objetos ... 4
Ventajas de la orientación a objetos ... 5
Enfoque Global Orientado a Objetos ... 5
Conceptos de OO ... 6
Todo objeto tiene una interfaz ... 8
El análisis OO. ... 9
El diseño OO... 13
La programación OO... 16
1.2. Paradigmas de programación... 17
1.3 Modelado Orientado a Objetos. ... 17
Modelado ... 18
Principios básicos del modelado ... 19
1.4 Abstracción, Encapsulamiento, Modularidad, Jerarquía. ... 19
Abstracción ... 20
Encapsulamiento... 21
Modularidad ... 21
Jerarquía... 23
Herencia Simple... 23
Polimorfismo ... 24
1.5 Tipos, Estado e identidad de un objeto. ... 25
Que es y que no es un Objeto... 25
Estado ... 25
Comportamiento ... 25
Identidad ... 26
Que es y que no es una Clase ... 26
1.6 Tipos de Relaciones. ... 27
1.7 Métricas de diseño. ... 29
Descripción de las métricas ... 29
Cantidad de clases desarrolladas... 29
Cantidad de clases externas especializadas ... 29
Promedio de statements por método de una clase ... 30
Cantidad de métodos de interfase por clase... 30
Cantidad de colaboradores por clase... 31
Cantidad de colaboradores externos por clase... 32
Cantidad de Mensajes Polimórficos ... 32
Mediciones relacionadas al uso de herencia ... 34
Cantidad de jerarquías de clases desarrolladas ... 34
Cantidad de jerarquías extendidas de clases externas... 34
Cantidad de niveles de especialización por jerarquía de clases ... 35
Cantidad de niveles agregados a jerarquías donde la raíz es externa ... 35
Cantidad de Clases Raíz no Abstractas ... 36
Porcentaje de Métodos Reemplazados en una Jerarquía ... 36
Porcentaje de Métodos Reemplazados en Jerarquías donde la raíz es externa ... 37
Cantidad de Jerarquías que Usan Herencia de Subtipo ... 38
Unidad I
Objetivo
Al final de esta unidad, habrás desarrollado los conocimientos y habilidades para comprender los siguientes conceptos:
• Qué es la Programación Orientada a Objetos.
• Aspectos fundamentales de dicho paradigma.
• Aspectos básicos del Lenguaje de Programación Java y Entornos de Desarrollo.
La teoría de la Orientación a Objetos es fundamental para una perfecta comprensión del lenguaje Java y un uso eficiente del mismo, tener muy claros y presentes estos conceptos., ya que constituyen la base para ser un buen programador de Java.
1.1 Análisis y Diseño Orientado a Objetos.
Visión general de la orientación a objetos
Aunque todavía suele asociarse la orientación a objetos a determinados lenguajes de programación (Java, C++, Smalltalk, etc.), es mayoritaria la opinión de que la OO es una metodología de desarrollo de sistemas (informáticos o no). La orientación a objetos puede aplicarse a la ingeniería de procesos, a la gestión empresarial, etc.
La orientación a objetos considera los sistemas como colecciones de objetos capaces de interactuar, que trabajan conjuntamente para realizar tareas. Como toda metodología, incluye actividades de análisis y diseño. En el caso de los sistemas de software, comprende también actividades de programación. En los siguientes subapartados veremos en qué consisten dichas actividades.
Dentro del marco general de la OO, hay muchas metodologías OO. Cada metodología OO detalla con precisión las técnicas que deben usarse en cada actividad y emplea una o más notaciones, generalmente gráficas, para describir los modelos que se van generando.
LA METODOLOGIA OO AL COMPLETO
ANALISIS OO DISEÑO OO PROGRAMACION OO
AUTO public class Auto{
Modelo: String private String Modelo;
AUTO Codigo: String private String Codigo;
arrancar() public void arrancar(){…}
estacionar() public void estacionar(){…}
Las tres etapas de la OO (aplicada a sistemas de software).
Esta sección está centrada en conceptos y definiciones de la orientación a objetos (OO), y no en su aplicación a lenguajes de programación concretos, por los siguientes motivos:
• El análisis y diseño orientado a objetos no tiene por qué estar ligado necesariamente a sistemas de software o de información.
• En sistemas de software la orientación a objetos no está exclusivamente asociada a lenguajes de programación concretos (aunque se presenten como lenguajes OO): es una metodología independiente del lenguaje utilizado, aunque hay lenguajes que cuentan con mejores mecanismos que otros para poder aplicar eficientemente esta metodología. Utilizar la OO es más que programar en uno o varios lenguajes de programación, es usar la OO como filosofía de desarrollo.
• Existe una gran diferencia entre comprender los fundamentos de la orientación a objetos y aplicarlos con éxito: es el eterno salto en el vacío entre la teoría y la práctica. Ahora bien, no comprender previamente los fundamentos de la OO y sus sutilezas, y utilizar lenguajes OO es encaminarse hacia un desastre casi seguro cuando el problema que se aborda es de cierta envergadura.
• El motivo de estos fallos conceptuales suele ser que el programador ha pasado de utilizar un lenguaje estructurado a uno presuntamente orientado a objetos sin tener claros o haber madurado los conceptos de la OO. Aparentemente son conceptos muy sencillos, pero solo aparentemente. Intentar continuar, consciente o inconscientemente, con un enfoque estructurado de programación en lenguajes OO puede hacerse, pero no es lo más adecuado.
Orientación a Objetos
La programación estructurada tradicional, propia del paradigma imperativo, se basa fundamentalmente en la ecuación de Wirth:
Algoritmos + Estructuras de Datos = Programas
Esta ecuación significa que en la programación estructurada u orientada a procedimientos los datos y el código se trata por separado y lo único que se realiza son funciones o procedimientos que tratan esos datos y los van pasando de unos a otros hasta que se obtiene el resultado que se desea.
La Programación Orientada a Objetos, POO (OOP, Object Oriented Programming, en ingles), es una técnica de programación cuyo soporte fundamental es el objeto. Un objeto es una extensión de un Tipo Abstracto de Datos (TAD), concepto ampliamente utilizado desde la década de los setenta. Un TAD es un tipo definido por el usuario, que encapsula un conjunto de datos y las operaciones sobre estos datos.
A la hora de definir TAD’s (u objetos) se usa un concepto que nos ayuda a representar la realidad mediante modelos informáticos, la abstracción, que es un proceso mental por el que se evitan los detalles para centrarse en las cosas más genéricas de manera que se facilite su comprensión. De hecho la abstracción no sólo se utiliza en la informática, un arquitecto al que le han encargado realizar los planos de un edificio no comenzará por diseñar los planos con máximo nivel de detalle, sino que comenzará a realzar ciertos esbozos en un papel para posteriormente ir refinando. Por supuesto que cuando está realizando los esbozos no se preocupa de por dónde van a ir las líneas eléctricas ni las tuberías de saneamiento, abstrae esos detalles para atacarlos posteriormente cuando tenga clara la estructura del edificio.
La diferencia entre el concepto de TAD y el de objeto radica en que además del proceso de abstracción que se utiliza para su definición, existen otros dos con los que se forma el núcleo principal de la programación orientada a objetos, estos son la herencia y el polimorfismo.
Ventajas de la orientación a objetos
Las ventajas más importantes de la programación orientada a objetos son las siguientes:
• Mantenibilidad (facilidad de mantenimiento). Los programas que se diseñan utilizando el concepto de orientación a objetos son más fáciles de leer y comprender y el control de la complejidad del programa se consigue gracias a la ocultación de la información que permite dejar visibles sólo los detalles más relevantes.
• Modificabilidad (facilidad para modificar los programas). Se pueden realizar añadidos o supresiones a programas simplemente añadiendo, suprimiendo o modificando objetos.
• Resusabilidad. Los objetos, si han sido correctamente diseñados, se pueden usar numerosas veces y en distintos proyectos.
• Fiabilidad. Los programas orientados a objetos suelen ser más fiables ya que se basan en el uso de objetos ya definidos que están ampliamente testados.
Estas ventajas son directas a los programadores. Estos, se podría decir, que son los ejecutores de un determinado proyecto software. Pero la orientación a objetos no sólo reporta beneficios a los programadores. En las etapas de análisis, previas a la codificación, el utilizar un modelado orientado a objetos reporta grandes beneficios ya que estas mismas ventajas son aplicables a todas las fases del ciclo de vida de un proyecto software.
Enfoque Global Orientado a Objetos
La tendencia actual es a tratar temas conceptuales de primer plano (o sea, en las fases de análisis) y no temas finales de implementación. Los fallos durante la etapa de implementación son más difíciles de corregir y más costosos que si se dan en las etapas previas. El modelado orientado a objetos tiende al refinamiento sucesivo de manera que se llega a la etapa de implementación con un diseño lo suficientemente explicito para que no existan casos inesperados y todo independientemente del lenguaje de programación (salvo en etapas muy próximas a la implementación donde no hay más remedio que contar con el soporte que se recibe del lenguaje elegido).
El desarrollo orientado a objetos es más una manera de pensar y no una técnica de programación.
Conceptos de OO
Lo primero que debiéramos hacer primero es tratar de definir que es un objeto:
Es una entidad tangible o abstracta que exhibe un comportamiento bien definido.
Un objeto es una cosa, generalmente extraída del vocabulario del espacio del problema o del espacio de la solución. Todo objeto tiene un nombre (se le puede identificar), un estado (generalmente hay algunos datos asociados a él) y un comportamiento (se le pueden hacer cosas a objeto y él puede hacer cosas a otros objetos). Un objeto de la clase Coches puede ser un Ford Mustang.
Existen diversas definiciones del concepto de objeto brindada por múltiples autores, sin embargo esta nos pareció muy adecuada para comenzar a comprender su significado.
Es decir, una persona, un automóvil, la nieve, etc, son objetos.
Sigamos avanzando, si ya comprendimos que es un objeto.
A diferencia de la programación estructurada, la programación OO, utiliza objetos en lugar de algoritmos como bloques constructivos fundamentales. Es decir que en un programa OO vamos a tener un conjunto de objetos que van a cooperar entré si para lograr la funcionalidad pretendida.
Cada objeto es instancia de una clase. Si bien este concepto se explicará con detalle más adelante, la idea que debemos tener es que la clase es como una plantilla o un tipo de dato, a partir de la cual podemos crear tantos objetos (instancias) como queremos. Generalmente a un objeto se le denomina instancia, ya que el proceso de crear un objeto a partir de una clase se denomina instanciación.
Las clases también suelen relacionarse en jerarquías que más adelante explicaremos en detalle. Todos estos elementos hacen que un programa sea considerado como orientado a objetos.
En este caso cuando hablamos de una descomposición orientada a objetos estamos utilizando la abstracción asociada a los conceptos de objetos y clases para estructurar un sistema lógicamente; a diferencia del diseño estructurado, en donde la principal abstracción es el algoritmo.
La notación más utilizada para describir los modelos lógicos y físicos, así como los modelos estáticos y dinámicos de un sistema esta dada por el lenguaje de modelado unificado (UML). Si bien este lenguaje está fuera del alcance de esta unidad, la idea del mismo es brindar las herramientas necesarias para describir los modelos de diseño de un sistema, de igual forma que usted utilizaba los diagramas de entidad-relación y de Flujo de Datos para el diseño estructurado.
La Programación Orientada a Objetos es un método de implementación en el que los programas son organizados como colecciones cooperativas de objetos, cada uno de los cuales es instancia de una clase y cuyas clases son miembro de alguna jerarquía de herencia.
Clase: Conjunto de objetos que tienen en común la misma estructura y comportamiento (objetos similares).
Atributo: Es una característica concreta de una clase. Un atributo es una propiedad de una clase identificada con un nombre. Describe un rango de valores que pueden tomar las instancias de la propiedad. Los atributos representan propiedades comunes a todos los objetos de una determinada clase. Un cliente tiene las propiedades nombre, apellidos, dirección, teléfono... La clase Coches tiene las propiedades Color, el Número de Puertas, Marca, Modelo, etc.
Los atributos son propiedades interesantes de las clases. Una instancia de una determinada clase tendrá valores concretos para sus atributos, mientras que las clases tienen rangos de valores que pueden admitir sus atributos.
Método: Es una operación concreta de una determinada clase. Una operación es una implementación de un servicio que puede ser requerido a cualquier objeto de la clase para que muestre su comportamiento. Una operación representa algo que el objeto puede hacer.
Por ejemplo, de la clase Coches podríamos tener un método arrancar( ) que lo que hace es poner en marcha el coche y otro frenar que le permite detenerse.
Hay que hacer una especial diferenciación para no confundir el concepto de clase con el de objeto. Un objeto es una instancia individual de una clase.
Instancia: Es una manifestación concreta de una clase (un objeto con valores concretos).
También se le suele llamar ocurrencia. Por ejemplo, una instancia de la clase Coches puede ser: Un Ford Mustang, de color Gris con 3 puertas.
Instancias de Coches (Objetos) Clase Coches
Definición = características + comportamiento
Características:
• Marca
• Modelo
• Color
• Nro. de puertas
Comportamiento:
• Arrancar
• Frenar
La idea de que todos los objetos, aún siendo únicos, son también parte de una clase de objetos, todos ellos con características y comportamientos en común, ya fue usada en el primer lenguaje orientado a objetos, Simula-67, que ya incluye la palabra clave clase, que permite la introducción de un nuevo tipo dentro de un programa.
La creación de tipos abstractos de datos (clases) es un concepto fundamental en la programación orientada a objetos. Los tipos abstractos de datos funcionan casi como los tipos de datos propios del lenguaje: es posible la creación de variables de un tipo (que se denominan objetos o instancias en el dialecto propio de la orientación a objetos) y manipular estas variables (mediante el envío o recepción de mensajes; se envía un mensaje a un objeto y éste averigua que debe hacer con él). Los miembros (elementos) de cada clase comparten algunos rasgos comunes: toda cuenta tiene un saldo, todo cajero puede aceptar un ingreso, etc. Al mismo tiempo, cada miembro tiene su propio estado, cada cuenta tiene un saldo distinto, cada cajero tiene un nombre. Por consiguiente, los cajeros, clientes, cuentas, transacciones, etc. también pueden ser representados mediante una entidad única en el programa del computador. Esta entidad es el objeto, y cada objeto pertenece a una clase particular que define sus características y comportamientos.
Una vez que se establece una clase, pueden construirse tantos objetos de esa clase como se desee, y manipularlos como si fueran elementos que existen en el problema que se trata de resolver. Sin duda, uno de los retos de la programación orientada a objetos es crear una correspondencia uno a uno entre los elementos del espacio del problema y los objetos en el espacio de la solución.
Todo objeto tiene una interfaz
¿Cómo se consigue que un objeto haga un trabajo útil?
Debe de haber una forma de hacer peticiones al objeto, de manera que éste desempeñe alguna tarea, como completar una transacción, dibujar algo en la pantalla o encender un interruptor. Además, cada objeto sólo puede satisfacer determinadas peticiones. Las peticiones que se pueden hacer a un objeto se encuentran definidas en su interfaz, y es el tipo de objeto el que determina la interfaz. Un ejemplo sencillo sería la representación de una lamparita:
El Diseño Orientado a Objetos es un método de diseño que abarca un proceso de descomposición orientado a objetos y una notación para describir los modelos lógicos y físicos, así como los modelos estáticos y dinámicos de un sistema.
El Análisis Orientado a Objetos es un método de análisis que examina los requerimientos desde el punto de vista de las clases y objetos que forman parte del dominio del problema.
Es decir ¿como podemos comenzar el análisis orientado a objetos?
Si tuviéramos una descripción de un problema en papel, una forma de comenzar el análisis sería tratando de identificar cuales son los objetos y las clases, es decir por ejemplo una buena metodología sería buscar los sustantivos en dicha descripción, ya que estos podrían llegar a ser los objetos de nuestro sistema.
En caso de no poseer una descripción, seguramente vamos a necesitar realizar múltiples entrevistas con nuestro cliente para que nos describa el sistema que está necesitando, y a partir de dicha descripción definir los objetos que formaran parte de nuestro sistema.
O en muchos casos vamos a recurrir a experiencias previas que nos permitan identificar dichos objetos.
En todos estos casos resultará indudable que una vez identificados los objetos, deberemos clasificarlos para poder conformar las clases de nuestro sistema. Por ejemplo, si identificamos en una empresa los objetos José, Laura, María, podemos clasificarlos como empleados y a su vez como personas. Estos últimos dos conceptos conformaran clases en nuestro sistema que estarán relacionadas de alguna forma.
El análisis OO.
El análisis descubre y modela los aspectos relevantes de un dominio donde hay algún problema que interesa resolver; a este dominio se le llama dominio del problema o de interés.
Por ejemplo, en el dominio de la física de altas energías, el problema consiste en averiguar cómo interaccionan las partículas elementales; en el dominio de una empresa, el problema podría consistir en gestionar la contabilidad.
En general, el análisis parte de una definición del problema, casi siempre imprecisa y ambigua, y genera dos cosas: a) una descripción precisa y exacta del problema; b) un modelo preciso, conciso, comprensible y exacto del dominio del problema.
En el campo de la ingeniería, el problema suele consistir en crear un sistema (eléctrico, mecánico, informático, arquitectónico, etc.) que satisfaga las necesidades de clientes y usuarios: gestionar un almacén, levantar un muro, evitar las sobrecargas de tensión, mejorar la eficacia de un motor... No resulta infrecuente que el problema consista en sustituir un sistema ya existente por otro. En ambos casos, el dominio del problema coincide con la parte del mundo real para la cual se desarrolla el sistema (un departamento, una empresa...).
Dentro del análisis, el análisis de requisitos se encarga de descubrir los requisitos que el sistema debe cumplir: “La aplicación permitirá registrar los envíos que lleguen”, “El muro deberá tener una sección máxima de 0,5 metros cuadrados”, “El circuito impedirá el paso de cualquier corriente con más de 100 miliamperios”, “El motor no disipará más del 40% de la energía que recibe”...
Por medio del análisis de requisitos, el analista descubre y formula precisamente los requisitos que debe cumplir un sistema para satisfacer las necesidades de clientes y usuarios.
Partiendo de la descripción del problema proporcionada por éstos, obtiene una lista de requisitos para el sistema. Los requisitos no corresponden a una propuesta de solución:
reflejan lo que el sistema debe hacer, pero no cómo debe hacerlo. El análisis de requisitos se revela crucial para establecer lo que realmente se pide al sistema: las descripciones de clientes y usuarios suelen ser incompletas, ambiguas e incluso inconsistentes.
Una vez se han obtenido los requisitos del sistema, el analista los usa (junto con su conocimiento del mundo real y sus entrevistas con especialistas en el dominio) para fabricar un modelo conceptual del dominio del problema, es decir, una representación de los conceptos más relevantes del dominio para el que se desarrolla el sistema.
A partir de la descripción del problema (requisitos), del conocimiento de los expertos en el dominio y del conocimiento general sobre el mundo real, el análisis OO describe el dominio del problema mediante clases y objetos. En otras palabras, construye un modelo de dominio orientado a objetos.
El análisis de requisitos y el OO están fuertemente vinculados: el primero describe el sistema deseado (el problema) mediante una lista de requisitos; el segundo usa los requisitos, junto con el conocimiento mencionado en el párrafo anterior, para generar un modelo de dominio OO, correspondiente al dominio del problema.
Un modelo de dominio se representa mediante diagramas de clases, diagramas de objetos, o mediante ambos. Los primeros presentan de forma estática las clases del dominio y sus relaciones; los segundos muestran interacciones entre objetos concretos.
Si los términos del modelo son poco habituales (por ejemplo, términos médicos), el modelo de dominio suele incluir un breve glosario con todos ellos.
Las etapas del análisis OO son éstas:
1) Identificación de las clases del dominio. Más adelante veremos dos técnicas para identificarlas.
2) Elaboración del glosario de términos procedentes del dominio (esta etapa suele omitirse si los términos son de uso común).
3) Identificación de las relaciones o asociaciones entre las clases.
4) Identificación de los atributos o propiedades de las clases. Desde la perspectiva del análisis, un atributo de una clase indica que todos los objetos de esa clase tienen ese atributo.
5) Organización de las clases (mediante jerarquías).
6) Perfeccionamiento del modelo obtenido.
El modelo obtenido por el análisis OO se expresa en el lenguaje del cliente y del usuario, no depende de ningún entorno informático y no considera las restricciones de implementación.
Sobre estas restricciones, llamadas requisitos no funcionales, volveremos más adelante.
Las clases del análisis son clases conceptuales, no de software.
En ingeniería del software, el proceso de análisis corresponde a esta figura.
Para identificar las clases conceptuales de un dominio, suelen usarse dos técnicas: la identificación de sustantivos y la comparación con una lista de categorías de clases.
La técnica de la identificación de sustantivos extrae los sustantivos (nombres y grupos nominales) que aparecen en la descripción del problema y considera que corresponden a clases candidatas.
La técnica de la comparación con una lista de categorías de clases determina las clases candidatas de un dominio basándose en una lista de categorías de clases. Asignando los conceptos del problema a las categorías de clases, se obtiene una lista de clases candidatas.
Ambas técnicas exigen un proceso de depuración, que se acelera con la experiencia del analista. Dada una lista de sustantivos o clases candidatas, convendrá aplicar las siguientes reglas de eliminación:
1) Redundancia. Si varios sustantivos se refieren a la misma entidad, se debe elegir uno de ellos (el más representativo). Por ejemplo, no tiene sentido mantener tres clases como Trabajador, Empleado y Asalariado.
2) Atributo. Los sustantivos que describen la estructura de las clases corresponden a atributos, no a clases. Por ejemplo, el código de un libro es un atributo de una clase Libro, no una clase por sí misma.
Nota: Aunque los términos “Diagrama” y “Modelo” se usan casi siempre como sinónimos, no significan exactamente lo mismo: un diagrama representa, a menudo parcialmente, un modelo. Un modelo puede describirse con varios diagramas y, a la vez, varios diagramas pueden representar un mismo modelo (siempre que sean consistentes).
La diferencia de significado resulta importante si se trabaja con UML, pues éste especifica que sólo hay un modelo de clases (incluido en el “modelo estructural estático”), que puede describirse con varios diagramas de clases. Por lo tanto, aunque en UML una clase sólo figura una vez en el modelo de clases, puede aparecer en varios diagramas de clases.
3) Irrelevancia. Los sustantivos sin relación con el problema o el dominio no son relevantes. Por caso, las clases candidatas Mostrador del Hospital y Máquina de Café resultan irrelevantes si se está elaborando una aplicación para un hospital. Siempre debe evitarse la introducción de clases no asociadas a los conceptos del dominio bajo estudio.
4) Acción. Los sustantivos correspondientes a acciones no originan clases. Por ejemplo, la clase candidata Cálculo del IVA no es una clase. En todo caso, calcularIVA sería una operación de alguna clase.
5) Estado. Los sustantivos que describen el estado de una entidad no corresponden a clases. Por ejemplo, Automóvil Veloz no es una clase (la clase es Automóvil).
6) Frecuencia temporal. Los sustantivos que describen frecuencias de tiempo no corresponden a clases. Por ejemplo, en la frase “Al cliente se le informa de su saldo cada semana”, Semana no es una clase.
7) Entidad de hardware o de software. Los sustantivos que describen entidades de hardware o de software no generan clases (salvo que se modele un sistema de hardware o de software). Por ejemplo, en el dominio de una empresa, aunque haya un requisito como “El cliente seleccionará mediante el teclado el producto que desea”, Teclado no será una clase. Sin embargo, una clase candidata CPU será clase si el dominio corresponde a componentes de hardware o a sistemas operativos.
La identificación de las relaciones entre las clases de un dominio se realiza a partir de las frases verbales presentes en la descripción del problema y de nuestro conocimiento de éste.
Las relaciones pueden aparecer explícitas (“El usuario posee una tarjeta de crédito”) o implícitas (“asiento de avión” significa que el avión contiene asientos; “itinerario de vuelo”
significa que un vuelo sigue un itinerario”).
El diseño OO
El diseño es un proceso que usa los resultados del análisis para generar una especificación que implemente un sistema o un producto. El análisis trabaja en el “espacio del problema”;
el diseño, en el “espacio de la solución”. Durante la etapa de análisis, lo fundamental es qué necesita hacer el sistema; cuando se aborda el diseño, lo importante es cómo construirlo.
En el caso del software, el diseño genera –dado un entorno informático y una lista de requisitos un modelo de software (modelo de diseño) que detalla cómo debe hacer las cosas el sistema para cumplir los requisitos y, en definitiva, solucionar el problema que se plantea en el dominio de interés.
En el diseño se consideran las restricciones derivadas de la implementación (requisitos no funcionales o técnicos). Por tanto, los modelos de diseño dependen del entorno informático – ordenadores personales, estaciones de trabajo, entornos distribuidos, agendas electrónicas, sistemas operativos, lenguajes de programación donde se vaya a implementar el sistema. En el diseño hay que contestar preguntas como éstas:
• ¿Cómo se puede distribuir entre varios ordenadores la aplicación, con el fin de que se distribuyan equitativamente las peticiones que recibe cada ordenador?
• ¿Qué componente de acceso a bases de datos es más conveniente para la aplicación?
• ¿Cómo puede ejecutarse este método en un tiempo máximo de 30 milisegundos?
• ¿Cómo puede utilizarse más eficazmente Java en la aplicación?
El diseño OO usa los resultados del análisis OO y del análisis de requisitos para producir un modelo de diseño basado en clases y objetos de software; a diferencia de lo que sucede en el análisis OO, los objetos y clases del diseño OO no modelan entidades del mundo real, sino de software.
La diferencia fundamental entre análisis y diseño OO es el nivel de detalle: el diseño refina las clases conceptuales del análisis hasta convertirlas en clases de software implementables en un lenguaje OO.
Durante el diseño OO, hay que completar pasos como éstos:
a) Representación de las clases. Para cada clase, hay que decidir si se representa mediante tipos primitivos (int, float, double...) o mediante otras clases más simples. Por ejemplo, un objeto Línea puede representarse mediante cuatro datos de tipo float o double (x1, y1, x2, y2) o mediante dos objetos Punto.
b) Diseño de los algoritmos que implementen las operaciones de las clases. Para ello hay que a) elegir los algoritmos, considerando factores como la complejidad computacional, la flexibilidad, la facilidad de implementación y la legibilidad; b) seleccionar las estructuras de datos pertinentes para los algoritmos (pilas, colas, árboles, etc.); y c) definir las clases y operaciones internas que se necesitarán para almacenar los datos intermedios generados por los algoritmos.
c) Reorganización de las clases y operaciones para aumentar, si es posible, la herencia.
d) Diseño de las asociaciones entre clases. En la fase de diseño hay que establecer cómo se implementarán las asociaciones o relaciones (punteros, conjuntos de punteros, diccionarios...).
Todo modelo de diseño OO especifica lo siguiente:
•••• Los tipos de objetos (clases) que necesita el sistema para resolver el problema.
Deben especificarse sus atributos, operaciones y relaciones.
•••• Las interacciones entre los objetos (instancias), las cuales cambian con el tiempo. Por ejemplo, un objeto Mecánico puede estar arreglando un objeto Automóvil y luego puede preguntar a un objeto Cliente sobre la forma de pago que desea.
El primer punto corresponde al modelo estático; el segundo, al dinámico.
Nota: el diseño OO toma los resultados del análisis OO con el fin de generar un modelo lo bastante detallado como para ser implementado en un lenguaje OO. Ahora bien, en la práctica, la separación entre análisis y diseño OO no siempre resulta tan tajante: a menudo se solapan ambas actividades.
La frontera entre análisis y diseño OO es sumamente borrosa en las metodologías iterativas de desarrollo de software. En una metodología iterativa, el desarrollo se estructura en una serie de pequeños proyectos cortos, de duración fija (2-3 semanas, por ejemplo). Estos proyectos se llaman iteraciones; cada iteración produce un sistema o subsistema que puede
probarse, ejecutarse e integrarse en un sistema mayor. Como cada iteración tiene sus tareas de análisis, diseño e implementación, en cada una se mezcla el análisis con el diseño.
En estas metodologías también se mezcla el diseño con la implementación, lo cual no es un inconveniente, más bien al contrario; pues la implementación desarrollada en una iteración se usa para encontrar errores en el diseño, que se corrigen en la siguiente iteración.
Por regla general, cuanto más grande es el proyecto de software que se aborda, más nítida aparece la separación entre análisis y diseño, y entre diseño e implementación.
Las clases conceptuales del modelo de dominio generado por el análisis OO suelen continuar en el diseño OO como clases de entidad (clases de software que contienen información persistente); también las relaciones entre las clases del modelo de dominio OO suelen permanecer en el diseño OO. Además de las clases de entidad, en el diseño OO hay que añadir a menudo clases de interfaz (clases de software que modelan la relación entre el sistema y los usuarios externos, ya sean éstos personas o sistemas) y clases de control (clases de software que se usan para representar la coordinación entre clases).
Las clases de interfaz suelen ser abstracciones de ventanas, formularios, paneles, sensores, teclados, ratones, impresoras, tarjetas de red...
Las clases de control suelen encapsular el control de un caso de uso o el sistema completo; especifican qué mensajes deben intercambiar los objetos, y en qué orden, para que el sistema cumpla una o más funciones. Por ejemplo, al caso de uso “Sacar en préstamo libros” se le podría asignar una clase de control SacarLibro que coordinara las acciones que deben llevar a cabo los objetos Libro, Ejemplar y SocioBiblioteca para que el usuario pueda llevarse en préstamo un libro. La clase Biblioteca de la figura siguiente es una clase de control:
representa el sistema informático de la biblioteca.
Además de las clases de interfaz y de control, un diseño OO suele necesitar clases definidas “de serie” en el lenguaje donde vaya a implementarse el diseño. Por ejemplo, los objetos Libro de la biblioteca se podrían guardar en una clase Vector o ArrayList de Java, clases ausentes en el modelo de análisis. Estas clases se emplean para implementar colecciones de objetos en la memoria de un ordenador o computador y, por ende, sus propiedades no derivan del dominio del problema ni del mundo real.
La programación OO
Cuando se consideran sistemas de software, la orientación a objetos consiste en el análisis OO, el diseño OO y la programación OO. La programación OO es el proceso que genera una aplicación a partir del diseño OO. Dicho en otras palabras, la POO materializa físicamente los diseños OO, que a su vez proceden del análisis OO. La fuerza de la POO radica en que la comprensibilidad y la facilidad de mantenimiento de los programas aumentan cuando se descomponen en clases.
El resultado de la POO es una aplicación capaz de ejecutarse en un entorno informático. A veces se dice que el resultado es el código fuente de la aplicación. Esto no es del todo cierto:
sus clientes no quedarán muy satisfechos si les da un listado con el código de la aplicación o un archivo de texto con el código. En realidad, el código fuente es un modelo que usan los programadores para comunicarse entre ellos, y que puede ser traducido fácilmente (con un
Algunas metodologías de ingeniería del software dedican poco tiempo a la documentación, pues es costosa. El resultado final es que, cuando hay que modificar sustancialmente un sistema o sustituirlo por otro, hay que empezar de cero el análisis y diseño, y el cliente debe volver a pagarlo, aunque sus requisitos apenas hayan variado. Esto no molesta, más bien al contrario, a las consultoras de software; pero sí a los clientes y a quienes intentamos mejorar la competitividad de las pequeñas y medianas empresas europeas.
De esas metodologías, algunas reducen al mínimo el análisis y diseño, y se centran en la programación. Este enfoque puede funcionar en proyectos pequeños, pero no en proyectos grandes o medianos, ni en aquellos en que se exigen características como escalabilidad o velocidad. Estas propiedades no surgen directamente de la programación, sino que deben ser tenidas en cuenta desde el principio.
1.2. Paradigmas de programación
Un paradigma es una forma de representar y manipular el conocimiento. En nuestro contexto, representa un enfoque particular o filosofía para la construcción del software. No es mejor uno que otro sino que cada uno tiene ventajas y desventajas con respecto a un tipo de problema a resolver. Hay situaciones donde un paradigma resulta más apropiado que otro.
Algunos ejemplos de paradigmas de programación:
• El paradigma imperativo es considerado el más común y está representado, por ejemplo, por el C o por BASIC.
• El paradigma funcional está representado por la familia de lenguajes LISP, en particular Scheme.
• El paradigma lógico, un ejemplo es PROLOG.
• El paradigma orientado a objetos. Un lenguaje completamente orientado a objetos es Smalltalk.
1.3 Modelado Orientado a Objetos.
El desarrollo de proyectos software ha sufrido una evolución desde los primeros sistemas de cálculo, implementados en grandes computadores simplemente ayudados mediante unas tarjetas perforadas donde los programadores escribían sus algoritmos de control, hasta la revolución de los sistemas de información e Internet. Han existido dos grandes cambios desde aquellos sistemas meramente algorítmicos donde todo el esfuerzo de desarrollo se centraba en la escritura de programas que realizaran algún tipo de cálculo. El primero de ellos es la aparición del modelo relacional, un modelo con fuerte base matemática que supuso el desarrollo las bases de datos y propició la aparición de los grandes sistemas de información. El segundo cambio es sobre los lenguajes de programación, la aparición de los Lenguajes Orientados a Objetos (aunque los primero lenguajes con características de orientación a objetos aparecieron en la década de los setenta, por ejemplo Simula 67) supuso una revolución en la industria software. El problema entonces radicaba en poder sacarle partido a los lenguajes orientados a objetos por lo que aparecieron numerosas metodologías para el
diseño orientado objetos, hubo un momento en el que se podía decir que el concepto de orientación a objetos estaba “de moda” y todo era orientado a objetos, cuando realmente lo que ocurría es que las grandes empresas que proporcionaban los compiladores y lenguajes de programación “lavaban la cara" a sus compiladores, sacaban nuevas versiones que adoptaran alguno de los conceptos de orientación a objetos y los vendían como orientados a objetos.
Para poner un poco de orden, sobre todo en lo que respecta a la modelización de sistemas software, aparece UML (Unified Modeling Languaje, Lenguaje Unificado de Modelado) que pretende unificar las tres metodologías más difundidas (OMT, Bootch y OOSE) e intentar que la industria software termine su maduración como Ingeniería . Y lo consigue en tal manera que lo que UML proporciona son las herramientas necesarias para poder obtener los planos del software equivalentes a los que se utilizan en la construcción, la mecánica o la industria aeroespacial. UML abarca todas las fases del ciclo de vida de un proyecto, soporta diferentes maneras de visualización dependiendo de quién tenga que interpretar los planos y en que fase del proyecto se encuentre. Lo que describiéremos en este curso es una introducción al diseño orientado a objetos y que solución aporta UML, explicando sus características principales.
Modelado
Para producir software que cumpla su propósito hay que obtener los requisitos del sistema, esto se consigue conociendo de una forma disciplinada a los usuarios y haciéndolos participar de manera activa para que no queden “cabos sueltos”. Para conseguir un software de calidad, que sea duradero y fácil de mantener hay que idear una sólida base arquitectónica que sea flexible al cambio. Para desarrollar software rápida y eficientemente, minimizando el trabajo de recodificación y evitando crear miles de líneas de código inútil hay que disponer, además de la gente y las herramientas necesarias, de un enfoque apropiado.
Para conseguir, que a la hora de desarrollar software de manera industrial se obtenga un producto de calidad, es completamente necesario seguir ciertas pautas y no abordar los problemas de manera somera, con el fin de obtener un modelo que represente lo suficientemente bien el problema que hemos de abordar. El modelado es la espina dorsal del desarrollo software de calidad. Se construyen modelos para poder comunicarnos con otros, para explicar el comportamiento del sistema a desarrollar, para comprender, nosotros mismos, mejor ese sistema, para controlar el riesgo y en definitiva para poder atacar problemas que sin el modelado su resolución seria imposible, tanto desde el punto de vista de los desarrolladores (no se pueden cumplir los plazos estimados, no se consigue ajustar los presupuestos...) como desde el punto de vista del cliente, el cual, si finalmente se le entrega el producto del desarrollo, se encontrará con infinidades de problemas, desde que no se cumplen las especificaciones hasta fallos que dejan inutilizado el sistema.
Cuando nos referimos al desarrollo software en el ámbito industrial, no se pretende que la capacidad de modelar se reduzca a empresas que disponen de gran numero de empleados o empresas que han de abordar proyectos eminentemente grandiosos, si no que nos referimos a la capacidad de obtener un producto comercial (sea cual sea su coste o tamaño) que cumpla lo que en la industria se suele denominar como calidad total y que además pueda reportar beneficios a corto o medio plazo, evitando, por ejemplo, implantaciones casi eternas debido a
Por todas estas razones es inevitable el uso de modelos. Pero, ¿qué es un modelo?. La respuesta es bien sencilla, un modelo es una simplificación de la realidad. El modelo nos proporciona los planos de un sistema, desde los más generales, que proporcionan una visión general del sistema, hasta los más detallados. En un modelo se han de incluir los elementos que tengan más relevancia y omitir los que no son interesantes para el nivel de abstracción que se ha elegido. A través del modelado conseguimos cuatro objetivos:
• Los modelos nos ayudan a visualizar cómo es o queremos que sea un sistema.
• Los modelos nos permiten especificar la estructura o el comportamiento de un sistema.
• Los modelos nos proporcionan plantillas que nos guían en la construcción de un sistema.
Los modelos documentan las decisiones que hemos adoptado.
En la realidad, no siempre se hace un modelado formal, la probabilidad de que exista un modelado formal para abordar un sistema es inversamente proporcional a la complejidad del mismo, esto es, cuanto más fácil sea un problema, menos tiempo se pasa modelándolo y esto es porque cuando hay de aportar una solución a un problema complejo el uso del modelado nos ayuda a comprenderlo, mientras que cuando tenemos un problema fácil el uso del modelado que hacemos se reduce a representar mentalmente el problema o, como mucho, a escribir unos cuantos garabatos sobre un papel.
Principios básicos del modelado
Existen cuatro principios básicos, estos principios son fruto de la experiencia en todas las ramas de la ingeniería.
a) La elección de qué modelos se creen influye directamente sobre cómo se acomete el problema. Hay que seleccionar el modelo adecuado para cada momento y dependiendo de que modelo se elija se obtendrán diferentes beneficios y diferentes costes. En la industria software se ha comprobado que un modelado orientado a objetos proporciona unas arquitecturas más flexibles y readaptables que otros por ejemplo orientados a la funcionalidad o a los datos.
b) Todo modelo puede ser expresado a diferentes niveles de precisión. Esto es, es necesario poder seleccionar el nivel de detalle que se desea ya que en diferentes partes de un proyecto y en diferentes etapas se tendrán unas determinadas necesidades.
c) Los mejores modelos están ligados a la realidad. Lo principal es tener modelos que nos permitan representar la realidad lo más claramente posible, pero no sólo esto, tenemos que saber, exactamente cuando se apartan de la realidad para no caer en la ocultación de ningún detalle importante.
d) Un único modelo no es suficiente. Cualquier sistema que no sea trivial se afronta mejor desde pequeños modelos casi independientes, que los podamos construir y estudiar independientemente y que nos representen las partes más diferenciadas del sistema y sus interrelaciones.
1.4 Abstracción, Encapsulamiento, Modularidad, Jerarquía.
En un modelo orientado a objetos, los elementos constitutivos más importantes son:
• Abstracción
• Encapsulamiento
• Modularidad
• Jerarquía
Por importantes queremos decir que un modelo sin alguno de estos elementos no puede ser considerado como Orientado a Objetos.
Abstracción
En la vida los seres humanos utilizamos el concepto de abstracción como manera fundamental de enfrentar la complejidad. Una buena abstracción es aquella que enfatiza los detalles significativos para el usuario y deja de lado aquellos que no son relevantes para el problema en cuestión.
Por ejemplo, cuando vamos a una consecionaria a comprar un automóvil seguramente formaremos una abstracción del auto que deseamos adquirir. En dicha abstracción concentraremos los detalles como por ejemplo si tiene airbags, levantavidrios eléctricos, aire acondicionado, llantas de aleación, etc; y dejaremos de lado detalles como por ejemplo si tiene 8 o 16 válvulas o el precio de los repuestos.
Sin embargo para un mecánico estos últimos aspectos pueden ser de fundamental importancia, por lo que la abstracción que él definirá de un automóvil será muy distinta a la de un usuario final. Es por ello que una abstracción se centra en la vista externa de un objeto, separando el comportamiento de la implementación.
Con este concepto lo que estamos queriendo decir es que cuando identificamos las clases y objetos que formarán parte de nuestro sistema, debemos enfocarnos en los aspectos (por ej:
comportamiento) significativos de cada uno de ellos.
Por ejemplo si estamos modelando un sistema de personal de una organización seguramente nos interesará saber el nombre y apellido de un empleado, pero no el color de sus ojos.
El decidir cuáles son las abstracciones correctas para un dominio en particular es uno de los principales problemas del diseño orientado a objetos.
En muchas ocasiones podemos caracterizar las relaciones entre objetos a través de un esquema cliente/servidor.
Es decir, un cliente es cualquier objeto que utiliza los recursos de otro objeto conocido como servidor. De esta forma podemos caracterizar el comportamiento de un objeto considerando los servicios que provee a otros objetos y las operaciones que puede realizar sobre otros objetos.
Toda abstracción tiene propiedades y operaciones. El concepto de operación es idéntico al concepto de función o método provenientes de otras culturas de programación. Una operación describe un comportamiento que el objeto es capaz de realizar. Por ejemplo, si a la clase Persona le definimos el método caminar, significa que toda instancia u objeto de dicha clase
Encapsulamiento
Es necesario entender que la identificación de una abstracción debe preceder a las decisiones de implementación. Con esto queremos decirle que antes de enfocarnos en los atributos y en el comportamiento de una abstracción debemos identificarla. No podemos jamás hablar sobre la forma de ladrar de un perro (comportamiento), sino identificamos previamente la abstracción perro.
Ahora bien que entendemos por encapsulamiento: cuando elegimos una implementación para un objeto, dicha implementación debe ser tratada como secreta y estar oculta para los clientes.
Por ejemplo, si nosotros tenemos un objeto automóvil, seguramente definiremos un método o función que denote el comportamiento de que un auto puede avanzar. Sin embargo a los usuarios del automóvil poco le importará si para avanzar se necesita apretar un botón o una palanca, ya que este aspecto es parte de la implementación del método avanzar correspondiente al objeto automóvil y está oculto a los clientes del mismo.
El encapsulamiento y la abstracción son conceptos complementarios, pues mientras la abstracción se enfoca en el comportamiento observable de un objeto, el encapsulamiento se enfoca en la implementación que da soporte a dicho comportamiento.
El encapsulamiento se logra a través del ocultamiento de información, que es el proceso de ocultar todos los secretos de un objeto que no contribuyen a sus características esenciales;
típicamente lo que se oculta son las propiedades de un objeto y la implementación de sus métodos.
En los lenguajes OO, el encapsulamiento garantiza que los usuarios de un objeto no puedan modificar el estado del objeto sin usar su interfaz (conjunto de métodos que son accesibles a otros objetos). Es decir, no pueden cambiar su estado de maneras no fijadas de antemano. En un objeto bien diseñado, los otros objetos sólo pueden interaccionar con él mediante su interfaz. Un buen encapsulamiento separa siempre las vistas que del objeto tienen el constructor y el usuario.
La gran ventaja del encapsulamiento consiste en que, si un módulo cambia internamente sin modificar su interfaz, el cambio no supondrá ninguna otra modificación del sistema. Por tanto, el encapsulamiento permite evitar que los programas sean tan interdependientes que un pequeño cambio provoque muchos efectos secundarios.
Modularidad
Según autores como Myers, “el particionar un programa en componentes individuales puede reducir su complejidad”.
En la mayoría de los lenguajes de programación orientados a objetos, las clases y objetos conforman la estructura lógica de un sistema. Estas abstracciones luego son colocadas en módulos para producir la arquitectura física del sistema.
En algunos lenguajes el concepto de módulo es similar a paquete o librería.
¿Por qué es necesario este concepto?...Especialmente en grandes aplicaciones tendremos gran cantidad de clases y objetos, agrupados en pocos módulos, ayudándonos a manejar dicha complejidad.
Otros autores como Liskov definen a la modularización como el “proceso de dividir un programa en módulos que pueden ser compilados separadamente, pero con conexiones con otros módulos”.
Cuando nos restringimos a software, un módulo es un conjunto de sentencias bajo un nombre por el cual puede ser llamado o invocado. Los módulos son la unidad de programación.
En Java, una clase constituye un módulo, pero eso no quiere decir que toda clase de Java sea un “buen” módulo. Las características deseables de un módulo, las que aumentan su modularidad, son las siguientes:
• Alta cohesión. La cohesión mide el grado de relación funcional interna de los componentes de un módulo. En la ingeniería del software, la cohesión se traduce en una medida del grado en que las líneas de código dentro del módulo colaboran para ofrecer una función concreta. Los módulos con cohesión alta son deseables porque la alta cohesión se relaciona con programas robustos (no fallan ante entradas inesperadas o erróneas), reutilizables (partes del programa se pueden emplear en otros programas), legibles (fáciles de entender) y compactos (no más largos de lo necesario).
• Bajo acoplamiento. El acoplamiento mide la interconexión entre módulos. En la ingeniería del software, el acoplamiento se traduce en una medida de la relación entre líneas de código pertenecientes a módulos diferentes. Lo dicho con respecto las ventajas de la alta cohesión se aplica también al bajo acoplamiento, pues el bajo acoplamiento suele implicar alta cohesión, y viceversa.
La idea de construir aplicaciones juntando módulos de software estandarizado e intercambiable proviene de la producción industrial en serie.
Modularidad es la propiedad de un sistema de ser descompuesto en un conjunto de módulos cohesivos y con bajo acoplamiento.
Los Módulos son contenedores físicos en los cuales podemos ubicar las clases y objetos de nuestro diseño lógico.
Estén relacionadas con dicho aspecto, es decir este módulo debiera contener objetos como botón, formulario, panel, etc.
Si el módulo de interfaz gráfica contiene el objeto automóvil, la pregunta que nos debiéramos hacer es la siguiente, ¿qué relación tiene con objetos de interfaz de usuario?. La respuesta es muy sencilla, ninguna. Por lo tanto un módulo de estas características no sería altamente cohesivo.
Un módulo de interfaz gráfica contendría sólo objetos relacionados con la creación de una interfaz de usuario, como paneles, botones, etiquetas, etc.
Otro de los problemas que se nos genera con módulos poco cohesivos es que dificulta en demasía la documentación por parte de un programador y la búsqueda de las clases y los objetos por parte de cualquier usuario del módulo.
Cuando hablamos de acoplamiento de módulos lo que estamos queriendo decir es que los módulos se relacionan entre sí, al igual que ocurre entre clases y objetos. Cada vez que un módulo se acopla o depende de otro módulo trae aparejado problemas de costo en la programación.
¿Costo en la programación? Si, leyó bien..Cuando un módulo A esta relacionado (depende) de B, si modificamos algo de B, seguramente deberemos recompilar no sólo B sino también A, ya que A depende de B.
Por lo tanto uno de los objetivos que busca la modularidad es la descomponer en sistema en módulos cohesivos (agrupando abstracciones relacionadas lógicamente) y bajamente acoplados (minimizando las dependencias entre módulos).
Jerarquía
Como usted ha visto, el concepto de abstracción es muy bueno para manejar la complejidad de un sistema, sin embargo en grandes sistemas este concepto no será suficiente para la cantidad de abstracciones que podemos llegar a identificar.
Sin embargo es posible simplificar nuestro entendimiento con respecto a un problema identificando las jerarquías de abstracciones de nuestro problema.
Sin embargo identificar jerarquías de abstracciones no es tan simple, ya que no todos los objetos están relacionados de la misma forma.
Las dos jerarquías más importantes se dan en la estructura de clase (jerarquía de herencia) y en la estructura de objetos (jerarquía “parte de”) de un problema.
Herencia Simple
Es un mecanismo mediante el cual se puede crear una nueva clase partiendo de una existente, se dice entonces que la nueva clase hereda las características de la case existentes aunque se le puede añadir más capacidades (añadiendo datos o capacidades) o modificar las que tiene. Básicamente la herencia define una relación entre clases, donde una clase (denominada subclase) comparte la estructura y comportamiento definido en una clase superior (denominada superclase). Este tipo de herencia se denomina herencia simple. Si bien existen otros tipos de herencia, la misma queda fuera de los límites de esta unidad, ya que el lenguaje de programación que vamos a utilizar sólo implementa el concepto anteriormente visto.
Típicamente una subclase aumenta o redefine la estructura y el comportamiento de su superclase. Si no lo entendimos, tratemos de explicarlo de otra forma.
Semánticamente la herencia denota una relación del tipo “es-un”.
La herencia genera jerarquías de generalización/especialización, ya que generalmente una subclase especializa la estructura y comportamiento más general de su superclase.
Por ejemplo supongamos que tenemos la VehiculosDeMotor. En esta clase tenemos los siguientes atributos: Cilindrada y Numero de Ruedas, y el método acelerar(). Mediante el mecanismo de herencia podemos definir la clase Coches y la clase Motos. Estas dos clases heredan los atributos Cilindrada y Numero de Ruedas de la clase VehículosDeMotor pero a su vez tendrán atributos propios (como hemos dicho antes el Numero de Puertas es un atributo propio de la clase Coches que no tienen sentido en la clase Motos). Se puede decir que Coches extiende la clase VehículosDeMotor, o que VehículosDeMotor es una generalización de las clases Coches y Motos.
Polimorfismo
Hace referencia a la posibilidad de que dos métodos implementen distintas acciones, aun teniendo el mismo nombre, dependiendo del objeto que lo ejecuta o de los parámetros que recibe. En el ejemplo anterior teníamos dos objetos que heredaban el método acelerar() de la clase VehiculosDeMotor. De hecho en clase VehiculosDeMotor al ser general no tiene sentido que tenga una implementación concreta de este método. Sin embargo, en las clases Coches y Motos si que hay una implementación clara y distinta del método acelerar(), lo podemos ver en el código fuente 1 y 2. De este modo podríamos tener un objeto VehículosDeMotor, llamado vdm, en el que residiera un objeto Coche. Si realizáramos la llamada vdm.acelerar() sabría exactamente que ha de ejecutar el método Coches::acelerar().
Coches::acelerar(){
Pisar más el pedal derecho }
Código fuente 1. Posible implementación para coches
Girar más el puño derecho }
Código fuente 2. Implementación para motos
1.5 Tipos, Estado e identidad de un objeto.
En esta sección trataremos de aclarar y diferenciar los conceptos de clase y objeto, ya que seguramente usted tendrá dudas con respecto a como diferenciar cada uno de ellos
Que es y que no es un Objeto
La habilidad de reconocer objetos físicos por parte de un ser humano varía enormemente.
Generalmente un niño desarrolla la habilidad de reconocer el concepto de objeto cerca del año, de acuerdo al desarrollo cognitivo del mismo.
En la sección anterior definimos a un objeto como una entidad que exhibe un comportamiento bien-definido. Desde la perspectiva del ser humano un objeto puede ser:
• Una entidad visible y/o tangible
• Algo que puede ser comprendido intelectualmente.
Generalmente un objeto modela alguna parte de la realidad y es por ello que lo definimos como algo que existe en el tiempo y el espacio.
Pero en el desarrollo de software no sólo nos van a interesar los objetos del mundo real, sino que también podríamos tener entidades abstractas, por ejemplo podríamos querer representar a través de un objeto un proceso químico, para la obtención de algún producto particular. Ese proceso, es para el ser humano abstracto, no es una entidad tangible del mundo real, sin embargo puede representarse a través de un objeto.
Estado
Una propiedad es una característica distintiva de un objeto. Por ejemplo un ascensor tiene la propiedad de desplazarse de arriba hacia abajo o viceversa.
Generalmente las propiedades de un objeto son estáticas, ya que por ejemplo toda persona tiene un nombre, sin embargo los valores que pueden adoptar dichas propiedades son dinámicos. Por ejemplo, dos personas pueden tener distinto nombre, o incluso tener el mismo nombre y ser objetos distintos.
Un Objeto tiene un estado, comportamiento y una identidad. Los términos de instancia y objeto pueden usarse indistintamente.
El estado de un objeto abarca todas las propiedades de un objeto y los valores de cada una de ellas.
Comportamiento
En un objeto el comportamiento está definido por las operaciones que pueden realizarse sobre el mismo.
Por ejemplo para que un objeto cliente pueda realizar la operación de extracción de dinero de un cajero automático, seguramente el objeto cajero tendrá definido el comportamiento (operación) extraerEfectivo.
Es decir, que el objeto cliente invocará una función miembro de otro objeto, cajero. En lenguajes OO esto se define como pasar un mensaje a otro objeto.
Un mensaje consta de un objeto receptor y de una operación a realizarse sobre el mismo.
Generalmente la invocación de un método (operación) sobre un objeto, provocará un cambio de estado en el mismo, pero no siempre es así.
Por ejemplo, si sobre un objeto persona invoco un método que devuelva el nombre de dicha persona el estado seguirá siendo el mismo luego de la invocación, ya que el valor de la propiedad nombre seguirá siendo el mismo.
Identidad
Generalmente muchos lenguajes de programación distinguen a los objetos a través de la utilización de variables. Por ejemplo los sistemas de base de datos utilizan claves primarias para distinguir entre registros, que pueden tener valores iguales o distintos en cada columna de una tabla.
Usted podría pensar que en el caso de objetos del tipo persona la identidad podría estar dada por el valor de una propiedad como por ejemplo dni. Sin embargo si pensamos de esta forma estamos equivocados. La identidad de un objeto no está dada por el valor de sus propiedades, como ocurre en una tabla de una base de datos, sino por la representación en memoria que el lenguaje de programación provee para dicho objeto.
Podemos tener dos objetos con el mismo estado, es decir con los mismos valores en sus propiedades, y seguiran siendo objetos distintos, ya que el lenguaje de programación proveera un espacio de memoria distinto a cada uno de ellos.
El comportamiento es como un objeto actúa y reacciona en términos de cambios de estado y envío de mensajes Una operación denota un servicio que una clase ofrece a sus clientes.
Identidad es la propiedad que permite a un objeto distinguirlo de los demás objetos.
Que es y que no es una Clase
Seguramente a usted no le habrá quedado claro cual es la diferencia entre el concepto de clase y objeto, ya que en muchos casos lo hemos utilizado intercambiadamente.
Sin embargo, existen diferencias importantes entre dichos términos. Mientras un objeto es una entidad concreta que existe en el tiempo y el espacio, una clase representa sólo una abstracción.
siendo estos objetos, mamíferos concretos. Es por ello que muchas veces suele definirse a la clase como una plantilla a partir de la cual puedo generar objetos.
Lo que debemos tener en claro es que la estructura y el comportamiento se define en las clases, no en los objetos. Los objetos son simplemente instancias de una clase.
Espero que haya entendido los conceptos vertidos en esta sección, respecto a las clases y objetos. Como se dijo originalmente estos conceptos son fundamentales para poder programar en lenguajes orientados a objetos como Java.
A partir de la siguiente sección comenzaremos explicando las particularidades de dicho lenguaje enfocándonos en los aspectos básicos del mismo.
Debe quedar completamente claro que el objetivo del presente módulo es introducir al alumno en esta tecnología, no desarrollar habilidades expertas en orientación a objeto y/o java.
Lo invito a que vayamos aprendiendo juntos, y recuerde que ante cualquier duda estaremos en el foro respondiendo sus inquietudes.
Una clase es un conjunto de objetos que comparten una estructura y un comportamiento común.
1.6 Tipos de Relaciones.
Las relaciones son la manera de representar las interacciones entre las clases. Por ejemplo el montaje de un ordenador, cada pieza interactúa con otra de una determinada manera y aunque por si solas no tienen sentido todas juntas forman un ordenador, esto es lo que se denomina una relación de asociación, pero además hay unas que no pueden funcionar si no están conectadas a otras como por ejemplo un teclado, el cual, sin estar conectado a una CPU es totalmente inútil, además si la CPU cambiase su conector de teclado este ya no se podría conectar a no ser que cambiase el también, esto se puede representar mediante una relación de dependencia. Es más, tenemos una disquetera de 1,44Mb, un disco duro, un CD-ROM.
Para referirnos a todos estos tipos de discos podríamos generalizar diciendo que tenemos una serie de discos con ciertas propiedades comunes, como pueden ser la capacidad, la tasa de transferencia en lectura y escritura... esto es lo que se denomina una relación de generalización. La construcción de relaciones no difiere mucho de la distribución de responsabilidades entre las clases. Si se modela en exceso se obtendrán diagramas con un alto nivel de dificultad para poder leerlos debido principalmente al lío que se forma con las relaciones, por el contrario, si se modela insuficientemente se obtendrán diagramas carentes de semántica.
Para poder representar con UML cómo se conectan las cosas entre sí, ya sea lógica o físicamente, utilizamos las relaciones. Existen tres tipos de relaciones muy importantes:
dependencias, generalizaciones y asociaciones. Una relación se define como una conexión entre elementos.
Existen cuatro tipos de relaciones entre los elementos de un modelo UML. Dependencia, asociación, generalización y realización, estas se describen a continuación:
Dependencia
Es una relación semántica entre dos elementos en la cual un cambio a un elemento (el elemento independiente) puede afectar a la semántica del otro elemento (elemento dependiente). Se representa como una línea discontinua (figura 14), posiblemente dirigida, que a veces incluye una etiqueta.
Asociación
Es una relación estructural que describe un conjunto de enlaces, los cuales son conexiones entre objetos. La agregación es un tipo especial de asociación y representa una relación estructural entre un todo y sus partes. La asociación se representa con una línea continua, posiblemente dirigida, que a veces incluye una etiqueta. A menudo se incluyen otros adornos para indicar la multiplicidad y roles de los objetos involucrados, como podemos ver en la figura siguiente
Generalización
Es una relación de especialización / generalización en la cual los objetos del elemento especializado (el hijo) pueden sustituir a los objetos del elemento general (el padre). De esta forma, el hijo comparte la estructura y el comportamiento del padre. Gráficamente, la generalización se representa con una línea con punta de flecha vacía.
Realización
Es una relación semántica entre clasificadores, donde un clasificador especifica un contrato que otro clasificador garantiza que cumplirá. Se pueden encontrar relaciones de realización en dos sitios: entre interfaces y las clases y componentes que las realizan, y entre los casos de uso y las colaboraciones que los realizan. La realización se representa como una mezcla entre la generalización y la dependencia, esto es, una línea discontinua con una punta de flecha vacía.