You are on page 1of 74

Universidad Autnoma de Puebla

Facultad de Ciencias de la Computacin

Ingeniera de Software

Principios del Diseo Orientado a Objetos

Prof. Dr. Manuel Martn Ortz

Puebla, Mxico Enero de 2003

Indice
INTRODUCCIN 4

1.

ENCAPSULACIN Y DEPENDENCIA ESTRUCTURA DE LA ENCAPSULACIN. NIVELES DE ENCAPSULACIN CRITERIOS DE DISEO Y NIVELES DE ENCAPSULACIN INTERDEPENDENCIA (CONNASCENCE). TIPOS DE INTERDEPENDENCIA CONTRA - INTERDEPENDENCIA (CONTRANASCENCE) = INDEPENDENCIA. FRONTERAS DE LA INTERDEPENDENCIA Y LA ENCAPSULACIN. INTERDEPENDENCIA Y MANTENIBILIDAD. ABUSOS DE INTERDEPENDENCIA EN SISTEMAS ORIENTADOS A OBJETOS. RECOMENDACIN FINAL.

5 5 5 7 9 9 13 15 16 18 19 20 20 21 21 22 23 23 26 26 28 29 29 30 32 33 35 35 38 40 41 44

1.1. 1.1.1. 1.1.2. 1.2. 1.2.1. 1.2.2. 1.3. 1.4. 1.5. 1.6. 2.

D O M I N I O S, E N C U M B R A M I E N T O Y C O H E S I N.

2.1. DOMINIOS DE UNA CLASE DE OBJETOS. 2.1.1. EL DOMINIO DE BASE 2.1.2. EL DOMINIO DE LA ARQUITECTURA. 2.1.3. EL DOMINIO DE LOS NEGOCIOS. 2.1.4. EL DOMINIO DE APLICACIN. 2.1.5. LA FUENTE DE LAS CLASES EN CADA DOMINIO. 2.2. ENCUMBRAMIENTO (ENCUMBRANCE). 2.2.1. QU ES EL ENCUMBRAMIENTO? 2.2.2. EL USO DEL ENCUMBRAMIENTO. 2.2.3. LA LEY DE DEMETRIO. 2.3. COHESIN DE UNA CLASE. 2.3.1. COHESIN DE MEZCLA DE INSTANCIA 2.3.2. COHESIN DE MEZCLA DE DOMINIO. 2.3.3. COHESIN DE MEZCLA DE ROLE. 3. ESPACIO DE ESTADOS Y COMPORTAMIENTO

3.1 ESPACIO DE ESTADOS Y COMPORTAMIENTO DE UNA CLASE. 3.2 ESPACIO DE ESTADOS DE UNA SUBCLASE. 3.3. EL COMPORTAMIENTO DE UNA SUBCLASE. 3.4. LOS INVARIANTES DE CLASE COMO UNA RESTRICCIN EN EL ESPACIO DE ESTADOS. 3.5. PRECONDICIONES Y POSTCONDICIONES.

DISEO

ORIENTADO

OBJETOS

4. CONFORMIDAD DE TIPOS Y COMPORTAMIENTO CERRADO. 4.1. CLASES VS. TIPOS. 4.2 EL PRINCIPIO DE CONFORMIDAD. 4.2.1. LOS PRINCIPIOS DE CONTRAVARIANZA Y COVARIANZA 4.2.2. ILUSTRACIN DE LA CONTRAVARIANZA Y COVARIANZA. 4.2.3. ILUSTRACIN DE CONTRAVARIANZA Y COVARIANZA. 4.2.4. RESUMEN DE LOS REQUERIMIENTOS PARA LA CONFORMIDAD DE TIPOS. 4.3. EL PRINCIPIO DE COMPORTAMIENTO CERRADO. 5. LOS PELIGROS DE LA HERENCIA Y EL POLIMORFISMO. 5.1. ABUSOS DE LA HERENCIA 5.1.1. AGREGADOS ERRNEOS. 5.1.2. JERARQUA INVERTIDA. 5.1.3. CONFUNDIENDO CLASES E INSTANCIAS. 5.1.4. MAL USO DE ES UN. 5.2. EL PELIGRO DEL POLIMORFISMO 5.2.1. POLIMORFISMO EN LAS OPERACIONES. 5.2.2. POLIMORFISMO DE VARIABLES. 5.2.3. POLIMORFISMO EN LOS MENSAJES 5.2.4. POLIMORFISMO Y GENERICIDAD. BIBLIOGRAFA

47 47 49 50 51 54 55 56 60 60 60 61 62 65 68 68 70 71 72 74

DISEO

ORIENTADO

OBJETOS

Introduccin
Este material se ha desarrollado como un complemento para el curso de Diseo Orientado a Objetos, en el se cubre varios aspectos tericos y prcticos. Se puede considerar el material como una seleccin de diversos materiales de estudio relativos al paradigma de orientacin a objetos que se han generado en la ltima dcada. En particular se han tomado muchos elementos y partes del libro Fundamentals Object-Oriented Design in UML [1], l cual es un manual de la serie Object Technology Series de la corporacin Booch - Jacobson Rumbaugh. Espero sea de utilidad para las personas que inician a estudiar o quieren revisar lo alusivo al diseo orientado a objetos.

Dedicatoria
Quiero dedicar este material a todos los compaeros y compaeras que con mucho esfuerzo han logrado culminar sus estudios y a pesar de las condiciones adversas que muchas veces la vida nos impone, y han sabido encontrar fuerzas donde muchos no las ven y alegra en los momentos de desnimo.

DISEO

ORIENTADO

OBJETOS

1. E n c a p s u l a c i n y D e p e n d e n c i a
Este captulo tratar las dos propiedades fundamentales de la estructura de los sistemas orientados a objetos: la encapsulacin y la dependencia. Si bien estas dos propiedades de la estructura del software estaban presentes en los sistemas tradicionales, la orientacin a objetos con sus nuevos paradigmas y complejidades, eleva su significado de manera considerable. La comprensin y mantenimiento del software orientado a objetos descansa en esencia sobre la encapsulacin y la dependencia. El tema central de ste captulo es la discusin de los conceptos antes mencionado y el cmo una buena combinacin de ellos ayuda a alcanzar un buen diseo orientado a objetos.

1.1.

Estructura de la encapsulacin.

Como es conocido, el software emergi los aos 40s del siglo XX como una coleccin de criaturas unicelulares conocidas como instrucciones en lenguaje de mquina. Posteriormente, stas envolvieron a otras criaturas unicelulares conocidas como lneas en cdigo ensamblador. Pero una estructura de mayor tamao apareci pronto, dentro de la cual muchas lneas de cdigo fueron reunidas en unidades procedurales con un solo nombre. Esta fue la subrutina o procedimiento. Un ejemplo de stas ltimas que alcanz un lugar en el Saln de la Fama es la funcin sqrt, que como sabemos calcula la raz cuadrada de un entero o real. La subrutina introdujo la encapsulacin al software. Fue la encapsulacin de lneas de cdigo en una estructura un nivel superior que el cdigo mismo. La subrutina en ese momento represent la maravilla del momento en el ambiente del software. Como es lgico, sta redujo los requerimientos de memoria agrupando docenas de instrucciones, y por otro lado ayud a los programadores, ofrecindoles un trmino simple que hace referencia a docenas de lneas de cdigo. Uno no se debe sorprender que con el advenimiento de la subrutina se produjera un gran entusiasmo entre los programadores y se convirti en una unidad de trabajo de todos los das.

1.1.1.

Niveles de encapsulacin

Se define el nivel de encapsulacin de la subrutina como nivel-1. El cdigo directo o rawel cero, que obviamente no contiene encapsulacin se refiere como nivel-0. La orientacin a objetos introduce un nivel ms avanzado de encapsulacin. La clase (u objeto) es una unin de subrutinas (conocidas como operaciones) en un nivel estructural todava mayor. Ya que las operaciones, que son unidades procedurales, se encuentran en el nivel-1 de encapsulacin, la clase se coloca en el nivel-2 de encapsulacin. (Fig. 1.1)

DISEO

ORIENTADO

OBJETOS

La analoga entre organismos y estructuras de software, pensada con mayor profundidad, no es completamente gratuita. Los mdulos procedurales, tales como aquellos que se encuentran en el diseo estructurado, no satisfacan la reusabilidad que la gente esperaba. Las clases autnomas se comportan mejor que los procedimientos. Las clases estn mas cerca de los rganos biolgicos por su capacidad de ser transplantados de aplicacin en aplicacin (de software evidentemente). Y las componentes lo hacen mejor todava que las clases. Una pregunta que podemos hacernos es: Y porqu detenerse en el nivel-2 de encapsulacin?. Nosotros ya La estructura de clase u objeto Lneas de cdigo Mdulo Procedural

Nivel-0

Nivel-1

Nivel-2

Figura 1.1. Niveles de encapsulacin que presentan las construcciones de software hemos visto estructuras de nivel-3 y nivel-4, en los cuales las clases se agrupan en estructuras de nivel an superior, stos corresponden a los paquetes y componentes. Estos se discutirn en captulos posteriores con mayor detalle. Fuera del nivel-3 y estructuras superiores, solo algunas clases o parte de sus interfaces se hacen visibles, a stas subestructuras se les conoce como parte pblica. Existe un tipo de clase llamada clase de negocios, sta se asocia en muchos casos con una organizacin grande estructura con el enfoque de objetos, stas clases se agrupan de manera horizontal en estructuras de nivel3 hacindose una correspondencia con las reas. Por ejemplo una aerolnea puede tener un rea relacionada con el pasajero, otra para los aeropuertos, otra para el personal y otra para los vuelos. As la clase relacionada con el programa de pasajeros frecuentes no tendra mucho que ver con la clase relativa a la lista de vuelos, las dos clases pueden ser encapsuladas en dos paquetes diferentes de nivel-3.

DISEO

ORIENTADO

OBJETOS

Las estructuras de nivel-3 pueden tambin ser agrupadas de manera vertical. Por ejemplo, las clases que operan juntas para implementar la poltica para ActualizarPasajeroFrecuente puede incluir: pasajero, Reservacin, ConfiguracionDeAsientosDeVuelo, Asiento, as como clases de menor importancia como: PrioridadDeAtencion, Fecha, Hora y dems.

1.1.2.

Criterios de diseo y niveles de encapsulacin

En la tabla siguiente (Tabla 1.1.) se resumen algunos criterios tradicionales del diseo estructurado en trminos de los niveles de encapsulacin. sta muestra que criterio se aplica a cada par de niveles de encapsulacin. Tabla 1.1. Criterios de diseo estructurado(nivel-1) que gobiernan las interelaciones entre los elementos de cada par de niveles de encapsulacin.
Para construccin de nivel-0 Desde construccin de nivel-0 (lnea de cdigo) construccin de nivel-1 (procedimiento) (lnea de cdigo) Programacin Estructurada Cohesin Acoplamiento Construccin de nivel-1 (procedimiento) fan-out

Por ejemplo, la cohesin es una medida clsica de la calidad de las relaciones entre un procedimiento (un constructor de nivel-1) y las lneas de cdigo ( una construccin de nivel-0) dentro de un procedimiento. Los principios de la programacin estructurada definen las relaciones entre una lnea de cdigo y otras lneas de cdigo dentro del mismo procedimiento. El fan-out, la cohesin y el acoplamiento son trminos del diseo estructurado [2,3]. A continuacin se hace una breve recapitulacin: Fan-out. Es una medida del nmero de referencias a otros procedimientos por lneas de cdigo dentro de un procedimiento dado. Cohesin. Es una medida del inconveniente simple que se presentan las lneas de cdigo dentro de un procedimiento dado para cumplir el propsito de ese procedimiento. Acoplamiento. Es una medida del nmero y la fuerza de las conexiones entre procedimientos.

DISEO

ORIENTADO

OBJETOS

La siguiente tabla (Tabla 1.2) es una extensin de la tabla anterior e incluye la encapsulacin de nivel-2. Puede notarse que las relaciones de los niveles bsicos(1 y 2) se mantienen prcticamente iguales, el nivel-2 de encapsulacin nos ofrece 5 relaciones a nominar. La cohesin entre clases es un anlogo obvio a la cohesin de un procedimiento, pero es un nivel de encapsulacin mayor. Esto demarca el inconveniente simple de un conjunto de operaciones (y atributos) al alcanzar el propsito de las clases. El acoplamiento entre clases es una medida del nmero y fuerza de las conexiones entre clases. Aunque los otros elementos (Tabla 1.2) no tienen nombre, es posible drselos de manera contextual. Esto nos lleva a nueve nombres, si se incluyese el nivel-3 de encapsulacin, la tabla tendra 16 elementos; estos pueden encontrarse con un poco de trabajo en la Literatura relacionada con la programacin Orientada a Objetos. Tabla 1.2. Extensin de la Tabla 1.1 que incluye el nivel-2 de encapsulacin
Para construccin de nivel-0 Desde construccin nivel-0 (lnea de cdigo) construccin nivel-1 (procedimiento) construccin nivel-2 (clase) de (lnea de cdigo) de Programacin Estructurada de Cohesin Acoplamiento construccin de nivel-1 (procedimiento) mensaje fan-out construccin de nivel-2 (clase)

____

____
Cohesin de clase Acoplamiento de clase

____

Ms con las definiciones dadas debe ser suficiente. Cuando el nmero de partculas elementales que la fsica estalla en cantidad, los fsicos empiezan a buscar cuando sus partculas son realmente fundamentales o se derivan de otras. De manera similar, cuando el nmero de criterios de diseo fundamentales crece de manera explosiva, puede ser que uno deba buscar un criterio mas profundo detrs de ellos. Si uno puede encontrar y determinar ese criterio, entonces se puede aplicar a los elementos del software en todos los niveles de encapsulacin inclusive en el nivel-5, s acaso uno ha alcanzado tal estado.

DISEO

ORIENTADO

OBJETOS

1.2.

Interdependencia (Connascence).

La palabra connascence se deriva del latn y significa que han nacidos juntos. Una acepcin alternativa es que tienen destinos entrelazados en la vida. Dos elementos de software que son interdependientes nacen de cierta necesidad relacionada puede ser durante el anlisis de requerimientos, diseo o programacin y comparten el mismo destino por al menos una razn. A continuacin se hace una definicin de interdependencia en el sentido de la Ingeniera de Software: La interdependencia entre dos elementos de Software A y B significa 1. que se puede postular algn cambio sobre A que requerir que B sea modificado (o al menos revisado con cuidado) con el propsito de preservar la consistencia global, o 2. que se puede postular algn cambio que requerir que tanto A como B sean modificados al mismo tiempo con el propsito de preservar la consistencia global. En esta seccin se discutir una variedad de formas de interdependencia. Y un propsito es presentar el concepto como una manera general para evaluar las decisiones en el proceso del diseo orientado a objetos, incluyendo aquellos diseos que contengan encapsulacin de nivel-3 y nivel-4.

1.2.1.

Tipos de interdependencia

Iniciaremos con un ejemplo simple de interdependencia en un esquema no orientado a objetos. Tomemos cierto elemento de software A correspondiente a una lnea tradicional de cdigo en forma de declaracin int i; // lnea A

y un elemento B en forma de asignacin: i := 12; // lnea B

En ste contexto hay al menos dos ejemplos de interdependencia entre A y B. Por ejemplo, en la (improbable) situacin que A fuese cambiada de tipo a char i; entonces B deber ser cambiada tambin. A este fenmeno se le llama interdependencia de tipo. As tambin, si A fuese cambiada a int j ; Entonces B deber ser cambiada a j :=12 ;. Esta se denomina interdependencia de nombre. En el ejemplo anterior se dice que se tiene interdependencia explcita, la cual es fcilmente detectable mediante un buen editor de texto. En otro contexto la interdependencia puede ser implcita, por ejemplo en la siguiente rutina en ensamblador uno puede notar

DISEO

ORIENTADO

OBJETOS

X: JUMP Y+200 Y:CLEAR R1 CLEAR R2 // 200 bytes de cdigo especfico // Esta es la instruccin a donde se debe saltar desde X llamemos a esta lnea Z

Es claro que la construccin de la rutina hay 200 bytes entre las instrucciones CLEAR R1 y CLEAR R2. De manera precisa exactamente 200 bytes, ste caso se denomina interdependencia de posicin. Esta se produce en el marco que entre la dos inocentes instrucciones en Y y Z hay una liga muy fuerte debida al desagradable salto de la lnea X. De cualquier manera la necesidad del desplazamiento (offset) de exactamente 200 bytes no es aparente, ni visible dentro del cdigo despus de la lnea Y, el infortunio ser para quin inserte otra instruccin en la seccin de los 200 bytes, ya que, si al darle mantenimiento al programa se realiza la insercin en sta zona por parte de algn programador, la prxima vez que el sistema corra se producir un error de secuencia (crash) inmediatamente despus de que se ejecute Y. En general debemos entender que lo explcito o implcito de la interdependencia no necesariamente se dar en los cdigos con representacin binaria nicamente o al usar medidas absolutas. La interdependencia ms explcita es la que consume mayor tiempo y costo para ser detectada (excepto en los casos que este bien documentada en el lugar correcto). Las interdependencias que estn dispersas a lo largo de grandes distancias de texto en la especificacin de una biblioteca de clases u otra documentacin, tambin consumirn gran cantidad de tiempo y son difciles de descubrir. Se deben puntualizar algunas cosas: 1. Dos elementos de software no necesitan comunicarse uno con otro en cierto orden para ser interdependientes. ( Un ejemplo de esto es la interdependencia de posicin entre las lneas Y y Z en la anterior rutina en ensamblador). 2. Algunas formas de interdependencia son direccionales. Si un elemento A hace referencia a un elemento B explcitamente, entonces A y B sern interdependientes unidireccionalmente (la direccin es de A hacia B). Muchos ejemplos de interdependencia de nombre son direccionales, por ejemplo, la interdependencia de nombre introducida cuando una clase hereda de otra. Si el elemento B tambin hace referencia al elemento A explcitamente, entonces A y B se dice que hay una interdependencia bidireccional. 3. Algunas formas de interdependencia son nodireccionales. Los elementos A y B sern interdependientes nodireccionales si nunca uno hace referencia explcita al otro. Por ejemplo, A y B sern interdependientes si usan el mismo algoritmo, a pesar que nunca uno haga referencia al otro en general.

10

DISEO

ORIENTADO

OBJETOS

Los ejemplos anteriormente descritos caen en la categora de interdependencia esttica. Esto es interdependencias que se corresponden al cdigo de las clases que uno escribe, compila y liga. Esto es interdependencias que uno puede valorar y hallar dentro de la estructura lxica del cdigo desarrollado. A continuacin se realizar una revisin general (no completamente exhaustiva) de algunas variedades de interdependencia esttica.

Interdependencia de nombre
Un ejemplo de sta como se vio antes (lneas A y B), en el cual dos variables necesitaban tener el mismo nombre en cierto orden para hacer referencia a la misma cosa. Otro ejemplo es el siguiente: Una subclase que utiliza una variable heredada de su superclase debe obviamente usar el mismo nombre de la variable que defini la superclase. Si el nombre es cambiado en la implementacin de la superclase, entonces deber ser modificada tambin en la subclase si se desea conservar lo correcto de la construccin.

Interdependencia de tipo o clase


Tambin se vio la interdependencia de tipo en el ejemplo anterior donde se defini la variable de tipo int. Si a i se le asigna el valor de 12 en la lnea B, entonces i deber ser declarada de tipo int en la lnea A.

Interdependencia de convencin
Digamos que la clase NumeroDeCuenta tiene instancias en las cuales los valores positivos de ella, tal como 1234, corresponden a personas; los negativos, como 234, corresponden a empresas; y el 0000 (cero) a todos los departamentos internos. El cdigo para esta convencin podra expresarse de la forma if orden.NumeroDeCuenta > 0 then Entonces existe una interdependencia de convencin entre todos los elementos de software que hagan contacto con un nmero de cuenta. A menos que sta convencin relativa al significado de la propiedad NumeroDeCuenta este encapsulado, estos elementos pueden estar repartidos a travs del sistema. A este fenmeno tambin se le denomina interdependencia valor-significado, y es similar al acoplamiento hbrido en el diseo estructurado y ha causado muchos problemas de mantenimiento en los sistemas. Otro ejemplo es el siguiente: supongamos que cierta propiedad llamada direccion de la clase RV se puede representar de diferentes maneras, por ejemplo norte = 0 ; este = 1 ; norte = N ; este = E ; norte = 0 ; este = 90 ; sur = 2 ; sur = S ; sur = 180 ; oeste = 3 ; oeste = W ; oeste = 270 ;

11

DISEO

ORIENTADO

OBJETOS

Todo cliente (instancia) de RV que utilice el atributo estar expuesto a escoger una convencin para representar la propiedad direccion; esto creara una gran interdependencia de convencin. Entonces, es importante escoger una convencin apropiada (por ejemplo la tercera) para representar a direccion.

Interdependencia del algoritmo


La interdependencia del algoritmo es similar a la interdependencia de convencin. Por ejemplo; Un elemento de software inserta smbolos en una tabla de hash. Otro elemento busca por un smbolo en la misma tabla. Es claro que para este proceso ambos deben usar el mismo algoritmo para el hashing. Otro ejemplo es el de encriptar y desencriptar una cadena.

Interdependencia de posicin
La mayor parte del cdigo en las unidades procedurales tiene interdependencia de posicin: Para que dos lneas de cdigo sean ejecutadas en la secuencia correcta, ellas deben aparecer en la secuencia lxica correcta dentro del listado fuente. Hay muchas clases de interdependencia de posicin, incluyendo la secuencial ( las cosas deben aparecer en el orden correcto) y de adyacencia (las cosas deben estar una junto a la otra). Otro ejemplo de interdependencia de posicin corresponde a la dependencia de un mensaje entre los argumentos formales del emisor (del mensaje: sender) y los argumentos corrientes del destino (del mensaje: target). En la mayora de los lenguajes, uno debe colocar los argumentos en la misma secuencia en que se definieron los formales, es decir debe haber una correspondencia entre los prototipos o plantillas y los llamados concretos. La interdependencia dinmica es la interdependencia que est basada ene l patrn de ejecucin del cdigo a ejecutarse de los objetos ms bien que de las clases, para ser estrictos. ste tiene tambin una variedad de casos, a saber:

Interdependencia de ejecucin
La Interdependencia de ejecucin es el equivalente dinmico de la interdependencia de posicin. Este se presenta en varias formas, incluyendo la secuencial (debe llevarse a cabo en un orden dado) y la de adyacencia (debe llevarse a cabo sin intervencin). Hay varios ejemplos de ste tipo de interdependencia, incluyendo la inicializacin de una variable antes de usarla, cambiar o leer los valores de variables globales en la secuencia correcta, y la prueba y modificacin de los valores de los semforos.

Interdependencia de valor
La Interdependencia de valor normalmente involucra alguna restriccin aritmtica. Por ejemplo durante la ejecucin de un sistema, la propiedad ApuntadorBajo a un buffer circular no puede ser mayor que la propiedad ApuntadorAlto (bajo las reglas del mdulo aritmtico). As tambin, las cuatro esquinas de un rectngulo deben preservar cierta relacin geomtrica entre sus valores. Uno no puede mover una esquina nicamente y mantener un rectngulo correcto. La interdependencia de valor es notoria cuando dos Bases de Datos contienen informacin redundante (repetida), a pesar de que este en diferentes formatos. En sta situacin, el software basado en estructuras procedurales debe mantener un puente de consistencia entre la bases de datos, para garantizar que cualquier dato duplicado tenga idnticos valores en cada Base de Datos. El
12

DISEO

ORIENTADO

OBJETOS

mantenimiento de ste software, que esta probablemente realizando tareas pesadas de traduccin de formatos, puede ser incmodo y complejo.

Interdependencia de identidad
Un ejemplo de Interdependencia de identidad se presenta por una restriccin tpica en un sistema orientado a objetos: Dos objetos, U1 y U2, cada uno de los cuales contiene una variable que apunta a otro objeto (UX), deben apuntar todo el tiempo al mismo objeto. Esto es, si U1 apunta a UX, entonces U2 debe apuntar a UX. (Por ejemplo si el reporte de ventas a punta a la tabla ENERO, entonces el reporte de operaciones debe apuntar tambin a la tabla ENERO). En sta situacin U1 y U2 tienen interdependencia de identidad; ellos deben apuntar al mismo (estrictamente idntico) objeto. U1 UX U2
Figura 1.2. Un ejemplo de Interdependencia de Identidad.

1.2.2.

Contra - interdependencia (contranascence) = independencia.

Hasta ahora, se ha identificado de manera tcita la interdependencia con relacionado. Por ejemplo, dos lneas de cdigo tienen interdependencia de nombre cuando la variable en cada una de ellas debe tener el mismo nombre. De cualquier forma, la interdependencia existe tambin en casos donde la diferencia es importante.. Primero veamos un ejemplo simple. Observemos las dos declaraciones siguientes: int i; int j; Por consistencia, exactitud y para que el cdigo compile sin errores, los nombres de las variables, i y j, deben diferir uno del otro. Hay una interdependencia en el trabajo de codificacin implcito: S por alguna razn, queremos cambiar el nombre de la primera variable a j, entonces debemos tambin cambiar el nombre de la segunda de j a alguna otra cosa. Por tanto las dos declaraciones no son independientes. Eventualmente a sta clase de interdependencia se le llama interdependencia de diferencia o interdependencia negativa . Una forma ms simple para denominar el fenmeno es pedir que se preserve la diferencia mas que la identidad. Es decir pedimos que dos elementos de software no tengan que ver algo el uno con el otro, as una forma simple y directa para describir el proceso es pedir que sean independientes.

13

DISEO

ORIENTADO

OBJETOS

Un caso familiar de independencia se observa en los entornos orientados a objetos que permiten la herencia mltiple ( o sea la habilidad que tiene una subclase de heredar de mltiples superclases). S la clase C hereda tanto de la clase A como de la B, entonces las caractersticas de A y de B no debern tener los mismos nombres: pues habr interdependencia de nombre entre las caractersticas de A y las caractersticas de B. Pongamos un ejemplo ms concreto, pensemos en una aplicacin de software en un negocio de renta de videos. En el siguiente diagrama (Fig. 1.3.) se muestra una situacin de herencia mltiple,
PhysicalInventoryItem props: length RecordingMedium props: length

ProgramRentalItem

Figura 1.3. Diagrama de herencia mltiple La clase ProgramRentalItem hereda de PhysicalInventoryItem y RecordingMedium. Ambas clases tienen un atributo llamado length. Pero el significado de length en la clase PhysicalInventoryItem se refiere a la longitud fsica de un tem en centmetros, y length en la clase RecordingMedium se refiere al tiempo de duracin de un programa ( la pelcula o lo que sea que contenga el video). Aunque uno pueda argumentar que duration sera un nombre ms apropiado para el segundo atributo, uno debe tomar lo que se encuentra dentro de la biblioteca de clases. En ste ejemplo, la clase ProgramRentalItem necesita heredar ambos atributos llamados length, y esta colisin en los nombres acarrea un serio problema. En la medida que uno es quin disea las clases, ser posible evitar ste tipo de enredos, pero s uno debe utilizar una biblioteca de clases preestablecida, entonces se debe tener cuidado con situaciones como la anterior. Esto implica un estudio detallado y fino, de los nombres de las propiedades y mtodos que conforman a las clases de donde uno hereda. A lo ancho de una biblioteca de clases completa, en la cual cualquier pareja puede compartir una subclase, hay un potencial cuadro de interdependencia de nombres a travs de todas las clases debido a la herencia mltiple. Por sta razn la herencia mltiple ha adquirido una mala reputacin y no debe sorprender que un buen lenguaje de programacin orientado a objetos contenga mecanismos que eviten esta interdependencia desenfrenada. Uno de los mejores mecanismos en un lenguaje es la instruccin rename de Eiffel. sta permite en ese entorno renombrar una caracterstica a solicitud del programador, con esto se evita la duplicidad de significados.

14

DISEO

ORIENTADO

OBJETOS

1.3.

Fronteras de la Interdependencia y la Encapsulacin.

Las caractersticas de interdependencia e independencia son el corazn de las construcciones modernas de la Ingeniera del Software. Para explicar esto, retomemos el tpico de encapsulacin (seccin 1.1). Aunque se ha definido la encapsulacin y los niveles a los cuales sta puede aspirar, no se ha dicho porque la encapsulacin es importante. La encapsulacin es un chequeo sobre la interdependencia, especialmente sobre la independencia. Imaginemos un sistema con 100,000 lneas de cdigo. Imaginemos adems que el sistema se organiz en un solo mdulo, por decir algo en el procedimiento principal (main). Imaginemos luego que nosotros debemos dar mantenimiento y hacer modificaciones a ste sistema. La interdependencia entre los cientos de nombres de las variables ser por s misma una pesadilla: Simplemente para elegir un nombre para una nueva variable, uno debe revisar docenas de nombres existentes para evitar la duplicidad. Otro problema ser la naturaleza engaosa del cdigo. Consideremos dos lneas de cdigo que son adyacentes en el listado fuente. Uno se debe preguntar por qu stas son adyacentes: Es porque ellas deben ser adyacentes (debido a la interdependencia de posicin) y luego preguntarnos que suceder si se inserta una lnea nueva de cdigo entre ellas, El sistema seguir funcionando? As, un sistema que no est partido en unidades encapsuladas tiene por naturaleza dos problemas: interdependencia potencial confusin sobre qu es verdadera interdependencia y dnde hay similaridad accidental o adyacencia.

El tomar en cuenta las interdependencias responde al porque la orientacin a objetos funciona. La orientacin a objetos elimina o al menos domestica algunas de las interdependencias que se presentan como rebeldes en los sistemas modulares tradicionales con slo el nivel-1 de encapsulacin. Revisemos un ejemplo, tomemos el caso antes expuesto de la tabla de hash. Asumiremos un sistema que mantiene una tabla simple de hash y est diseado con slo el nivel-1 de encapsulacin (correspondiendo a un diseo simplemente estructurado). El sistema deber acceder a la tabla de hash desde diferentes puntos dentro del cdigo (al menos dos). El cdigo en stas posiciones tendr interdependencia de algoritmo; s uno quiere introducir un mejor algoritmo de hashing, entonces uno tendr que buscar todas las posiciones dentro del cdigo que usan el algoritmo anterior y realizar los cambios necesarios, por ejemplo en los parmetros. El nivel-1 de encapsulacin no nos guiar a los lugares donde se encuentra el llamado, ni nos indicar cuntos son. Inclusive si hubiese slo dos posiciones con el algoritmo de hashing, stos pueden ser cercanos o lejanos dentro del listado del programa. Uno los deber ubicar por si mismo, excepto que la documentacin sea lo bastante fina para ayudarnos a encontrarlos. En contraparte, un sistema orientado a objetos, con al menosnivel-2 de encapsulacin, debe tener un nicho natural para el algoritmo de hashing, digamos en la clase TablaDeSimbolos. Aunque persista una interdependencia de algoritmo entre la operacin de InsertaSimbolo y la operacin BuscaSimbolo, la interdependencia estar bajo control. S el diseo orientado a objetos utilizado es bueno, entonces no ha-

15

DISEO

ORIENTADO

OBJETOS

habr interdependencia debida al algoritmo de hashing en algn lugar del sistema (esto es, en cualquier lugar fuera de la clase TablaDeSimbolos). En general un buen diseo permitir la sustitucin del algoritmo de manera transparente y no debern modificarse los sitios donde se invoque a los mtodos de insercin y bsqueda.

1.4.

Interdependencia y mantenibilidad.

La interdependencia ofrece tres lneas gua para mejorar el mantenimiento de los sistemas, stas son: 1. Minimizar completamente la interdependencia mediante la fragmentacin del sistema en elementos encapsulados. 2. Minimizar cualquier interdependencia remanente que cruce las barreras de la encapsulacin. 3. Maximizar la interdependencia dentro de las fronteras de la encapsulacin. Estas reglas van ms all de la orientacin a objetos. Se pueden aplicar a cualquier diseo para la construccin de software con nivel-2 o nivel-3 de encapsulacin, e inclusive para niveles superiores. As, como ya se debe haber notado, stas reglas expresan un viejo principio del diseo: Mantenga las cosas similares juntas y las dismiles aparte. De cualquier forma, ste viejo principio no nos dice como saber si una cosa es similar o dismil respecto a otra, de hecho, hay elementos de software con interdependencia mutua. La figura siguiente (Fig. 1.4.) muestra dos clases con interdependencia entre ellas, la interdependencia es direccional, la direccin se especifica con la punta de la flechas.

Operacin

Clase

Variable privada

Clase 1

Clase 2

Figura 1.4. Esquema de interdependencia entre clases, las lneas ms gruesas violan las fronteras de encapsulacin.

16

DISEO

ORIENTADO

OBJETOS

Algunas de stas interdependencias (ilustradas con las lneas anchas) violan los principios de diseo orientado a objetos debido a que conectan el diseo interno de una clase con el diseo interno de otra: de tal manera que las cosas parecidas se han puesto en diferentes estructuras de software. Por ejemplo, una lnea de un mtodo de la Clase 1 hace referencia a variables dentro de la Clase 2 lo cual viola el principio de encapsulacin orientada a objetos.. Podemos decir que una interdependencia direccional viola la encapsulacin slo cuando cruza dentro de una unidad encapsulada. En la siguiente figura (Fig. 1.5.) se muestra otra pareja de clases que no violan la interdependencia de encapsulacin.

Operacin

Clase

Variable privada

Clase 1

Clase 2

Figura 1.5. Las lneas muestran las interdependencias, y ninguna viola las fronteras de encapsulacin. La interdependencia representa un conjunto de vnculos en el software. La interdependencia explcita es aparente en el cdigo fuente y puede ser descubierta a menudo con slo un editor de textos usando la opcin de bsqueda o mediante un listado de referencias cruzadas. La interdependencia implcita (que no es evidente mediante un anlisis simple del cdigo fuente en si) puede ser detectada slo con un anlisis humano apoyado por la documentacin existente del sistema. La mente humana es una herramienta cara en general ( en caso que se pague por el trabajo), y muchas veces falible, para hacer el seguimiento de la interdependencia de dispersin amplia en el software. La interdependencia implcita, especialmente cuando traspasa los lmites de la encapsulacin presenta un reto extra a quien da mantenimiento a un sistema. La interdependencia implcita llega a ser particularmente difcil de seguir y ubicar meses despus que el cdigo ha sido diseado, escrito y liberado. Puede ser que en un futuro las herramientas CASE puedan ayudar para monitorear las interdependencias en general y revelen interdependencias implcitas. Esto ser de gran utilidad en sistemas de larga escala que exhiban encapsulacin de nivel-2 o superior.

17

DISEO

ORIENTADO

OBJETOS

1.5.

Abusos de interdependencia en Sistemas orientados a objetos.

Como se ha visto en las secciones anteriores, las posibilidades de la encapsulacin de nivel-2 que ofrece la orientacin a objetos es de gran beneficio para un diseador que trata de controlar (domar domesticar) la interdependencia. De cualquier manera, en esta ltima seccin acerca de la interdependencia, se darn tres ejemplos de cmo los diseadores que utilizan el paradigma de orientacin a objetos violan el principio de mantener la interdependencia en casa, es decir dentro de los lmites de la encapsulacin. 1. La funcin friend de C++. Esta funcin fue creada en C++ expresamente para violar las fronteras de la encapsulacin. Es un elemento fuera de las fronteras de una clase que tiene acceso a los elementos privados de un objeto de dicha clase. Es decir, s una funcin friend ff toma el manejador de un objeto de clase la C1, podr interactuar al interior de tal objeto lo quiere o no aquel. La interdependencia entre ff y C1 es por lo tanto alta; esto incluye varios tipos de interdependencia: de nombre, de tipo, de convencin, etc. As cualquier cambio que el diseador realice al diseo interno de C1 requerir un ajuste en ff de manera exhaustiva. S ff es el friend de slo una clase, uno puede argumentar que ff es realmente parte de esa clase y que todos los accesos caen dentro de sus fronteras. Lo cual suena bien, pero si ff es tambin el friend de C2, C3 y C4, entonces el argumento fallar. Desgraciadamente muchos diseos en C++ utilizan sta estructura. Un uso legtimo desde los principios correctos del diseo orientado a objetos de la construccin friend es la depuracin de los estados internos de los objetos que todava estn bajo prueba. 2. Herencia sin restricciones. La construccin basada en la herencia puede algunas veces introducir interdependencias terribles. S uno permite a una clase que haga uso tanto de elementos visibles externamente (pblicos) y elementos slo visibles internamente (privados) de una superclase, entonces uno introducir un gran compromiso de interdependencia a lo largo de las fronteras de encapsulacin de ella (la superclase). Esto incluir interdependencias de nombre, clase y otras variedades. En general debemos cuidar que la herencia recibida por una subclase de su superclase est restringida slo a aquellos miembros que ya sean visibles externamente en la superclase (miembros pblicos). Otra forma de postular esto es la siguiente, La nocin de heredar el comportamiento abstracto debe estar divorciado de la nocin de heredar la implementacin interna de tal comportamiento [4]. 3. Dependencia en los accidentes de implementacin. Supongamos que un programador conocido como El tlacuache ha creado una clase Set que ofrece el comportamiento de la estructura matemtica conjunto (Set). sta clase incluye operaciones tales como add, remove, size, etc. La clase aparentemente est bien diseada y escrita, y bien realizada. El tlacuache utiliz Set en diferentes lugares dentro de su aplicacin. Por ejemplo, utiliz la operacin retrieve, la cual recupera elementos de un conjunto uno por uno en orden aleatorio hasta que han sido servidos todos los elementos (es decir que se cubri todo el conjunto). En general El tlacua18

DISEO

ORIENTADO

OBJETOS

che sabe que retrieve recupera los elementos en el orden exacto en el cual ellos fueron insertados en el conjunto, pero esto no esta documentado o descrito como una propiedad de la operacin. El posteriormente hace uso de ste hecho, de manera accidental y no documentada, muchas veces dentro de su aplicacin. Por lo tanto el ha creado una interdependencia de algoritmo a lo largo de las fronteras de la encapsulacin entre su aplicacin y las caractersticas internas de la operacin retrieve. Cuando posteriormente Set es reemplazado por una implementacin correcta por otros programador, la cual cumple con el contrato original que dicta recuperar los elementos del conjunto de forma aleatoria, muchas de las aplicaciones que ha distribuido el tlacuache empiezan a dar problemas y muchos de los usuarios de ellas se incomodan, pero no hay donde encontrar al tlacuache. Se dice que ha cambiado de identidad y se mud a un pas rabe como incgnito. Esperemos que el da de los tlacuaches pase pronto y no regrese.

1.6.

Recomendacin final.

Para finalizar, una regla bsica de diseo orientado a objetos que se puede extraer de sta seccin es la siguiente: Se deben minimizar las interdependencias en general incluyendo la independencia separando los sistemas en elementos encapsulados. Posteriormente se debe minimizar cualquier remanente de interdependencia que cruce las fronteras de la encapsulacin maximizando la interdependencia dentro de las fronteras de encapsulacin

19

DISEO

ORIENTADO

OBJETOS

2. D o m i n i o s, E n c u m b r a m i e n t o y C o h e s i n.
Las clases en un sistema no son siempre lo que parecen ser. En esta seccin se definirn algunos conceptos que ayudan a entender y colocar en una jerarqua a una clase.

2.1. Dominios de una clase de objetos. Un sistema normal orientado a objetos contendr clases organizadas en cuatro grandes dominios, cada uno de stos dominios tienen diferentes grupos dentro de ellos. La lista siguiente presenta un resumen de stos cuatro grandes dominios. 1. Dominio de Aplicacin. Comprende a las clases valorables para una aplicacin. Sus grupos interiores de ste dominio son: 2. Clases para el manejo de eventos Clases para el reconocimiento de eventos

Dominio de Negocios. Comprende a las clases valorables para una industria o compaa. Sus grupos interiores son: Clases de relacin Clases de role (papel que se juega) Clases de atributo

3. Dominio de la Arquitectura. Comprende a las clases valorables para una arquitectura de implementacin. Sus grupos interiores son: Clases de interface-humana Clases de manipulacin de bases de datos Clases de comunicacin con la mquina

3. Dominio de Base. Comprenden a las clases valorables a lo largo de todos los negocios y arquitecturas. Sus grupos son: Clases Semnticas Clases estructurales Clases fundamentales

20

DISEO

ORIENTADO

OBJETOS

En los apartados siguientes se explicar el significado de cada dominio comenzando con las clases de la parte baja de la estructura anterior.

2.1.1. El Dominio de Base

Las clases en el dominio de base se pueden usar en muchas aplicaciones de diferentes industrias corriendo sobre un amplio rango de arquitecturas. En otras palabras, el dominio de base comprende a las clases con la reusabilidad ms extensa posible. El dominio de base tiene tres grupos de clases como se indic antes, algunos ejemplos de clases de cada grupo son: Las Clases fundamentales incluyen a Integer, Boolean y Char entre otras. stas clases son tan bsicas que muchos lenguajes orientados a objetos las incluyen como predefinidas como tipos de datos simples y tradicionales. Las Clases estructurales implementan estructuras. Comprenden una lista equivalente a la de una asignatura tpica de Algoritmos y Estructuras de Datos en los estudios de Licenciatura o Ingeniera en Computacin. Elementos de sta son Stack (Pila), Queue (Cola), List (Lista), BynaryTree (rbol Binario), Set (Conjunto), etc. A stas se les conoce tambin como clases contenedoras (container classes), stas estn muy a menudo diseadas por medio de la genericidad. Las Clases Semnticas incluyen a Date (fecha), Time (hora), Angle (ngulo), Money (dinero), Mass (masa), Point, Line, Polygon y Circle. Las clases semnticas tienen un significado ms rico que Integer o Char. Adicionalmente, los valores de sus atributos pueden ser expresados en unidades, tal como horas, minutos, pesos, dlares, etc.

Las clases del dominio de base, por definicin, pueden ser de gran utilidad en cualquier aplicacin en cualquier lugar. Una clase List o Date puede aprovecharse tanto en un sistema orientado a la medicina como a un sistema de una videoteca. Una clase de base puede estar construida sobre otras clases de base. Por ejemplo Angle puede usar a Real en su implementacin, y Polygon puede usar a Set.
2.1.2. El Dominio de la Arquitectura.

Las clases en ste dominio se pueden usar tambin en muchas aplicaciones de muchas industrias diferentes. Sin embargo, la reusabilidad de las clases arquitectnicas est limitado a una arquitectura especfica de computadora. Algunos ejemplos de los grupos que conforman ste dominio son: Las Clases de comunicacin con la mquina incluyen por ejemplo a Port que brinda el servicio de acceder a un puerto fsico de la mquina (paralelo, serial, USB, Ethernet, etc.). RemoteMachine que facilita identificar o permitir que se conecte una mquina remota a travs de una red de enlace.
21

DISEO

ORIENTADO

OBJETOS

Las Clases de Manipulacin de Bases de Datos incluyen a Transaction que permite realizar una transaccin en una base de datos y Backup que realiza un respaldo de la base de datos o de una parte de ella. Las Clases de Interface Humana incluyen a Window que es el elemento bsico de las aplicaciones en los entornos grficos multitarea y a CommandButton que dentro de las interfaces grficas corresponde a un botn que al ser pulsado ejecuta una tarea dentro de una aplicacin.

stas clases son tiles en cualquier aplicacin o negocio, mientras tanto la aplicacin est implementada sobre una arquitectura fsica soportada por estas clases. En otras palabras, no puede haber una biblioteca de clases en el dominio de la arquitectura simple para todo mundo, debido a que clases como Port o Backup existirn en muchas versiones para los diferentes tipos de arquitecturas de mquina que existen. Por lo tanto la seleccin de la biblioteca de clases en el dominio de la arquitectura depender de la arquitectura fsica y real del hardware y software que donde uno implementar la aplicacin a desarrollarse.
2.1.3. El Dominio de los Negocios.

Las clases de ste dominio son tiles en muchas aplicaciones, pero slo dentro de un contexto simple, tal como la medicina, la banca, o las lneas reas. Algunos ejemplos de estas clases son: Las Clases de atributo capturan las propiedades de las cosas en el mundo de los negocios. Como ejemplo de stas tenemos Balance (de una cuenta de banco) o BodyTemperature (de un paciente mdico). Aunque estas clases son similares a Money y Temperature (que son clases de base semnticas), no son idnticas. Un balance de una cuenta de banco y la temperatura del cuerpo de un paciente sern sujetos de ciertas reglas que no se aplican a las clases de base generales. Por ejemplo, el valor de un balance de cuenta puede estar restringido a estar en ciertos lmites. La transgresin de estos lmites puede indicar un error o disparar otra actividad financiera. Las Clases de Role se derivan de el papel que juegan las cosas en los negocios, Un Role o Papel en el anlisis orientado a objetos es anlogo al tipo-entidad en el modelado de informacin. Ejemplos de estas clases son Customer (cliente) y Patient (paciente). Cuando uno analiza el dominio de los negocios, estas clases son las clases que primero y ms obviamente uno identifica. Las Clases de relacin se derivan de las asociaciones entre las cosas en el mundo de los negocios. stas incluyen a AccountOwnership (propietario de una cuenta de banco) y PatientSupervision (por parte de una enfermera).

La aplicabilidad de ciertas clases de negocios puede ser ms restringida que una industria entera: Ellas sern tiles slo a una corporacin simple, ya que aunque algunas corporaciones grandes se estructuran internamente en diferentes reas de operacin, la utilizacin de una clase de operacin dada no puede extenderse ms que a una divisin de la corporacin. Por ejemplo, supongamos que una empresa est desarrollando siete clases diferentes de OrdenDeCompra y la compaa tiene slo nueve divisiones. Uno podra sugerir que ellos hagan reingeniera con la empresa para reducir el nmero de clases OrdenDeCompra incompatibles, pero uno podra tener la duda que ellos puedan de alguna forma reducir el nmero a una sola clase,

22

DISEO

ORIENTADO

OBJETOS

porque posiblemente dos divisiones no necesariamente levantan las ordenes de compra exactamente de la misma manera. Otra vez puede verse el patrn en el cual las clases en los dominios superiores se construyen sobre clases de los inferiores. Por ejemplo, AccountOwnership har referencia a las clases Customer y Account (cuenta) y al menos a un atributo de Account ser de la clase Balance.

2.1.4. El Dominio de Aplicacin.

Una clase en ste dominio se utiliza dentro de una aplicacin simple o de un pequeo nmero de aplicaciones relacionadas. ste dominio contiene dos grupos de clases: de reconocimiento de eventos que corresponde a la deteccin de que cierto evento particular ha sucedido y de manejo de eventos que corresponde a la ejecucin apropiada de la accin correcta para un evento particular. Ejemplos de stas son: Clases de Reconocimiento de eventos. En el sentido de la programacin son demonios de eventos, construcciones de software que monitorean la entrada para checar la ocurrencia de eventos especficos en el medio ambiente. Un ejemplo es un objeto de la clase PatientTemperatureMonitor, la cual registrar por los eventos patient develops fever el paciente tiene fiebre y patient becomes hypothermic el paciente esta muy fro en general respecto a una media o a otros pacientes. Clases de Administracin de eventos. stas llevan a cabo las acciones apropiadas cuando un evento de cierto tipo ocurre. Un ejemplo de stas es un objeto de la clase WarmHypothermicPatient, la cual inmediatamente enva mensajes a otros objetos para incrementar la temperatura del paciente y solicitar atencin mdica haciendo sonar una alarma en el cuarto de enfermeras. Obviamente el objeto WarmHypothermicPatient pasar a su estado activo ante el evento correspondiente a un paciente hipotrmico.

Una clase en el dominio de Aplicacin tiene una reusabilidad muy pequea. Es importante notar que, la mayor parte de las clases en ste dominio son relevantes a slo una aplicacin y no tienen reusabilidad en general. Por ejemplo la clase ProgramaPacienteParaCirugia probablemente sea usada slo en un Sistema de Administracin Quirrgica.
2.1.5. La fuente de las clases en cada dominio.

Para la mayor parte de la gente, la habilidad para acomodar las bibliotecas de clases con el software reusable es la razn misma de la orientacin a objetos y muchos equipos de trabajo dedican muchos de sus esfuerzos de diseo en este sentido con el propsito de alcanzar la exquisitez de la reusabilidad de las clases que han construido. Pero como se ha mostrado en las secciones anteriores, las clases en los diferentes dominios tienen diferentes grados de reusabilidad. Las clases en el dominio ms bajo tienen gran reusabilidad, mientras que las clases del dominio ms alto tienen menos. La figura 2.1 ilustra lo antes dicho.

23

DISEO

ORIENTADO

OBJETOS

Aplicacin
Manejo de eventos Reconocimiento de eventos

Baja Reusabilidad

Negocios
Relaciones Role Atributos Media Reusabilidad

Arquitectura
Interface humana Manipulacin de BD Comunicacin con la mquina

De base
Semntica Estructural Fundamental Alta Reusabilidad

Fig. 2.1. Dominios de las clases y su reusabilidad El origen de las clases depende fuertemente del dominio al que pertenece una clase. Para la clase de base la respuesta es simple: Generalmente es adquirida o comprada a un fabricante de clases, por decir a quien vende o distribuye compiladores o herramientas de dicha categora. El emprender y desarrollar bibliotecas de clase base es normalmente difcil y caro. Por supuesto, si un equipo o persona decide hacerlo, entonces podr tener las clases que quiera y pueda, pero invertir un gran esfuerzo en lograrlo. Eventualmente para la venta de aplicaciones puede resultar miles de veces ms caro que comprar la biblioteca, pero sta tarea alguien la debe hacer. Uno en general debe aumentar la biblioteca de clases que ha comprado con algunas clases de diseo propio, esto est bien. Pero comprar, pedir prestada o regalada cualquier conjunto de clases base que uno necesite muchas veces resulta mejor opcin que desarrollarla, siempre que el tiempo sea un factor determinante para la entrega de una aplicacin a los clientes. Muchas veces cuando se est en la tarea de innovacin se deben desarrollar las clases de base requeridas, por ejemlo ante nuevo hardware no soportado por el sistema operativo o en el marco de la implementacin de nuevos algoritmos para la solucin optimizada de ciertos problemas. La fuente de las clases en el dominio de la arquitectura es similar a las de base, pero hay cuatro diferencias importantes: Uno puede tener que comprar clases en el dominio de la arquitectura del vendedor(es) del hardware y software que se adquiere. Tambin existen los llamados vendedores alternativos (third-party) que proveen bibliotecas para las arquitecturas ms populares.

24

DISEO

ORIENTADO

OBJETOS

Uno puede sufrir ciertas incompatibilidades a lo largo de ciertas partes de la biblioteca en el dominio de la arquitectura si se usan productos de diferentes vendedores. El proveedor de la biblioteca puede haber construido su producto en base a una biblioteca diferente a la que uno est utilizando. La biblioteca en el dominio de la arquitectura adquirida probablemente requiera mayor refinamiento, ajuste y modificaciones que la biblioteca de base con que se cuenta, debido a los dos puntos anteriores.

Las clases en el dominio de los negocios son de especial inters y retadoras. Estas son clases que no es posible comprar por el momento por al menos dos razones. La primera, los vendedores no tienen la experiencia industrial para desarrollar clases para hospitales o bancos o aviacin o telecomunicaciones a la medida. Y la segunda radica en que el mercado para sta clase de bibliotecas sera como una pesadilla ya que cada comprador desea la personalizacin de ellas. Uno puede escuchar al respecto argumentos como el siguiente: Nuestra compaa est orgullosa en ser especial y diferente. La clase por decir algo - Producto que Uds. nos venden no coincide con nuestras necesidades como empresa. (Puff !!) De cualquier manera la situacin est cambiando. Ahora se pueden encontrar clases en el dominio de los negocios y componentes para algunos propsitos corporativos a la venta, ejemplos de esto son la banca y las telecomunicaciones. Todava y por un buen intervalo de tiempo el software en el dominio de los negocios ser ampliamente vendible, por tanto hoy uno deber seguir desarrollando las clases para este tipo de aplicaciones. Y uno deber tener mucho cuidado en analizar los requerimientos usando tcnicas tal como el modelado funcin-relacin o el entidad-relacin porque ellas se convertirn en el tesoro de cada compaa que desarrolla su software. De igual manera uno tendr que prestar gran cuidado en su diseo, pues stas clases tendrn una significativa reusabilidad s han sido bien analizadas y diseada, pero su reusabilidad ser nula si no lo estn.. Lo competitivo de una empresa depender del tiempo para poner en marcha los nuevos sistemas de software, lo cual depender tambin de manera significativa de la calidad de las clases de negocios en la biblioteca utilizada. El dominio que esta en la parte alta de la estructura de dominios es el dominio de aplicacin. No debemos preocuparnos mucho por el diseo para la reusabilidad en este estrato; de cualquier manera aunque uno haga su mejor esfuerzo de diseo, uno no alcanzar mucha reusabilidad, lo cual es natural. La fuente principal para las clases en ste dominio son los eventos de negocios que se descubren durante el anlisis. Puede ser que en los prrafos anteriores la categora de construccin sea mejor que el trmino clase, ya que los reconocedores de eventos y manejadores de eventos deban ser implementados como procedimientos tradicionales o instancias simples de los paquetes de utileras, ms que clases originales e interesantes.

25

DISEO

ORIENTADO

OBJETOS

2.2. Encumbramiento (encumbrance). En la seccin anterior se han tratado los dominios de las clases de una manera cualitativa, ahora pasaremos a un anlisis cuantitativo, que nos dir que tan alto una clase descansa respecto al dominio fundamental. Llamaremos a sta medida Encumbramiento.
2.2.1. Qu es el encumbramiento?

Este mide las dimensiones de la maquinara auxiliar de una clase. Es decir todas las otras clases de las cuales que una clase dada depende para poder operar. En otras palabras, si uno cuenta todas las clases a que hace referencia con detalle una clase C, el nmero total de ellas ser el encumbramiento de C (es decir que tan arriba en la estructura de clases se encuentra C). Para definir de manera formal encumbramiento, primero definiremos algunos trminos, Definicin. El conjunto de referencias directas a una clase C es el conjunto de clases a las cuales C hace referencia de manera directa. En la mayor parte de los lenguajes orientados a objetos, una clase C puede hacer referencia directa a otra clase D en cualquiera de las siguientes maneras: C hereda de D. C tiene un atributo de clase D. C tiene una operacin con un argumento de entrada de clase D. C tiene una variable de clase D. C tiene un mtodo que enva un mensaje con un argumento de retorno de clase D. C tiene un mtodo que contiene una variable local de clase D. C provee a D como un parmetro de clase actual a una clase parametrizada. C tiene a D como una clase friend (en C++).

Definicin. Supongamos que el conjunto de referencias directas de la clase C contiene a las clases C1, C2, , Cn. Entonces, el conjunto de referencias indirectas de la clase C es la unin de las referencias directas de la clase C y los conjuntos de referencias indirectas de C1, C2, , Cn.
26

DISEO

ORIENTADO

OBJETOS

Una definicin matemtica ms formal es la siguiente: El conjunto de referencias indirectas de una clase C es equivalente a la cerradura transitiva sobre el conjunto de referencias directas de C. La primera definicin de referencias indirectas es claramente recursiva. El lmite de la recursin est tanto para el caso directo como indirecto en el punto donde se alcanzan las clases fundamentales, pues luego de ellas no hay mas clases. Definicin. El encumbramiento directo de una clase es el tamao de su conjunto de referencias directas de clase. Y el encumbramiento indirecto de una clase es el tamao del conjunto de sus referencias indirectas de clase. A continuacin se har una ilustracin del encumbramiento, usemos una flecha para mostrar una referencia de clase directa. En la figura 2.2. se presenta un ejemplo de referencia de clase directa. C En ste ejemplo el conjunto de referencias de clase directas es {C1, C2, C3}, por lo tanto el encumbramiento de C es simplemente 3. La figura 2.3. muestra un conjunto de referencia indirectas. Uno determina el encumbramiento indirecto de C contando todas las clases en el diagrama, esto es, todas las clases en el rbol cuya raz es C y cuyas hojas son las clases fundamentales ubicadas en la parte inferior (denotadas por Fk).

C1

C2

C3

Fig. 2.2. C y su conjunto de referencias directas

El encumbramiento indirecto de C es por tanto 12. Debemos tener cuidado en incluir las referencias directas de clase en el conteo del conjunto de referencias indirectas de clase. C3 Una situacin concreta se muestra en la figura 2.4.. En sta se puede observar que el encumbramiento indirecto de Rectangle es 4, ya que tiene cuatro clases - Point, Length, Real y Boolean - en su conjunto de referencias indirectas. Aunque Real pueda hacer referencia a Boolean, por ejemplo en una operacin de comparacin y a Integer en una operacin de redondeo, se puede adoptar la convencin usual cero para definir el encumbramiento de Real a cero.

C1

C2

C11

C12

C21

C31

C32

F1

F2

F3

F4

Fig. 2.3. C y su conjunto de referencias de clase indirectas

27

DISEO

ORIENTADO

OBJETOS

Rectangle (4)

Fig. 2.4. Rectangle y su conjunto de referencias de clase indirectas.

Point (3)

Length (2)

Boolean (0)

Real (0)

2.2.2. El uso del encumbramiento.

El encumbramiento nos da una medida de la sofisticacin de una clase - esto es, que tan arriba esta la clase respecto al dominio fundamental. Entonces, las clases en dominios superiores tendrn un mayor encumbramiento indirecto y aquellas en los dominios inferiores en posicin tendrn menor encumbramiento indirecto.

Un encumbramiento indirecto inesperado puede indicar una falla en el diseo de una clase. Por ejemplo, s uno encuentra una clase con mayor encumbramiento indirecto en un dominio bajo, entonces podr haber problemas con la cohesin de la clase (este concepto se discutir a detalle en la siguiente seccin). De manera alternativa, s una clase en un dominio superior tiene menor encumbramiento indirecto, entonces sta ha sido probablemente diseada a rasguos; esto es, el diseador la ha construido directamente a partir de Integer, Char, y otras clases fundamentales, en vez de haber reutilizado clases intermedias de la biblioteca.

28

DISEO

ORIENTADO

OBJETOS

2.2.3. La Ley de Demetrio.

Lieberherr y Holland [5] proponen la Ley de Demetrio como un principio gua para limitar el encumbramiento directo de una clase, limitando el tamao de su conjunto de referencias directas. Una sntesis general de la Ley de Demetrio es la siguiente: Para un objeto obj de clase C y para cualquier operacin op definida para obj, el destino de un mensaje dentro de la implementacin de op debe ser uno de los siguientes objetos: 1. 2. 3. 4. 5. El objeto obj mismo especficamente, self y super (en Smalltalk), this (en C++ y Java), o current (en Eiffel). Un objeto referido como un argumento dentro de la firma de op. Un objeto referido mediante una variable de obj (incluyendo cualquier objeto dentro de las colecciones que hacen referencia a obj). Un objeto creado por obj. Un objeto referido por una variable global o de la clase principal (main).

Hay dos versiones de la ley, las cuales difieren slo en la interpretacin del tercer punto. La Ley Fuerte de Demetrio define a una variable como variable nica, a una variable definida en la clase C misma. La Ley Dbil de Demetrio define a una variable, ya sea una variable de C o una variable que C ha heredado de su superclases. La Ley de Demetrio es eminentemente razonable, pues restringe las referencias arbitrarias a otras clases dentro de una clase dada. Bajo esta ley, el cdigo dentro de C har referencia a slo el mnimo nmero posible de otras clases. Obviamente es preferible usar la Ley Fuerte de Demetrio ala Dbil porque adems limita la interdependencia a lo largo de las fronteras de la encapsulacin como se explic en el captulo anterior, es decir de las fronteras de clase de las superclases de C. Como se discuti en el captulo anterior tambin, limitar la interdependencia en ste sentido facilita el mantenimiento y evolucin del sistema por dos razones: Libera al diseador de las superclases de C de redisear su implementacin interna, y Mejora la comprensin de C, puesto que s alguien trata de entender el diseo de C no estar continuamente arrastrado por los detalles de implementacin de las superclases de C, o lo que es peor, aquellos de una clase completamente ajena.

2.3. Cohesin de una clase. La cohesin de clase es la medida de la interelacin de las caractersticas (los atributos y operaciones) localizados en la interface externa de una clase.
29

DISEO

ORIENTADO

OBJETOS

En la Tabla 1.2. se inserto el trmino de cohesin de clase en un nivel de encapsulacin superior que el correspondiente a la cohesin de procedural (modular). En el diseo estructurado, la cohesin procedural se interpreta como la medida de cmo las lneas de cdigo corresponden entre s con un mdulo procedural simple, como es una funcin o un procedimiento. Puede ser que el trmino tipo de cohesin sea un trmino mejor que cohesin de clase, ya que con ste concepto se trata de evaluar que tan bien una clase corresponde a una implementacin de cierto tipo de dato abstracto. Una clase con baja cohesin (o bien mala cohesin) tiene un conjunto de caractersticas que no corresponden entre s. Una clase con alta cohesin (o buena cohesin) tiene en conjunto de caractersticas que contribuyen en conjunto al tipo de abstraccin implementada por la clase. Existe otra interpretacin de cohesin de clase por ciertos autores, stos consideran como los mtodos que implementan las operaciones de una clase usan las variables internas de la clase. La idea es la siguiente: Mientras mayor sea el traslape en el uso de los mtodos al usar las variables, ser mayor la cohesin de la clase. sta interpretacin es cuestionable, por al menos razones. La primera razn es que la cohesin es una propiedad que debe ser aparente desde el exterior de una unidad de software encapsulada. Por lo tanto, parece errneo tener que ver en el interior de una clase (en sus partes privadas) con el propsito de evaluar su cohesin. La segunda razn es que sta medida es inestable y muy dependiente del diseo interno particular de los mtodos, que podr cambiar a lo largo del tiempo de vida de la clase. En consecuencia, una clase joven y poco madura (es decir aquella que empieza a disearse y desarrollarse) aparentar tener una cohesin baja que una clase madura (aquella que ha crecido a su forma final y adulta en sus caractersticas e implementacin). Esto es injusto en general, pues implica un rechazo a los nuevos miembros en la familia de clases. Hay tres problemas identificables de cohesin en la asignacin de las caractersticas de las clases, stos son observables desde el diseo externo de la clase, concretamente los problemas se denominan: cohesin de mezcla de instancia (mixed-instance cohesion) cohesin de mezcla de dominio (mixed-domain cohesion) cohesin de mezcla de role (mixed-role cohesion)

De los tres, la cohesin de mezcla de instancia es tpicamente el mayor pecado y la cohesin de mezcla de role el menor. Una clase puede tener todos, algunos o ninguno de stos tres problemas de cohesin. Una clase que no presente alguna de estas tres cohesiones mezcladas en enteramente cohesiva y se dice que tiene cohesin ideal. A continuacin se har una discusin de cada tipo de mezcla de cohesin y se evaluarn sus sntomas en la fase de diseo.
2.3.1. Cohesin de mezcla de instancia

Una clase con cohesin de mezcla de instancia tiene ciertas caractersticas que estn indefinidas para ciertos objetos de la clase.

30

DISEO

ORIENTADO

OBJETOS

Por ejemplo, digamos que un departamento de ventas tiene vendedores con comisin y sin comisin. Digamos que Juan trabaja con comisin y Mara sin comisin. En una aplicacin orientada a objetos que soporte a ste departamento, hay una clase Vendedor, de la cual los objetos que apuntan a las variables juan y maria son instancias. Considerando el caso anterior, el primero de los mensajes siguientes tiene sentido, pero el segundo no lo tiene: juan.EmitirComisionPorMes; maria.EmitirComisionPorMes; Uno podra mantener los dos mensajes y definir la comisin del objeto maria a cero. De cualquier forma, esto se vuelve un lo. Mara no tiene comisin cero; ella tiene una comisin indefinida. Es mas, Vendedor podra necesitar tambin una variable booleana EsComisionado (posiblemente disponible como un atributo). Y uno podra incluir en la operacin Vendedor. EmitirComisionPorMes una instruccin if que prevenga la impresin de cheques por comisin de <$ 0.00 > para los objetos sin comisin. En general la idea va a trabajar, pero es un feo diseo. El problema real es que la clase Vendedor tiene cohesin de mezcla de instancia, porque es muy burda para la aplicacin: se ha unido tanto a vendedores con comisin y sin comisin en una sola clase. Lo que uno debe hacer es crear subclases ms finas VendedorConComision y VendedorSinComision a nuestro diseo. Estas nuevas subclases heredarn de su superclase, Vendedor. As un vendedor con comisin (el caso de Juan) ser representado por una instancia de VendedorConComision, mientras que un vendedor sin comisin se representara por una instancia de VendedorSinComision. Y la operacin EmitirComisionPorMes se ubicar en EmitirComisionPorMes, el diseo se muestra en la figura 2.5.

Vendedor

Vendedor ConComision
/comisionPorMes : Money

Vendedor SinComision

Fig. 2.5. Remocin del problema de cohesin para Vendedor aadiendo subclases. La cohesin de mezcla de instancia usualmente indica una jerarqua de clases que no est bien refinada o que simplemente es incorrecta. Y como se ha visto, obliga a introducir trucos en el cdigo que empaan el trabajo de anlisis y diseo, en el ejemplo anterior corresponde al if que se introdujo para hacer compatibles las instancias, ste fenmeno se puede detectar al revisar los ifs que separan los casos dentro de una clase para que se puedan consideran las variantes incompatibles.
31

DISEO

ORIENTADO

OBJETOS

2.3.2. Cohesin de mezcla de dominio.

Una clase con cohesin de mezcla de dominio contiene un elemento que directamente encumbra a la clase con una clase extrnseca de un dominio diferente. En la definicin anterior, se ha usado el concepto de dominio en el mismo sentido que se toma en la seccin 2.1., Pero ahora se requiere definir el concepto de extrnseco(a). La clase B es extrnseca a A si A puede ser completamente definida sin una nocin de B. B es intrnseca a A s B captura algunas caractersticas inherentes a A. En ste contexto, Rinoceronte es extrnseco a Persona, pues en ningn sentido rinoceronte captura alguna caracterstica de una persona. Pero, Fecha (como en fecha de nacimiento) es intrnseca a Persona. Hay muchos ejemplos de cohesin de mezcla de dominios, algunos son obvios y otros muy sutiles. Como primer ejemplo suponga que a la clase Real (de nmero real) se le crease un atributo ArcTan (ngulo cuya tangente es). Esta inclusin relaciona a los nmeros reales con los ngulos, pero muchas cosas son nmero reales y los nmeros reales no corresponden a la categora de los ngulos. Esto es una muestra de mezcla de dominios que no es evidente y elevara a los objetos de tipo Real a la categora de objetos de tipo Angulo, lo cual no es correcto pues los dominios son diferentes. Qu pasara si le adicionamos una operacin llamada convierteTemperatura a la clase Real si podemos convertir grados Centgrados a Farenheit y Kelvin a Raumur ? Esto encumbrar a Real junto a Temperatura. O bien, si queremos encontrar la equivalencia entre pesos y euros, podramos encumbrar Real con Money. La lista de posibilidades absurdas no tiene fin, la figura 2.6. presenta una opcin:

Real
ArcTan : Angle FarenheitEquival : FarenheitTemp CantidadEnEuros : DineroEuropeo TuPropioInvento : ?

Figura 2.6. Real con cohesin de mezcla de dominio exagerada Cuando uno disea una clase en cierto dominio, uno deber incluir clases de los dominios inferiores en el diseo esto es lo que brindar reusabilidad. Pero uno debe estar seguro que se requieren esas clases debido a las propiedades intrnsecas de la clase que se est diseando. Por ejemplo, es correcto esperar que para la clase Cuenta se tenga una operacin que regrese un objeto de la clase Dinero o bien que tenga un atri-

32

DISEO

ORIENTADO

OBJETOS

buto de la clase Fecha. Pero uno debe guardar una mala sospecha si una clase regresa un objeto de la clase en el dominio de la arquitectura TercerPinDelPuertoSerialDB9. La afirmacin: Una clase en el dominio de la arquitectura a menudo se mezcla con el dominio de los negocios, es incorrecta, excepto que el proyecto de negocios en desarrollo se refiera a la construccin de infraestructura de arquitectura de computadoras (por ejemplo una aplicacin para INTEL o AMD). El viejo lema orientado a objetos de que una cosa debe conocer algo acerca de s misma, como en el caso de que un documento debe saber como imprimirse a s mismo, puede ser un poco atrayente. Una clase Documento con un conocimiento especfico de una impresora tiene cohesin de mezcla de dominios. Cuando uno disea una clase en un dominio dado, uno debe ser particularmente cauteloso de introducir clases de dominios superiores en la clase que est diseando. Por sta razn la clase Real tiene un problema. Real es una clase fundamental, y no debe ser encumbrada con clases de dominios superiores.

2.3.3. Cohesin de mezcla de role.

Una clase C con cohesin de mezcla de role contiene un elemento que directamente encumbra a la clase con una clase extrnseca que se ubica en el mismo dominio de C. A diferencia de una clase con cohesin de mezcla de dominio, una clase con cohesin de mezcla de role no favorece a ambos dominios. De cualquier forma, no incluye mas que un role de un dominio simple (donde role significa una abstraccin de un grupo de cosas parecidas en el mundo real). Un ejemplo famoso se refiere a personas y gatos. Digamos que se tiene una clase Persona con un atributo numDeGatosEnPosesion (nmero de gatos que la persona posee). Si la operacin de recuperacin (get) para el atributo es una funcin simple (con el mismo nombre numDeGatosEnPosesion), podramos usar algo como felipe. numDeGatosEnPosesion para encontrar cuantos gatos posee el objeto felipe (de la clase Persona). Es notorio que: La clase Persona no tiene cohesin de mezcla de instancia, porque los objetos sin-gatos pueden regresar simplemente un valor cero. No tiene cohesin de mezcla de dominio, porque Persona y Gato estn en el mismo dominio de asunto. PERO, tiene cohesin en el dominio de role, porque Persona y Gato son conceptos diferentes, extrnsecos uno con otro. En trminos puros de diseo, la cohesin de mezcla de role es la transgresin menos seria de las cohesiones de clase. De cualquier forma, al disearse una clase para aumentar la reusabilidad, entonces se debe prestar especial atencin a la cohesin de mezcla de role. Qu pasa cuando uno trata de reutilizar Persona en una aplicacin donde los gatos no intervienen? Es posible retomar la clase Persona inicial, pero uno deber acarrear equipaje extra (lo relativo a la posesin de gatos en el ejemplo) innecesario, y es posible que

33

DISEO

ORIENTADO

OBJETOS

se reciban algunos mensajes incmodos por parte del compilador o ligador relativos a la ausencia de gatos en las personas. La cohesin de mezcla de role es para todo mundo atractiva pues, Es muy sencillo escribir el cdigo correspondiente para hallar cuantos gatos tiene alguien: felipe. numDeGatosEnPosesion Muchas aproximaciones al modelado de la informacin podran tratar a numDeGatosEnPosesion como un atributo de Persona.

En general a pesar de lo atractivo de los argumentos anteriores, uno no debe distraerse en la creacin automtica de la clase (Persona) con cohesin de mezcla de role. Hay muchas otras opciones de diseo que no comprometen la cohesin de la clase (Persona) que pueden ser consideradas.

En resumen podemos decir que: Como diseador con orientacin a objetos, uno debe aspirar a crear clases con cohesin ideal, esto es, clases carentes de cohesin de mezcla de instancia, mezcla de dominio o mezcla de role. Las clases con cohesin ideal tienen la mxima reusabilidad, y debe ser el objetivo primario de la prctica orientada a objetos, particularmente para las clases en el dominio de los negocios.

34

DISEO

ORIENTADO

OBJETOS

3. E s p a c i o d e E s t a d o s y C o m p o r t a m i e n t o
En sta seccin se introducirn dos propiedades fundamentales de las clases: el espacio de estados y el comportamiento, luego se explorar el espacio de estados de las subclases y su comportamiento, se introducir el invariante de clase como una restriccin sobre el espacio de estados y finalmente las precondiciones y postcondiciones de las operaciones, las cuales juntas forman el contrato entre una operacin y un cliente de sta operacin. Las clases invariantes, las precondiciones y postcondiciones forman la espina dorsal de un diseo orientado a objetos, al mtodo se le denomina diseo por contrato.

3.1 Espacio de estados y comportamiento de una clase. Una clase representar una abstraccin uniforme de las propiedades de los objetos individuales que corresponden a la clase. A pesar de que esto suena como una frase clebre, realmente qu significan stas palabras? Por abstraccin debemos entender que uno no necesariamente tiene que considerar todas las posibles propiedades de las cosas del mundo real que estn representadas en los objetos de software. Por ejemplo, al crear una clase ClienteBancarioHumano, no est uno obligado a incluir la propiedad DiametroCraneal en la clase. Por uniforme entenderemos que la abstraccin que uno selecciona para una clase se aplica de la misma manera a cada uno de los objetos que son instancias de ella. Por ejemplo, Si uno est interesado en la fecha de nacimiento para ClienteBancarioHumano, entonces estamos interesados en la fecha de nacimiento de todos los clientes bancarios humanos. Por propiedades de debe entender simplemente que: Las dos propiedades de una clase estn en su espacio de estados y en su comportamiento permitido. Gran parte de la discusin de sta seccin girar alrededor de los conceptos de espacio de estados y comportamiento y sus implicaciones prcticas en el diseo orientado a objetos.

35

DISEO

ORIENTADO

OBJETOS

Antes de proceder a una definicin formal de stos conceptos se har una ilustracin de ellos. Pensemos en un caballo como pieza de un tableo de ajedrez como se muestra en la figura 3.1 - a ste lo podemos representar como un objeto de la clase CaballoAjedrez.

Fig. 3.1. Un tablero de ajedrez con una reina y un caballo.

Las lneas negras indican los posibles comportamientos del caballo y las claras el de la reina. El espacio de estados para el CaballoAjedrez corresponde a todo cuadro en el tablero, y el espacio de estados para la ReinaAjedrez tambin corresponde a todos los cuadros del tablero. Pero las clases ReinaAjedrez y CaballoAjedrez no son iguales, Cul es la diferencia entre ellas?; su comportamiento. La reina se pude mover a lo largo de cualquier columna, rengln o diagonal a partir del punto donde ella se encuentra, por lo cual ella podr alcanzar cualquier posicin en un tablero vaco en slo dos jugadas. O sea puede ubicarse en otro estado de su espacio de estados. Por otro lado, el caballo necesitar realizar hasta seis (6) jugadas para alcanzar cualquier cuadro en el tablero. Diremos que las clases ReinaAjedrez y CaballoAjedrez tienen espacios de estados idnticos, pero diferentes comportamientos. Imagine ahora otra clase de caballo, tal que se mueva como lo hace un caballo de ajedrez normal, pero no le es permitido ocupar los cuatro cuadros centrales del tablero (Fig. 3.1.). Este caballo es diferente al primero, ya que aunque se mueve con las mismas reglas (es decir tiene el mismo comportamiento), su estado de estados es diferente al del primero.

36

DISEO

ORIENTADO

OBJETOS

Revisando los ejemplos anteriores, se puede concluir que dos clases pueden diferir ya sea en sus espacios

Fig. 3.2. Un Caballo con restriccin de los 4 cuadros centrales de estados, en su comportamiento o en ambas cosas. El espacio de estados de una clase C es el conjunto de todos los estados que tiene permitidos un objeto de la clase C. Las dimensiones del espacio de estados son las coordenadas necesarias para especificar el estado de un objeto dado. Definiremos informalmente, el estado de un objeto es el valor que l tiene en un momento dado. Con mayor propiedad diremos que, el estado de un objeto es el conjunto ordenado de objetos a lo cuales el objeto hace referencia a un tiempo dado. Por ejemplo, el estado de un objeto Alberca ahora puede ser definido por la terna (30, 2, 10, 25) largo, profundidad y ancho en metros y temperatura en grados centgrados. En otras palabras, este objeto Alberca actualmente hace referencia a un objeto de la clase Longitud (30 m), otro de clase Profundidad (2.5 m), uno mas de clase Ancho (10 m) y a uno de clase Temperatura (25 C) . Una imagen que uno se puede formar del espacio de estados corresponde a un arreglo de puntos, donde cada punto corresponde a un estado. Cada objeto que es una instancia de la clase es un punto que pasa su vida movindose de un lugar a otro dentro del espacio de estados de la clase. Estos movimientos se denominan transiciones. En la figura 3.3. se presenta una representacin de un espacio de estados tridimensional, que corresponde a una clase llamada Producto. Las dimensiones de la matriz corresponden a tres propiedades de la clase:

37

DISEO

ORIENTADO

OBJETOS

peso, precio y disponibilidad. Ya que stas variables son mutamente independientes, un objeto se puede encontrar en cualquier lugar de la matriz. Los objetos se representan como puntos dentro de la retcula (matriz).

Peso del Producto

Disponibilidad del Producto Precio del Producto

Figura 3.3. Espacio de estados de la clase Producto como una matriz 3D, cada producto (instancia) es un punto en la rejilla.

Las dimensiones del espacio de estados de una clase son equivalentes a los atributos primarios definidos en la clase. En general, dado que cada dimensin es en si una clase, los valores a lo largo de cada dimensin son objetos de la dimensin de la clase.

3.2 Espacio de estados de una subclase. Si B es una subclase de A, entonces el espacio de estados de B puede estar completamente contenido dentro del espacio de estados de A. Diremos que el espacio de estados de B esta confinado por el espacio de estados de A. Un ejemplo de sta situacin es el siguiente, digamos que la clase A corresponde a VehiculoDeCarretera. Por simplicidad, asumiremos que su espacio de estados tiene una sola dimensin: PesoCorriente. Definiremos los lmites de peso superior e inferior en 0.5 tons y 10.0 tons (toneladas) para VehiculoDeCarretera.PesoCorriente. Supongamos ahora que la subclse B es Automovil. Si se definen sus lmites inferior y superior en 1.0 tons y 3.0 tons para Automovil.PesoCorriente, entonces estaremos en buena forma. El espacio de estados de Automovil esta confinado dentro del espacio de estados de VehiculoDeCarretera y por lo tanto Automovil es una subclase vlida de VehiculoDeCarretera. La figura 3.4 muestra los rangos de VehiculoDeCarretera.PesoCorriente y Automovil.PesoCorriente de manera grfica.

38

DISEO

ORIENTADO

OBJETOS

Puede observarse que si se definieran los lmites inferior y superior de Automovil.PesoCorriente en 0.2 y 14.0 tons se presentara un problema. Por ejemplo, un automvil de 13 tons no caera en la definicin de VehiculoDeCarretera, pues limita a los vehculos de carretera a 10 tons. De donde, el espacio de estados de Automovil ya no estara confinado dentro del de VehiculoDeCarretera y por lo tanto Automovil ya no sera una subclase vlida de VehiculoDeCarretera. Esta violacin al espacio de estados puede permitir a un objeto ser una instancia legal de su propia clase,
espacio de estados de Automovil

espacio de estados de VehiculoDeCarretera

11

Figura 3.4. Espacio de estados unidimensional de Automovil y VehiculoDeCarretera.

pero una instancia ilegal de su superclase. En trminos del ejemplo tendramos que: Un coche es un automvil, pero no un vehculo de carretera - lo cual es absurdo. En general dado que una subclase hereda de su superclase, entonces est en la libertad de definir nuevas propiedades particulares (para la subclase), esto implica que una subclase en general puede tener mas dimensiones que su superclase lo cual no debe sorprendernos. Si B es una subclase de A, entonces el espacio de estados de B debe comprender al menos las dimensiones de A, pero puede incluir otras ms. En caso que comprenda mas dimensiones, se dir que el espacio de estados de B extiende al de A. En el ejemplo anterior un caso sera el siguiente, Automovil puede incluir una dimensin llamada NumeroDePasajerosActual, que en general no sea una dimensin de VehiculoDeCarretera, por ejemplo ausente en los vehculos de carga, pipas de agua, etc. Esto puede en general confundir, pues uno puede preguntar Cmo puede el espacio de estados de una subclase tanto estar confinado por y extender al espacio de estados de su superclase? La respuesta es la siguiente: Dentro de las dimensiones definidas por la superclase, el espacio de estados de una subclase puede ser menor que el de la superclase pero al mismo tiempo, el espacio de estados de la subclase puede extenderse a otras dimensiones que estn indefinidas en la superclase. En la figura 3.5. se muestra el espacio de estados de Automovil simultneamente confinado por y extendiendo al espacio de estados de VehiculoDeCarretera.

39

10

12

DISEO

ORIENTADO

OBJETOS

En la dimensin PesoCorriente, el espacio de estados de Automovil est todava confinado dentro de VehiculoDeCarretera, por que el rango de Automovil.PesoCorriente todava cae dentro del rango de VehiculoDeCarretera.PesoCorriente. Por otro lado, Automovil tiene una dimensin extra (NumeroDePasajerosActual) en su espacio de estados. Por lo tanto su espacio de estados se extiende a una segunda dimensin; Especficamente, como se muestra, un automvil puede tener de cero a siete pasajeros abordo. Mientras que para la clase ms general (la superclase) est indefinido VehiculoDeCarretera. NumeroDePasajerosActual.
NumeroDePasajerosActual

10 9 8 7 6 5 4 3 2 1 0 0 1 2 3 4

Espacio de estados de Automovil

Espacio de estados de VehiculoDeCarretera

10

11

12

13

14

PesoCorriente

Figura 3.5. Espacio de estados 2D para Automovil y de espacio de estados 1D para VehiculoDeCarretera.

3.3. El comportamiento de una Subclase. La mayora de los objetos excepto aquellos inmutables realizan transiciones dentro de su espacio de estados en la medida que uno o varios de sus atributos cambian de valor. Estas transiciones constituyen el comportamiento permitido para una clase, que se define de la siguiente manera: El comportamiento admitido de una clase C es el conjunto de transiciones que un objeto de clase C tiene permitido realizar entre los estados en el espacio de estados de C. Esta definicin implica que no todas las posibles transiciones son legales para un objeto. Un objeto se mueve dentro del interior del espacio de estados de su clase slo en la manera prescrita para l dado el comportamiento de la clase. En el ejemplo anteriormente expuesto de los caballos en el tablero de ajedrez, un caballo puede encontrarse en cualquiera de las 64 casillas del tablero, pero slo se permiten un conjunto finito de transiciones en una jugada simple a partir de una posicin definida, las cuales a lo mas son 8.

40

DISEO

ORIENTADO

OBJETOS

Y qu se puede decir acerca del comportamiento en las subclases?, Habr una relacin entre el comportamiento de una subclase y su superclase, como sucede con sus espacios de estados?, ste comportamiento estar confinado y/o extendido en una subclase? La respuesta a stas preguntas es afirmativa. Primero, consideremos la extensin del comportamiento que B (la subclase) posee, pero de que A (la superclase) carece. Es obvio que dicho comportamiento extra que tiene B debe existir, pero cmo una instancia e B administra la parte del espacio de estados de B que se extiende fuera del correspondiente de A? Tomemos el ejemplo de los vehculos. En ste, Automovil tiene un comportamiento facilitado por operaciones tales como SubePasajero y BajaPasajero, que permiten incrementar o decrementar el nmero de pasajeros. ste comportamiento de forma clara va ms all de cualquier comportamiento que VehiculoDeCarretera pueda tener, despus de todo, VehiculoDeCarretera no tiene alguna nocin de lo que es un pasajero pues est fuera de su especificacin. Es decir VehiculoDeCarretera carece de la dimensin NumeroDePasajerosActual en su espacio de estados. De donde, cualquier comportamiento que se mueva en la dimensin de NumeroDePasajerosActual no ser posible definir para VehiculoDeCarretera. En el ejemplo discutido se muestra que Automovil puede extender el comportamiento de su superclase, VehiculoDeCarretera, en la medida que Automovil extiende el espacio de estados de VehiculoDeCarretera. El comportamiento de Automovil estar confinado por el comportamiento de VehiculoDeCarretera. En la medida que el espacio de estados de Automovil est confinado por el espacio de estados de VehiculoDeCarretera. Un ejemplo posible es el siguiente: Uno podr incrementar un 5 ton al peso de un vehculo para un vehculo de carretera genrico, en la medida que ste no exceda el lmite de 10 ton, de cualquier forma uno no podr incrementar 5 ton al peso de un automvil por que su peso mximo es de 3 ton y al hacer esto uno se saldr del espacio de estados de Automovil. En general el confinamiento del comportamiento de una clase es un principio muy importante en el diseo de las subclases, a este principio se le denomina comportamiento cerrado y ser discutido en el captulo siguiente.

3.4. Los Invariantes de Clase como una restriccin en el espacio de estados. La mayora de los espacios de estados que se han ilustrado en ste captulo han sido completos en el sentido que un objeto puede ocupar cualquier lugar en la rejilla del espacio de estados. Pero, muchas clases no autorizarn a sus objetos sta libertad. Por ejemplo el caso del caballo en el tablero con bloque de la figura 3.2. muestra un caso de restriccin. En general ser necesario definir de manera formal los estados permitidos para los objetos de una clase. El espacio de estados legal de una clase se define por sus invariantes de clase.

41

Un invariante de clase es una condicin que todo objeto de esa clase debe satisfacer en todo momento cuando el objeto est en equilibrio. O O R I E N T A D O A O B J E T O S DISE La expresin cuando un objeto est en equilibrio significa que un objeto puede obedecer a sus invariantes de clase todo el tiempo cuando no est inmerso en un ambiente de cambios de estado. En particular, un objeto debe estar en la lnea de invariantes cuando el objeto es inicializado en el momento de la instanciacin en general mediante algn constructor de la clase y antes y despus que cualquier operacin (pblica) sea ejecutada. Para ejemplificar tomemos la clase Triangulo. Si los lados de un tringulo son Triangulo.a, Triangulo.b y Triangulo.c, como se muestra en la figura 3.6. Triangulo props: b a a b c c

Figura 3.6. Clase Tringulo y sus propiedades bsicas. Un invariante de clase para Triangulo puede ser: a + b c and b + c a and c + a b. Que establece que, independientemente de la clase de objeto de la clase Triangulo uno tenga, la suma de las longitudes de cualquiera de sus lados debe ser mayor o igual que la longitud de tercer lado. El espacio de estados de Triangulo se puede representar como un sistema (Figura 3.7) de tres coordenadas etiquetadas a, b y c. Ms en general esto est restringido slo a un conjunto de puntos en el espacio (a, b, c), en particular aquellos que satisfacen el invariante para Triangulo formarn es verdadero espacio para la clase.

b Figura 3.7. Espacio de estados 3D para Triangulo donde no todas las posiciones representan tringulos vlidos.

42

DISEO

ORIENTADO

OBJETOS

Por ejemplo no es posible formar un tringulo con lados (1, 2, 5) o (2, 3, 9), pues violan el invariante de clase. Ms las ternas (3, 4, 5) y (4, 4, 6) si lo satisfacen. En la figura 3.8 se muestra una jerarqua de las variedades de tringulos.
Triangulo

TrianguloRectangulo

TrianguloIsosceles

TrianguloIsoscelesRectangulo

Figura 3.8. Cuatro tipos de tringulos vlidos

La clase TrianguloIsosceles tiene el invariante, a = b or b = c or c = a. Por otro lado la clase TrianguloRectangulo tiene el invariante (basado en el Teorema de Pitgoras), si c es el lado mayor, a2 + b2 = c2 . Dado que las invariantes se heredan, una clase dada debe obedecer las invariantes de sus superclases. Por lo tanto como TrianguloIsosceles y TrianguloRectangulo son subclases de Triangulo, tambin heredarn el invariante a + b c and b + c a and c + a b. En consecuencia, los objetos de la clase TrianguloIsosceles siempre obedecern al invariante compuesto (a + b c and b + c a and c + a b) and (a = b or b = c or c = a.). Para mantener stas caractersticas adicionales, la clase TrianguloIsoscelesRectangulo - que hereda tanto de TrianguloIsosceles como de TrianguloRectangulo tiene un espacio de estados formado por los puntos que son vlidos en forma simultnea TrianguloIsosceles y TrianguloRectangulo. Su invariante de clase es en consecuencia el and lgico de los invariantes de TrianguloIsosceles y TrianguloRectangulo, explcitamente:
(a + b c and b + c a and c + a b) and (a = b or b = c or c = a) and si c es el lado mayor, a2 + b2 = c2.

43

DISEO

ORIENTADO

OBJETOS

En lenguajes como C++ y Java, un invariante de clase es un constructor terico, que no se implementa de manera directa en el lenguaje. En estos lenguajes, los invariantes de clase no se heredan realmente en el mismo sentido que se heredan los atributos.

3.5. Precondiciones y Postcondiciones. Una vez que se han revisado los invariantes o reglas que gobiernan a una clase de manera global, en esta seccin se estudiarn las condiciones que rigen las operaciones de manera individual. Toda operacin tiene una precondicin y una postcondicin. La precondicin es una condicin que debe cumplirse cuando la operacin inicia su ejecucin. En caso de no cumplirse, entonces la operacin podr de manera legtima rehusar su ejecucin y posiblemente disparar alguna excepcin. La postcondicin es una condicin que debe ser verdadera cuando la operacin termina su ejecucin. S no es verdadera, entonces la implementacin de la operacin tiene defectos y debern ser corregidos. Esquemticamente tendremos (fig. 3.9):

En caso de no cumplirse
Precondicin Postcondicin No ejecutar operacin y disparar excepcin. Implementacin incorrecta de la operacin y se requiere corregirla.

Figura 3.9. Medidas a tomar en caso de una violacin a la pre o post condicin.

Tomemos por ejemplo la operacin Pila.pop, que extrae el elemento que se encuentra en la cima de la pila. La precondicin para sta operacin es not vaca. Si la precondicin de una operacin se cumple, la implementacin de la operacin debe garantizar que la postcondicin de ella se cumpla cuando sta se termine. Por ejemplo, la postcondicin para Pila.pop puede ser (numElementos = old numElementos-1) and not Llena, donde la funcin old se debe interpretar cualquier valor que esto tena antes de que la operacin sea ejecutada.

44

DISEO

ORIENTADO

OBJETOS

Bertrand Meyer y otros autores describen las pre- y postcondiciones de una operacin como un contrato entre una operacin y un cliente que enva un mensaje a esa operacin [6]. La metfora del contrato implica que 1. Si el transmisor (sender) del mensaje puede garantizar que la precondicin sea verdadera, entonces el receptor (target) encargado de la operacin garantizar que la postcondicin sea verdadera despus de la ejecucin. 2. Si, por otro lado, el transmisor del mensaje no puede garantizar que la precondicin sea verdadera, entonces el contrato completo se ha violado y es invlido: La operacin no est obligada a ser ejecutada y de serlo a garantizar la postcondicin. Debemos puntualizar que un invariante de clase es verdadero tanto cuando una operacin inicia su ejecucin y cuando la termina. As la historia completa de las pre- y postcondiciones es que una operacin est enmarcada (ensandwichada) por las dos condiciones compuestas, tal que: Invariante de clase and Precondicin de la operacin Ejecucin de la operacin

Invariante de clase and Postcondicin de la operacin Como un ejemplo, consideremos una clase Rectangulo, que define cuatro propiedades puede que no sea la mejor construccin, pero sirve para el ejemplo. La operacin que se introducir es escalaHorizontal y lo que har es estirar o reducir el tamao del rectngulo a travs de factor real multiplicativo y tendr un argumento FactorEscala. La ficha de la clase puede quedar de la siguiente manera: Rectangulo props: w1 h1 w2 h2 // ancho inferior // alto izquierdo // alto superior // alto derecho

metodos: escalaHorizontal(real FactorEscala)

45

DISEO

ORIENTADO

OBJETOS

El invariante de clase para se puede definir: w1 = w2 and h1 = h2. Una precondicin para la escalaHorizontal ser: AnchoMaximoPermitido w1 * FactorEscala . Y la postcondicin natural ser: w1 = (old w1) * FactorEscala. Poniendo todo junto tendremos que: w1 = w2 and h1 = h2 and AnchoMaximoPermitido w1 * FactorEscala escalaHorizontal(real FactorEscala)

w1 = w2 and h1 = h2 and w1 = (old w1) * FactorEscala La primera lnea corresponde a la precondicin, la segunda a la operacin y la tercera a la postcondicin. Es bueno aclarar que algunas personas escriben los invariantes de clase como parte de las pre- y postcondiciones de las operaciones; lo cual eventualmente es tedioso y redundante. Sin embargo, los invariantes de clase estn dados implcitamente y uno puede incluirlos en la fase de diseo ya sea dentro de las operaciones o de los mtodos que las implementan. En resumen podemos decir que: 1. Todo objeto de una clase dada debe satisfacer los invariantes de clase. Estos invariantes actan como una constriccin, limitando el tamao del espacio de estados de la clase. Una subclase heredar los invariantes de clase de su(s) superclase(s) y aadir un conjunto extendido de restricciones propias en general. 2. Cada operacin de una clase tendr una precondicin y una postcondicin, que en conjunto forman un contrato entre la operacin y el cliente de tal operacin [6]. Las precondiciones deben cumplirse para ejecutar la operacin. Las postcondiciones establecen cuando la operacin se ha realizado con xito. Hablando formalmente, los invariantes de clase son parte de toda precondicin y postcondicin de una operacin. Desde el punto de vista prctico, uno no escribe los invariantes de clase como parte de las pre- y postcondiciones, los aplica implcitamente. 3. Los invariantes de clase, junto con las pre- y postcondiciones de las operaciones forman un marco de trabajo (framework) para el proceso de diseo conocido como Diseo por Contrato, el cual garantiza que la operacin del objeto receptor generar una respuesta correcta a un mensaje enviado a l y que el cliente ha obedecido las precondiciones de la operacin.

46

DISEO

ORIENTADO

OBJETOS

4. Conformidad de Tipos y Comportamiento Cerrado.


Una jerarqua robusta de clase es de servicio pesado (heavy-duty) y de una tranquilidad permanente. Los objetos de una clase tendrn un buen comportamiento en relacin a los objetos de una superclase, y la jerarqua como un todo soportara los embates del tiempo. Por otro lado, los diseos pobres de la jerarqua de clases tendrn una vida corta, influyendo negativamente en los proyectos realizados y la orientacin a objetos. En este captulo se introducirn un par de principio que son vitales en la construccin de la salud y la fortaleza de las jerarquas de clase. Los principios son la conformidad de tipos y el comportamiento cerrado.

4.1. Clases vs. Tipos. La mejor manera de pensar de una clase es como una implementacin de un tipo, que corresponde a una vista abstracta o externa de la clase. De otra manera, los tipos incluyen el propsito de la clase, junto con su espacio de estados y su comportamiento. De manera especfica el tipo de una clase esta definido por los siguientes elementos: 1. el propsito de la clase 2. el (los) invariante(s) de la clase 3. los atributos de la clase 4. las operaciones de la clase 5. las precondiciones y postcondiciones 6. las definiciones 7. las firmas

47

DISEO

ORIENTADO

OBJETOS

Una clase en suma, incorpora un diseo interno que implementa caractersticas externas como un tipo. El diseo interno, incluye el diseo de las variables de la clase y el diseo de los algoritmos para los mtodos de operacin. Claro est que un tipo simple puede ser implementado mediante una serie de clase, donde cada clase tendr su propio diseo interno particular. Por ejemplo, uno puede crear diversas clases del mismo tipo con el propsito de darle a cada clase sus propias ventajas para hacerla eficiente en algunas circunstancias especiales. De igual forma uno puede disear una versin especial de una clase que utilice un algoritmo que corra muy rpido sobre un modelo particular de computadora. Por ejemplo pensemos en diseo de ColeccionOrdenada que implemente por un lado: recorrido y otra que sea muy eficiente para insertar y eliminar elementos. Ambas versiones de ColeccionOrdenada pueden implementar el mismo tipo con los mismos atributos y operaciones. La figura 4.1. muestra en notacin UML un tipo, que es idntico al smbolo de la clase, pero tiene el estereotipo life en el compartimiento de nombre. Cuando los tipos aparecen en un diagrama, uno deber usar el estereotipo class en los smbolos de clase para distinguirlos con nfasis de los tipos (fig 4.1).
type Coleccion {abstract}
addElement(new element){abstract}

class ArbolConApuntadores

implementa a

type Arbol

class ArbolConMatricesDispersas

addElement(new element)

implementa a

Figura 4.1. El tipo Coleccin con su subtipo Arbol, que est implementado por dos clases

Las lneas punteadas marcadas con el estereotipo implementa a indican que clase es una implementacin de que tipo. Como se muestra en la figura 4.1, un tipo simple puede ser implementado por mltiples clases, cada una probablemente con sus caractersticas propias de eficiencia Normalmente, stas clases no tienen nombres tan largos; y sus tcnicas de implementacin podrn aparecer en sus documentaciones internas.

48

DISEO

ORIENTADO

OBJETOS

La flecha a la izquierda muestra que el tipo Arbol es un subtipo de coleccin. El hecho que Coleccin sea tambin {abstract} significa que Coleccin no necesita ser implementada por alguna clase; slo los subtipos de Coleccin requerirn implementar clases. En general un tipo representa la vista externa de una clase, el concepto de subtipo es diferente del de subclase. Incluso sin una definicin formal de subtipo, uno puede probablemente intuir que las subclases no son subtipos vlidos de sus superclases respectivas, como se realizar en el ejemplo siguiente. Dado que uno puede crear cualquier clase sintcticamente como una subclase de cualquier otra, podramos crear algo como que Elefante herede de Rectangulo o que ReporteDeVentas herede de Ladrillo. stas en general son estructuras vlidas y legales de clase/subclase, pero semnticamente no tienen sentido, por que las subclases no tienen que ver con sus respectivas superclases. Por ejemplo, no tendr sentido aplicar el Teorema de Pitgoras a un elefante con el propsito de hallar su hipotenusa. Y por otro lado la operacin ComisionDeEnvio no calza con una pieza de material de construccin cuando est esperando un representante de ventas. As que, siempre que S sea una subclase de T, no se sigue de manera automtica que S sea tambin un subtipo de T. Uno deber trabajar con el diseo de la clase S si desea hacerlo un subtipo de T. Esto se basar en que S deber ser un subtipo vlido de su superclase T.

4.2 El principio de Conformidad. El principio de diseo que se deriva de la conformidad de tipos viene de la teora abstracta de tipos de datos, en la cual se fundamenta la orientacin a objetos. ste principio, que es extremadamente importante en la creacin de las jerarquas de clases que forman una biblioteca de clases, establece que Si S es un subtipo vlido de T, entonces S debe estar en conformidad a T. En otras palabras, un objeto de tipo S puede ser suministrado en cualquier contexto donde un objeto de tipo T sea esperado, y lo consistencia se preservar a pesar de que cualquier operacin de acceso al objeto sea ejecutada. Por ejemplo, Circulo es un subtipo de Elipse. Cualquier objeto que es un crculo es tambin una elipse es decir una elipse simtrica, redondeada. As, cualquier operacin que espere a una elipse como argumento de un mensaje, no tendr problemas en recibir un crculo. Lgicamente la operacin fallar si la operacin intenta achatar al crculo, pues dejar de serlo y ya no cumplir con su invariante de clase. Como se ha marcado, una subclase y un subtipo corresponden a conceptos distintos, regresando al punto se puede decir que En un diseo orientado a objetos, el tipo de cada clase debe estar en conformidad con el tipo de su superclase. En otras palabras, la jerarqua de herencia para las clases/subclases deber seguir el principio de conformidad de tipos.

49

DISEO

ORIENTADO

OBJETOS

La razn que subyace en ste argumento es que con el propsito de fortalecer el polimorfismo, uno debe ser capaz de pasar objetos de una subclase en lugar de objetos de una superclase. Pero como se garantizar que el de tipo de cada subclase realmente y de manera honesta esta en conformidad al tipo de su superclase? La respuesta es la siguiente: Se requiere de dos principios anexos a la conformidad mas: el principio de contravarianza y el principio de covarianza, stos usarn las nociones de: invariante de clase, pre- y postcondiciones de las operaciones, espacio de estados y comportamiento.

4.2.1. Los Principios de Contravarianza y Covarianza

Estos principios no son simples de exponer y comprender, por lo cual se recomienda una lectura minuciosa y reflexiva. Para garantizar la conformidad de tipos en una subclase, uno primero necesita garantizar que el invariante de la subclase sea al menos tan fuerte como el de la superclase. Por ejemplo s, Rectangulo tiene el invariante w1 = w2 and h1 = h2. Cuadrado tiene el invariante w1 = w2 and h1 = h2 and w1 = h1. Entonces todo marcha bien, por que el invariante de Cuadrado es ms fuerte que el Rectangulo. Puede verse que un objeto que utilice el invariante de Cuadrado estar obligado a utilizar el invariante de Rectangulo, pero un objeto que cumpla con el invariante de Rectangulo no cumplir en general el correspondiente a Cuadrado. Segundo, uno necesita garantizar las siguientes tres restricciones en la operacin a realizarse: 1. Toda operacin de la superclase tiene una operacin correspondiente en la subclase con el mismo nombre y firma. 2. Toda precondicin de una operacin no puede ser ms fuerte a la de la operacin correspondiente en la superclase. ste se denomina Principio de Contravarianza, denominado as por que la fuerza de las precondiciones de una operacin en las subclases van en sentido contrario a la fuerza del invariante de clase. Esto es, las precondiciones de una operacin son, de haberlas, ms dbiles. 3. Toda postcondicin de una operacin debe ser al menos tan fuerte como la correspondiente a la operacin en la superclase. Esto se llama Principio de Covarianza, y es denominado as por que la fuerza de las postcondiciones de una operacin en una subclase estn en sentido contrario

50

DISEO

ORIENTADO

OBJETOS

que la fuerza del invariante de clase. Esto es, las postcondiciones de una operacin son, de haberlas, ms fuertes. Los trminos ms fuerte y ms dbil en las restricciones antes expuestas no describen la calidad o robustez en algn sentido. En general debemos entender que ms fuerte no se debe considerar mejor o ms dbil como algo peor. stas restricciones se satisfarn trivialmente si una subclase hereda una operacin tal cual es de su superclase. En ese caso, el nombre, firma, precondiciones y postcondiciones son idnticas tanto en la superclase como en la subclase. Una situacin que se vuelve interesante, es cuando una subclase invalida (override) una operacin de una superclase mediante una operacin propia. En la seccin siguiente se plantea un ejemplo ilustrativo.

4.2.2. Ilustracin de la Contravarianza y Covarianza.

La clase Empleado tiene una subclase Administrador, es decir los administradores son una subclase de los empleados. Qu se debe garantizar para que Administrador sea un subtipo vlido de Empleado? Primero, Digamos que el invariante de Empleado es escolaridad > 0 y el invariante de Administrador es escolaridad > 20. Esto ocasiona que el invariante de clase de Administrador es ms fuerte que el de Empleado, por lo cual hasta aqu todo est en regla con las reglas de diseo. Segundo, consideremos calculaEstimulo como una operacin de Empleado. sta tomar a EvalRend (Evaluacin del Rendimiento) y calcular PorcEstim (Porcentaje de Estmulo), que corresponde a un porcentaje del salario base del empleado (sin prestaciones). En la figura 4.2. se muestra un diagrama en UML para la firma de calculaEstimulo. Empleado
calculaEstimulo(EvalRend)

Administrador
calculaEstimulo(EvalRend) Figura 4.2. Definicin de calculaEstimulo para Empleado y Administrador.

Digamos por simplicidad que EvalRend (el argumento que se pasa a calculaEstimulo) es un entero entre 0 y +5. Y que la salida de calculaEstimulo est entre 0 y 10 por ciento.

51

DISEO

ORIENTADO

OBJETOS

Los algoritmos para calcular los estmulos debern ser diferentes para los administradores y los que no son administradores. En consecuencia, la clase Administrador puede invalidar calculaEstimulo con una operacin implementada por ella (con el mismo nombre y firma). Regresando a la operacin calculaEstimulo como fue definida en la clase Administrador. Recordando que para que Administrador est en conformidad con Empleado, entonces Administrador.calculaEstimulo debe tener una precondicin igual a o ms dbil que Empleado.calculaEstimulo. Esto implica que en particular el rango del argumento de entrada EvalRend de Administrador.calculaEstimulo debe ser igual a o mayor que el rango del argumento de entrada EvalRend de Empleado.calculaEstimulo. Una manera recordar que mayor rango = condicin ms dbil, es asociar mayor como flojo suelto y en contraposicin menor como apretado. As entonces, cada uno de los siguientes rangos para el argumento de entrada EvalRend para Administrador.calculaEstimulo ser legal: 05 08 -19 // igual para las clases Administrador y Empleado // mayor (ms dbil) en Administrador // mayor (ms dbil) en Administrador. Suponiendo que una // evaluacin negativa tiene sentido. Al contrario, los siguientes rangos para el argumento de entrada EvalRend de Administrador.calculaEstimulo sern ilegales: 15 24 // menor (ms fuerte) en Administrador // todava menor (ms fuerte) en Administrador

En la figura 4.3 se ilustra los ejemplos anteriores, relativos a los rangos para EvalRend.

} }
0 1 2 3 4 5 6

Rangos legales

Rangos ilegales
EvalRend
7 8 9 10 11 12 13 14

Figura 4.3. Contravarianza: posibles rangos para EvalRend en

Administrador.calculaEstimulo(EvalRend)
52

DISEO

ORIENTADO

OBJETOS

Para que Administrador est en conformidad con Empleado, la operacin calculaEstimulo de Administrador debe tener una postcondicin igual o ms fuerte que la correspondiente calculaEstimulo de Empleado. Esto significa que en particular, el rango del argumento de salida PorcEstim de Administrador.calculaEstimulo debe ser menor que o igual al rango del argumento de salida PorcEstim de Empleado.calculaEstimulo. As, cada uno de los siguientes rangos para el argumento de salida PorcEstim de Administrador.calculaEstimulo ser legal: 0% 10% 0% 6% 2%4% // igual en ambas clases Administrador y Empleado // menor (ms fuerte) en Administrador // todava menor (ms fuerte) en Administrador.

Al contrario, los siguientes rangos para el argumento de salida PorcEstim de Administrador.calculaEstimulo sern ilegales: 0% 12% -1% 13% // mayor (ms dbil) en Administrador // mayor (ms dbil) en Administrador. Suponiendo que un estmulo // negativo tiene sentido. En la figura 4.4. se muestran los rangos legales e ilegales para PorcEstim de forma pictrica:

}
0 1 2 3 4 5 6 7 8 9 10 11

Rangos legales

}
12 13 14

Rangos ilegales
PorcEstim

Figura 4.4. Covarianza: posibles rangos para PorcEstim en

Administrador.calculaEstimulo(EvalRend)

Los principios de precondiciones dbiles y postcondiciones fuertes en las operaciones de las subclases no son intuitivos. Estos principios son importantes en el diseo orientado a objetos cuando uno quiere que la jerarqua de clases implantada siga una jerarqua de tipos correcta.

53

DISEO

ORIENTADO

OBJETOS

La relevancia de la conformidad de tipos proviene de las demandas del diseo de segundo orden, en el cual un argumento (de un mtodo) en un sistema orientado a objetos, que es un objeto, acarrea el cdigo gentico completo de su clase junto con l. El diseo de segundo orden aparece cuando los argumentos de un mensaje presentan encapsulacin de nivel-2 en otras palabras, cuando los argumentos de los mensajes son referencias a objetos. En el diseo de primer orden, los componentes de software se comunican pasndose argumentos con nivel-1 de encapsulacin (funciones y procedimientos). En el diseo de orden cero, los argumentos son simplemente datos. Se entiende entonces que: El diseo estructurado corresponde a un diseo de orden cero, con algunas ocurrencias de diseo de primer orden cuando se pasan como argumentos funciones o procedimientos.

4.2.3. Ilustracin de contravarianza y covarianza.

Supongamos que se quiere conectar una manguera de un dimetro con otra de otro dimetro, para esto resultar til un cople convertidor con un dimetro en un extremo (correspondiente a una manguera) y otro dimetro en el otro extremo (correspondiente a la otra manguera). Las mangueras acopladas formarn un nuevo sistema con un atributo nuevo, que no permite un mayor alcance que cada una por separado. Lo cual es conveniente pues resuelve nuevos problemas. Esquemticamente podemos presentar la situacin con la figura siguiente (figura 4.5)

argumentos de entrada actuales

argumentos de entrada formales

argumentos de salida formales

argumentos de salida actuales

invocando operacin i

operacin invocada T.op

invocando operacin i

Figura 4.5. Invocacin de la operacin op del supertipo T.

Usando la metfora del convertidor de dimetros para las mangueras, la figura ilustra la conexin del llamado una operacin i al llamado de una operacin op sobre una clase T. Del lado izquierdo (extremo de entrada), se ve que los argumentos de entrada actuales de i pasan como parmetros a la operacin op. Ya que el rango de todo argumento actual de i cae dentro del rango de sus correspondientes argumentos formales en op, los argumentos de entrada sern aceptables para op. Para simbolizar esto, se ha dibujado la entrada del tubo que corresponde a los argumentos formales de entrada mas grande que el correspondiente a los argumentos de entrada actuales de i.

54

DISEO

ORIENTADO

OBJETOS

A la derecha (extremo de salida), se tiene la situacin contraria, como la operacin invocada op regresa su resultado. En este caso, el rango de cada argumento formal de salida debe caer dentro del rango de valores
argumentos de entrada actuales argumentos de entrada formales argumentos de salida formales argumentos de salida actuales

invocando operacin i

operacin invocada S.op

invocando operacin i

Figura 4.6. Invocacin de la operacin op sobre un subtipo S.

aceptables para los argumentos actuales de i correspondientes. Para simbolizar el hecho, se han dibujado los argumentos formales de salida de op como un tubo de menor dimetro que el tubo que corresponde a los argumentos de salida actuales de i. Echando un vistazo a la figura 4.6, se muestra otra operacin op, sta vez definida sobre S, que es una subclase de T. En otras palabras, S.op invalida y redefine T.op. Si S es un subtipo vlido de T, entonces las operaciones de S, como es el caso de op, deben obedecer a los principios de contravarianza y covarianza. Se ha simbolizado el principio de contravarianza haciendo que el dimetro del tubo que representa a los argumentos formales de entrada de S.op (al lado izquierdo) sea todava mayor que el dimetro del tubo correspondiente a los argumentos de entrada formales de T.op. As, si el tubo de los argumentos formales de entrada de T.op fuera suficientemente grande para aceptar los argumentos actuales de i, entonces el de S.op sera con seguridad suficientemente grande tambin. En ste contexto se debe entender el concepto de rango grande en vez que el concepto ms general de supertipo como una ilustracin de precondiciones dbiles. En el lado derecho (el lado de salida), otra vez se tiene la situacin contraria. Ahora se ha simbolizado el principio de covarianza haciendo que el tubo de los argumentos de salida formales de S.op es todava menor que el tubo correspondiente a los argumentos de salida formales de T.op. Es decir, si el tubo de los argumentos de salida formales de T.op fuera suficientemente pequeo para coincidir con el tubo de los argumentos actuales de i, entonces el de S.op sera seguramente suficientemente pequeo tambin. Las figuras anteriores tratan de ilustrar la naturaleza de los principios de contravarianza y covarianza. Para un subtipo que conforma a un objeto del subtipo debe ser aceptable en todo lugar un objeto del supertipo correspondiente, esto es para casar con su supertipo.

4.2.4. Resumen de los requerimientos para la conformidad de tipos.

55

DISEO

ORIENTADO

OBJETOS

El principio de conformidad exige que para que una subclase S sea un subtipo vlido de la clase T, se cumplan las siguientes seis demandas 1. El espacio de estados de S debe tener las mismas dimensiones de T. Pero S puede tener dimensiones adicionales que extienden el espacio de estados de T. 2. En las dimensiones que S y T comparten, el espacio de estados de S debe ser ya sea igual a o caer dentro del espacio de estados de T. Es decir, el invariante de clase de S debe ser igual o ms fuerte que el respectivo de T. Para cada operacin de T que S invalide y redefina con S.op. 3. S.op debe tener el mismo nombre como T.op. 4. La lista de argumentos de la firma formal de S.op debe corresponder a la lista de argumentos de la firma formal de T.op. 5. La precondicin de S.op debe ser igual a o ms dbil que la precondicin de T.op. En particular, cada argumento de entrada formal a S.op debe ser un supertipo de (o del mismo tipo que) el argumento de entrada formal a T.op. Esto establece el principio de contravarianza. 6. La postcondicin de S.op debe ser igual a o mas fuerte que la postcondicin de T.op. En particular, cada argumento de salida formal de S.op debe ser un subtipo de (o del mismo tipo que) el argumento de salida formal de T.op. Este es el principio de covarianza.

4.3. El Principio de Comportamiento Cerrado. En las secciones anteriores, se ha estudiado el principio de conformidad de tipos. Aunque el respeto a la conformidad de tipos es necesario para ser capaces de disear jerarquas de clases de sonido, la conformidad de tipos no es suficiente. Hablando informalmente, la conformidad de tipos por si sola nos llevar a un diseo aplicable solo en situaciones de solo lectura (read-only) para el sonido, esto es, solo ante operaciones de lectura.

En una jerarqua de herencia basada sobre una jerarqua de tipo/subtipo, la ejecucin de cualquier operacin sobre un objeto de clase C incluyendo cualquier operacin heredada de la(s) superclase(s) de C debe obedecer al invariante de clase de C. Para manejar situaciones en las cuales se ejecuten operaciones de modificacin, se requerir el Principio de Comportamiento Cerrado. ste principio pide que el comportamiento heredado por una subclase de una superclase respete el invariante de la subclase. Sin ste principio, uno podr disear subclases con operaciones de modificacin que sern propensas a un comportamiento errneo.

Principio de comportamiento cerrado.

56

DISEO

ORIENTADO

OBJETOS

Como un ejemplo de ste principio, analicemos cmo el comportamiento definido en una superclase Poligono puede afectar a objetos de una subclase Triangulo. Es importante hacer notar que en el desarrollo de ste ejemplo, en cada uno de los casos expuestos, el objeto involucrado es de la clase Triangulo, pero el comportamiento esta definido por una operacin de Poligono. Caso 1. Tomaremos el objeto tr1 como el tringulo izquierdo de la figura 4.7, y la operacin perteneciente a Poligono llamada mover, que hace que un objeto se mueva a la derecha un centmetro.

tri1 : Poligono
mover

mover(distanc : longitud)

Fig. 4.7. Operacin Poligono.mover, aplicada al tringulo tr1, preserva la triangularidad.

Despus del movimiento, tr1 sigue siendo un tringulo. Este comportamiento para una instancia de Poligono deja al objeto que estaba en el espacio de estados de Triangulo dentro del mismo espacio de estados. Diremos que la subclase Triangulo es cerrada bajo el comportamiento definido por la operacin mover de su superclase. Caso 2. Tomemos otra vez a tr1 como un tringulo. Y consideremos una operacin aumentaVer-

tri1 : Poligono
aumentaVertice

aumentaVertice(new Vert : punto)

Fig. 4.8. Operacin Poligono.aumentaVertice, aplicada (errneamente) al tringulo tr1, destruye la propiedad de triangularidad.

tice (heredada de Poligono) que incorpora un nuevo vrtice al polgono (Figura 4.8.). Despus de sta transicin, tr1 ya no ser un tringulo: se convertir en un cuadriltero. Diremos que la subclase Triangulo no es cerrada bajo el comportamiento definido por la operacin aumentaVertice de la superclase Poligono. La cerradura de una subclase bajo el comportamiento de su superclase no se da de manera automtica, como se mostr en el caso 2. Uno debe disear dentro. Es decir, para disear una subclase, uno debe de manera explcita y deliberada invalidar ciertas operaciones de la superclase que puedan violar el invariante de la subclase.

57

DISEO

ORIENTADO

OBJETOS

En el ejemplo, como diseador de Triangulo, uno debe realizar una de las tres acciones correctivas siguientes: Evitar la Herencia de aumentaVertice, o Invalidar aumentaVertice de tal forma que no tenga efectos ( posiblemente disparando una excepcin), o Estar preparado (en la operacin aumentaVertice) reclasificar al objeto Triangulo como Rectangulo, si ese comportamiento, que no preserva la cerradura de Triangulo es aceptable en la aplicacin.

En general, el diseador de una clase tiene el deber de garantizar el comportamiento cerrado de la clase. Los diseadores de otras clases en consecuencia no debern preocuparse por el mantenimiento del invariante de clase. De cualquier forma no ser mala costumbre hacer una revisin de rutina. Si uno est diseando una clase que enva un mensaje a un objeto invocando una operacin de modificacin, uno deber revisar la cerradura del comportamiento de la clase en cuestin. Si uno enva un mensaje suponiendo el caso general (superclase), uno debe estar preparado para esperar un rechazo del mensaje por parte del objeto o simplemente hacer un retorno (return) sin accin alguna. Si este s el problema, entonces antes de enviar el mensaje se requerir realizar una de las siguientes aciones: Revisar la clase en tiempo de ejecucin (run time) con la prueba, o Restringir el polimorfismo sobre la variable que apunta a la prueba, o Disear el mensaje bajo la hiptesis que la prueba es de lo ms especfico, es decir una clase en la parte ms baja de la jerarqua es decir, la clase con las mayores restricciones en su comportamiento.

En resumen podemos decir que el principio de conformidad enuncia que: una clase B es un subtipo de la clase A solo s un objeto de la clase B ser aceptable en cualquier contexto en el cual un objeto de la clase A sea esperado y ninguna operacin de modificacin sea ejecutada. Por otro lado Si una clase B es una subclase de la clase A, entonces B estar en conformidad con A. Para alcanzar sta propiedad, uno debe asegurar lo siguiente: 1. El invariante de cada subclase es al menos tan fuerte como el de su superclase

58

DISEO

ORIENTADO

OBJETOS

2. Cada operacin de la superclase tiene una operacin correspondiente en la subclase con el mismo nombre y firma; cada precondicin en las operaciones de las subclases no son ms fuerte que la operacin correspondiente en la superclase 3. Y que cada postcondicin en las operaciones de las subclases es al menos tan fuerte a la operacin correspondiente en la superclase. Los dos ltimos principios estn vinculados, respectivamente, con el principio de contravarianza y el principio de covarianza, los cuales son muy importantes para determinar las clases correctas en los argumentos de las operaciones de las subclases. Cada clase en una jerarqua de clases deber obedecer al principio de comportamiento cerrado. Esto obliga a que el comportamiento que una subclase hereda de su(s) superclase(s) respete el invariante de la subclase. El diseador de subclases lograr esto mediante: 1. La prohibicin de la herencia de comportamientos conflictivos. 2. La invalidacin de operaciones a heredarse que tengan conflictos de comportamiento. 3. La migracin de los objetos de una clase a otra, siempre que se haya violado el invariante de clase, eventualmente se deber crear una clase especializada en caso de no hallarse alguna a donde migrar el objeto.

Los principios planteados en ste captulo son importantes en s y nos guan para un buen diseo.

59

DISEO

ORIENTADO

OBJETOS

5. Los Peligros de la Herencia y el Polimorfismo.


La herencia y el polimorfismo colocan a la orientacin objetos en un lugar aparte respecto a la manera tradicional de la construccin de software. En general aunque la herencia en muy poderosa, es a la vez el mecanismo de construccin de software ms sobreutilizado desde la aparicin de la instruccin goto de los primeros lenguajes de tercera generacin. Los principiantes en el mundo de la programacin orientada a objetos sienten que deben disear sus aplicaciones usando la herencia en toda oportunidad posible con el propsito de demostrar que son capaces en el mundo de la orientacin a objetos. Lo cual resulta en diseos muchas veces difciles o bien imposibles de implementar. 5.1. Abusos de la Herencia Los siguientes ejemplos han sido tomados de algunos diseos reales [1] y se han adaptado para mostrar algunos de los problemas de la herencia mal manejada. El propsito de sta seccin es examinar diferentes patrones de herencia y prevenir la prdida de tiempo en los proyectos de software apuntando a entender donde es apropiada e inapropiada la herencia.
5.1.1. Agregados errneos.

En la parte superior de la figura 5.1.a. se muestra un diagrama de herencia de clase, se puede ver que la clase Avion con sus cuatro supuestas subclases: Ala, Cola, Motor y Fuselaje. Avion

Ala

Cola

Motor

Fuselaje

Fig. 5.1.a. Un Diagrama de herencia para la clase Avion con un mal diseo implcito.

ste diseo no podr expresarse como cdigo, pues no existe una manera para programar las subclases que requiere la aplicacin. El diseador ha mezclado los conceptos de herencia de clase y composicin de objetos. Si uno hace una lectura del diagrama como se presenta, uno deber asumir que una cola es una clase de Avion y que tambin un ala es una clase de Avion.

60

DISEO

ORIENTADO

OBJETOS

El diseo que se muestra en la figura 5.1.b. hay herencia mltiple y corresponde a otro supuesto diseo que resuelve la composicin de objetos. Ala Cola Motor Fuselaje

Avion
Fig. 5.1.b. Un Diagrama de herencia mltiple para la clase Avion con otro mal diseo implcito.

El diseador de ste segundo Avion lee el diagrama como, Un avin es un ala, una cola, un motor y un fuselaje. Lo cual suena en general correcto. Sin embargo la manera correcta de interpretar el diagrama es: Un aeroplano es simultneamente una clase de ala, una clase de cola, una clase de motor y una clase de fuselaje Y esto es evidentemente errneo. Si uno intenta usar ste segundo modelo para generar cdigo, se enfrentar a la situacin de que un avin tiene dos alas.
5.1.2. Jerarqua Invertida.

El ejemplo de herencia que se muestra en la figura 5.2. requiere a ojos vista una segunda revisin, debido a que su estructura corresponde de manera exacta a un mapa organizativo normal.
MiembroMesaDirectiva

Gerente

Un empleado reporta a un gerente y un gerente reporta a un accionista. Pero hay un problema. Lo que el diagrama dice es que: Un empleado es una clase de administrador, y que un administrador es una clase de miembro de la mesa directiva.

Empleado

Uno puede notar que la realidad es otra, uno espera que Un miembro de la mesa directiva es una clase de administrador y que un administrador es una clase de empleado.

Figura 5.2. Todo parece bien pero es as ?

Para realizar una representacin correcta, uno deber simplemente invertir la figura 5.2 y colocar a Empleado, que es la clase ms general, en la parte superior.

61

DISEO

ORIENTADO

OBJETOS

5.1.3. Confundiendo Clases e Instancias.

El ejemplo de herencia mltiple que se presenta en la figura 5.3. es muy sutil. Cuando uno lo revisa con calma, puede verse que algo anda mal, pero no es inmediato ver qu es lo incorrecto. Oso EspecieEnPeligro

Panda

Fig. 5.3. Qu significa Panda realmente?

Un camino para entender el problema es formularse la siguiente pregunta. Cules son las instancias de las tres clases involucradas? En el cuadro siguiente se presentan algunas posibilidades. Panda An An Ling Ling Hee Hee Yogi Teddy Winnie Oso EspecieEnPeligro musaraa de nariz corta orqudea araa de montaa rata gigante de Sumatra

Puede notarse que, dos clases (Panda y Oso) tienen animales individuales como instancias, mientras que la tercera (EspecieEnPeligro) tiene especies enteras como instancias. Es correcto decir que: Ling Ling es una instancia de Panda o Ling Ling como Panda, es tambin una instancia de oso. Pero no es correcto decir que: Ling Ling es una instancia de especie en peligro. Por lo tanto, la clase Panda puede heredar de Oso, pero no de EspecieEnPeligro. Entonces, Cmo debemos realizar el diseo para que modele el hecho de que algunas especies estn en peligro? En la figura 5.4. se presenta una propuesta. El diagrama del lado izquierdo muestra la clase Panda que hereda de Oso. Un panda es una clase de oso, pero por ser {incomplete} nos dice que, no la nica

62

DISEO

ORIENTADO

OBJETOS

clase de oso. El diagrama de la derecha muestra que EspecieEnPeligro y EspecieSinPeligro heredan de Especies: Las dos clases representan subconjuntos mutuamente exclusivos de la clase completa especies.

Oso

Especies

{incomplete}

{disjoint, complete}

Panda

EspecieEnPeligro
Fig. 5.4. Una jerarqua de herencias corregida

EspecieSinPeligro

Las dos clases a la izquierda tienen que ver con animales, mientras que la clase a la derecha tiene que ver simplemente con especies. Pero Cmo se ligan los dos lados? Cmo se disea el hecho que los pandas y algunas otras especies estn en peligro? Un posible diseo puede incorporar un atributo de instancia, estaEnPeligro: boolean, en Oso, o bien en su superclase. A pesar que esto puede funcionar, es una medida excesiva, debido a que produce tambin mucha generalidad. Por ejemplo, uno estra posibilitado a definir que Yogi esta en peligro, mientras que Teddy no lo est. En la figura 5.5. se incorpora una nueva clase Animal, a la cual se le asigna un atributo especie y una variable interna especie para vincularla con el objeto Especie. Cada subclase de Animal representa una especie (como Oso, Panda, Musaraa, etc), y especie contiene el valor fijo apropiado para objetos de esa clase.

63

DISEO

ORIENTADO

OBJETOS

Animal
especie : Especie

Especie
nombreTaxonomico : Nombre /estaEnPeligro : Boolean

{incomplete}

Oso
/especie = oso(const)

{disjoint, complete}

EspecieEnPeligro
/estaEnPeligro = true(const) /cuandoInicioPeligro : Date

EspecieSinPeligro
/estaEnPeligro = false(const)

{incomplete}

Panda
/especie = panda(const)

Fig. 5.5. Jerarqua de herencia correcta, con mayor detalle.

Por ejemplo, cada objeto Oso puede dar un valor especfico al ser instanciado, o bien cada objeto Oso puede recuperar el valor de su atributo especie de una constante de clase nuestraEspecie: Especie =oso dentro de la clase como un todo. De cualquier manera Oso.especie obtendr su valor, los objetos de la clase Oso pueden preguntar por sus especies as como por las propiedades asociadas a sus especies en tiempo de ejecucin con instrucciones tales como: this.especie.estaEnPeligro; this.especie.PesoMaximo; Donde PesoMaximo: Peso, por ejemplo, puede ser un atributo de instancia de Especie y estaEnPeligro: Boolean puede ser un atributo de instancia, por el momento constante, tanto en EspecieEnPeligro como en EspecieSinPeligro, definidas en el estado true y false de manera respectiva.

64

DISEO

ORIENTADO

OBJETOS

5.1.4. Mal uso de es un.

En ste ejemplo se requiere recordar la longitud, ancho y alto de habitaciones digamos de un hotel que dentro de la aplicacin se tratarn como cuboides. Adems se requiere conocer el volumen de cada habitacin. Suponiendo que se cuenta con la clase Cuboide en la biblioteca de clases, se disear un Salon de clases que herede simplemente de Cuboide, la situacin se muestra en la figura 5.6. En general el diseo suena bien. Un objeto de la clase Salon puede regresar su volumen simplemente ejeCuboide
/volumen volumen reducir ( ) rotar ( )

Salon

Fig 5.6. Un diseo simple de Salon que hereda de Cuboide.

cutando su operacin de recuperacin volumen (implementada como una funcin) que hereda de Cuboide; de donde no se requiere algn cdigo adicional en principio. Adems, ya que un saln es un cuboide, el requerimiento es un (is a) para una herencia vlida se satisface. Ms de una manera sutil es aqu donde el diseo falla. El primer problema es el comportamiento que Salon hereda de Cuboide. ste comportamiento viene de las operaciones de Cuboide, tales como reducir, rotar, etc. Ya que stos comportamientos son ilegales para un Salon (al menos en el mundo real), lo cual nos obliga a invalidarlos, esto es cancelarlos para Salon. Ms se pueden observar problemas mayores cuando uno tiene que tratar con salones de otra geometra. Supongamos que ciertos salones son ovalados. La herencia, que ha trabajado bien para cuboides, tambin funcionar con valos. As pues, como se muestra en el diagrama de la figura 5.7., Salon hereda de manera mltiple tanto de Cuboide como de Ovalo. Pero qu significa esto? La herencia mltiple implica que un saln es tanto un valo y un cuboide. Esto nos llevar a un saln con una forma extraa, y en particular no es exactamente lo que al disear uno espe65

DISEO

ORIENTADO

OBJETOS

raba. Una posibilidad (de primera impresin) sera invertir el diagrama, el modelo se presenta en la figura 5.7 a la derecha.

Cuboide
/volumen volumen

Ovalo
/volumen volumen

Salon
/volumen volumen {cmo esta implementado ??}

Salon
volumen {heredado de dnde ??}

Cuboide
/volumen volumen

Ovalo
/volumen volumen

Fig. 5.7. Dos intentos para introducir salones ovaladas

Parece ser que no se ha logrado algo con la segunda propuesta, ya que la jerarqua en la cual Cuboide u Ovalo heredan de Salon con un esfuerzo mnimo. Si uno instancia un objeto a partir de Cuboide u Ovalo, entonces ese objeto heredar todas las propiedades necesarias para Salon. Pero todava existe un problema, y ste es el comportamiento extrao (tal como reducir y rotar), que ahora no es posible invalidar (override). El segundo diseo en la figura 5.7. tiene problemas ms profundos. Se sabe, del captulo que abord el encumbramiento, que no debemos encumbrar una clase de un dominio bajo (Cuboide u Ovalo) con alguna de un dominio alto (Salon). De hacerlo, la biblioteca de geometra desarrollada necesitar la clase Salon para poder operar. Y por otro lado, ya que no todos los cuboides son salones, la clase Cuboide presentar cohesin de mezcla de instancias, as como cohesin de mezcla de dominios. La raz del problema est como se plante antes en la afirmacin original: Un saln es un cuboide, que se utiliz para justificar la herencia. Un requerimiento ms preciso es, Un saln tiene el atributo de forma. La forma de todos los salones en sta aplicacin es la de un cuboide Lo cual marca la diferencia. Un nuevo diseo para Salon se muestra en la figura 5.8. Ahora, Salon tiene una variable de instancia forma que hace referencia a un objeto de la clase FormaCerrada3D (o una de sus subclases, tales como Cuboide, Ovalo o Tetraedro). En otras palabras, Salon contiene la declaracin, var forma: FormaCerrada3D;

66

DISEO

ORIENTADO

OBJETOS

Cuando se inicializa un saln particular, la variable forma es asignada a un objeto de la forma y tamao correcto para un saln dado. La operacin Salon.volumen ahora opera preguntando al objeto que hace referencia mediante la variable forma para evaluar el volumen, como muestra la figura 5.8.. La frmula particular que se utilice para evaluar el volumen del cuboide o el volumen del valo, depender de la forma actual del saln definida mediante el mecanismo de polimorfismo.
forma

Salon
/volumen : Volumen volumen : Volumen

FormaCerrada3D
0* 1 {abstract}
/volumen : Volumen volumen : Volumen {abstract}

Cuboide
/volumen : Volumen volumen : Volumen

Ovalo
/volumen : Volumen volumen : Volumen

Fig. 5.8. Un Salon tiene una forma de classe FormaCerrada3D, y requiere su volumen de forma.

sta tcnica para acceder al cdigo de otra clase se llama despacho de mensajes (forwarding). Un objeto de la clase Salon despacha el mensaje de volumen a otro objeto de clase Cuboide (o a quin corresponda). El esquema de diseo de envo de mensajes, que es un mecanismo alternativo a la herencia, no garantiza de manera automtica el acceso a todas las facilidades de otra clase. En vez de esto, uno tiene que dirigir el acceso, mensaje por mensaje, a los atributos y operaciones de la ora clase que uno requiere usar. Uno puede ver los dolores de cabeza que el esquema original, basado en un diseo de herencia ocasion y valorar como el modelo de despacho de mensajes lo ha arreglado. Algunos autores usan el trmino delegacin en vez de despacho de mensajes. Ms ste ltimo se acostumbra utilizar con mayor frecuencia en el diseo orientado a objetos.

67

DISEO

ORIENTADO

OBJETOS

5.2. El peligro del Polimorfismo El polimorfismo promueve precisin en la programacin orientada a objetos permitiendo que una operacin sea definida con el mismo nombre en ms de una clase y permitiendo que una variable haga referencia a un objeto de ms de una clase. Eso implica que el polimorfismo habilita al ambiente operativo a escoger de manera automtica la operacin correcta a ejecutar como resultado de un mensaje, sin necesidad de utilizar una sentencia case complicada. As pues, las operaciones y variables pueden exhibir polimorfismo. En un buen diseo orientado a objetos, stas dos facetas del polimorfismo trabajan de manera armnica. En un diseo imperfecto, el polimorfismo puede ser un riesgo: Un objeto puede recibir un mensaje que no entienda y puede en consecuencia disparar una excepcin en tiempo de ejecucin. En sta seccin se discutirn y analizarn algunos detalles peligrosos correspondientes al uso del polimorfismo.
5.2.1. Polimorfismo en las operaciones.

Para explicar el riesgo de enviar mensajes a un objeto que no entienda y como evitar este riesgo se requiere introducir algunos trminos. El mbito (scope) del polimorfismo de una operacin op es el conjunto de clases sobre las cuales op est definida. Un mbito del polimorfismo (AdP)que forma una derivacin de la jerarqua de la herencia esto es, una clase A junto con sus subclases se denomina un como de polimorfismo, con A como el vrtice (apex) del polimorfismo. En la figura 5.9. se presenta un rbol de herencia de clase. Si una operacin op est definida sobre cada una de las clases sombreadas, entonces stas clases sombreadas forman el cono de polimorfismo de op (CdP).

Vrtice de Polimorfismo (VdP)

Vrtice de Polimorfismo (VdP)

Fig. 5.9. La estructura de un CdP.

68

DISEO

ORIENTADO

OBJETOS

ste es un como en el cual las clases sombreadas forman una rama completa: la clase A es el vrtice de polimorfismo (VdP). Pongamos un ejemplo ms concreto, si tomamos la operacin ObtenerArea definida sobre Poligono y sobre todas las subclases de Poligono ya sea localmente o a travs de herencia -, entonces el AdP de ObtenerArea forma un cono, teniendo a Poligono en el vrtice. La figura 5.10 ilustra la situacin.

Poligono
/ ObtenerArea ObtenerArea

Triangulo
/ ObtenerArea ObtenerArea

Rectangulo
/ ObtenerArea ObtenerArea

Hexagono
/ ObtenerArea ObtenerArea

Figura 5.10. El Cono de Polimorfismo (CdP) de ObtenerArea.

tra situacin corresponde al caso en el cual una operacin no esta definida en todas las clases de una rama de la jerarqua, a caso se le conoce como un mbito de Polimorfismo desigual (ragged). En la figura 5.11 slo las clases sombreadas contienen la operacin, digamos oper. En ste caso no se forma un cono sobre una rama completa.

Fig. 5.11. La estructura de un CdP desigual.

69

DISEO

ORIENTADO

OBJETOS

Un caso simple y conocido de AdP desigual para una operacin puede ser la operacin print la cual asumiremos enva informacin de cierto objeto a un objeto DriverDeImpresora la cual tiene un conjunto disperso de clases que requieren de la operacin de impresin. Por ejemplo, sta estar definida en HojaDeClaculo, ProcesadorDeTexto y CorreoElectrnico, pero no en clases del tipo Elefante, ControlTCPIP y Objeto. Por tanto, su AdP no ser un cono. Ntese que en la jerarqua Objeto se encuentra en la cima del rbol.
5.2.2. Polimorfismo de Variables.

En general el polimorfismo tambin se presenta en las variables, las cuales en varios momentos apuntan a objetos que corresponden a diversas clases. Se puede definir el mbito del Polimorfismo de forma alterna, sta vez aplicado los trminos a una variable que guarda un manejador de un objeto, en vez de a una operacin. El mbito de polimorfismo de una variable v es el conjunto de clases cuyos objetos son apuntados mediante v (durante el tiempo de vida completo de v). El mbito de polimorfismo de una variable es similar al mbito de polimorfismo de una operacin. Ambos comprenden a un conjunto de clases. Las clases en el AdP para una variable, de cualquier manera, son aquellas a las que pertenecen todos los objetos a los cuales la variable puede hacer referencia en algn momento durante la ejecucin del sistema. Se pueden usar tambin los trminos cono de polimorfismo y vrtice de polimorfismo para una variable, en el mismo sentido que se us para una operacin. A continuacin se enlistan tres ejemplos que ilustran el mbito de polimorfismo para una variable. 1. Digamos que la declaracin var t:Triangulo permite a la variable t apuntar a cualquier objeto de la clase Triangulo o bien de los descendientes de Triangulo (Esto es natural en lenguajes como Java, Eiffel, o C++, en los cuales el polimorfismo de una variable se restringe comnmente a los descendientes de una clase). En ste ejemplo, por tanto, el AdP de la variable forma un cono, donde la clase Triangulo se encuentra en el vrtice superior del rbol. Digamos que a una variable v l es permitido, en varios momentos, apuntar a un objeto de la clase Caballo, Circulo, o Cliente. ( Esto puede ocurrir con facilidad en Smalltalk, en el cual el polimorfismo de las variables es tpicamente sin restricciones; en otros lenguajes, uno deber declarar a v que pertenezca a la clase ms general, Objeto). En ste ejemplo el AdP de la variable no es un cono en el cual las clases Caballo, Circulo, y Cliente no tienen una superclase comn inmediata para formar un cono de polimorfismo (CdP). Al menos, se presume (por la disparidad de ellas) que no tienen una superclase comn. EN ste ejemplo digamos que (otra vez en Smalltalk) tenemos una declaracin var x: Object, donde la clase Object es la cima de la jerarqua de clases. En otras palabras, la variable x puede apuntar a cualquier objeto donde se encuentre (puesto que todas las clases son descendientes de Object). Esta vez el mbito de polimorfismo de la variable formar un cono. Obviamente ste cono es el ms grande de todos, debido a que su vrtice es la cima de la jerarqua de herencia de las clases.

2.

3.

70

DISEO

ORIENTADO

OBJETOS

5.2.3. Polimorfismo en los mensajes

Un mensaje se compone de una variable que apunta a un objeto destinatario y a un nombre de operacin que establece la operacin a ser invocada. Como se ha discutido, tanto la variable como la operacin tienen un AdP. La relacin entre estos dos AdPs tiene un impacto significativo sobre la confiabilidad del sistema. Asumiremos que los AdP de la operacin y de la variable son conos de polimorfismo (CdPs) es decir, que forman conos completos. Llamemos al mensaje de prueba ObjDest.ObjOper, donde ObjDest es la variable que apunta al objeto destino y ObjOper es la operacin que ser invocada sobre el objeto destino. Existen dos posibles parentescos entre el CdP de ObjDest y el CdP de ObjOPer: Caso 1: El CdP de ObjDest cae dentro del CdP de ObjOper. En otras palabras, el CdP de la variable cae dentro del CdP de la operacin. Esto se muestra en la figura 5.13.
AdP de ObjOper

AdP de ObjDest

Figura 5.13. El CdP de la variable ObjDest cae dentro del AdP de la operacin ObjOper.

Caso 2: Parte o todo del CdP de ObjDest cae fuera del CdP de ObjOper. Es decir, algunos de los CdP de la variable caen fuera de los CdP de la operacin. Esto se ilustra en la figura 5.14.
AdP de ObjOper

AdP de ObjDest

Figura 5.14. Parte del CdP de la variable ObjDest cae fuera del AdP de la operacin ObjOper.

En el primer caso, todo se puede considerar correcto dentro del diseo. No importa que objeto ObjDest apunte a, aquel objeto ser de la clase que entiende el mensaje ObjOper. En el segundo caso, se puede

71

DISEO

ORIENTADO

OBJETOS

decir que no enfrentamos a un diseo pobre y nada robusto. Puede notarse que al ejecutar la aplicacin es muy posible que ObjDest apunte a un objeto para el cual su clase no tenga definida ObjOper. Si esto sucede, entonces el programa probablemente explotar (se detendr) con un error en tiempo de ejecucin (run-time error). Siempre que uno quiera utilizar los lujos de los mensajes polimrficos, uno debe asegurarse que exista contencin completa del AdP de los mensajes de las variables en el AdP de los mensajes de las operaciones. Uno debe ser especialmente diligente si tanto las variables destino o las operaciones tienen un AdP disperso y desigual.
5.2.4. Polimorfismo y genericidad.

Una clase parametrizada (denominada plantilla de clase en C++) es una clase que toma un nombre de clase como un argumento siempre que uno de sus objetos sea instanciado. Los diseadores de software frecuentemente utilizan clases parametrizadas para construir contenedores tales como listas, pilas y rboles ordenados. Pero las clases parametrizadas de igual forma que los mensajes polimrficos pueden crear problemas en tiempo de ejecucin, debido a conflictos en el mbito del polimorfismo. Para ilustrar la situacin, introduzcamos una clase parametrizada ArbolOrdenado<NodoDeClase>. La siguiente instruccin instancia un rbol ordenado especfico: arbolNumReal := ArbolOrdenado<Real>.New; que crea un nuevo objeto, un rbol ordenado al cual apunta arbolNumReal, que almacenar nmeros reales en sus nodos. Tambin se puede escribir arbolClientes := ArbolOrdenado<Cliente>.new; que podr almacenar objetos de la clase Cliente en sus nodos. Dentro de la clase ArbolOrdenado, uno podr escribir instrucciones tales como nodo := NodoClase.new; sta instruccin crear un nodo nuevo de la clase Real (para el primer objeto ArbolOrdenado anterior) o bien de la clase Cliente (para el segundo objeto ArbolOrdenado). Tambin en el cdigo de ArbolOrdenado (digamos en la operacin imprimeArbol), nos gustara ver algo como nodo.imprime; que enviar un mensaje al objeto que apunta el nodo para que se imprima a si mismo. En algn otro lugar del cdigo dentro de ArbolOrdenado, no gustara realizar comparaciones de la forma: if newItem.lessThan(nodoActual) // newItem y nodoActual apuntan a un objeto NodoClase then

72

DISEO

ORIENTADO

OBJETOS

El problema con la comparacin anterior es ste: El diseador de ArbolOrdenado no tiene ni la ms mnima idea que clase actual ser pasada como un argumento en tiempo de ejecucin. Por ejemplo, alguien puede escribir ArbolOrdenado<Fuselaje>.New, ArbolOrdenado<Complex>.New, o ArbolOrdenado<Animal>.New. La primera de las tres clases puede no entender imprime, y la segunda puede no entender lessthan, mientras que la tercera puede no entender ni imprime ni lessThan. Por tanto, existe un tremendo riesgo de fallas en tiempo de ejecucin cuando un objeto se almacene en el rbol, por ejemplo de la clase Animal y se le indique imprmete tu mismo. El problema se da porque el mbito de NodoClase es ilimitado.

Con esto terminamos sta pequea introduccin al diseo orientado a objetos, pero es claro que hay mas que estudiar, aprender y practicar.

73

DISEO

ORIENTADO

OBJETOS

Bibliograf a
[1] [2] [3] [4] [5] [6] Page-Jones Meilir. Fundamentals of Object-Oriented Design in UML. Dorset House Publishing, New York: Addison-Wesley, 2000. Page-Jones Meilir. The practical guide to structured systems design, 2nd. ed. Englewood Cliffs, N.J.: Prentice Hall, 1988. Yourdon & Constantine. Structured Design, 2nd ed. Englewood Cliffs, N.J. Prentice-Hall, 1979. Porter H. H.., Separating the Subtype Hierarchy from the Inheritance of Implementation, Journal of ObjectOriented Programming, Vol. 4. No. 9, pags. 20-29, 1992. Lieberherr K.J. & I.M. Holland. Assuring Good Style for Object Oriented Programs. IEEE Software, Vol 6, No. 9, pags. 38-48, 1989. Meyer, B. Object-Oriented Software Construction. Englewood Cliffs, N.J. Prentice-Hall, 1988.

74

You might also like