Download - type object

Transcript
Page 1: type object

UNIVERSIDAD DE ORIENTE

NÚCLEO MONAGAS

ESCUELA DE ING. Y CIENCIAS APLICADAS

CURSO ESPECIAL DE GRADO

CIENCIAS DE LA COMPUTACIÓN

Type Object

Profesor: Jonathan Vásquez

Integrantes: Centeno G., Renny J. C.I. 21.350.253

Fernández G., Ana B. C.I.21.329.313

Maturín, Abril del 2015

Page 2: type object

CONTENIDO

1. Introducción………………………………………………………………..... 32. Marco teórico

2.1 ¿Qué es un type object? ……………………………………………….. 4 2.2 ¿Cuándo usar los type objects?......................................................... 4 2.3 Estructura…………………………………………………………………. 4 2.4 Ventajas…………………………………………………………………… 5 2.5 Desventajas………………………………………………………………. 5 2.6 A tener en cuenta………………………………………………………… 6 2.7 Decisiones de diseño……………………………………………………. 6 2.8 Type objects en distintos lenguajes……………………………………. 8

3. Desarrollo …………………………………………………………………….. 94. Conclusión……………………………………………………………………. 115. Bibliografía……………………………………………………………………. 12

Page 3: type object

1. INTRODUCCIÓN

Existen numerosos términos relacionados con el diseño y desarrollo de software. Algunos de estos términos, como las buenas prácticas y los modelos de diseño, mencionan que los objetos deben aprender a verse como conjuntos de comportamientos más que como un conjunto de datos. Los modelos de diseño, en particular, representan herramientas de comunicación con un gran poder de simplificar. Representan un vocabulario común al momento de programar que se comparte con otros programadores. Mediante el empleo de un modelo de diseño existe un mayor nivel de abstracción, pues establece un conjunto de objetos y clases y la relación existente entre los mismos. Dependiendo del tipo de problema que se quiera solucionar, se podrá elegir el modelo de diseño que se puede implementar.

Desde tiempos inmemoriales, en el desarrollo de software se ha lidiado con la difícil tarea de manejar la complejidad de construir sistemas. Para ello, siempre se ha buscado contar con normas que permita a los programadores llegar a un consenso con respecto a que estilo o que estructura se debe seguir al momento de construir o desarrollar un software. Y, aunque hasta ahora no existe un receta exacta con respecto a los procedimientos que deben llevarse a cabo para lograr esta laboriosa tarea, vale la pena decir que la mayoría de los éxitos de software de hoy en día no se deben a ningún tipo de metodología. Se deben más a los puntos de vista de los programadores. Por esto es necesario formalizar las maneras en las que los desarrolladores toman decisiones e ir generando herramientas a partir de esta formalización. Entre estas herramientas se encuentran los modelos de diseño.

Estos modelos de diseño representan la intención de formalizar una práctica de diseño, una simple herramienta para diseñar software. Además, representas mejoras en cuanto a la capacidad de explorar nuevos niveles de diseño. Ayuda a evaluar hasta qué punto se puede dejar abierta la construcción de software a cambios y hasta qué punto se puede cerrar una solución para poder implementarla. El empleo de modelos de diseño trae como consecuencias programas más elegantes y representa una especie de documentación para resolver problemas que pueden presentarse con regularidad. Entre estos modelos de diseño se encuentran los type objects.

Page 4: type object

2. MARCO TEÓRICO2.1. ¿Qué es un type object?

Según Nystrom (2009) los type object “permiten la creación flexible de nuevas clases al crear una clase en particular, de la cual cada instancia representa un distinto tipo de objeto”. El propósito de los type object, según Johnson y Wolf (1996) es:

Disociar instancias de sus clases, para que esas clases puedan ser implementadas como instancias de otra clase. Type object permite crear clases dinámicamente durante el tiempo de ejecución, y capacita al sistema para establecer sus propias normas o reglas de comprobación de tipos, guiando a que los sistemas sean más simples y sin tantas líneas de código. Los objetos referenciados al mismo type object, funcionarán como si fueran del mismo tipo. Esto permite compartir información y comportamientos a través de un conjunto de objetos similares, funcionando casi como lo hacen las subclases, sólo que sin tener que formular todo el código de las distintas subclases.

2.2. ¿Cuándo usar los type objects?

Según Nystrom (2009), este diseño es “muy útil cada vez que se requiere definir una variedad o una gran cantidad de distintos tipos de cosas, pero el sistema de tipos de lenguaje del que se está haciendo uso es demasiado rígido”. En particular, según Johnson y Wolf (1996) conviene usar los type objects cuando se cumpla cualquiera de estas condiciones:

- Las instancias de una clase necesitan ser agrupadas de acuerdo a sus atributos y/o su comportamiento en común.

- La clase necesita una subclase para cada conjunto, con el fin de poder implementar los atributos y/o comportamiento de cada grupo.

- La clase requiere de una gran cantidad de subclases y/o la cantidad de subclases requerida es desconocida.

- Se necesita la capacidad de crear nuevos grupos durante el tiempo de ejecución, que no fueron considerados durante el período de diseño.

- Se requiere la capacidad de cambiar la subclase de un objeto, aún después de que ésta ha sido instanciada, sin tener que convertirla en una nueva clase.

- Se necesita de la capacidad de anidar grupos recursivamente, de modo que un grupo sea un ítem en otro grupo.

- Se desea la capacidad de poder crear o modificar nuevos tipos sin tener que recompilar o modificar el código.

2.3. EstructuraSegún Johnson y Wolf (1996):

Page 5: type object

- Typeclass: es la clase de typeobject. Posee una instancia diferente para cada tipo de objeto.

- Typeobject: es una instancia de typeclass. Representa un tipo de objeto. Establece todas las propiedades de un objeto que son las mismas para todos los objetos del mismo tipo.

- Clase: es la clase de objeto. Representa instancias de typeclass.- Objeto: es una instancia de clase. Representa un ítem único que posee un

contexto único. Establece todas las propiedades de ese único ítem que pueden diferir de las propiedades de otros ítems del mismo tipo. Está asociado a un typeobject que describe su tipo. Delega propiedades que define su tipo a su typeobject.

2.4. Ventajas Según Johnson y Wolf (1996), las ventajas de los type objects son:

- Creación de clases en tiempo de ejecución: este diseño permite que nuevas clases sean creadas en tiempo de ejecución. Estas nuevas clases no son exactamente clases, son instancias llamadas typeobjects que son creadas por la typeclass, así como cualquier instancia es creada por una clase.

- Evita la necesidad de muchas clases: el sistema ya no necesitará de numerosas clases para representar diferentes tipos de objetos. En lugar de eso, el sistema puede usar una typeclass y numerosos typeobjects.

- Cambio dinámico de tipos: el diseño permite que el objeto cambie dinámicamente su typeobject, que tiene el efecto de cambiar su clase. Esto es más sencillo que transformar el objeto en una nueva clase.

- Creación de subclases independientes: pueden crearse subclases independientes de typeclass y de clase.

- Typeobjects múltiples: el diseño le permite al objeto tener múltiples typeobjects, donde cada uno define alguna parte del tipo de objeto. El objeto entonces debe decidir qué tipo de comportamiento delegar a qué typeobject.

2.5. DesventajasSegún Johnson y Wolf (1996), las desventajas de los type objects son:

- Complejidad de diseño: el modelo factoriza un único objeto lógico en dos clases. La relación entre estas dos últimas clases, el objeto y su tipo, es difícil de comprender. Esto es confuso para los programadores y creadores de modelos que no estén familiarizados con los typeobjects. Es difícil reconocer o describir la relación entre typeobject y object. Esta confusión repercute tanto en la simplicidad como en la mantenibilidad. En otras palabras: “usa herencia, es más sencillo”.

- Complejidad de implementación: el modelo extrae las diferencias de implementación de las subclases y las coloca en el estado de las instancias de typeobject. Donde cada subclase podía implementar un método de distintas formas, ahora la typeclass sólo puede implementar el método de

Page 6: type object

una única manera y cada estado de los typeobjects debe hacer que la instancia se comporte de forma distinta.

- Manejo de referencias: cada objeto debe mantener una referencia con su typeobject. Así como un objeto sabe cuál es su clase, un objeto sabe cuál es su typeobject. Pero donde sea que el sistema o el lenguaje establezca automáticamente y mantenga la relación clase-instancia, la aplicación debe establecer y mantener por sí misma la relación typeobject-object.

2.6. A tener en cuenta

Según Nystrom (2009), este modelo “busca cambiar la definición de “tipo” desde el imperativo pero rígido lenguaje del código al más flexible mundo de objetos en la memoria”. El mismo autor se refiere a que la flexibilidad es buena, pero pierdes ciertas ventajas al alojar tus tipos en la memoria:

- El seguimiento de los typeobjects debe ser realizado manualmente: una de las ventajas de usar algo parecido a los tipos del sistema de c++ u otros lenguajes de programación orientados a objetos es que el compilador se encarga de registrar todas las clases automáticamente. Los datos que definen cada clase son automáticamente compilados dentro del segmento de memoria estática del ejecutable y simplemente funciona. Cuando se usa el modelo de typeobjects, el programador es responsable no sólo de los typeobjects, sino de las typeclasses. Es el programador quien debe asegurarse que las typeclasses se registren en la memoria y que los typeobjects sean correctamente inicializados. En pocas palabras, el programador se libra de algunas limitaciones o restricciones del compilador, pero el costo es que debe reimplementar algunas de las acciones que el compilador suele hacer por el programador.

- Es difícil definir el comportamiento de cada tipo: a través de las subclases, el programador puede sobreescribir un método y hacer lo que desee hacer (llamar otros códigos, calcular valores a través de procedimientos, entre otros.) En cambio, cuando se usa el modelo de los typeobjects, se reemplaza un método sobreescrito con un miembro variable. Esto hace que sea muy sencillo utilizar typeobjects para definir datos específicos de un tipo, pero se hace difícil definir el comportamiento específico del mismo tipo. Hay algunas formas en las que se puede eludir esta limitación. Una de las soluciones es contar con un set de comportamientos predefinidos y luego usar los datos en el typeobject para seleccionar sencillamente uno de esos comportamientos. Una solución más potente es soportar completamente la definición de los comportamientos en la data.

2.7. Decisiones de diseñoSegún Nystrom (2009):

Page 7: type object

El modelo de typeobjects permite al programador construir su propio tipo de dato, como si estuviera creando su propio lenguaje de programación. El espacio de diseño es bastante amplio, y el programador puede realizar varias cosas bastante interesantes. Sin embargo, algunos detalles pueden reducir las posibilidades del programador. El tiempo y el mantenimiento son factores que pueden alejar al que se encuentre programando de cualquier cosa particularmente complicada. Más importante aún, cualquier cosa que se diseñe por medio del modelo de typeobjects debe poder ser entendida por usuarios, que por lo general no son otros programadores. Mientras más sencillo pueda hacerse, más entendible y usable será para los usuarios.

- ¿El typeobject debe ser encapsulado o expuesto?Si el typeobject es encapsulado: la complejidad del modelo de typeobject estará oculta del resto del código base. Se convierte en un detalle de implementación que sólo le corresponde a sus instancias. Debe irse escribiendo el código reenviando métodos para todo aquello que el type object exponga. Esta es la parte tediosa del diseño. Si la typeclass tiene una gran cantidad de métodos, la clase del objeto debe tener sus propios métodos y debe establecerse cuáles se quiere que sean públicos.Si el typeobject es expuesto: el código puede interactuar con los type objects sin contar con instancias de la typeclass. El type object ahora es parte del API público del objeto. En general, una interfaz reducida son más sencillas de mantener que aquellas que son amplias. Mientras menos se exponga al código base, menos complejidad y menos mantenimiento debe realizarse.

- ¿Cómo son creados los typeobjects?En este modelo cada objeto es ahora un par de objetos. El objeto principal y el type object que usa. ¿Pero cómo se crean ambos?Se construye el objeto en su type object.Se llama una función constructor en el type object.

- ¿Puede el tipo cambiar?Hasta ahora se presume que una vez que un objeto es creado y unido a su type object, no puede cambiarse esa unión. El tipo con el que un objeto es creado es el mismo con el que un objeto muere. Esto, sin embargo, no es estrictamente necesario. Se puede permitir a un objeto cambiar su tipo en el tiempo.

- ¿Qué tipo de herencia es soportado?Sin herencia: es simple, pero puede guiar al doble de los esfuerzos.Herencia simple: es relativamente simple y la búsqueda de atributos es más lenta.Herencia múltiple: casi toda la duplicación de datos puede ser evitada. Es complejo.

Page 8: type object

2.8. Type Objects en distintos lenguajes2.8.1 Python

typedef struct _typeobject { PyObject_VAR_HEAD char *tp_name; /* For printing, in format "<module>.<name>" */ int tp_basicsize, tp_itemsize; /* For allocation *//* Métodos para implementar operaciones estándar */ destructor tp_dealloc; printfunc tp_print; getattrfunc tp_getattr; setattrfunc tp_setattr; cmpfunc tp_compare; reprfunc tp_repr; /* El método puede ser utilizado en clases estándar */ PyNumberMethods *tp_as_number; PySequenceMethods *tp_as_sequence; PyMappingMethods *tp_as_mapping;

2.8.2 C++ class Breed{public: Breed(int health, const char* attack) : health_(health), attack_(attack) {}

int getHealth() { return health_; } const char* getAttack() { return attack_; }

private: int health_; // Starting health. const char* attack_;};class Monster{public: Monster(Breed& breed) : health_(breed.getHealth()), breed_(breed) {}

const char* getAttack() { return breed_.getAttack(); }

private: int health_; // Current health. Breed& breed_;}

Page 9: type object

3. Desarrollo

La programación orientada a objetos ofrece muchas facilidades al momento de escribir un código. No por nada, este paradigma es considerado tan útil. Los lenguajes desarrollados bajo los principios de la orientación a objetos han facilitado la comunicación entre los programadores y las máquinas, de modo que el programador pueda dictarle a la computadora las instrucciones exactas de lo que se requiere que haga, obteniendo así los resultados esperados. Estas facilidades derivan de las características de la programación orientada a objetos. Por ejemplo, la abastracción y el encapsulamiento. Otra de las características de la programación orientada a objetos es la herencia. Esta característica es específica de este tipo de programación y se caracteriza porque una clase nueva puede crearse a partir de una existente. En otras palabras, gracias a la herencia pueden crearse subclases a partir de una clase primaria y el conjunto de subclases contendrá un conjunto de métodos y atributos heredados de la clase primaria o la clase padre. La herencia tiene la ventaja de que además de los métodos y atributos heredados, se pueden definir nuevas características y funciones para las subclases.

Ahora bien, la herencia es particularmente importante y útil en la programación porque puede ahorrar bastante código y tiempo. Es decir, en lugar de escribir una y otra vez los mismos códigos de los mismos métodos y atributos que se desea que tengan distintas clases, simplemente se crea una clase base, que le herede sus métodos y atributos a otras clases hijas. El problema comienza cuando de alguna forma, la herencia en lugar de ahorrar código, sólo hace que tengan que escribirse cantidades y cantidades de subclases. Es decir, no existe ningún problema cuando se sabe que debe crearse un número restringido o limitado de subclases. Por ejemplo, se puede crear una clase llamada “animal” y sus subclases referentes al tipo de alimentación que llevan los animales serán “carnívoro”, “herbívoro”, y “omnívoro”. Esas únicas tres clases, ya que no existe alguna otra clasificación en este ámbito. Sin embargo, existirán ocasiones en los que las subclases no tendrán un número limitado.

Tal es el caso del diseño de un juego. En el juego se quieren crear criaturas que se enfrenten al protagonista. Pueden existir distintos tipos de criaturas que comparten atributos como la salud y sus ataques. La primera reacción de un programador que esté acostumbrado a la programación orientada a objetos es pensar en la herencia. Como los distintos tipos de criaturas tienen características en común, la respuesta obvia es crear una clase base o clase padre que contenga y describa los atributos que las subclases (los distintos tipos de criatura) hereden. Entonces, dentro de las subclases pueden crearse nuevos atributos para las criaturas o modificar los ya existentes. Esto resulta sencillo cuando las únicas criaturas que se tienen en el juego son dragones y trolls. Pero luego si luego se añaden vampiros, hombres lobos, zombies, momias, goblins, nomos, orcos, y se va más allá hasta incluso crear razas de criaturas nuevas, entonces la lista de

Page 10: type object

subclases será interminable. Este es uno de esos casos en los que las subclases, en lugar de ayudar a simplificar el código, lo hacen más complejo. Para cada nueva criatura que se quiera poner dentro del juego, habrá que crear una nueva subclase. Es obvio que si se piensa en diez criaturas, esto puede no resultar tan tedioso. Pero, ¿qué pasa si se quieren tener cientos y cientos de criaturas en el juego? Entonces deberían crearse cientos y cientos de subclases.

Para estos casos, se cuenta con la opción de crear type objects. ¿Qué significa esto? Continuando con el ejemplo anterior, se decide crear una clase “criatura” y otra clase aparte llamada “raza o tipo de criatura”. Es de notar que entre estas dos clases no existe ningún tipo de herencia. Es decir, ninguna clase es subclase de la otra. Ahora, cada nueva criatura que se cree será una instancia de la clase “criatura”. Ahora se pueden crear todas las criaturas que se deseen simplemente creando objetos que representen instancias de la clase “criatura”. Sin embargo, ¿cómo se hará para que estos objetos o criaturas que se están creando identifiquen a qué raza pertenecen y adquieran los atributos que les pertenecen a dichas razas? Pues cada uno de los objetos que se creen como instancias de la clase “criatura” sólo tendrá que hacer una referencia a la clase “raza” que se creó. En esta última clase deberá definirse cuáles son los atributos y métodos que se desea que tengan los objetos. Como puede notarse, para esto no se necesitará tanto código, como se necesitaría si se trataran de crear las criaturas mediante subclases, como es obvio que trate de hacerse.

Entonces, de acuerdo al ejemplo anteriormente expuesto, ¿qué hacen los type objects? Cuando un objeto hace referencia a un type object, obtiene todos los métodos y atributos contenidos en este último. Es decir, si varios objetos hacen referencia al type object, entonces todos estos objetos se van a comportar de manera similar. Así pasa normalmente con las subclases, sólo que utilizar el diseño de los type objects permite ahorrar líneas de código y tiempo. Una ventaja que ofrecen los type objects es que permiten la modificación de métodos y atributos sin tener que recompilar todo el código nuevamente. Esta capacidad de crear y modificar métodos en tiempo de ejecución, permite a su vez la creación dinámica de clases. Como todo, el uso de type objects tiene sus ventajas y sus desventajas. Entre las ventajas se encuentra precisamente la creación dinámica de clases, que se evita la necesidad de emplear o codificar muchas subclases, que pueden crearse subclases independientes, entre otros.

Por otro lado, este diseño usando type objects también presenta sus desventajas. Como por ejemplo la complejidad de diseño, la complejidad de implementación y el manejo de referencias. Además, hay que tener en cuenta que al crear type objects se pieden ciertos beneficios que otorgaba el compilador, por ejemplo la gestión de las clases en la memoria. Las clases ya no se registrarán automáticamente en la memoria. Es importante destacar que cada lenguaje orientado a objetos posee su forma de implemetar sus type objects. Entre los lenguajes orientados a objetos que poseen esta característica están Java y C++.

Page 11: type object

4. CONCLUSIÓN

Lo primero que debe resaltarse es que los lenguajes de programación orientados objetos siempre tratan de brindarle al programador las maneras de que la experiencia de programar no sea tan tediosa. Aunque muchas veces no lo parezca y, precisamente porque se basa en el principio de la abstracción que sólo busca que el programa cumpla con su función sin importar cómo lo haga, siempre existe una forma más fácil de llevar a cabo lo que se quiere en un programa. No hay que olvidar que los lenguajes de programación nacieron precisamente para facilitar la comunicación entre el programador o el desarrollador con la máquina.

Estos lenguajes de programación orientados a objetos cumplen con las características básicas del paradigma orientado a objetos. El aprovechamiento de cada una de estas características dependerá del programador. Una de las facilidades que brinda la programación orientada a objetos es el uso de la herencia. La herencia ahorra tiempo a los programadores y el tedio de tener que escribir una y otra vez las mismas líneas de código. Esto lo hace mediante la función que permite que una clase (o clase hija) adquiera métodos o atributos de otra (que vendría siendo la clase padre).

Sin embargo, existen determinadas ocasiones en las que la herencia no les sirve a los programadores para ahorrar código. Es más, cuando se presentan casos en que las subclases no tienen un número limitado o reducido, entonces las subclases no resultan tan eficientes, porque deben escribirse las líneas de código para cada subclase.

Entonces, como un método o modelo que ayuda a solventar estos problemas, se encuentran los type objects. Una vez más, la idea es ahorrarle tiempo al programador y hacer menos tedioso su trabajo. Los type objects se basan en el principio de crear clases de clases. Cuando se quieran crear varios objetos simplemente se hacen las instancias de una clase en particular. Ahora, si se quiere que esos objetos que se están creando compartan ciertos atributos y características, lo que se hace es crear otra clase que defina y describa estas mismas características y luego simplemente hacer una referencia desde cada uno de los objetos que se están creando hasta esta clase.

Ese es el funcionamiento básico de los type objects. A pesar de que la estructura del programa puede resultar un poco más compleja y al programador puede hacérsele un poco difícil entender la relación entre las clases en cuanto a los type objects, su uso en definitiva puede ahorrar el tiempo y las líneas de código, además de suponer ventajas como la creación dinámica de clases. Por esto siempre es buena idea tener la creación de type objects en situaciones donde otras alternativas en lugar de simplificar el diseño del programa sólo logran complicarlo.

Page 12: type object

5. BIBLIOGRAFÍA

JOHNSON, Ralph y Wolf, Bobby. The type object pattern, 1996. http://www.cs.ox.ac.uk/jeremy.gibbons/dpa/typeobject.pdf [Consulta: Lunes, 13 de abril del 2015, 15:00]

NYSTROM, Robert. Type Object, 2009. http://gameprogrammingpatterns.com/type-object.html [Consulta: Lunes, 13 de abril del 2015, 17:00]

Phyton Software Foundation. Type objects, 2015. https://docs.python.org/2/c-api/typeobj.html [Consulta: Lunes, 13 de abril del 2015, 18:00]


Top Related