Clases - 2011-C2


Lunes 19/09/2011 - Clase 6 - Prototipos

posted Sep 19, 2011, 2:20 PM by Javier Fernandes   [ updated Sep 20, 2011, 5:55 AM by Nicolas Passerini ]

Introducción

Arrancamos contando que Self es un lenguaje de los '90 con ideas muy interesantes, que si bien no es directamente conocido, tiene detrás muchas ideas interesantes que la industria fue incorporando, como la idea de VM HotSpot.

Contamos que Self era algo complicado de mostrar, no por el lenguaje en sí, ya que es muy poderoso, y tiene ideas muy interesantes, sino más bien por su entorno de desarrollo, que ha quedado obsoleto y es bastante complejo de utilizar. Esto es el morphic

Self entonces

Basta de historia y manos a la obra !

Abrimos una imagen, pero antes algo de conceptos del lenguaje.

En Self solo hay objetos, en un sentido un poco más estricto que en smalltalk. Por ejemplo en smalltalk las clases son objetos especiales.
Vimos la idea de slots: data slot o method slot.

La interacción entre los objetos de mi sistema es enviando mensajes.

Qué rol cumplen las clases en un lenguaje basado en clases ?
  • instanciación
  • herencia (lo interesante de la herencia lo abstraemos como el siguiente punto)
  • reutilización de código.
    • entre objetos: como la que me dá una clase naturalmente.
    • entre conjuntos similares de objetos: es el tipo de reutilización que nos da la herencia, traits, mixins.
  • tipado (en self no nos molesta porque no tiene checkeo de tipos).

Instanciación

La forma de resolver la instanciación sin clases es a través de dos mecanismos:
  • la clonación de un objeto particular llamado prototipo.
  • la creación de un objeto literal:
    • ej en smalltalk: 'hola', 1, [:a | a+1], $a, #x
Vimos un ejemplo entonces en self.

Creamos el objeto más simple 

().

Get it lo devuelve y lo muestra. Es un objeto sin slots.
Do it ejecuta

Vemos que el botoncito "E" sirve para abrir un pequeño workspace para trabajar con ese objeto.

Veamos un objeto un poco más interesante.

(| altura = 10. base = 10|).

Ahora sí a este objeto le podemos preguntar self altura  y self base.

Vemos que el 10, es un solo objeto.

Definamos otro objeto "parecido"...

(| altura = 10. base <- 5|).

En este caso altura tiene el valor constante  mientras que base es un slot variable, inicializado en el valor 5.

Ahora en su workspace podemos hacer...

self base: 4

Luego modificamos el objeto agregándole un slot.
Botón derecho "Add slot"

Y le agregamos un slot 

superficie = (base * altura)

Como reutilizamos ?

Los objetos pueden tener un tipo especial de slot de delegación (parent).
Cualquier mensaje que el objeto no entienda lo va a delegar automáticamente.

A través del parent traits cloneable hacemos que nuestro rectágulo sea cloneable

Usamos el clone para crear un clone.
Pero luego vemos que si modificamos el objeto original no se actualiza el clonado.

Entonces, para poder compartir código entre objetos vamos a crear un parent.

Creamos un nuevo objeto literal ().
Botón derecho Move y movemos los slots al nuevo objeto que va a ser nuestro parent.

Luego a los rectángulos le agregamos el slot parent* apuntando al objetito que creamos.
Este objeto parent no es un rectángulo, porque no tiene los slots de base y altura, sino que va a ser una especia de trait rectangulo.

Con esta técnica se emula la idea de clase.

Por qué tenemos dos objetos y no tenemos la base y la altura ? porque la base son slots constantes, valores, que no quiere compartir. 
Nuestro trait sería la clase, y nuestra instancia sería el objeto concreto.

Comparación con Herencia

Al tener slots parent aparece la idea de que sería parecido a la herencia. Y de hecho, recién mencionamos que la forma de reutilizar comportamiento emulaba las clases.
En realidad contamos esto, para introducir el lenguaje, comparándolo con lo que ya conocemos (Clases). Pero realmente no tiene sentido trabajar en un lenguaje prototipado, para pensar en imitar la forma de trabajar con clases.

Estaríamos perdiendo el poder agregado que nos dá un lenguaje puro de objetos.

Entre las diferencias con la herencia vemos que ésta última es una relación entre clases, mientras que el mecanismo de delegación de self es entre objetos.
No hay nada especial en la forma de compartir código en Self, más que relaciones entre objetos y la delegación automática. 

Más con traits

Luego le agregamos un factory method a nuestro trait. nuevoConBaseAltura

Make Creator

Creamos un nuevo slot en el lobby llamado figuras y lo marcamos (botón derecho) como creator (Make creator). Ahora el título de la ventan de nuestro objeto pasa a llamarse "figuras".

Esto marca algo importante de paradigma de objetos puro, que es que nuestros objetos no tienen nombre per se. En un esquema de clases las clases tienen nombre, en objetos puro no hay clases, ergo, no hay nombres.

Modificando Parent slots

Por último vimos que modificando el parent de un objeto estaríamos cambiándole su comportamiento completamente. Sería lo análogo a cambiarle la clase a un objeto (o superclase) en tiempo de ejecución.

Prototipos con Javascript

Luego jugamos un poco en javascript con objetos, prototipos y funciones.

Clase 5 - 12/09/2011 - Aspect-Oriented Programming (AOP)

posted Sep 12, 2011, 3:00 PM by Javier Fernandes   [ updated Sep 13, 2011, 3:49 AM by Nicolas Passerini ]

Aspectos Administrativos

Al principio de la clase vimos algunos aspectos (valga la redundancia) administrativos, respecto de los TP's.
Dijimos que la próxima clase ibamos a hacer la primer entrega y revisión del TP1.

Vimos que el segundo TP va a ser incluso más libre permitiendo elegir entre: Aspectos, Prototipos y Metaprogramación.

AOP

Luego de lo administrativo arrancamos con el tema de la clase: aspectos.

Contamos que el concepto de aspectos es de modelar una lógica que atraviesa varias clases, métodos y/o jerarquías, llamada "cross-cutting concerns".
Implementar esta lógica "a mano" involucraría modificar y repetir código en cada uno de esos lugares.

Entonces un aspecto nos permite resolver problemas como: quiero que todos mis objetos sean observables; dado mis test-cases quiero poder analizar qué partes de mi código está siendo testeado (ejecutado) y qué partes no.

Esto último existe de hecho en varios lenguajes de programación y se llama Code Coverage (ej de herramientas http://cobertura.sourceforge.net/)

Conceptos de AOP: Join-Point, Point-cut y Advice

Vimos luego los conceptos core del dominio de la programación orientada a aspectos.
Si bien vamos a ver aspectos con una implementación para java llamada AspectJ estos conceptos son abstractos y forman parte de AOP. Con lo cual serán comunes a todos los frameworks de aspectos.
Dependiendo del framework se podrán definir de diferentes formas.

  • Join-point: representa un punto en la ejecución del código de mi programa que resulta interesante. Es decir, en el cual me interesaría saber que está ejecutándose. Por ejemplo: la asignación de una variable de instancia, o el llamado a un método.
  • Point-Cut: es un conjunto de join-points a fin de poder definir un contexto más complejo. Es decir que se combinan, varios point-cuts, ejemplos: asignaciones de variables llamadas "blah" en mis clases del paquete objetos3.ejemplos y para las clases anotadas con @MeInteresa.
  • Advice: dado un pointcut, es decir un contexto de un punto de ejecución, representa una manipulación de ese código. Por ejemplo, poder agregar código antes y después de ese punto (around).
Luego vimos un ejemplo de la syntaxis de AspectJ para definir un aspecto para loggear llamadas a métodos.
Ese ejemplo está en la página del site

Weaving

Luego surgió la pregunta natural de "cómo hace la magia ?" (de interceptar el código y manipularlo).
Acá surge otro concepto de la programación de aspectos, que es el weaving.

Weaving es el proceso que utilizan los fwks de aspectos de código para implementar aspectos, es decir para manipular el código. Para combinar el código del aspecto con la lógica base (de nuestro dominio o clases a aspectear).
De ahí que el nombre en inglés significa tejer.

Enumeramos un par de estratégias de weaving:
  • Compilación: modificando el compilador y utilizando uno custom. Ej: aspectj, phantom.
  • Classloader: una vez cargadas las clases en java no se pueden modificar. Sin embargo, las clases las carga un objeto llamado ClassLoader y uno podría hacer el suyo propio, para, justo antes de cargar la clase, modificar su bytecode. Ejemplo javassist, Apache Commons BCEL
  • Interception: decora los objetos para interceptar los llamados. Ej: Spring AOP, Java Dynamic Proxies.
  • Preprocesador / Generación de Código: analizo el código como texto, antes de la compilación. Ej: Annotation Processing Tool APT.
  • Metaprogramación (?)
  • Debugging Hooks

Mock Objects

De pasada hablamos de Mock Objects. Que aparece cuando trabajamos en testcase y tenemos interfaces u objetos que queremos "mockear" es decir simular, a través de una nueva implementación dummy solo a fines de poder testear otra lógica. 
Ejemplo, cuando tengo que testear una lógica de negocio core, que eventualmente envía emails a través de un objeto de tipo MailSender.
Como en el testcase no voy a poder enviar mails, tengo que simular ese objeto de alguna forma.

La forma tradicional sería hacer una subclase de MailSender que no haga nada. Sería un DummyMailSender.

Ahora, hacer esto para muchas clases es bastante molesto, entonces aparecen los frameworks de MockObjects.
Estos frameworks permiten el mismo efecto pero sin la necesidad de crear una subclase.

Podemos mencionar dos fwks en java: JMock y Mockito

Estos proveen un API donde vamos a definir "quiero un objeto que implemente MailSender, y que checkee que al ejecutarse el test le llamen al método enviarMail con el texto 'te mando un mail' como parámetro".
El fwk se va a encargar de crear un proxy, es decir "simular" una subclase.
Quizás para esto utiliza un tipo de metaprogramación o proxies dinámicos como vimos que hacen algunos fwks de aspectos.

Ejemplos en AspectJ

Luego nos metimos en directo a ver ejemplos en código de aspectj.

Vemos el primer ejemplo simple de objetos observables.

Luego vimos que el aspecto es de hecho un objeto, y que puedo obtenerlo y acceder a su estado o hasta invocarle métodos.

Después vimos que ese aspecto que es un objeto tiene un ciclo de vida que define cuando se va a crear la instancia del aspecto y cuanto va a vivir. Esto puedo definirlo a través de 
  • pertarget para asignarlo a la instancia del objeto definido según un pointcut.
  • perthis: 

Ejemplo con Annotations

En segundo término vimos una forma alternativa de lograr el mismo resultado. Pero estableciendo un contrato entre los objetos a aspectear y el aspecto.
Acá el aspecto aplica solo a las clases anotadas con @Observable.

Ejemplo con Mixins

Vimos que define que los objetos anotados con @Observable ahora pasan a implementar una nueva interfaz.
Y el mismo aspecto le define las implementaciones de esos métodos, en forma parecida (conceptualmente) a la idea de Open Class que vimos en Nice.

Clase 4 - Traits y Mixins

posted Sep 5, 2011, 12:30 PM by Nicolas Passerini   [ updated Sep 6, 2011, 3:00 PM ]

Hoy hablamos sobre traits y mixins. Pueden encontrar material de lectura en Traits y Mixins.
El ejemplo que hicimos en clase es similar al que está explicado en este resumen.

Les debo pasarles el link a Talents.

1-3 of 3