Programación en castellano
Inicio > Tutoriales > Lenguajes orientados a objeto > J2EE > Catálogo de Patrones de Diseño J2EE. Y II: Capas de Negocio y de Integración
-Tutoriales

Catálogo de Patrones de Diseño J2EE. Y II: Capas de Negocio y de Integración


Transfer Object Assembler

. Contexto

En una aplicación de la plataforma J2EE, los componentes de negocio del lado del servidor se implementan utilizando beans de sesión, beans de entidad, DAOs, etc. Los clientes de la aplicación necesitan acceder a datos que frecuentemente se componen de múltiples objetos.

. Problema

Los clientes de aplicaciones normalmente solicitan los datos del modelo o parte del modelo para presentarlos al usuario o para usarlos en un paso de procesamiento intermedio antes de proporcionar algún servicio. El modelo de la aplicación es una abstracción para los datos de negocio y la lógica de negocio implementada en el lado del servidor como componentes de negocio. Un modelo se podría se expresar como una colección de objetos que se han juntado de una manera organizada. En una aplicación J2EE, el modelo es una colección de objetos distribuidos como beans de sesión, beans de entidad, DAOs u otros objetos. Para que un cliente obtenga los datos del modelo, debe acceder individualmente a cada objeto distribuido que define el modelo. Esta aproximación tiene varios inconvenientes:

  • Como el cliente debe acceder a todos los componentes distribuidos individualmente, hay un acoplamiento fuerte entre el cliente y los componentes de negocio del modelo sobre la red.
  • El cliente acede a los componentes distribuidos mediante la capa de red, y eso puede provocar una degradación del rendimiento si el modelo es complejo y con númerosos componentes distribuidos. La degradación de la red y del cliente ocurre cuando el modelo de la aplicacón implementa varios componentes de negocio distribuidos y el cliente interactúa directamente con esos componentes para obtener los datos del modelo. Todos esos accesos resultan en llamadas a métodos remotos que sobrecargan la red e incrementan las charlatanería entre el cliente y la capa de negocio.
  • El cliente debe reconstruir el modelo después de obtener sus partes desde los componentes distribuidos. Por lo tanto, el cliente necesita tener suficiente lógica de negocio para construir el modelo. Si la construcción del modelo es compleja y se ven implicados en su definición numerosos objetos, podría haber una sobrecarga adicional en el rendimiento del cliente debido al proceso de construcción. Además, el cliente debe contener lógica de negocio para manejar las relaciones entre los componentes, lo que resultará en un cliente más complejo y todavía más grande. Cuando el cliente construye el modelo de la aplicación, la cosntrucción sucede en el lado del cliente. La construcción de modelos complejos podría resultar en una sobrecarga importante en el rendimiento del lado del cliente para clientes con recursos limitados.
  • Como el cliente está fuertemente acoplado con el modelo, los cambios en el modelo requieren cambios en el cliente. Además, si hay diferentes tipos de clientes, es más difícil manejar los cambios entre todos los tipos de cliente. Cuando hay acoplamiento fuerte entre el clente y la implementación del modelo, lo que ocurre cuando el cliente tiene conocimiento directo del modelo y maneja las relaciones de los componentes de negocio, los cambios en el modelo necesitan cambios en el cliente. Además, hay otro problema de duplicación de código para acceder al modelo, lo que ocurre cuando una aplicación tiene muchos tipos de clientes. Esta duplicación hace que los clientes (su código) sea difícil de manejar cuando el modelo cambia.

. Causas

  • Se requiere la separación de la lógica de negocio entre el cliente y los componentes del lado del servidor.
  • Como el modelo consta de componentes distribuidos, el acceso a cada componente está asociado con un una sobrecarga de red. Es deseable minimizar el número de llamadas a métodos remotos.
  • Normalmente el cliente sólo necesita obtener el modelo para presentarlo al usuario. Si el cliente debe interactúar con varios componentes para construir el modelo "al vuelo", se incrementa la comunicación entre el cliente y el servidor. Dicha sobrecarga de comunicación podría reducir el rendimiento de la red.
  • Incluso si el cliente quiere realizar un actualización, normalmente sólo actualiza ciertas partes del modelo, y no el modelo completo.
  • Los clientes no necesitan preocuparse de las intrincadas dependencias en la implementación del modelo. Es deseable perder acoplamiento entre los clientes y los componentes de negocio que implementan el modelo de la aplicación.
  • Los clientes no necesitan poseer la lógica de negocio adicional requerida para construir el modelo partiendo de varios componentes de modelo.

. Solución

Utilizar un Transfer Object Assembler para construir el modelo o submodelo requerido. El Transfer Object Assembler usa Transfer Objects para recuperar los datos de los distintos objetos de negocio y otros objetos que definen el modelo o una parte del modelo.

El Transfer Object Assember construye un Transfer Object compuesto que representa los datos de diferentes componentes de negocio. El Transfer Object transporta datos del modelo al cliente en una sóla llamada a método. Como los datos del modelo pueden ser complejos, se recomienda que el Transfer Object no sea modificable. Es decir, el cliente obtiene esos Transfer Objects con el único propósito de usarlos para presentaciones y procesamientos de sólo-lectura. Si está permitido que los clientes hagan cambios en los Transfer Objects.

Cuando el cliente necesita los datos del modelo, y si el modelo está representado por un único componente genérico (como un Composite Entity), el proceso de obtención del modelo es muy simple. El cliente simplemente solicita el componente genérico para su Transfer Object compuesto. Sin embargo, la mayoría de las aplicaciones del mundo real tienen un modelo compuesto de una combinación de muchos componentes genéricos y específicos. En este caso, el cliente debe interactuar con numerosos componentes de negocio para obtener todos los datos necesarios para representar el modelo. El inconveniente inmediato de esta aproximación se puede ver en que los clientes se convierte en fuertemente acoplados con la implementación del modelo (elementos del modelo) y que los los clientes tienden a realizar numerosas llamadas a métodos remotos para obtener los datos de cada componente individual.

En algunos casos, un único componente genérico proporciona el modelo o parte del modelo como único objeto Transfer Object (simple o compuesto). Sin embargo, cuando varios componentes representan el modelo, un único Transfer Object (simple o compuesto) podria no representar todo el modelo. Para representar el modelo, es necesario obtener Transfer Objects de varios componentes y ensamblarlos en un Transfer Object Compuesto. El servidor, no el cliente, debería realizar la construcción del modelo "al-vuelo".

. Estructura

La siguiente figura muestra el diagrama de clases que representa las relaciones para el patrón Transfer Object Assembler:

. Participantes y Responsabilidades

El diagrama de secuencia de la siguiente figura muestra la interacción entre los distintos participantes en el patrón Transfer Object Assembler:

. TransferObjectAssembler

El TransferObjectAssembler es la clase principal de este patrón. Construye un nuevo Transfer Object basado en los requerimientos de la aplicación cuando el cliente solicita un Transfer Object compuesto. Entonces TransferObjectAssembler localiza los ojemplares BusinessObject requeridos para recuperar los datos para construir el Transfer Object compuesto. Los BusinessObjects son objetos de la capa de negocio como beans de entidad o de sesión, DAOs, etc.

. Cliente

Si el TransferObjectAssembler se implementa como un objeto Java normal, el cliente normalmente es un Session Facade que proporciona la capa controladora para la capa de negocio. Si el TransferObjectAssembler se implementa como un bean de sesión, el cliente puede ser un Session Facade o un Business Delegate.

. BusinessObject

BusinessObject participa en la construcción del nuevo Transfer Object proporcionando los datos requeridos por el TransferObjectAssembler. Por lo tanto, el BusinessObject es un rol que cumple un bean de sesión, un bean de entidad, un DAO, o un objeto normal de Java.

. TransferObject

TransferObject es un Transfer Object compuesto construido por TransferObjectAssembler y devuelto al cliente. Este representa los datos complejos de varios componentes que definen el modelo de la aplicación.

. BusinessObject

BusinessObject es un rol que pueden cumplir un bean de sesión, un bean de entidad, o un DAO. Cuando el ensamblador necesita obtener los datos directamente desde el almacenamiento persistente, para construir el Transfer Object, puede utilizar un DAO. Esto se puede ver en los diagramas como el objeto DataAccessObject.

. Estrategias

Esta sección explica las diferentes estrategias para implementar el patrón Transfer Object Assembler.

. Java Object

El TransferObjectAssembler puede ser un objeto normal de Java y no necesariamente un bean enterprise. En dichas implementaciones, se sitúa enfrente del TransferObjectAssembler un bean de sesión. Este bean de sesión normalmente es un Session Facade que realiza otras tareas relacionadas con proporcionar servicios de negocio. El TransferObjectAssembler se ejecuta en la capa de negocio, sin importar las estrategias de implementación. La motivación para esto es evitar las llamadas remotas desde el TransferObjectAssembler hacia los objetos fuente sin cruzar de capa.

. Session Bean

Esta estrategia implementa el TransferObjectAssembler como un bean de sesión. Si se prefiere la implementación de un bean de sesión para proporcionar el TransferObjectAssembler como un servicio de negocio, normalmente se implementa como un bean de sesión sin estado. Los componentes de negocio que componen el modelo de la aplicación están constantemente implicados en transaciones con otros clientes. Como resultado, cuando un TransferObjectAssembler construye un nuevo Transfer Object desde varios componentes de negocio, produce una "foto" del modelo en el momento de la construcción. El modelo podría cambiar inmediatamente después si otro cliente modifica uno o más de sus componentes de negocio, cambiando efectivamente el modelo de negocio de la aplicación.

Por lo tanto, implementar TransferObjectAssembler como un bean de sesión con estado no proporciona ningún beneficio sobre su implementación como un bean de sesión sin estado, ya que es inútil preservar el estado del modelo compuesto cuando está cambiando el modelo subyacente. Si cambia éste modelo, hace que el Transfer Object contenido por el Assembler sea obsoleto. Cuando luego se le pide al TransferObjectAssembler, el Transfer Object, o devuelve un estado obsoleto o reconstruye el Transfer Object para obtener una imagen más reciente. Por lo tanto, se recomienda que el Assembler sea un bean de sesión sin estado.

Sin embargo, si el modelo subyacente no cambia o lo hace muy raramente, el ensamblador podría ser un bean de sesión con estado para retener el Transfer Object recientemente construido. En este caso, el TransferObjectAssembler debe incluir mecanismos para reconocer los cambios en el modelo subyacente y reconstruir el modelo para la próxima petición del cliente.

. Business Object

Existen diferentes objetos que pueden soportar el rol del BusinessObject

  • Puede ser un bean de sesión. El Transfer Object Assembler podría utilizar un Service Locator para localizar el bean de sesión requerido. El Transfer Object Assembler le pide a este bean de sesión que le proporcione los datos para construir el Transfer Object compuesto.
  • El BusinessObject también puede ser un bean de entidad. El Transfer Object Assembler podría utilizar un Service Locator para localizar el bean de entidad requerido. El Transfer Object Assembler le pide a este bean de entidad que le proporcione los datos para construir el Transfer Object compuesto.
  • O puede se run DAO. El Transfer Object Assembler le pide a este DAO que le proporcione los datos para construir el Transfer Object compuesto.
  • También puede ser un objeto Java normal. El Transfer Object Assembler le pide a este objeto Java que le proporcione los datos para construir el Transfer Object compuesto.
  • Por último, el BusinessObject puede ser otro Transfer Object Assembler. El primer Transfer Object Assembler le pide al segundo Transfer Object Assembler que le proporcione los datos para construir el Transfer Object compuesto.

. Consecuencias

  • Independiza la Lógica de Negocio
    Cuando el cliente incluye lógica para manejar las interacciones con componentes distribuidos, es más díficil separar claramente la lógica de negocio de la capa de cliente. El Transfer Object Assembler contiene la lógica de negocio para mantener las relaciones entre objetos y para construir el Transfer Object compuesto que representa el modelo. El cliente no necesita conocer cómo construir el modelo o los distintos componentes que proporcionan los datos para ensamblar el modelo.
  • Reduce el Acoplamiento entre los Clientes y el Modelo de la Aplicación
    El Transfer Object Assembler oculta a los clientes la complejidad de la construcción de los datos del modelo y establece un acoplamiento ligero entre los clientes y el modelo. Con este acoplamiento ligero, si el modelo cambia, el Transfer Object Assembler también requerirá ese cambio. Sin embargo, el cliente no depende de la constucción del modelo ni de las relaciones entre los componentes del modelo de negoico, por eso los cambios en el modelo no afectan directamente al cliente.
  • Mejora el Rendimiento de Red
    El Transfer Object Assembler reduce drásticamente la sobrecarga de red que producen las llamadas a métodos remotos. El cliente puede solicitar datos del modelo de la aplicación desde el Transfer Object Assembler con una sóla llamada a método. El ensamblador construye y devuelve el Transfer Object compuesto. Sin embargo, este Transfer Object compuesto podría contener una gran cantidad de datos. Así, aunque el Transfer Object Assembler reduce el número de llamadas a través de la red, hay un incremento en la cantidad de datos transportados en cada llamada. Este inconveniente se debe tener en cuenta cuando apliquemos este patrón.
  • Mejora el Rendimiento del Cliente
    El Transfer Object Assembler del lado del servidor construye el modelo como un Transfer Object compuesto sin utilizar ningún recurso del cliente. El cliente no utiliza su tiempo para ensamblar el modelo.
  • Mejora el Rendimiento de la Transación
    Normalmente, las actualizaciones se aíslan en una parte muy pequeña del modelo y se pueden realizar mediante transaciones específicas. Estas transaciones se enfocan en las partes aisladas del modelo en lugar de bloquear el objeto genérico (modelo). Después de que el cliente obtiene el modelo y lo muestra o procesa localmente, el usuario (o cliente) podría necesitar actualizar o modificar el modelo. El cliente puede interactúar directamente con un Session Facade para conseguir esto a un nivel de especificidad aceptable. El Transfer Object Assembler no está implicado en la transación para actualizar o modificar el modelo. Hay un mejor control del rendimiento porque el trabajo de transaciones con el modelo sucede con el nivel de especificidad apropiado.
  • Podría Presentar Transfer Objects Obsoletos
    El Transfer Object Assembler construye Transfer Objects bajo pedido. Estos Transfer Objects son fotografías del estado actual del modelo, representadas por varios componentes de negocio. Una vez que el cliente obtiene un Transfer Object del ensamblador, este Transfer Object es enteramente local al cliente. Como los Transfer Objects no se preocupan de la red, otros cambios hechos a los componentes de negocio usados para construir el Transfer Object no se verán reflejados en éste. Por lo tanto, despues de obtener el Transfer Object, se puede convertir en obsoleto rápidamente si hay transaciones sobre los componentes de negocio.

. Código de Ejemplo

. Implementar el Transfer Object Assembler

Consideremos una aplicación de control de proyectos donde varios componentes de la capa de negocio definen el modelo complejo. Supongamos que un cliente quiere obtener el modelo de datos compuesto de datos de varios objetos de negocio, como:

  • Información del Proyecto desde el componente Project.
  • Información del Manager del Proyecto desde el componente ProjectManager.
  • Lista de Tareas del Proyecto desde el componente Project.
  • Información de Recursos desde el componente Resource.

Se puede definir un Transfer Object compuesto como se ve en el siguiente ejemplo. Se puede implementar un Transfer Object Assembler para ensamblar este Transfer Object.

 
public class ProjectDetailsData {
  public ProjectTO projectData;
  public ProjectManagerTO projectManagerData;
  public Collection listOfTasks;
  ...
}

El listado de tareas de ProjectDetailsData es una collection de objetos TaskResourceTO. TaskResourceTO es una combinación de TaskTO y ResourceTO. Abajo podemos ver estas clase:

Ejemplo de la clase TaskResourceTO:


public class TaskResourceTO {
  public String projectId;
  public String taskId;
  public String name;
  public String description;
  public Date startDate;
  public Date endDate;
  public ResourceTO assignedResource;
  ...

  public TaskResourceTO(String projectId, 
    String taskId, String name, String description, 
    Date startDate, Date endDate, ResourceTO 
    assignedResource) {
        this.projectId = projectId;
        this.taskId = taskId;
        ...
        this.assignedResource = assignedResource;
    }
    ...
}

Ejemplo de la clase TaskTO:


public class TaskTO {
  public String projectId;
  public String taskId;
  public String name;
  public String description;
  public Date startDate;
  public Date endDate;
  public assignedResourceId;

  public TaskTO(String projectId, String taskId, 
      String name, String description, Date startDate, 
      Date endDate, String assignedResourceId) {
        this.projectId = projectId;
        this.taskId = taskId;
        ...
        this.assignedResource = assignedResource;
    }
    ...
}

Ejemplo de la clase ResourceTO:


public class ResourceTO {
  public String resourceId;
  public String resourceName;
  public String resourceEmail;
  ...
  
  public ResourceTO (String resourceId, String 
    resourceName, String resourceEmail, ...) {
      this.resourceId = resourceId;
      this.resourceName = resourceName;
      this.resourceEmail = resourceEmail;
      ...
  }
}

En el siguiente listado tenemos la clase ProjectDetailsAssembler que ensambla el objeto ProjectDetailsData:


public class ProjectDetailsAssembler 
  implements javax.ejb.SessionBean {

  ...

  public ProjectDetailsData getData(String projectId){ 

    // Construct the composite Transfer Object
    ProjectDetailsData pData = new 
                      ProjectDetailsData();

    //get the project details; 
    ProjectHome projectHome = 
        ServiceLocator.getInstance().getHome(
          "Project", ProjectEntityHome.class);
    ProjectEntity project = 
      projectHome.findByPrimaryKey(projectId);
    ProjectTO projTO = project.getData();
  
    // Add Project Info to ProjectDetailsData
    pData.projectData = projTO;

    //get the project manager details;
    ProjectManagerHome projectManagerHome =
      ServiceLocator.getInstance().getHome( 
        "ProjectManager", ProjectEntityHome.class);
  
    ProjectManagerEntity projectManager = 
      projectManagerHome.findByPrimaryKey(
        projTO.managerId);

    ProjectManagerTO projMgrTO = 
      projectManager.getData();
  
    // Add ProjectManager info to ProjectDetailsData
    pData.projectManagerData = projMgrTO;

    // Get list of TaskTOs from the Project
    Collection projTaskList = project.getTasksList();

    // construct a list of TaskResourceTOs
    ArrayList listOfTasks = new ArrayList();
  
    Iterator taskIter = projTaskList.iterator();
    while (taskIter.hasNext()) {
      TaskTO task = (TaskTO) taskIter.next();

      //get the Resource details; 
      ResourceHome resourceHome = 
      ServiceLocator.getInstance().getHome( 
        "Resource",         ResourceEntityHome.class);
  
      ResourceEntity resource = 
        resourceHome.findByPrimaryKey(
          task.assignedResourceId);

      ResourceTO resTO = resource.getResourceData();

      // construct a new TaskResourceTO using Task
      // and Resource data
      TaskResourceTO trTO = new TaskResourceTO( 
              task.projectId, task.taskId,
              task.name, task.description,
              task.startDate, task.endDate,
              resTO);

      // add TaskResourceTO to the list
      listOfTasks.add(trTO);
    }
    
    // add list of tasks to ProjectDetailsData
    pData.listOfTasks = listOfTasks;

    // add any other data to the Transfer Object
    ...
  
    // return the composite Transfer Object
    return pData;

  }

  ...
}

. Patrones Relacionados

  • Transfer Object
    Transfer Object Assembler usa el patrón Transfer Object para poder crear y transportar Transfer Objects al cliente. Los Transfer Objects creados llevan los datos que representan el modelo de la aplicación desde la capa de negocio hasta los clientes que han solicitado los datos.
  • Composite Entity
    El patrón Composite Entity promueve el diseño de un bean de entidad genérico, donde las entidades pueden producir Transfer Objects compuestos similares al producido por el Transfer Object Assembler. Sin embargo, el Transfer Object Assembler es más aplicable cuando el Transfer Object compuesto construido se deriva de varios componentes (beans de sesión, beans de entidad, DAOs, etc.), mientras que el patrón Composite Entity construye el Transfer Object desde sus propios datos (es decir, un único bean de entidad).
  • Session Facade
    El Transfer Object Assembler se implementa típicamente como un bean de sesión sin estado. Como tal, podría ser visto como una aplicación especial limitada del patrón Session Facade. Más importante, Transfer Object Assembler construye Transfer Objects que no se pueden modificar. Por lo tanto, el cliente que lo recibe sólo puede utilizarlo para propósitos de presentación y procesamiento. El cliente no puede actualizar el Transfer Object. Si el cliente necesita actualizar los objetos de negocio de los que deriva el Transfer Object compuesto, podría tener que acceder al Session Facade (bean de sesión) que proporciona ese servicio de negocio.
  • Data Access Object
    Una posible estrategia para el Transfer Object Assembler implica obtener datos para el Transfer Object compuesto desde almacenamiento persistente sin utilizar beans enterprise. En estos casos se puede aplicar el patrón Data Access, y aprovecharnos de sus beneficios parar proporcionar acceso al almacenamiento persistente al Transfer Object Assembler.
  • Service Locator
    El Transfer Object Assembler necesita localizar y utilizar varios objetos de negocio. Se puede utilizar el patrón Service Locator en conjunción con el patrón Transfer Object Assembler siempre que sea necesario localizar un objeto o servicio de negocio.
 
Patrocinados
 

Copyright © 1999-2007 Programación en castellano. Todos los derechos reservados.
Formulario de Contacto - Datos legales - Publicidad
Mantenida por: Claudio y Dani.

Hospedaje web y servidores dedicados linux por Ferca Network

red internet: jugar gratis | amor | navidad 2009 | registro de dominios | servidores dedicados
más internet: comprar | gratis | posicionamiento en buscadores | decoración libre | gifs animados