Por otro blog llegue a este video que vale la pena:
http://youtube.com/w/?v=43DZEy_J694&v3
Es sobre el libro "Everything Is Miscellaneous" de David Weinberger.
La teoría que expone es que el modelo de categorización de la información y conocimiento que tenemos (formada por Aristóteles y de la cual se toma la idea en los lenguajes de objetos con clasificación) se debe a limitaciones de la herramientas que usamos para crear dicha categorización, por ejemplo tener archivos para guardar tarjetas de resumen de libros nos obliga a que dicha tarjeta este en un único archivo, y por lo tanto nos obliga a categorizar dicho libro en una única categoría, la que ese archivo representa.
Como actualmente las herramientas que tenemos son más flexible debido a la "Era Digital", este estilo de clasificación no es más necesario y puede ser más flexible. Traducido a lenguajes de objetos, no se necesita tener una jerarquía estática y única de clases...
En el blog que saque este link, relacionaban esta flexibilidad con dynamic binding lo cual tiene mucho sentido, puesto que dinamic binding justamente nos permite hacer que objetos cuyas clases estén en ramas distintas de una jerarquía sigan siendo polimorficos entre sí, o sea, no es ncesario tener un único y estático eje de clasificación.
jueves, 28 de junio de 2007
Relación entre objetos y entes del dominio
Realmente se me hace difícil seguir una línea de conducción en lo que estaba escribiendo sobre el paradigma de objetos por el poco tiempo que le puedo dedicar, así que decidí cambiar un poco el enfoque y escribir sobre lo que estuve pensando en el día, para que salga más rápido y no tener el blog "dormido"... Así que aquí va lo que estuve re-pensando los últimos días y tiene que ver con tener un buen modelo de objetos.
Distinguir si se necesitan distintos objetos para representar distintos entes es generalmente sencillo. Es fácil distinguir que el objeto "1ro de Enero de 1997" no es el mismo que "2do de Enero de 1997". Son objetos distintos puesto que representan entes distintos, en este caso dos fechas y es sencillo ver que son dos entes distintos por su identidad.
El mayor problema está en descubrir aquellos objetos que no se ven en primera instancia, que generalmente están implícitos por cuestiones contextuales o de ambigüedad de lenguaje natural. Un ejemplo de ambigüedad del lenguaje natural se da con la palabra "día" en castellano, por ejemplo "¿Qué día es hoy?". La respuesta puede ser "Hoy es Lunes" u "Hoy es 25 de Junio del 2007". Está claro que "Lunes" y "25/6/2007" son entes distintos y por lo tanto deben ser representados por objetos distintos. Pero si el usuario en los requerimientos habla de "día", ¿a cúal se refiere? ¿al día de la semana, a la fecha, o a ambos y según el contexto se usa uno u otro?. No resolver este problema de ambigüedad, en definitiva de interpretación, puede llegar a generar grandes problemas en la evolución del sistema. (En inglés no se sufre de esta ambigüedad puesto que existen las palabras "Day" y "Date" para día y fecha)
Un ejemplo de entes implícitos es el concepto de "mes del año" del Calendario Gregoriano, por ejemplo "Febrero de 2004". Este es un concepto que generalmente no se reconoce en el modelo porque cuesta "verlo" en el dominio y se lo confunde con el concepto que representa un mes, por ejemplo "Febrero". Pero está claro que no podemos saber cuantos días tiene "Febrero", solo se puede saber cuantos días tiene "Febrero del 2004", o "Febrero del 2005", o sea, el mes del año. No "encontrar" estos objetos en el dominio implica que no serán modelados y hará que cuando se los necesite se terminen implementando soluciones de compromiso, repitiendo "código", etc.
Hay casos también donde se crean más objetos (en este caso conceptos) que los necesarios o definidos en el dominio, o sea que se crean más abstracciones de las necesarias. (Hasta ahora no hable sobre las Clases, pero me refiero a ello). Por ejemplo, al modelar un Autómata Finito Determinístico [1] uno de los problemas que surgen es si se debe crear una abstracción para el "Alfabeto". Un alfabeto (para el contexto del autómata) no es más que un conjunto de símbolos, y ya existen abstracciones para representar conjuntos, por ejemplo en Smalltalk es la clase Set, es por ello que se debe, para este caso, utilizar un Set para representar un Alfabeto y no crear una nueva abstracción (clase) "Alfabeto" que solamente agregaría complejidad al modelo. O sea, se puede ver que el nombre Alfabeto es puramente contextual a la definición del Autómata.
En definitiva, a lo que quiero llegar y aún me cuesta probar formalmente es que para mi tener un "buen" modelo implica tener un isomorfismo entre los objetos del modelo y los entes del dominio. Esto significa que por cada ente del dominio hay un único objeto que lo representa. Esto pasa para objetos concretos (por ejemplo "Lunes") como para entes abstractos o conceptos (por ejemplo "Día").
Si logramos tener este isomorfismo entre el modelo y el dominio, cada vez que realicemos una observación del dominio puede suceder lo siguiente con el modelo:
1) Que dicha observación sea modelada sin ningún problema, o sea, el modelo la contempla de tal manera que por cada ente de dicha observación tengo un objeto en el modelo que lo representa y esta nueva observación es un caso contemplado por el modelo.
2) Que dicha observación no pueda ser resuelta en el modelo. Esto implica que el modelo no es lo suficiente maduro aún, que el estado del conocimiento que dicho modelo representa no es completo respecto del dominio de problema. Para soportar esta observación puede ser necesario:
a) Crear nuevos objetos o conceptos únicamente. Este es el mejor caso, indica que el modelo esta por buen camino, que está madurando bien
b) Tener que partir objetos y conceptos ya existentes en otros más "chicos", más cohesivos. En este caso el modelo aún está un poco inmaduro.
c) Tener que juntar objetos y conceptos ya existentes en otros más generales. Esto es muy raro que suceda puesto que implica que se hizo una "factorización" excesiva, lo cual es muy raro.
d) Cualquier combinación de los tres puntos anteriores.
En fin, mucho para pensar al respecto, pero básicamente quería hacer este comentario sobre el isomorfismo que me parece interesante.
También me parece que utilizar la palabra "bueno" para calificar un modelo es difícil de consensuar. Ultimamente me estoy tirando más por usar "completo" o "maduro", y de estas dos me gusta más "maduro" puesto que "completo" denota la idea de "cerrado", de no necesitar más cambios, algo muy difícil de lograr más aún si suponemos que constantemente se aprende algo nuevo.
Otra idea interesante es pensar en el grado de madurez de un modelo como en función a los cambios que necesita cada vez que se realiza o aparece una nueva observación del dominio que representa. La idea es que esta función debería tender a cero a medida que crecen las observaciones. Si esto no se da, el modelo está en problemas...
[1] El ejercicio de modelar un Autómata Finito Determinístico se le ocurrió a Dan Rozenfarb en la materia de POO. Es un ejercicio muy interesante puesto que la definición al ser matemática, o sea formal y sin ambigüedades, permite un traducción directa al modelo de objetos. La definición es la siguiente:
Un autómata finito determinístico (o AFD) es una 5-upla (Q, S, d, q0, F) cuyos elementos son:
Q = {q0, q1, q2, ...} es un conjunto finito, no vacío, de estados.
S = {a,b, ...}, llamado alfabeto, es un conjunto finito de símbolos de entrada.
d: Q x S -> Q es una función de transición, también denominada control finito.
q0 pertenece a Q es el estado inicial.
F incluído en Q es el conjunto de estados finales.
Lo más importante es saber si un AFD acepta o no una secuencia de caracteres
Distinguir si se necesitan distintos objetos para representar distintos entes es generalmente sencillo. Es fácil distinguir que el objeto "1ro de Enero de 1997" no es el mismo que "2do de Enero de 1997". Son objetos distintos puesto que representan entes distintos, en este caso dos fechas y es sencillo ver que son dos entes distintos por su identidad.
El mayor problema está en descubrir aquellos objetos que no se ven en primera instancia, que generalmente están implícitos por cuestiones contextuales o de ambigüedad de lenguaje natural. Un ejemplo de ambigüedad del lenguaje natural se da con la palabra "día" en castellano, por ejemplo "¿Qué día es hoy?". La respuesta puede ser "Hoy es Lunes" u "Hoy es 25 de Junio del 2007". Está claro que "Lunes" y "25/6/2007" son entes distintos y por lo tanto deben ser representados por objetos distintos. Pero si el usuario en los requerimientos habla de "día", ¿a cúal se refiere? ¿al día de la semana, a la fecha, o a ambos y según el contexto se usa uno u otro?. No resolver este problema de ambigüedad, en definitiva de interpretación, puede llegar a generar grandes problemas en la evolución del sistema. (En inglés no se sufre de esta ambigüedad puesto que existen las palabras "Day" y "Date" para día y fecha)
Un ejemplo de entes implícitos es el concepto de "mes del año" del Calendario Gregoriano, por ejemplo "Febrero de 2004". Este es un concepto que generalmente no se reconoce en el modelo porque cuesta "verlo" en el dominio y se lo confunde con el concepto que representa un mes, por ejemplo "Febrero". Pero está claro que no podemos saber cuantos días tiene "Febrero", solo se puede saber cuantos días tiene "Febrero del 2004", o "Febrero del 2005", o sea, el mes del año. No "encontrar" estos objetos en el dominio implica que no serán modelados y hará que cuando se los necesite se terminen implementando soluciones de compromiso, repitiendo "código", etc.
Hay casos también donde se crean más objetos (en este caso conceptos) que los necesarios o definidos en el dominio, o sea que se crean más abstracciones de las necesarias. (Hasta ahora no hable sobre las Clases, pero me refiero a ello). Por ejemplo, al modelar un Autómata Finito Determinístico [1] uno de los problemas que surgen es si se debe crear una abstracción para el "Alfabeto". Un alfabeto (para el contexto del autómata) no es más que un conjunto de símbolos, y ya existen abstracciones para representar conjuntos, por ejemplo en Smalltalk es la clase Set, es por ello que se debe, para este caso, utilizar un Set para representar un Alfabeto y no crear una nueva abstracción (clase) "Alfabeto" que solamente agregaría complejidad al modelo. O sea, se puede ver que el nombre Alfabeto es puramente contextual a la definición del Autómata.
En definitiva, a lo que quiero llegar y aún me cuesta probar formalmente es que para mi tener un "buen" modelo implica tener un isomorfismo entre los objetos del modelo y los entes del dominio. Esto significa que por cada ente del dominio hay un único objeto que lo representa. Esto pasa para objetos concretos (por ejemplo "Lunes") como para entes abstractos o conceptos (por ejemplo "Día").
Si logramos tener este isomorfismo entre el modelo y el dominio, cada vez que realicemos una observación del dominio puede suceder lo siguiente con el modelo:
1) Que dicha observación sea modelada sin ningún problema, o sea, el modelo la contempla de tal manera que por cada ente de dicha observación tengo un objeto en el modelo que lo representa y esta nueva observación es un caso contemplado por el modelo.
2) Que dicha observación no pueda ser resuelta en el modelo. Esto implica que el modelo no es lo suficiente maduro aún, que el estado del conocimiento que dicho modelo representa no es completo respecto del dominio de problema. Para soportar esta observación puede ser necesario:
a) Crear nuevos objetos o conceptos únicamente. Este es el mejor caso, indica que el modelo esta por buen camino, que está madurando bien
b) Tener que partir objetos y conceptos ya existentes en otros más "chicos", más cohesivos. En este caso el modelo aún está un poco inmaduro.
c) Tener que juntar objetos y conceptos ya existentes en otros más generales. Esto es muy raro que suceda puesto que implica que se hizo una "factorización" excesiva, lo cual es muy raro.
d) Cualquier combinación de los tres puntos anteriores.
En fin, mucho para pensar al respecto, pero básicamente quería hacer este comentario sobre el isomorfismo que me parece interesante.
También me parece que utilizar la palabra "bueno" para calificar un modelo es difícil de consensuar. Ultimamente me estoy tirando más por usar "completo" o "maduro", y de estas dos me gusta más "maduro" puesto que "completo" denota la idea de "cerrado", de no necesitar más cambios, algo muy difícil de lograr más aún si suponemos que constantemente se aprende algo nuevo.
Otra idea interesante es pensar en el grado de madurez de un modelo como en función a los cambios que necesita cada vez que se realiza o aparece una nueva observación del dominio que representa. La idea es que esta función debería tender a cero a medida que crecen las observaciones. Si esto no se da, el modelo está en problemas...
[1] El ejercicio de modelar un Autómata Finito Determinístico se le ocurrió a Dan Rozenfarb en la materia de POO. Es un ejercicio muy interesante puesto que la definición al ser matemática, o sea formal y sin ambigüedades, permite un traducción directa al modelo de objetos. La definición es la siguiente:
Un autómata finito determinístico (o AFD) es una 5-upla (Q, S, d, q0, F) cuyos elementos son:
Q = {q0, q1, q2, ...} es un conjunto finito, no vacío, de estados.
S = {a,b, ...}, llamado alfabeto, es un conjunto finito de símbolos de entrada.
d: Q x S -> Q es una función de transición, también denominada control finito.
q0 pertenece a Q es el estado inicial.
F incluído en Q es el conjunto de estados finales.
Lo más importante es saber si un AFD acepta o no una secuencia de caracteres
martes, 19 de junio de 2007
Modelo del Calendario Gregoriano
El sábado participe de una clase del Master de Ingeniería de Software de la UCA, de la matería que dirige Angel Perez Pulleti. Hablamos sobre el dominio del Tiempo, más exactamente sobre como medirlo usando el Calendario Gregoriano que es el modelo por default que usamos en las culturas "occidentales".
La verdad que fue una clase muy interesante. Los alumnos tenían que proponer un modelo a partir de un enunciado con problemas y casos específicos que le habíamos dado para luego hacer una crítica sobre los mismos y proponer alguna solución mejor.
Me di cuenta que este problema es un muy buen problema para ver todos los errores típicos que se comenten cuando se desarrolla (modela) con objetos. Por ejemplo:
1) Usar una única abstracción para representar varios entes del dominio. Ej. la clase Fecha se utiliza para representar fechas, años, meses.
2) Se utilizan abstracciones incorrectas para representar entes del dominio. Ej. los días (Lunes, Martes, etc) y meses (Enero, Febrero, etc) son Números, por lo tanto:
a) Se puede "realizar cosas" con dichos objetos que no corresponden con los entes del dominio que representan. Por ejemplo se puede multiplicar días (Lunes*Martes) ya que es equivalente a hacer 1*2 (si Lunes es 1 y Martes 2), o sumar meses (Enero+Diciembre).
b) No se puede "realizar cosas" con dichos objetos que si se puede con los entes que representan del dominio, como saber "la cantidad de días" de un mes ya que un Número no posee dicha responsabilidad. O saber si el Lunes está antes que el Domingo, puesto que esta respuesta dependen del contexto y no es "fija" como saber si el 1 está antes del 7.
3) Se ponen malos nombres a las abstracciones, por ejemplo Tiempo o Día a la clase que representa fechas. ¿Por qué Tiempo es un mal nombre?, el ejemplo que uso es el siguiente. Si les pregunto "¿Qué tiempo es?", ustedes, ¿qué responden?. Seguro que algunos dirán "¿a qué te referís? no tiene sentido esa pregunta" y otros se aventurarán a pensar "este gil hizo mal la pregunta... en realidad quizo decir qué tiempo hacía o cómo está el tiempo... y en este momento hace mucho frío". Bien, ahí esta el motivo por el cual es un mal nombre, por que es ambiguo (depende de la interpretación que le demos) y por lo tanto no representa directamente el concepto que se está tratando de sintetizar con dicha clase. El gap semántico entre lo que quiere representar y es, es grande. La pregunta correcta sería "¿Qué fecha es?". Lo mismo sucede con Día, si pregunto ¿qué día es?, algunos dirán "es Lunes", otros dirán "es el primero de enero del 2007", de vuelta una palabra ambigua. Por lo tanto es mejor usar Fecha para el último caso y DíaDeLaSemana para el primero.
4) Y por último, la más común, faltan abstracciones. No se dan cuenta que Mes (por ej. Enero) y MesDelAño (por ej. Enero del 2007) no son lo mismo o que existen DiaDelMes (por ej. 25 de Diciembre), etc.
En fin, un lindo ejercicio.
La verdad que fue una clase muy interesante. Los alumnos tenían que proponer un modelo a partir de un enunciado con problemas y casos específicos que le habíamos dado para luego hacer una crítica sobre los mismos y proponer alguna solución mejor.
Me di cuenta que este problema es un muy buen problema para ver todos los errores típicos que se comenten cuando se desarrolla (modela) con objetos. Por ejemplo:
1) Usar una única abstracción para representar varios entes del dominio. Ej. la clase Fecha se utiliza para representar fechas, años, meses.
2) Se utilizan abstracciones incorrectas para representar entes del dominio. Ej. los días (Lunes, Martes, etc) y meses (Enero, Febrero, etc) son Números, por lo tanto:
a) Se puede "realizar cosas" con dichos objetos que no corresponden con los entes del dominio que representan. Por ejemplo se puede multiplicar días (Lunes*Martes) ya que es equivalente a hacer 1*2 (si Lunes es 1 y Martes 2), o sumar meses (Enero+Diciembre).
b) No se puede "realizar cosas" con dichos objetos que si se puede con los entes que representan del dominio, como saber "la cantidad de días" de un mes ya que un Número no posee dicha responsabilidad. O saber si el Lunes está antes que el Domingo, puesto que esta respuesta dependen del contexto y no es "fija" como saber si el 1 está antes del 7.
3) Se ponen malos nombres a las abstracciones, por ejemplo Tiempo o Día a la clase que representa fechas. ¿Por qué Tiempo es un mal nombre?, el ejemplo que uso es el siguiente. Si les pregunto "¿Qué tiempo es?", ustedes, ¿qué responden?. Seguro que algunos dirán "¿a qué te referís? no tiene sentido esa pregunta" y otros se aventurarán a pensar "este gil hizo mal la pregunta... en realidad quizo decir qué tiempo hacía o cómo está el tiempo... y en este momento hace mucho frío". Bien, ahí esta el motivo por el cual es un mal nombre, por que es ambiguo (depende de la interpretación que le demos) y por lo tanto no representa directamente el concepto que se está tratando de sintetizar con dicha clase. El gap semántico entre lo que quiere representar y es, es grande. La pregunta correcta sería "¿Qué fecha es?". Lo mismo sucede con Día, si pregunto ¿qué día es?, algunos dirán "es Lunes", otros dirán "es el primero de enero del 2007", de vuelta una palabra ambigua. Por lo tanto es mejor usar Fecha para el último caso y DíaDeLaSemana para el primero.
4) Y por último, la más común, faltan abstracciones. No se dan cuenta que Mes (por ej. Enero) y MesDelAño (por ej. Enero del 2007) no son lo mismo o que existen DiaDelMes (por ej. 25 de Diciembre), etc.
En fin, un lindo ejercicio.
lunes, 11 de junio de 2007
Definición de Programa
En el último post sobre la tería de Objetos había comentado que las herramientas que ofrece el Paradigma de Objetos para modelar son los Objetos y los Mensajes.
Es a partir de estas herramientas que un programa dentro del Paradigma de Objetos se define como: "Objetos que colaboran entre sí enviandose Mensajes" [1]
Esto implica que un modelo realizado con este paradigma, no es más ni menos que objetos colaborando. Para poder entender esta definición es necesario aclarar que significa cada una de sus palabras claves que están en negrita.
Objeto: Un objeto es una representación de un Ente del dominio del problema que se está modelando. Un Ente puede ser cualquier cosa, como por ejemplo una cantidad de dinero, un número, un billete, una acción, un empresa, lo que se entiende por todo o lo que se entiende por nada, etc. Cómo podemos ver, es una definición muy vaga quizá, pero por suerte los seres humanos tenemos la capacidad de atachar a estas definiciones emociones, vivencias, etc. que le van dando significado al término y lo van desambiguando.
Mensaje: Los mensajes son el mecanismo que utilizan los objetos para comunicarse entre sí. Haciendo una analogía con una conversación entre dos personas, un mensaje sería aquello que una persona le dice a otra.
Colaboración: Es el hecho de enviar un mensaje y esperar su respuesta. Cada vez que un objeto envía un mensaje a otro, se está realizando una colaboración y esta termina cuando el objeto receptor del mensaje devuelve una respuesta.
Se puede pensar en este modelo de colaboración entre objetos como una simplificación de la comunicación entre personas. Digo simplificación porque en este caso, existe un objeto emisor del mensaje que espera hasta que el receptor del mensaje responda, y siempre existirá una respuesta al envío de un mensaje, aunque esa respuesta sea "nada", que es "algo".
Por lo tanto, cada conversación que un objeto mantiene con otro es "sincrónica", sin embargo nada impide que un objeto lleve varias conversaciones simultáneamente, de la misma manera que una persona puede estar realizando varias "tareas" a la vez.
Una característica que posee la "colaboración" entre objetos es que el objeto receptor del mensaje no conoce al objeto emisor del mismo. Esto no cumple con la analogía que venimos haciendo, sin embargo el resultado de esta característica es que se puede asegurar que un objeto siempre responderá de la misma manera a un mensaje, no importa quién le envíe el mensaje. O sea, no sucede como en los humanos, donde generalmente la respuesta no será la misma si el que pide una tarea es el jefe o un compañero. (Esto no impide que esta situación se pueda modelar con objetos, de hecho se ha hecho, pero va más allá de lo que quiero hablar ahora).
Hay muchos temas interesantes que surgen a partir de esta definición de programa, cómo por ejemplo que el único acoplamiento entre objetos son los mensajes que se envían o el único problema que puede existir en este modelo es que un objeto no sepa responder un mensaje o que en definitiva un mensaje es un objeto. Estos temas lo trataré más adelante, sin embargo lo que más me importa recalcar para concluir este post es la definición de Objeto. Cuando se la entiende y aplica correctamente, permite obtener mejores modelos. Les voy adelantando que el "kit de la cuestión" está en tener un objeto en el modelo por cada ente de la realidad. Por lo tanto las preguntas que se pueden empezar a hacer son: ¿Cómo se define un objeto a partir del ente que representa? ¿Cómo se si un ente en realidad es uno o dos? ¿Hay que modelar todos los entes? etc.
-----------
[1] Esta definición fue creada por Máximo Prieto
Es a partir de estas herramientas que un programa dentro del Paradigma de Objetos se define como: "Objetos que colaboran entre sí enviandose Mensajes" [1]
Esto implica que un modelo realizado con este paradigma, no es más ni menos que objetos colaborando. Para poder entender esta definición es necesario aclarar que significa cada una de sus palabras claves que están en negrita.
Objeto: Un objeto es una representación de un Ente del dominio del problema que se está modelando. Un Ente puede ser cualquier cosa, como por ejemplo una cantidad de dinero, un número, un billete, una acción, un empresa, lo que se entiende por todo o lo que se entiende por nada, etc. Cómo podemos ver, es una definición muy vaga quizá, pero por suerte los seres humanos tenemos la capacidad de atachar a estas definiciones emociones, vivencias, etc. que le van dando significado al término y lo van desambiguando.
Mensaje: Los mensajes son el mecanismo que utilizan los objetos para comunicarse entre sí. Haciendo una analogía con una conversación entre dos personas, un mensaje sería aquello que una persona le dice a otra.
Colaboración: Es el hecho de enviar un mensaje y esperar su respuesta. Cada vez que un objeto envía un mensaje a otro, se está realizando una colaboración y esta termina cuando el objeto receptor del mensaje devuelve una respuesta.
Se puede pensar en este modelo de colaboración entre objetos como una simplificación de la comunicación entre personas. Digo simplificación porque en este caso, existe un objeto emisor del mensaje que espera hasta que el receptor del mensaje responda, y siempre existirá una respuesta al envío de un mensaje, aunque esa respuesta sea "nada", que es "algo".
Por lo tanto, cada conversación que un objeto mantiene con otro es "sincrónica", sin embargo nada impide que un objeto lleve varias conversaciones simultáneamente, de la misma manera que una persona puede estar realizando varias "tareas" a la vez.
Una característica que posee la "colaboración" entre objetos es que el objeto receptor del mensaje no conoce al objeto emisor del mismo. Esto no cumple con la analogía que venimos haciendo, sin embargo el resultado de esta característica es que se puede asegurar que un objeto siempre responderá de la misma manera a un mensaje, no importa quién le envíe el mensaje. O sea, no sucede como en los humanos, donde generalmente la respuesta no será la misma si el que pide una tarea es el jefe o un compañero. (Esto no impide que esta situación se pueda modelar con objetos, de hecho se ha hecho, pero va más allá de lo que quiero hablar ahora).
Hay muchos temas interesantes que surgen a partir de esta definición de programa, cómo por ejemplo que el único acoplamiento entre objetos son los mensajes que se envían o el único problema que puede existir en este modelo es que un objeto no sepa responder un mensaje o que en definitiva un mensaje es un objeto. Estos temas lo trataré más adelante, sin embargo lo que más me importa recalcar para concluir este post es la definición de Objeto. Cuando se la entiende y aplica correctamente, permite obtener mejores modelos. Les voy adelantando que el "kit de la cuestión" está en tener un objeto en el modelo por cada ente de la realidad. Por lo tanto las preguntas que se pueden empezar a hacer son: ¿Cómo se define un objeto a partir del ente que representa? ¿Cómo se si un ente en realidad es uno o dos? ¿Hay que modelar todos los entes? etc.
-----------
[1] Esta definición fue creada por Máximo Prieto
miércoles, 6 de junio de 2007
Números y objetos
Ayer estuve ayudando a mi hija mayor con unos problemas de matemática. Un problema decía algo así: "Tenes 398 estampillas y queres repartirlas en páginas de 9 estampillas cada una. ¿Cúantas páginas se necesitan? ¿Cúantos espacios libres quedan?"
(Si se preguntan que tiene que ver esto con modelar usando objetos, aguanten un poco)
Por suerta ella se dio cuanta que tenía que dividir, hasta ahí todo bien, pero no pudo responder bien cuantos espacios libres quedaban. ¿Por qué? porque no interpretaba que el resto de la división (o sea, el número 2) representaba 2 estampillas y no 2 páginas, como había pensado en primera instancia.
Hoy cuando venía para el trabajo me saltó a la cabeza el motivo por el cual creamos el modelo de Medidas, que hicimos público bajo en nombre de Aconcagua. El motivo se debía principalmente a que nos dimos cuenta que los números "no tienen significado", son "símbolos abstractos" a los cuales el ser humano, según el contexto, les da un significado. La manera de hacer explícito dicho significado es "adosando" a cada número una palabra (o unidad como comunmente lo conocemos).
Por lo tanto, si a mi hija le hubiesen enseñado a dividir usando "numeros con unidades" y no solo números, creo que hubiese entendido que el resto no eran páginas sino estampillas. Esto significa que en vez de hacer "398/9", debería haber hecho "398 estampillas/9 estampillas/página". De esta manera está claro que el resultado (cociente) son páginas (se simplifica estampillas del numerador con estampillas de denominador y queda página) y el resto estampillas.
Lo curioso de esto es que ella sabía que tenía que hacer "398/9" (¿quizá de memoria?), pero al escribir esta división solo con números perdió por completo el significado de estos, por lo tanto no interpretó que le sobraban estampillas y no páginas.
¿Qué tiene que ver esto con computación y objetos?. Bueno, si un ser humano puede "olvidar" el significado de un número, imaginensé una computadora que no interpreta más allá del contexto que le provee el programa.
Este es el error típico que se encuentra en todo sistema bancario, financiero, etc. donde se mezclan dolares con pesos, pesos con euros, bonos con acciones, etc. El error (haciendo una analogía con el problema que tenía que resolver mi hija) es que seguramente el modelo que hagamos (programa) utilizará el objeto "398" para representar el ente de la realidad "398 estampillas", y no el objeto "398 estampillas" para representar dicho ente (No se confundan con que el ente de la realidad "398 estampillas" se escribe igual que el objeto "398 estampillas". El primero "vive" en la realidad, el segundo en el modelo, en la simulación, por ende lo representa. Son dos entes distintos).
Esto implica que el programa (o sea lo objetos) perdieron toda información sobre qué significa ese objeto "398" y solo saben que es un número. El que tiene esa información, ese conocimiento, es el programador, en su cabeza (cuando hizo el programa, seguramente luego se olvidará), pero como todos sabemos los programadores se equivocan como todo ser humano y por lo tanto no faltará mucho para que alguno interprete que sobraron 2 páginas o que se puede sumar 3 dólares con 4 pesos, puesto que seguramente esto será resuelto sumando 3 y 4 en vez de "3 dólares" y "4 pesos".
En fin, ahora entiendo por qué los programadores tenemos la costumbre de utilizar solamente números: ¡¡¡ASI NOS ENSEÑARON!!!
Comentario sobre Aconcagua: Básicamente modela lo que llamamos Medidas (que es un nombre que le queda chico a lo que realmente representa pero por ahora no importa). Una medida es por lo tanto un objeto compuesto por una cantidad y una unidad como por ejemplo: "3 dólares", "398 estampillas", "4 horas", etc. Ahora lo interesante de las medidas es su comportamiento y es que se las puede operar aritméticamente como cualquier número y con cualquier otra medida o número. Por ejemplo, se puede hacer "10 metros * 10 metros" que dará "100 metrosCuadrados", o "398 estampillas / (9 estampillas/1 página)" lo que dara "44.22 páginas". Nos salvo de muchos problemas, puesto que le pasamos EL PROBLEMA a la computadora.
(Si se preguntan que tiene que ver esto con modelar usando objetos, aguanten un poco)
Por suerta ella se dio cuanta que tenía que dividir, hasta ahí todo bien, pero no pudo responder bien cuantos espacios libres quedaban. ¿Por qué? porque no interpretaba que el resto de la división (o sea, el número 2) representaba 2 estampillas y no 2 páginas, como había pensado en primera instancia.
Hoy cuando venía para el trabajo me saltó a la cabeza el motivo por el cual creamos el modelo de Medidas, que hicimos público bajo en nombre de Aconcagua. El motivo se debía principalmente a que nos dimos cuenta que los números "no tienen significado", son "símbolos abstractos" a los cuales el ser humano, según el contexto, les da un significado. La manera de hacer explícito dicho significado es "adosando" a cada número una palabra (o unidad como comunmente lo conocemos).
Por lo tanto, si a mi hija le hubiesen enseñado a dividir usando "numeros con unidades" y no solo números, creo que hubiese entendido que el resto no eran páginas sino estampillas. Esto significa que en vez de hacer "398/9", debería haber hecho "398 estampillas/9 estampillas/página". De esta manera está claro que el resultado (cociente) son páginas (se simplifica estampillas del numerador con estampillas de denominador y queda página) y el resto estampillas.
Lo curioso de esto es que ella sabía que tenía que hacer "398/9" (¿quizá de memoria?), pero al escribir esta división solo con números perdió por completo el significado de estos, por lo tanto no interpretó que le sobraban estampillas y no páginas.
¿Qué tiene que ver esto con computación y objetos?. Bueno, si un ser humano puede "olvidar" el significado de un número, imaginensé una computadora que no interpreta más allá del contexto que le provee el programa.
Este es el error típico que se encuentra en todo sistema bancario, financiero, etc. donde se mezclan dolares con pesos, pesos con euros, bonos con acciones, etc. El error (haciendo una analogía con el problema que tenía que resolver mi hija) es que seguramente el modelo que hagamos (programa) utilizará el objeto "398" para representar el ente de la realidad "398 estampillas", y no el objeto "398 estampillas" para representar dicho ente (No se confundan con que el ente de la realidad "398 estampillas" se escribe igual que el objeto "398 estampillas". El primero "vive" en la realidad, el segundo en el modelo, en la simulación, por ende lo representa. Son dos entes distintos).
Esto implica que el programa (o sea lo objetos) perdieron toda información sobre qué significa ese objeto "398" y solo saben que es un número. El que tiene esa información, ese conocimiento, es el programador, en su cabeza (cuando hizo el programa, seguramente luego se olvidará), pero como todos sabemos los programadores se equivocan como todo ser humano y por lo tanto no faltará mucho para que alguno interprete que sobraron 2 páginas o que se puede sumar 3 dólares con 4 pesos, puesto que seguramente esto será resuelto sumando 3 y 4 en vez de "3 dólares" y "4 pesos".
En fin, ahora entiendo por qué los programadores tenemos la costumbre de utilizar solamente números: ¡¡¡ASI NOS ENSEÑARON!!!
Comentario sobre Aconcagua: Básicamente modela lo que llamamos Medidas (que es un nombre que le queda chico a lo que realmente representa pero por ahora no importa). Una medida es por lo tanto un objeto compuesto por una cantidad y una unidad como por ejemplo: "3 dólares", "398 estampillas", "4 horas", etc. Ahora lo interesante de las medidas es su comportamiento y es que se las puede operar aritméticamente como cualquier número y con cualquier otra medida o número. Por ejemplo, se puede hacer "10 metros * 10 metros" que dará "100 metrosCuadrados", o "398 estampillas / (9 estampillas/1 página)" lo que dara "44.22 páginas". Nos salvo de muchos problemas, puesto que le pasamos EL PROBLEMA a la computadora.
lunes, 4 de junio de 2007
Herramientas para construir modelos computables
Hasta ahora comenté que un programa es un modelo computable de un dominio de problema y que un buen modelo es aquel que "reproduce" cada observación del dominio correctamente.
Ahora quería hablar sobre las herramientas que contamos para crear estos modelos.
La primera y principal es el "Lenguaje de Programación". Esta herramienta es la que permitirá "escribir", "expresar" los modelos que estamos realizando.
Pero además de esta herramienta existen "principios conceptuales" o maneras de pensar sobre los problemas, que vienen dados por el Paradigma al cual adhiere el lenguaje de programación.
Por ejemplo, si usamos Pascal para desarrollar, conceptualmente nuestro modelo estará formado por procedimientos y estructuras de datos, puesto que son las herramientas conceptuales del Paradigma Estructurado.
Si usamos Lisp, nuestro modelo estará compuesto de funciones Lambda que proveerán el sistema de reescritura necesario que simule el dominio de problema en cuestión, puesto que las funciones Lambda son la herramienta conceptual principal del Paradigma Funcional.
Si se usa Smalltalk, solo se utilizarán dos herramientas conceptuales para crear los modelos computables, los Objetos y los Mensajes. Estos son los componentes básicos del Paradigma de Objetos Minimal y Puro. (la idea de Minimal y Puro es una idea que creó Máximo Prieto, por lo menos que yo sepa).
La característica Minimal tiene por objetivo definir el Paradigma con la "mínima" cantidad de elementos básicos e inducir/deducir el resto a partir de estos. Las ventajas de tener una definición Minimal es que dicha definición debería ser simple, puesto que es la más "chica" posible. Por lo tanto, debería ser fácil de recordar, inmune a contradicciones, etc. Tiene todas la características positivas de algo simple.
La característica de Puro evita tomar definiciones de otro Paradigma y tiene por objetivo evitar el "ruido" que se generaría debido a comparaciones y analogías incorrectas con elemetnos de otros Paradigmas.
Por lo tanto, crear un Modelo Computable usando el Paradigma de Objetos, consiste en "combinar" únicamente Objetos y Mensajes. Estos son los "building blocks" de todo aquello que se pueda crear, son los ladrillos y el cemento que nos permitirán construir software. Todos los problemas que se presenten y se quieran resolver con este Paradigma, deberán ser pensados y solucionados solamente con Objetos y Mensajes.
Veremos entonces, a partir de esta premisa, qué es modelar con objetos, en definitiva, qué es un programa desarrollado con el Paradigma de Objetos.
Nota Histórica: El primero en hablar de Paradigmas de Programación fue Robert Floyd en su ACM Turing Award Lecture, "The Paradigms of Programming" en 1979. Aunque él se refería como paradigmas también a lo que actualmente conocemos como Idioms o Técnicas de Programación, el término quedó dentro del vocabulario de nuestra profesión cómo una manera de clasificar los lenguajes de programación, o las distintas maneras de pensar sobre cómo construir modelos de software.
Ahora quería hablar sobre las herramientas que contamos para crear estos modelos.
La primera y principal es el "Lenguaje de Programación". Esta herramienta es la que permitirá "escribir", "expresar" los modelos que estamos realizando.
Pero además de esta herramienta existen "principios conceptuales" o maneras de pensar sobre los problemas, que vienen dados por el Paradigma al cual adhiere el lenguaje de programación.
Por ejemplo, si usamos Pascal para desarrollar, conceptualmente nuestro modelo estará formado por procedimientos y estructuras de datos, puesto que son las herramientas conceptuales del Paradigma Estructurado.
Si usamos Lisp, nuestro modelo estará compuesto de funciones Lambda que proveerán el sistema de reescritura necesario que simule el dominio de problema en cuestión, puesto que las funciones Lambda son la herramienta conceptual principal del Paradigma Funcional.
Si se usa Smalltalk, solo se utilizarán dos herramientas conceptuales para crear los modelos computables, los Objetos y los Mensajes. Estos son los componentes básicos del Paradigma de Objetos Minimal y Puro. (la idea de Minimal y Puro es una idea que creó Máximo Prieto, por lo menos que yo sepa).
La característica Minimal tiene por objetivo definir el Paradigma con la "mínima" cantidad de elementos básicos e inducir/deducir el resto a partir de estos. Las ventajas de tener una definición Minimal es que dicha definición debería ser simple, puesto que es la más "chica" posible. Por lo tanto, debería ser fácil de recordar, inmune a contradicciones, etc. Tiene todas la características positivas de algo simple.
La característica de Puro evita tomar definiciones de otro Paradigma y tiene por objetivo evitar el "ruido" que se generaría debido a comparaciones y analogías incorrectas con elemetnos de otros Paradigmas.
Por lo tanto, crear un Modelo Computable usando el Paradigma de Objetos, consiste en "combinar" únicamente Objetos y Mensajes. Estos son los "building blocks" de todo aquello que se pueda crear, son los ladrillos y el cemento que nos permitirán construir software. Todos los problemas que se presenten y se quieran resolver con este Paradigma, deberán ser pensados y solucionados solamente con Objetos y Mensajes.
Veremos entonces, a partir de esta premisa, qué es modelar con objetos, en definitiva, qué es un programa desarrollado con el Paradigma de Objetos.
Nota Histórica: El primero en hablar de Paradigmas de Programación fue Robert Floyd en su ACM Turing Award Lecture, "The Paradigms of Programming" en 1979. Aunque él se refería como paradigmas también a lo que actualmente conocemos como Idioms o Técnicas de Programación, el término quedó dentro del vocabulario de nuestra profesión cómo una manera de clasificar los lenguajes de programación, o las distintas maneras de pensar sobre cómo construir modelos de software.
viernes, 1 de junio de 2007
Extreme Validation
El viernes 18 de Mayo de 2007, Andres Valloud y Leandro Caniglia dieron una charla en la materia de Programación Orientada a Objetos sobre un concepto que llaman "Extreme Validation".
La idea es interesante y la presentación salió muy bien. El modelo que presentaron se puede ver en el paper que Leandro presento en Smalltalk Solutions 2007
El otro dia se me vino a la cabeza un modelo de validadores distintos al que ellos usan y queria comentarlo para ver que les parece.
La idea es cambiar un poco el punto de vista y tener una clase de validador por tipo de validación. O sea, la jerarquía de clases quedaría algo así:
Validator
...IsRequiredValidator
...IsNumberValidator
...IsStringValidator
... (bla bla)
...CompositeValidator
Validator definiria el mensaje #validate: anObject que seria abstracto. Cada validador implementaria lo necesario según el tipo de validación que hace. El CompositeValidator delegaría el #validate: a cada validador que lo compone.
Luego, cada clase conocería su validador (quizá a travez de una variable de instancia de clase) que en la mayoría de los casos seguramente sería un CompositeValidator. Por ejemplo:
Person class>>initializeValidator
validator := CompositeValidator
with: (IsRequiredValidator aspect: #name)
with: (IsNumberValidator aspect: #age between: 0 and: 100) ... bla bla bla.
Lo que vi de interesante de hacer estos cambios es:
1) No se tiene una jerarquía paralela de validadores puesto que hay validadores por tipo de validación, no por objeto a validar
2) Se puede controlar la secuencia de validación puesto que el CompositeValidator seguiría la secuencia de validación a patir de como se lo creo.
3) No seria necesario crear los validadores constantemente (como creo que lo están haciendo, a menos que los cacheen en algún lado), solo se crearían una vez con un mensaje como #initializeValidator...
4) Cuando se crean nuevas clases del modelo, no es necesario crear nuevas clase de validación, simplemente se componen validadores existentes. Esto es indicio de un buen modelo, o sea, aparecen nuevos elementos en el dominio de validación que implican solo la creación de nuevos objetos en mi modelo y no la creación de nuevas clases puesto que lo aparecen son validadores y no nuevos "conceptos de validación".
5) La clase validator no será una "library" de funciones de validación, sino que habra una clase de validación por cada tipo de validación. De esta manera se está reificando el concepto de tipo de validación y no se está implementado en Validator responsabilidad relacionada a validaciones que necesitan otros objetos.
Quizá la desventaja es que el CompositeValidator debería implementar algo similar a lo que hace TestCase y TestCaseResult para guardarse el resultado de validación, motivo por el cual Andrés había sublasificado Validator de TestCaseAbstract en primera instancia, pero no lo veo problemático.
Según lo que enseñamos en POO, sublasificar Validator de TestCaseAbstract no es correcto conceptualmente. El motivo se debe a que TestCaseAbstract tiene más comportamiento (responde más mensajes) del que un Validator realmente representa . En este caso en vez de que Validator tenga menos comportamiento que el necesario (un error común de análisis del dominio), tiene más (un error común cuando se "abusa" el uso de la subclasificación). Esto lo convierte en un Validator+un TestCase, y por lo tanto sabrá responder mensajes que no le corresponden, produciendo inconsistencias y errores.
Para aquellos que estuvieron en la presentación, ¿qué les parece?
La idea es interesante y la presentación salió muy bien. El modelo que presentaron se puede ver en el paper que Leandro presento en Smalltalk Solutions 2007
El otro dia se me vino a la cabeza un modelo de validadores distintos al que ellos usan y queria comentarlo para ver que les parece.
La idea es cambiar un poco el punto de vista y tener una clase de validador por tipo de validación. O sea, la jerarquía de clases quedaría algo así:
Validator
...IsRequiredValidator
...IsNumberValidator
...IsStringValidator
... (bla bla)
...CompositeValidator
Validator definiria el mensaje #validate: anObject que seria abstracto. Cada validador implementaria lo necesario según el tipo de validación que hace. El CompositeValidator delegaría el #validate: a cada validador que lo compone.
Luego, cada clase conocería su validador (quizá a travez de una variable de instancia de clase) que en la mayoría de los casos seguramente sería un CompositeValidator. Por ejemplo:
Person class>>initializeValidator
validator := CompositeValidator
with: (IsRequiredValidator aspect: #name)
with: (IsNumberValidator aspect: #age between: 0 and: 100) ... bla bla bla.
Lo que vi de interesante de hacer estos cambios es:
1) No se tiene una jerarquía paralela de validadores puesto que hay validadores por tipo de validación, no por objeto a validar
2) Se puede controlar la secuencia de validación puesto que el CompositeValidator seguiría la secuencia de validación a patir de como se lo creo.
3) No seria necesario crear los validadores constantemente (como creo que lo están haciendo, a menos que los cacheen en algún lado), solo se crearían una vez con un mensaje como #initializeValidator...
4) Cuando se crean nuevas clases del modelo, no es necesario crear nuevas clase de validación, simplemente se componen validadores existentes. Esto es indicio de un buen modelo, o sea, aparecen nuevos elementos en el dominio de validación que implican solo la creación de nuevos objetos en mi modelo y no la creación de nuevas clases puesto que lo aparecen son validadores y no nuevos "conceptos de validación".
5) La clase validator no será una "library" de funciones de validación, sino que habra una clase de validación por cada tipo de validación. De esta manera se está reificando el concepto de tipo de validación y no se está implementado en Validator responsabilidad relacionada a validaciones que necesitan otros objetos.
Quizá la desventaja es que el CompositeValidator debería implementar algo similar a lo que hace TestCase y TestCaseResult para guardarse el resultado de validación, motivo por el cual Andrés había sublasificado Validator de TestCaseAbstract en primera instancia, pero no lo veo problemático.
Según lo que enseñamos en POO, sublasificar Validator de TestCaseAbstract no es correcto conceptualmente. El motivo se debe a que TestCaseAbstract tiene más comportamiento (responde más mensajes) del que un Validator realmente representa . En este caso en vez de que Validator tenga menos comportamiento que el necesario (un error común de análisis del dominio), tiene más (un error común cuando se "abusa" el uso de la subclasificación). Esto lo convierte en un Validator+un TestCase, y por lo tanto sabrá responder mensajes que no le corresponden, produciendo inconsistencias y errores.
Para aquellos que estuvieron en la presentación, ¿qué les parece?
La característica principal de un buen modelo
Es muy difícil determinar si un modelo es bueno o malo. Es más, en sistemas hay variables o puntos de vistas técnicos que puede influir en esta decisión.
Ahora me voy a limitar a definir si un modelo es bueno o malo cualquiera sea el modelo o el ámbito en el que está hecho. Para mi, un modelo es bueno si:
Para toda observación realizada en el dominio de problema modelado, el modelo reproduce esta observación correctamente (la simula correctamente).
Por observación me refiero a todo aquello que sucede en el dominio que se pueda medir, percibir, etc. En definitiva, que podemos observar (y no me refiero a solamente con los ojos).
Fijensé que esta definición implica que el modelo puede reproducir o simular TODO lo que sucede en el dominio de problema, y además lo hace correctamente.
Por ejemplo, tomando como ejemplo la fórmula de velocidad final de física (es un modelo), esta dice:
velocidadFinal := velocidadInical + aceleración * tiempo.
¿Es este un buen modelo?
Aquellos que hayan tenido física en la secundaria o al menos el CBC saben que no, puesto no tiene en cuenta el rozamiento, un ente que en la realidad existe y hace que este modelo no funcione para ciertas observaciones. Sin embargo es un buen modelo si recortamos aún más la realidad y asumimos que no existe el rozamiento.
Para este nuevo recorte, este modelo podrá reproducir cualquier observación que hagamos sobre la velocidad final que tiene un cuerpo luego de aplicarle una aceleración por cierto tiempo a partir de una velocidad inicial, y por eso la física lo usa y a nosotros nos lo enseñaron.
En conclusión, un buen modelo debe poder reproducir todo lo que sucede en el dominio de problema que modela, de no ser así el modelo no es bueno.
Las preguntas que surgen ahora son, ¿cómo logro un buen modelo?, ¿hay características que tiene todos los buenos modelos?...
Estas ideas las formé hablando con varios amigos y también de los siguientes libros:
[1] The Design of Everyday Things de Donald A. Norman
[2] La fisica Aventura Del Pensamiento de A. Einstein y L. Infeld
Ahora me voy a limitar a definir si un modelo es bueno o malo cualquiera sea el modelo o el ámbito en el que está hecho. Para mi, un modelo es bueno si:
Para toda observación realizada en el dominio de problema modelado, el modelo reproduce esta observación correctamente (la simula correctamente).
Por observación me refiero a todo aquello que sucede en el dominio que se pueda medir, percibir, etc. En definitiva, que podemos observar (y no me refiero a solamente con los ojos).
Fijensé que esta definición implica que el modelo puede reproducir o simular TODO lo que sucede en el dominio de problema, y además lo hace correctamente.
Por ejemplo, tomando como ejemplo la fórmula de velocidad final de física (es un modelo), esta dice:
velocidadFinal := velocidadInical + aceleración * tiempo.
¿Es este un buen modelo?
Aquellos que hayan tenido física en la secundaria o al menos el CBC saben que no, puesto no tiene en cuenta el rozamiento, un ente que en la realidad existe y hace que este modelo no funcione para ciertas observaciones. Sin embargo es un buen modelo si recortamos aún más la realidad y asumimos que no existe el rozamiento.
Para este nuevo recorte, este modelo podrá reproducir cualquier observación que hagamos sobre la velocidad final que tiene un cuerpo luego de aplicarle una aceleración por cierto tiempo a partir de una velocidad inicial, y por eso la física lo usa y a nosotros nos lo enseñaron.
En conclusión, un buen modelo debe poder reproducir todo lo que sucede en el dominio de problema que modela, de no ser así el modelo no es bueno.
Las preguntas que surgen ahora son, ¿cómo logro un buen modelo?, ¿hay características que tiene todos los buenos modelos?...
Estas ideas las formé hablando con varios amigos y también de los siguientes libros:
[1] The Design of Everyday Things de Donald A. Norman
[2] La fisica Aventura Del Pensamiento de A. Einstein y L. Infeld
Suscribirse a:
Entradas (Atom)