1
Í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
2
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.
3
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.
4
• 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.
5
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.
6
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).
Una clase contiene los atributos y las operaciones sobre esos atributos que hacen que una clase tenga la entidad que se desea.
7
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
8
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.
9
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:
10
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.
11
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.
12
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”).
13
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?
14
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
15
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.
16
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
interprete o un compilador) a un lenguaje inteligible para los ordenadores.
17
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
18
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
la falta de previsión o al haber abordado los problemas muy a la ligera.
19
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:
20
• 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 será capaz de responder a dicho comportamiento.
21
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.
22
¿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.
23
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.
24
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
Motos::acelerar(){
25
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
26
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.
Por ejemplo, la clase mamífero contendrá las características comunes a todos los
mamíferos. A partir de dicha clase podemos crear tantos objetos mamíferos como queramos,
27
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
28
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.
29
1.7 Métricas de diseño.
Se aplica las métricas para valorar la calidad de los productos de ingeniería o los sistemas
que se construyen.
Proporcionan una manera sistemática de valorar la calidad basándose en un conjunto de
reglas claramente definidas.
Se aplican a todo el ciclo de vida permitiendo descubrir y corregir problemas potenciales.
Descripción de las métricas
Cantidad de clases desarrolladas
Aspecto a medir: Tamaño
Objetivo: definir una medida que permita dimensionar el producto.
Comentario: se usa como marco de referencia de otras métricas. Por ejemplo valorar la
cantidad de jerarquías de herencia con respecto al total de clases.
Forma de cálculo: se cuentan las clases declaradas dentro del alcance de medición.
• Clases a considerar: Toda clase desarrollada, extendida, usada, que es instanciada en el sistema, clases no instanciadas pero definidas en el sistema.
• Clases a no considerar: Clases cuyos padres son externos al sistema, usada para definir
una nueva clase, por extensión. Tipos primitivos de datos, como ser Integer, Carácter, etc.
Antecedente de la métrica: Ha sido planteada por Lorenz-Kidd [1994].
Cantidad de clases externas especializadas
Aspecto a medir: Reutilización
Objetivo: Determinar la cantidad de clases externas al sistema que son reutilizadas por
medio del mecanismo de herencia.
Comentario: se identifican las clases externas que el propio sistema está especializando,
reutilizando. Es significativo mostrar la cantidad de clases reutilizadas por librería de clases.
Forma de cálculo: se cuentan las clases externas que tienen una clase hija que pertenece al
alcance de medición.
• Clases a considerar: Toda clase externa al alcance de medición que es extendida en el
producto.
• Clases a no considerar: Tipos primitivos de datos, como ser Integer, Carácter, etc. Clases
que pertenecen al alcance de medición y tienen subclases que pertenecen al alcance de
medición. Clases que pertenecen al alcance de medición y son padres de clases externas.
Antecedente de la métrica: Lorenz [1994] plantea “Número de veces que una clase es
30
reusada”. Mide el número de referencias a una clase, las veces que una aplicación usa una
clase.
Promedio de statements por método de una clase
Aspecto a medir: Granularidad de métodos.
Objetivo: Determinar si existe una cantidad excesiva de statements en los métodos que
componen una clase.
Comentario: Se considera que una cantidad excesiva de statements en un método pueden
ser la consecuencia de una inadecuada factorización de los métodos.
Forma de cálculo: Sumatoria de la cantidad de statements en todos los métodos de la clase,
divido el número total de métodos.
• Clases a considerar: Toda clase desarrollada, perteneciente al sistema a evaluar.
• Clases a no considerar: Clases externas al sistema a medir, es decir clases importadas o
extendidas.
Antecedente de la métrica: Ha sido planteada por Lorenz [1994] . El gráfico que ejemplifica
la métrica presenta valores obtenido de la medición de un proyecto en Smalltalk. No brinda
suficiente información para evaluar los datos que muestra sobre las mediciones realizadas.
Cantidad de métodos de interfase por clase
Aspecto a medir: Responsabilidad pública.
Objetivo: Medir los contratos asumidos por una clase.
Comentario: Esta métrica permite detectar clases que posean un exceso de responsabilidad
pública o carencia de la misma. Una visualización rápida por medio de la cantidad de métodos
públicos nos permite apreciar la distribución de responsabilidades del sistema y focalizar la
atención en la clase que presenta valores llamativos.
Forma de cálculo: Se cuentan los métodos de interfase que tiene la clase.
• Métodos a considerar: Se cuentan los métodos de interfase propios de la clase y métodos
de interfase heredados de la clase padre.
• Métodos a no considerar: Los métodos que no pertenecen a la interfase de la clase.
• Clases a considerar: Toda clase declarada dentro del alcance de medición.
• Clases a no considerar: Clases externas al sistema a medir, clases importadas o
extendidas.
Antecedente de la métrica: Ha sido planteada por Lorenz [1994]. No presenta valores
experimentales.
Es interesante el comentario de Meyer [1998] al respecto:
31
"... en el contexto de la orientación a objetos la noción de punto función, una medida de
funcionalidad ampliamente aceptada, puede ser substituida por una medida mucho más
objetiva: el número de operaciones exportadas de las clases relevantes, que no requiere
ninguna decisión humana, ya que pueden ser medidas trivialmente por una herramienta de
análisis simple."
Cantidad de colaboradores por clase
Aspecto a medir: Colaboración - Agregación.
Objetivo: Medir el uso de agregación en el diseño del sistema.
Comentarios: La agregación de una clase se determina por el número de colaboradores
habituales que la clase utiliza. La presencia de dichos colaboradores define una asociación de
agregación o conocimiento entre la clase dueña y las clases referenciadas31.
Forma de cálculo: se cuentan los objetos colaboradores declarados estáticamente en la
definición de la clase32 y que pertenecen a tipos de datos distintos a la clase considerada.
• Objetos a considerar: Objetos definidos en la clase a través de una variable de instancia a
la cual se le solicita colaboración, por medio del envío de un mensaje en algún método de la
clase. Asimismo, se deben contabilizar los objetos declarados en la superclase, si la hubiera, e
invocados en la clase corriente. Los objetos cuyas clases están declaradas dentro del alcance
de medición (internos) y los objetos externos.
• Objetos a no considerar: Estos objetos pueden variar dependiendo del lenguaje de
programación implementado. Sin embargo, a continuación se detallan algunos objetos que no
deberían ser considerados colaboradores, porque están implícitos en la mayoría de las
implementaciones. Tipos de datos primitivos, objetos que representan a tipos primitivos de
datos y objetos comunes.
Ej. Integer, String, Byte, Char, int, char, short, flota, etc.
• Clases a considerar: Toda clase desarrollada, perteneciente al sistema a evaluar.
• Clases a no considerar: Clases externas al sistema a medir, es decir clases importadas
o extendidas.
Antecedente de la métrica:
Lorenz [1994] plantea “Número de variables de instancia en una clase” donde cuenta la
cantidad de variables de instancias públicas, privadas y protegidas. Plantea valores de
referencia para “Número medio de variables de instancia por clase”.
Brian [1999], cita en un extenso y profundo artículo sobre medidas de acoplamiento varias
métricas para atributos de clase (DAC Data Abstraction Coupling, DAC´, IFCAIC, ACAIC,
OCAIC, FCAEC, DCAEC, OCAEC), donde el atributo tiene el tipo de otra clase. Todas tienen
una validación empírica y la mayoría teórica.
32
Cantidad de colaboradores externos por clase
Aspecto a medir: Reutilización - Agregación
Objetivo: determinar el uso de colaboradores externos en el sistema. Esta métrica completa
el planteo de la medición de reutilización.
Comentarios: la agregación realizada con clases externas al sistema es otra forma posible
de reutilizar clases.
Forma de cálculo: se cuentan los objetos colaboradores externos declarados estáticamente
en la definición de la clase y que pertenecen a tipos de datos distintos a la clase considerada.
• Objetos a considerar: Los objetos cuyas clases no están declaradas dentro del alcance de
medición (externos). Objetos definidos en la clase a través de una variable de instancia a la
cual se le solicita colaboración, por medio del envío de un mensaje en algún método de la
clase. Asimismo, se deben contabilizar los objetos declarados en la superclase, si la hubiera, e
invocados en la clase corriente.
• Objetos a no considerar: Objetos internos. Estos objetos pueden variar dependiendo del
lenguaje de programación implementado. Sin embargo, a continuación se detallan algunos
objetos que no deberían ser considerados colaboradores, porque están implícitos en la mayoría
de las implementaciones. Tipos de datos primitivos, objetos que representan a tipos primitivos
de datos y objetos comunes.
Ej. Integer, String, Byte, Char, int, char, short, flota, etc.
• Clases a considerar: Toda clase desarrollada, perteneciente al sistema a evaluar.
• Clases a no considerar: Clases externas al sistema a medir, es decir clases importadas o
extendidas.
Antecedente de la métrica:
Lorenz [1994] plantea “Número de variables de instancia en una clase” donde cuenta la
cantidad de variables de instancias públicas, privadas y protegidas. Plantea valores de
referencia para “Número promedio de variables de instancia por clase” .
Brian [1999], cita en un extenso y profundo artículo sobre medidas de acoplamiento varias
métricas para atributos de clase (DAC Data Abstraction Coupling, DAC´, IFCAIC, ACAIC,
OCAIC, FCAEC, DCAEC, OCAEC), donde el atributo tiene el tipo de otra clase. Todas tienen
una validación empírica y la mayoría teórica.
Cantidad de Mensajes Polimórficos
Aspecto a medir: Polimorfismo
Objetivo: medir el uso de polimorfismo en la invocación de los métodos.
33
Comentarios: Se considera mensajes enviados a tipos internos y externos al alcance de
medición.
Forma de Cálculo: Se cuentan los mensajes polimórficos enviados a tipos internos y
externos al alcance de medición.
Mensaje a considerar: Un mensaje es contabilizado como mensaje polimórfico en el código
fuente si se cumplen las siguientes condiciones:
• La firma33 del mensaje debe estar definido en la clase raíz de la jerarquía de clases.
• El mensaje debe ser aplicado sobre un objeto cuyo tipo pertenezca a la jerarquía de
clases.
• La jerarquía de clases, deben tener dos o más subclases.
El tipo correspondiente a la declaración del objeto (que recibe el mensaje) no puede
pertenecer, a ninguno de los tipos que están en el último nivel, en la jerarquía de herencia.34
Mensaje a no considerar: si no cumple algunas de las características establecidas
anteriormente.
• Tipos a considerar: las tipos internos o externos al alcance de medición.
• Tipos a no considerar: clases que son hojas de la jerarquía de clases a la que
pertenecen, clase padre abstracto que tiene una sola hija concreta.
Antecedente de la métrica:
Benlarbi y Melo (posterior al [1997]) calculan las medidas del polimorfismo de una forma
estática, analizando las interfases de las clases en C++. "Definimos las medidas de dos
aspectos principales de comportamiento polimorfo proporcionado por C ++: el polimorfismo
basado en decisiones de unión en tiempo de compilación (por ejemplo sobrecargando
funciones) y el polimorfismo basado en decisiones atadas durante el tiempo de ejecución (por
ejemplo funciones virtuales)".
Definen las siguientes tablas de métricas.
Llegan a la conclusión que la aplicación del polimorfismo puede incrementar la probabilidad
de fallas en OO software. Se entiende que este resultado inesperado se debe a que en realidad
están midiendo el mecanismo interno de la jerarquía de clases (sobrecarga y sobre-escritura)
que usa el lenguaje para lograr un comportamiento polimórfico. No mide en sí mismo el
34
polimorfismo. Están midiendo /analizando el planteo de la interfase de la clase; el uso
potencial –no actual- del polimorfismo. Resultado que es esperado, y coincide con otras
mediciones, si se entiende que son conclusiones aplicables a el planteo de herencia.
Es frecuente (Lorenz [1994], Briand [1999]) la medición de la invocación de los métodos
para medir acoplamiento, no así la consideración de los mensajes polimórficos.
Mediciones relacionadas al uso de herencia
Se describe un conjunto de métricas que permiten destacar aspectos claves en la aplicación
de la herencia. Como se reflejó en el capítulo anterior el mecanismo de herencia tiene ventajas
y dificultades. Se realiza una definición cuidadosa de métricas orientadas a definir alarmas
sobre aspectos tales como sobre-escritura, niveles de especialización, uso de clases abstractas,
uso de herencia de subtipo. Se trató de focalizar las mediciones en los aspectos críticos.
El análisis de los valores en su conjunto lleva a resaltar aspectos que deben ser analizados
con más profundidad, para estar en condiciones de dar un juicio sobre el uso de herencia en el
sistema estudiado.
Cantidad de jerarquías de clases desarrolladas
Aspecto a medir: Herencia
Objetivo: medir el uso de herencia.
Comentarios: se define esta métrica como valor de referencia, útil para la valoración de los
resultados obtenidos en otras métricas. Por ejemplo, valores obtenidos en la medición de
cantidad de mensajes polimórficos.
Forma de Cálculo: se cuentan las jerarquías de clases propias implementadas en el sistema.
• Jerarquías a considerar: jerarquías donde la raíz pertenece al alcance de medición
• Jerarquías a no considerar: jerarquías donde la raíz no pertenece al alcance de medición
• Clases a considerar: Toda clase, que pertenezca a una jerarquía de clases declarada
dentro del alcance de medición.
• Clases a no considerar: Clases internas al alcance de medición, que heredan de una
“superclase”, que esté fuera del alcance de medición.
Antecedente de la métrica: no se encontraron antecedentes. Se estima que la falta de
mediciones que plantean marcos de referencia, como es esta métrica, pueda ser la causa de la
dificultad que se percibe en la bibliografía para interpretar los valores reportados.
Cantidad de jerarquías extendidas de clases externas
Aspecto a medir: Herencia
Objetivo: medir el uso de herencia.
Comentarios: puede suceder que algunas de las jerarquías que sean principales a la
aplicación tengan una raíz externa.
35
Forma de Cálculo: se cuentan las jerarquías de clases, que tengan una clase padre externa,
y que al menos tenga una clase hija que pertenezca al alcance de medición, que a su vez sea
padre de una clase que pertenezca al alcance de medición.
• Jerarquías a considerar: jerarquías donde la raíz no pertenece al alcance de medición
• Jerarquías a no considerar: jerarquías donde la raíz pertenece al alcance de medición.
Jerarquía donde la raíz no pertenece al alcance de medición y tiene un padre externo, que
tiene una hija perteneciente al alcance de medición que no es padre de una clase que
pertenece al alcance de medición.
Antecedente de la métrica: no se encontraron antecedentes.
Cantidad de niveles de especialización por jerarquía de clases
Aspecto a medir: Herencia.
Objetivo: Determinar la especialización alcanzada por la clase “raíz” en cada jerarquía de
clases.
Comentario: En el capítulo anterior se citan trabajos que reportan dificultades en los niveles
bajos de especialización. Se plantea esta métrica para focalizar la atención en jerarquías
complejas.
Forma de cálculo: Primero se determina la rama de subclases con mayor profundidad. La
cantidad de niveles de la jerarquía es igual a la cantidad de clases de la rama de mayor
profundidad35 menos una clase.
• Jerarquías a considerar: toda jerarquía donde la clase raíz pertenezca al alcance de
medición.
• Jerarquías a no considerar: familias de clases externas al sistema, ramas de familias de
clases externas, clases que pertenecen a la librería del lenguaje utilizado.
Antecedente de la métrica: Henderson-Sellers [1996] planteas DIT Depth of inheritance
Tree, Lorenz-Kidd [1994], Class hierarchy nesting level, similares a la planteada.
Cantidad de niveles agregados a jerarquías donde la raíz es externa
Aspecto a medir: Herencia.
Objetivo: Determinar la especialización alcanzada de una clase externa en el alcance de
medición.
Comentario: En el capítulo anterior se citan trabajos que reportan dificultades en los niveles
bajos de especialización. Se plantea esta métrica para apuntar la atención a jerarquías
complejas.
36
Forma de cálculo: A partir de la clase externa al alcance de medición, que es padre de al
menos una clase que pertenece al alcance de medición, determinar la rama de subclases que
pertenece al alcance de medición con mayor profundidad (la cantidad de niveles se cuentan a
partir del padre externo). Para esta rama, la cantidad de niveles agregados es igual a la
cantidad de clases de la rama de mayor profundidad menos una clase.
• Jerarquías a considerar: toda jerarquía donde la clase raíz es externa, donde existe un
padre externo, y en el alcance de medición la clase hija es padre de una clase que
pertenece al alcance de medición.
• Jerarquías a no considerar: jerarquías donde existe un padre externo, y en el alcance
de medición la clase hija no tiene hijos.
Antecedente de la métrica: no se encontraron.
Cantidad de Clases Raíz no Abstractas
Aspecto a medir: Herencia.
Objetivo: identificar las jerarquías que no tienen una clase raíz abstracta.
Comentario: Declarar la clase raíz como clase abstracta, implica que cada subclase debe
proveer una implementación completa de los métodos definidos en la clase raíz. De esta forma
se asegura el uso de polimorfismo. Gamma et al. [1995] dice que facilita “programar para una
interfase, y no para una implementación”.
Liskov asegura el uso de polimorfismo, si se programa para el tipo abstracto.
Forma de cálculo: se cuentan las clases raíz que no son abstractas.
• Clases a considerar: Clases que pertenecen al alcance de medición, y son raíz de una
jerarquía, que pertenece al alcance de medición.
• Clases que no deben considerarse: Clases que pertenezcan a la librería del lenguaje de
programación. Cualquier clase externa que tenga subclases que pertenecen al alcance de
medición.
Antecedente de la métrica: Lorenz-Kidd [1994] plantea “Número de clases abstractas”.
Afirma: "el número de clases abstractas es una indicación del uso exitoso de la herencia y el
esfuerzo que se ha hecho al buscar conceptos generales en el dominio de problema”. Gama
[1995] afirma "Cuando la herencia es usada con cuidadosamente (algunos dirán
correctamente), todas las clases derivadas de una clase abstracta compartirán su interfase”.
Porcentaje de Métodos Reemplazados en una Jerarquía
Aspecto a medir: Herencia.
Objetivo: determinar si la cantidad de métodos sobrescritos es excesiva.
37
Comentarios: el porcentaje de métodos heredados que son remplazados en cada subclase
de una jerarquía de clases propia, da una idea del uso o abuso de la sobre-escritura. El
problema principal de la redefinición de métodos (overriden) se centra en aquellos casos donde
la firma se mantiene, pero la implementación es remplazada completamente. Como
consecuencia, se rehace el comportamiento del método y se descarta completamente el
comportamiento heredado de la clase padre. La jerarquía que tiene un porcentaje alto de
métodos redefinidos detiene el mecanismo de herencia, que la clase padre aporta en la
subclase.
Forma de cálculo: PMRJ = (CMR / CMH) * 100.
CMR = Cantidad de métodos remplazados.
CMH = Cantidad de métodos heredados.
Clases a considerar: subclases de una jerarquía de herencia definida en el alcance de
medición.
Clases a no considerar: Clases externas a la jerarquía de herencia. Subclases, que
pertenecen a la jerarquía de herencia y que hereden de una clase definida abstracta.
Métodos a considerar: Métodos heredados donde la signatura es igual a la original y la
implementación es totalmente re-escrita o dejada en blanco.
Métodos a no considerar: Métodos heredados que la signatura es igual a la original y la
implementación es extendida o realizada.
Antecedente de la métrica:
Li et al. [1998ª] plantea “Percentage of redefined methods in a class (PRMC), Percentage of
redefined methods per level within a hierarchy (PRMH)”. Mide los métodos redefinidos:
reemplazados, extendidos o realizados. El problema se presenta en el reemplazo sucesivo de
métodos.
Lorenz et al. [1994] plantea “Average number of methods overridden per class”, como un
cociente de “Total number overridden methods” sobre “Total number of classes”. La forma en
que cuenta los métodos sobrescritos es similar al presenta trabajo. Se diferencian en la forma
en que esta planteado el cociente.
Porcentaje de Métodos Reemplazados en Jerarquías donde la raíz es externa
Aspecto a medir: Herencia.
Objetivo: determinar si se esta usando bien el mecanismo de herencia cuando se esta
reusando clases.
Comentarios: no tiene sentido reutilizar una clase a la cual se le sobrescriben un alto
porcentaje de métodos.
38
Forma de cálculo: PMRJ = (CMR / CMH) * 100.
CMR = Cantidad de métodos remplazados.
CMH = Cantidad de métodos heredados.
Clases a considerar: subclases de una jerarquía de herencia donde la raíz es externa y tiene
una clase hija en el alcance de medición que a su vez tiene una hija.
Clases a no considerar: subclases de una jerarquía de herencia donde la raíz es externo y
tiene una clase hija en el alcance de medición que no tiene hijos.
Subclases, que pertenecen a la jerarquía de herencia de raíz externo y que hereden de una
clase definida abstracta.
Métodos a considerar: Métodos heredados donde la signatura es igual a la original y la
implementación es totalmente re-escrita o dejada en blanco.
Métodos a no considerar: Métodos heredados que la signatura es igual a la original y la
implementación es extendida o realizada.
Antecedente de la métrica:
Li et al. [1998ª] plantea “Percentage of redefined methods in a class (PRMC), percentage of
redefined methods per level within a hierarchy (PRMH)”. Mide los métodos redefinidos:
reemplazados, extendidos o realizados. El problema se presenta en la reemplazo sucesivo de
métodos.
Lorenz et al. [1994] plantea “Average number of methods overridden per class”, como un
cociente de “Total number overridden methods” sobre “Total number of classes”. La forma en
que cuenta los métodos sobrescritos es similar al presenta trabajo. Se diferencian en la forma
en que esta planteado el cociente.
Cantidad de Jerarquías que Usan Herencia de Subtipo
Aspecto a medir: Herencia
Objetivo: Determinar si las jerarquías de clases diseñadas contemplan la herencia de
subtipo.
Comentarios: las subclases deben cumplir el principio de conformidad de tipo enunciado en
el capítulo anterior.
Forma de cálculo: Número de jerarquías de clases que componen el sistema y que respetan
la herencia de subtipo.
• Jerarquías a considerar: Toda jerarquía, que pertenezca a una jerarquía de clases
propias al sistema, partiendo de una raíz propia.
Top Related