Functor y Paso de Mensajes En el desarrollo de programación distribuida es necesario poder descomponer las partes esenciales del sistema en pequeñas porciones lógicas o módulos los cuales deben cumplir con responsabilidades individuales, destinados a la consecución del objetivo principal de dicho sistema, para ello, estos módulos tiene que trabajar unidos. En los términos de la ingeniería de software estos módulos son conocido como componentes, esta tecnología ha empezado a demostrar que ofrece ventajas en tiempo de desarrollo y reducción de costos en el proceso de desarrollo de software [1], decido a que es una unidad de instalación o despliegue independiente, con autonomía de ejecución así sea desarrollada por terceros y no tiene estado persistente [6,42], en el lenguaje de programación Mozart un componente es conocidos como functor. Un functor es una función cuyos argumentos son los módulos que necesita y cuyo resultado es un nuevo módulo, es decir, toma las interfaces de módulos como argumentos, crea un nuevo modulo y retorna esa interfaz de modulo[5,226], por esto mismo, los functores tienen una abstracción lingüística propia, divida en tres partes, primero import que especifica que otros módulos se van a utilizar, export que especifica la interfaz de modulo generado y define donde se hace la implementación de los módulos y el código. Los functores al ser una unidad de compilación poseen la ventaja de ser manejados en archivos, pueden ser en estilo de código fuente o pueden ser manejados como objetos. Los archivos que son manejados en código fuente permiten la compilación y de esta manera pueden ser manejados como objetos y así tener un modulo similar a una librería. Los functores poseen ventajas como lo son las referencias externas que tiene a otras entidades de lenguajes, por ejemplo, es fácil hacer que un functor contenga datos calculados en tiempo de ejecución, esto es útil, por ejemplo, para incluir grandes tablas de datos de imagen en forma de código fuente. Un functor es ligero, puede ser utilizado para encapsular una sola entidad, como un objeto o una clase, con el fin de hacer explícitos los módulos necesarios por la entidad. Este componente de software es muy útil, la estructura del functor se representas de la siguiente manera[1,229]: functor export append:Append sort:Sort member:Member ... define proc {Append ... } ... end proc {MergeSort ...} ... end proc {Sort ... } ... {MergeSort ...} ... end proc {Member ...} ... end end Para poder lograr que los componentes se comuniquen es necesario aplicar un modelo de comunicación, en este caso se utilizara el modelo de concurrencia por paso de mensajes que provee Mozart Oz, este modelo es una extensión del modelo de la concurrencia declarativa, que a su vez es una extensión del modelo de la programación declarativa. La concurrencia por paso de mensajes es un modelo en el cual se incluye un elemento llamado puerto, estos son canales de comunicación asíncrono, por el cual, muchos flujos pueden realizar los envíos de mensajes sin tener un orden especifico. Los puertos son tipos abstractos de datos que poseen dos operaciones: {NewPort S P}: Crea un nuevo puerto con punto de acceso P y flujo S. {Send P X}: Coloca X en el flujo correspondiente al punto de entrada P. Los mensajes que llegan al puerto no necesariamente tiene que llevar una respuesta de este, razón por la cual el objeto que envía el mensaje puede ejecutar otra tarea, a su vez, el puerto puede recibir varios mensajes y tenerlos en cola y procesarlos en orden de llegado, es un pila FIFO. Otra gran ventaja que poseen los puertos es que son seguros, debido a que estos son variables de solo lectura, no pueden ser poblados desde el exterior. Los objetos puertos están compuestos por uno o más puertos y objetos de flujo, mejorándolos en muchos aspectos, por ejemplo, la comunicación muchos-uno es posible, muchos objetos pueden tener referencia a un puerto pero cada uno envía el mensaje de manera independiente, además los puertos pueden ser incluidos en estructuras de datos. Los objetos puertos pueden crear nuevos puertos y enviar mensajes a estos. Este tipo de objetos es el adecuado en sistemas distribuidos, ya que se puede modelar cada “site” del sistema como un puerto. Para desarrollar los objetos puerto que posean una interfaz de requerimiento y estén alambrados con otros objetos utilizaremos la siguiente codificación[2,43]: proc {NuevObjPuerto Proc Flujoin Reqin} thread for Msg in Reqin do {Proc Msg} end end {NewPort Flujoin Reqin} end La función anterior está definida con el objeto de parametrizar explícitamente el flujo que se asociara al objeto puerto “Reqin” para su posterior alambrado. Por medio de esta función se puede notar que los mensajes serán procesados por un procedimiento “Proc”, para poder iniciar un nuevo objeto puerto es necesario ejecutar la siguiente instrucción: {NuevoObjPuerto ProcX F1 R1} Donde R1 es el nombre del puerto F1 es el flujo asociado ProcX es el procedimiento a aplicar a los mensajes Para poder configurar el puerto creado anteriormente solo se debe enviar un mensaje a través de este para que sea procesado, para lograrlo se debe ejecutar la siguiente instrucción: {Send R1 dato1} Esto enviara el mensaje de dato1 al puerto R1 para quedar en cola y ser procesado por ProcX. [5] Roy, P. V., and Haridi, S. Concepts, Techniques and Models of Computer Programming. MIT Press, 2004. [6] Henry A. Diosa, Especi_caci_on de un Modelo de Referencia Arquitectural de Software A Nivel de Con_guraci_on, Estructura y Comportamiento,2008 [1] http://pegasus.javeriana.edu.co/~jcpymes/Docs/DSBC.pdf