viernes, 16 de enero de 2009

Tip 2: Clearly identify what represents the identity of an object

En el primer Tip (si ya se, lo escribí hace mucho...) comenté sobre lo interesante que es tener como objetivo lograr un isomorfismo entre los objetos de mi modelo y los entes del dominio del problema.
Además, como ya puse en otros posts, no hay que perder de vista que los objetos representarán la esencia de dichos entes mediante su comportamiento, no estructura, relaciones, etc.
Sin embargo hay otro punto del que siempre hablamos y es la identidad. La identidad es la que permite identificar únivocamente un ente. Todo ente posee una identidad y por lo tanto el objeto que lo representa en nuestro modelo también debe tener una. Sin embargo hay una gran confusión entre lo que es identidad, lo que algunos llaman "estado de un objeto" y lo que es la identidad del objeto. Voy a empezar por este último.
Un objeto, por ser a la vez un ente de la realidad (además de estar representado otro) también posee una identidad. Esa identidad en un ambiente de objetos está generalmente implementada por medio de la posición de memoria que ocupa el objeto. Es lo que hace que ese objeto sea único, no puede haber otro objeto en la misma zona de memoria que otro. 
En Smalltalk, se puede saber si dos objetos ocupan la misma zona de memoria usando el mensaje #== Este mensaje tiene por propósito verificar si dos "objetos" son identicos, o sea, si ocupan la misma zona de memoria pero no puede decir nada sobre la identidad del ente que representan dicho objetos. En rigor de verdad, si dos objetos son idénticos significa que están representando al mismo ente y por lo tanto representan la misma identidad del ente, pero si dos objetos no son identicos no se puede asegurar que estén representando a entes no idénticos. Es acá donde se ve claramente la diferencia entre identidad de objeto e identidad de ente. Un ejemplo lo va a aclarar.
En Smalltalk existe la clase Date, pero si evalúo dos veces la siguiente colaboración "Date today" obtengo dos objetos que no son idénticos pero que sí representan al mismo ente, el día de hoy. Por lo tanto no hay que confundir identidad de objeto que viene dado por el ambiente de objetos de identidad del ente que la tenemos que definir nosotros en nuestro modelo.
¿Cómo representamos la identidad del ente? Dependerá del ente que estemos modelando o la implementación que utilicemos. Por ejemplo, los SmallInteger en Smalltlk nos dan la sensación de ser únicos (o sea, de que hay uno y solo un objeto por cada uno de ellos). A nivel implementativo sabemos que no es así, pero es un claro ejemplo donde la identidad del ente esta asociada a la identidad del objeto. Otro ejemplo son los objetos instancia de Symbol, no puede haber más de un objeto para el mismo símbolo que representan de la realidad. Como vismo, no sucede así con las fechas y con otros objetos como aquellos instancias de Time, Point, etc.
¿Qué es lo que representa entonces la identidad de los entes para estos objetos? Siempre es un conjunto de colaboradores internos (variables de instancia) que cumplen ese propósito. En el caso de Date, dependiendo de la implementación serán el número de día, mes y año. En el caso de Point serán esos objetos que representan la coordenada x e y. 
Una característica interesante que tenemos que cumplir con estos colaboradores que representan la identidad de los objetos es que no pueden cambiar, puesto que si lo hacen el mismo objeto estaría en un instante de tiempo representando un ente y luego otro, sería un objeto con "problema de personalidad" no les parece?. Es por ello que es fundamental entender bien qué colaboradores internos representan la identidad de un objeto puesto que ellos no pueden cambiar. Hay otras implicancias interesantes de este hecho, la primera es que el mensaje #= del objeto devolverá true si los colaboradores internos que representan la identidad del ente son iguales. Esto significa que si queremos saber si dos objetos representan el mismo ente, debemos usar el mensaje #=, es este mensaje el que nos dirá si dos objetos representan a un ente idéntico o en otras palabras, a exactamente el mismo ente. Moraleja, no confundir identidad de objeto de identidad de ente y por lo tanto nunca, pero nunca usar el mensaje #== en un modelo a menos que ese modelo esté tratando con un dominio de problema computacional y donde realmente se tenga por intención saber si se está tratando a exactamente "el mismo objeto" sin importar si además si representan exactamente el mismo ente.
Esto que estoy comentando les debería disparar una nueva explicación de porque el hash debe estar relacionado con el #= y por qué cuando un objeto cambia los colaboradores que representan la identidad cambia su hash que termina produciendo un descalabro importante en aquellos objetos que dependen de la invariabilidad de esta característica.
También esto tiene que empezar a dispararnos la idea de que hay colaboradores internos que representan la identidad del ente que modela el objeto y otros que no. ¿qué características pueden tener estos otros? ¿pueden cambiar? ¿que representan?. Son muchas preguntas, no tengo una respuesta 100% segura, pero en la mayoría de los casos me parece que dichos colaboradores existirán por motivos implementativos como por ejemplo tener un cache, poder acceder más rápido a un objeto, etc. y no a cuestiones esenciales del dominio de problema en si, pero no lo puedo asegurar.
Otra pregunta interesante para hacerse es, ¿debería el lenguaje ofrecerme herramienta particulares para hacer uso de esta diferencia? Por ejemplo, que defina una clase de esta manera:
Object subclass: #Point
   identityDefinedBy: 'x y'
   instanceVariableNames: ''
   ... etc.
Al hacerlo, automáticamente el ambiente podría asegurar que la identidad no puede cambiar, y algo más interesante aún que la misma se defina en el momento de crear el objeto, algo que veremos en el próximo tip.... mientras tanto tiro la idea, yo aún no tengo un posición tomada.

Desarrollo ágil y vacaciones

Este fin de año terminé destruido, me dí cuenta que durante el 2008 hice muchas cosas e indudablemente sentí el impacto. Por suerte mañana empiezo mis vacaciones y esta vez me voy a tomar 3 semanas seguidas, siento que realmente las necesito. Espero poder desconectarme lo suficiente para volver con ganas para este año, aunque voy a limitar un poco lo que hago porque no quiero terminar otra vez así. Uno de los temas que creo que voy a limitar es la cantidad de tesis que estoy dirigiendo, aunque no lleve mucho tiempo hacerlo el problema es tener que estar pensando en todas ellas simultáneamente más todo el resto de cosas que tengo que hacer... 
Pero como en ciertas cosas no puedo con mi genio y me enteré de este seminario ágil, por ahí presente algo relacionado a la importancia que tiene para mi trabajar en un lenguaje dinámico si realmente se quiere se "ágil". Todo esto me vino a la mente después de haber visto ayer en Mercap Cinema (una vez por semana nos juntamos en el almuerzo a ver videos técnicos) la entrevista en la que estuvieron Dan Ingall y Allen Wirfs-Brook, en donde Dan hace hincapié y repite miles de veces la idea de "self sustainable system" o "meta circular system" y Allen hace una comparación entre Internet y la imagen de Smalltalk basada en la idea que no hay que bajar internet para cambiar una página de la misma manera que no hay que bajar la imagen de Smalltalk para cambiar un método. 
En fin, todo esto me hizo pensar lo poco que se entiende aún este espíritu dinámico que posee Smalltalk y que no tiene nada que ver con ser "dinámicamente tipado", sino con el hecho de tener un imagen y poder modificar un sistema mientras corre, donde ese sistema puede ser hasta sí mismo! (que es lo que hace incapíe Dan). Creo que la gente está empezando a ver la importancia de los lenguajes dinámicamente tipados y por lo tanto estaría bueno mostrarles un poco más allá y ver que opinan. 
En XTrade, donde utilizamos GemStone como server de objetos, es muy común que hagamos cambios sin bajar el sistema, simplemente modificando por medio de un script de topaz (un cliente de texto de GemStone) lo necesario para arreglar un error. Lamentablemente no tuvimos tiempo aún de implementar la modificación del cliente del sistema, que está escrito en VisualAge,  sin tener que cambiarlo completamente, o sea, bajando el cliente y volviéndolo a subir reemplazando toda la imagen, pero sabemos cómo podríamos hacerlo. En una aplicación Web esta característica es aún más interesante.
En fin, ¿qué les parece? ¿sería interesante una charla así en ese contexto? El título que pensé sería algo así: "No se puede ser ágil sin ser dinámico o que nos falta para ser técnicamente ágiles"