domingo, 3 de octubre de 2010

Sobre el nombre "Objeto"

Hace unos años, creo que ahora ya no es más asi, pero tal vez me equivoque, en las clases de introducción a objetos se daba una metodología para aplicar al diseño con objetos que consistía en lo siguiente: a partir de los requerimientos de un determinado sistema, se debían subrayar los sustantivos; con toda seguridad, se afirmaba, éstos terminarán siendo las clases del sistema. En cambio los verbos iban a dar al menos una idea del comportamiento que se esperaba de los objetos resultantes de esas clases. Era, evidentemente, un método copiado de las clases sobre entidad-relación.
La vulgata informática, cuando debe referirse a los objetos, suele utilizar íconos de objetos tridimensionales, lo que no hace más que aumentar la confusión que la polisemia del término conlleva, pues una cosa es un objeto en el sentido de cosa, algo material, tangible, con dimensiones espaciales,  y otra muy distinta es un objeto informático.
Del mismo modo, en muchas plataformas informáticas en las que se habla de objetos, éstos también se confunden con las cosas. En HTML, por ejemplo, se insertan objetos, que no son otra cosa que files, el equivalente a la cosa en el mundo digital.
Esto ha llevado a muchos a creer que los objetos son algo así como la sustancia aristotélica llevada al mundo digital, es decir, que al modelar con objetos hay que pensar en términos de entes o sustancias que se definen por sus propiedades. Que modelar con objetos significa encontrar las cosas y preguntarse qué son, qué es lo que las define, qué propiedades tienen. Propiedad es lo que es propio; lo que define al objeto sería algo que está en él mismo.
La palabra objeto no ayuda para tratar de aclarar este malentendido, pero la lectura que cualquier buen código escrito con objetos revela que lo que se trata de modelar no son cosas.
Un objeto informático se define en términos de comportamiento. Cuando se trabaja con  objetos no importan tanto qué son, o qué pretenden ser o representar sino más bien cómo se comportan, como interactúan con otros objetos. Comprendemos el sentido de un objeto cuando comprendemos su comportamiento. Son decisiones relacionadas con el comportamiento lo que nos hace profundizar en el análisis y encontrar aspectos no previstos, comportamientos que por su particularidad merecen un lugar especial. Un objeto entonces sería un "conducto", es decir, algo que se define por su conducta. En tanto  cada mensaje sería un "conductema", la mínima expresión de "conducta". Si se sigue el planteo ideal de que cada mensaje realice una sola acción, cada mensaje consiste entonces en un comportamiento atómico, un comportamiento que no se puede dividir en otros.
Esta es la razón por la que los programadores de objetos cambiamos los nombres de las clases, los nombres de los mensajes, los nombres de los argumentos: porque a medida que comprendemos mejor que es lo que hace un objeto, recién ahí empezamos a entenderlo y por ende, como nombrarlo. 
Si los objetos son unidades de comportamiento, entonces no es la función referencial del lenguaje la que nos es más útil. Para poder comprender el funcionamiento de un determinado dominio en términos de comportamiento, y no en términos que lo que "es", es más util el relato. Los objetos son unidades de comportamiento en una narración, pero una narración total, una narración que cuenta todo lo que sucede y lo que puede suceder.


Pero el nombre "objeto" tampoco está tan mal.
Un objeto es observado, manipulado, conocido por un sujeto. El paradigma de objetos mostraría de ese modo un extremo de la cadena del conocimiento: un objeto que es observado por un sujeto. Eliminar al sujeto, pensar en términos de objetos que deben ser encontrados y que poseen propiedades que deben ser descubiertas, es creer que hay un ser que ya está definido, un ser que es idéntico a sí mismo. Pero como no se trata del ser sino del hacer, es decir, poder ver lo que los objetos hacen, el sujeto es imprescindible, pues ese ver el comportamiento de los objetos es necesariamente subjetivo. No se trata de revelar una realidad dada sino de construir una nueva realidad en la cual los objetos se definen por lo que el sujeto quiere que hagan, o dicho de otra forma, un modelo construido en función de lo que el sujeto interpreta que los objetos hacen en la realidad.
El error es creer que un sistema con objetos es una representación objetiva. 

11 comentarios:

  1. Prefiero ver a un modelo de objetos como una representación (subjetiva seguramente) de una porción de la realidad. Los objetos deberían ser como una especie de metáfora de lo que representan.
    El objetivo de que un modelo sea así es achicar el gap semántico. Es decir disminuir la "distancia conceptual" entre el modelo y el dominio real representado.
    La ventajas de este enfoque son:
    1) comunicar, pensar y hablar sobre el modelo es más fácil.
    2) cualquier impacto en la "realidad" impactaría de manera similar en el modelo (y no más).

    Igualmente, comparto la opinión de que subrayar y armar clases no es una buena práctica. La construcción de nuevas clases debería ser algo que surge luego de ir trabajando con casos concretos, de manera iterativa e incremental.
    Saludos.

    ResponderEliminar
  2. Tengo algunas cosas escritas sobre la cuestión del modelo de objetos como representación de la realidad. En breve las paso en limpio y las subo.
    Te adelanto que mi idea es que no es necesario postular nada con respecto a la realidad, porque lo que se modela con objetos son otros modelos. Muchas veces cuando decimos "realidad" nos estamos refiriendo a modelos: de nuestra mente, de sistemas manuales, de normas, costumbres, etc.
    Pero tanto la cuestión de la "realidad" como la de la "representación" son problemas muy grosos. Claro que nunca está de más analizarlos, darlos vuelta, replantearlos.

    ResponderEliminar
  3. Y sí, "modelar la realidad" lleva a modelos superfluos que no hacen nada útil.

    Lo que en realidad se debe modelar son las decisiones de diseño que resuelven los requerimientos funcionales que ha pedido el cliente.

    Según Alan Kay, quien inventó el término "orientado a objetos", en realidad se debió haber llamado "orientado a mensajes", porque eso orienta más respecto de cómo debe organizarse los sistemas.

    Comparto plenamente la opinión de Alan, aunque pienso que se queda corto.

    Según Martin Fowler, el tema de la OO divide a los que piensan que los objetos son representaciones del mundo real (is-a y has-a) y a los que piensan que en realidad la herencia es un mecanismo de implementación para eliminar código repetido. Opto más por lo segundo, aunque no hay que desconsiderar a Barbara Liskov y su principio de substitución.

    El problema es que no todos peuden tener la razón al mismo tiempo. Mientras es agradable pensar que todos los objetos (o mejor dicho las jerarquías de clases) deben seguir LSP (Liskov Subtitution Principle) para estar bien modeladas, tambipen es cierto que en la práctica no hay ningún sistema que esté escrito de esa manera y esté 100% bien modelado. Ni siquiera Smalltalk, el primer lenguaje 100% orientado a objetos.

    Para eso se inventó Traits, para eliminar código repetido sin usar herencia múltiple, que todos sabemos que no funciona.

    Pero aún así hay temas que sólo resuelve AOP (Aspect Oriented Programming) como el login y la seguridad.

    El modelamiento en jerarquías está muy desacreditado. Es cosa de ver el lenguaje Self que funciona sólo con prototipos, sin clases. Hay interfaces de usuario muy interesantes hechas en Self con algo llamado Morphic que según yo es una implementación de Naked Objects.

    En resumen, como la mayor parte de la gente entiende OO (OO = Herencia + Encapsulación + Polimorfismo) no es la única manera de enterderlo. Por decirlo de otra manera, hay más patrones de diseño que el patrón Template Method, que es la base del polimorfismo.

    La Herencia rompe la Encapsulación. ¿Necesito decir más?

    ResponderEliminar
  4. Yo me quedo más con el enfoque de Rebecca Wirfs-Brock
    http://www.wirfs-brock.com/PDFs/013-015.pdf

    ResponderEliminar
  5. Guillermo. Totalmente de acuerdo en el tema de la herencia. Precisamente hablar de una relación "is-a" implica definir el ser de un ente.
    La herencia en Smalltalk debe ser entendida como un parche, (y traits es un super parche).
    Creo que a cualquier programador Smalltalk, tarde o temprano le pasa que se encuentra con que la herencia, que tan simpática parecía al principio, no hace más que ponerle trabas.
    Es el momento de entender que es una herramienta con fecha de vencimiento.
    Gracias por las referencias, no conozco todo lo que mencionás y me vienen muy bien.

    ResponderEliminar
  6. Muy bueno el post (me encanta esta linea de reflexion).
    Hago una pregunta, por que es tan taxativa esta frase: "Un objeto informático se define en términos de comportamiento. Cuando se trabaja con objetos no importan tanto qué son, o qué pretenden ser o representar sino más bien cómo se comportan, como interactúan con otros objetos. Comprendemos el sentido de un objeto cuando comprendemos su comportamiento"?
    Realmente yo pienso muchas veces en los objetos en lo que representan. Un caso particular, puedo tener un objecto de la clase A, que tiene todo el protocolo B. Si veo el comportamiento, diria que es un B, pero a mi me sirve entender que es un A (puro contenido semantico). Como el primer comentario de Gaboto

    ResponderEliminar
  7. La frase es taxativa sólo porque a veces soy vehemente, no porque pretenda emitir una gran verdad. De hecho, esta forma de ver las cosas es para mi bastante nueva, porque hasta hace muy poco pensaba más en términos de representación.
    Con respecto a tu ejemplo, no contradice en nada lo que digo. Si existe A y existe B, por más protocolo que compartan, deberían tener un comportamiento distinto, aunque sea levemente distinto y aunque representen cosas (o conceptos, ideas, entes, lo que sea) distintas. Por supuesto que es posible tener un A y B que tengan exactamente el mismo comportamiento, pero es como una violación a los principios básicos de la elegancia en la programación, pues se estarían diciendo dos veces lo mismo.
    Si uno tiene la necesidad de un A y un B que hacen lo mismo, la solución de diseño tradicional es poner todo el comportamiento en un tercer objeto en el que delegan. En ese caso una vez más está claro que el objeto se define por su comportamiento. La pregunta entonces sería ¿porqué un A y un B? Yo diría que si existen un A y un B tales es porque si bien hacen lo mismo, lo hacen en circunstancias distintas. Con lo cual su comportamiento es distinto, a pesar de tener el mismo protocolo. Claro que esto lleva la idea de comportamiento a un nivel más complejo que lo que simplemente se ve en el código.

    ResponderEliminar
  8. Hola,
    la verdad, disiento un poco.
    Te diría, no me importa violar algún que otro principio :)
    Veo -sin mirar demasiado-, dos razones por las que el código existe:
    a) Para que las cosas funcionen
    b) Para entender las cosas.

    Y es sobre b donde apunto. A y B hacen las mismas cosas, y ademas, el comportamiento es el mismo; pero son dos cosas distintas, y es eso lo que quiero expresar en el código.
    Si no fuese así, tendría que saber TODO todo el tiempo, y eso no es algo deseable -o, al menos, es algo que no me sale-.

    El hecho de que finalmente se implemente el comportamiento en un tercer objeto, es realmente un detalle de implementación, que podría ser delegadas a un tercero (compilador, nativizador, optimizador, otro programador, yo media hora mas tarde).
    Con esto no estoy negando las ventajas de la no duplicación, pero no quiero que el foco de la idea se corra.

    saludos

    ResponderEliminar
  9. Si, me parece correcto separar lo implementativo. Pero entonces, mi respuesta a ese dilema es: si estoy pensando que dos cosas que hacen exactamente lo mismo, son dos cosas distintas, en algo me estoy equivocando.
    En el mundo de afuera de la programación no se si puede haber un caso. En general es al revés, consideramos que dos cosas son iguales (es decir, SON lo mismo, las nombramos del mismo modo) a pesar de que hacen cosas distintas, aunque las diferencias sean sutiles.

    ResponderEliminar
  10. cuales seria la trabas impuestas por la herencia ? algun ejemplo ? y que significa que los Traits son un superparche ?

    saludos

    ResponderEliminar
  11. Esta cuestión de la herencia surgió a partir de comentarios, pero no era la idea central del post. Me parece que es un problema muy arduo y amerita que se lo piense más y se le dedique un post.
    Los problemas de la herencia aparecen claramente cada vez que se termina pensando en herencia múltiple. El objeto A y el objeto B que pertenecen a distintas jerarquias, tiene algunos comportamientos comunes. Tanto recurrir a un lenguaje que implemente herencia múltiple, como Traits, son parches desde el punto de vista del concepto de herencia. Uno no hereda características de sus tios políticos. Es algo que hay que agregar ante la insuficiencia del marco conceptual, algo que está afuera de la herencia.

    ResponderEliminar