Diferencia entre revisiones de «Guía de Product Beginner Developer»

De Thubanpedia
Saltar a: navegación, buscar
(Manejo de Eventos)
(Identificar componentes)
Línea 468: Línea 468:
 
Otro punto importante a la hora de escribir código legible es nombrar correctamente los atributos de nuestras interfaces de usuario.  Veamos algunos ejemplos:
 
Otro punto importante a la hora de escribir código legible es nombrar correctamente los atributos de nuestras interfaces de usuario.  Veamos algunos ejemplos:
  
<source lang="xml"><combobox id="seleccioneAlMenosUno"/></source>
+
<combobox id="seleccioneAlMenosUno"/>
  
  
 
Si bien es práctico para la persona que escribe el código, porque conoce todos los componentes de la UI que está construyendo, es realmente difícil de localizar para alguien externo que lo lee por primera vez. Por el contrario, si se escribe el código anteponiendo un prefijo que indique el tipo de componente, seguramente se provee ayuda  referencial al lector, sin que éste tenga que rastrear la definición propiamente dicha del componente para conocerla:
 
Si bien es práctico para la persona que escribe el código, porque conoce todos los componentes de la UI que está construyendo, es realmente difícil de localizar para alguien externo que lo lee por primera vez. Por el contrario, si se escribe el código anteponiendo un prefijo que indique el tipo de componente, seguramente se provee ayuda  referencial al lector, sin que éste tenga que rastrear la definición propiamente dicha del componente para conocerla:
  
<source lang="xml"><combobox id="cmbSelectOne"/></source>
+
<combobox id="cmbSelectOne"/>
  
  

Revisión de 07:00 16 oct 2014


Introducción

El objetivo de este documento es proporcionar una visión general del entorno de desarrollo de la plataforma Thuban®. Está dirigido a todos los programadores que quieran iniciarse en el desarrollo bajo esta plataforma y conocer los conceptos básicos de arquitectura y estándares de desarrollo.

¿Qué es Thuban®?

Thuban® es una plataforma de Enterprise Document Management (EDM) especialmente diseñada para trabajar en entornos de alta exigencia donde los documentos y los procesos son la clave fundamental del negocio. Su arquitectura —que está orientada a servicios— le permite ser flexible, integrable y escalable. Al estar desarrollada en Java, se puede portar muy fácilmente.

EDM comprende las estrategias, métodos y herramientas utilizadas para capturar, gestionar, almacenar, preservar y entregar los documentos relacionados con los procesos de las organizaciones. Las herramientas y estrategias de EDM permiten el manejo de la información no estructurada de la organización, en cualquier lugar donde la misma exista.

Como plataforma de EDM, Thuban® cuenta con un conjunto de herramientas que le permiten abarcar el ciclo completo de la información: captura, indexación, procesamiento, consulta, monitoreo y mejora continua.

Arquitectura de Thuban®

Thuban® posee una arquitectura orientada a servicios y un diseño multicapa definido de la siguiente manera:

Beg1.png



DAO: Es la capa de acceso a datos.


SERVICES: Es la capa que define los contratos de los servicios y la lógica de negocio de los mismos.


SERVICE LOCATOR: Es una capa que —mediante configuración— permite dotar al sistema de la inteligencia necesaria para funcionar con múltiples repositorios, pudiendo situar a la solución como plataforma de integración y/o migración.


WEB-SERVICES: Interfaz simplificada para la invocación de los servicios a través de SOAP.






Estas capas utilizan Spring Framework y el concepto de Inversión de Control (en Inglés: Inversion of control ó IoC) para manejar las relaciones entre componentes. La inversión de control es un principio que se utiliza en diversas arquitecturas de software donde la relación de componentes es en base al comportamiento (“el qué”), sin necesidad de que otros subsistemas conozcan la implementación real de ese componente (“el cómo”).


El core de Thuban® utiliza tres Frameworks que conforman su columna vertebral:

- Spring Framework: De código abierto, se ha popularizado como alternativa y/o sustituto del modelo de Enterprise JavaBean (EJB). Thuban® lo utiliza principalmente para el manejo de la capa de Servicios.

- Zk Framework: Orientado en AJAX y de código abierto, permite crear interfaces de usuario rápidamente sin utilizar Javascript. En su núcleo conviven un conjunto de componentes que dialogan y generan eventos disparados por la actividad del usuario final. Es similar al modelo de programación encontrado en aplicaciones desktops. Thuban® utiliza esta tecnología para construir las interfaces de usuario y separar la lógica de presentación.

- Hibernate: es una herramienta ORM (Mapeo Objeto-relacional; en Inglés: Object-Relational mapping) que facilita el mapeo de atributos entre una base de datos relacional y el modelo de objetos de una aplicación mediante archivos declarativos XML (llamados "hbm") que permiten establecer cómo son estas relaciones.


En forma paralela se utiliza Maven para la gestión de librerías y construcción de proyectos. Está basado en XML y utiliza archivos llamados POM (Project Oriented Model) para describir el proyecto que se va a construir, sus dependencias con otros módulos y/o componentes externos.

¿Cómo empezar a trabajar en Thuban®?

Thuban® está completamente desarrollado en Java. En la actualidad, para respetar los estándares de desarrollo presentes en cada uno de nuestros clientes, se utiliza JDK 1.4 como kit de desarrollo. En cuanto a herramientas, el equipo recomienda Eclipse como IDE (en Inglés: Integrated Development Environment). Se utiliza Eclipse por ser de código abierto, brindar actualizaciones constantes y gran variedad de plug-ins para personalizar el entorno de desarrollo.


Thuban® mantiene un versionado de producto. Cada versión de producto tiene un significado especial, por ejemplo, la versión "5.8.0" equivaldría a:

- Versión general: 5

- Mantenimiento: 8

- Parche: 0


Para efectivizar el versionado, se utiliza Subversion como sistema de control de versiones. A cada lanzamiento de producto se le asocia un branch en el repositorio. El mismo tiene un tag representativo del mantenimiento actual pero sin especificación de parche. Por ejemplo, si el lanzamiento actual de producto es "5.8.X", corresponde a la versión general "5", el mantenimiento "8" y un parche no definido. Cuando sea productiva, al final del lanzamiento, se generará el binario "5.8.0" y las sucesivas mejoras "5.8.1", "5.8.2", etc.


Thuban® comprende cinco aplicaciones Java:


Beg2b.png
Beg3.png





PowerDesk: Se encarga de la gestión de documentos. Es la cara visible de usuario y el producto central de la plataforma Thuban®. Para tener una noción más concreta del sistema, se puede consultar el Thuban PowerDesk




Beg4.png




Server: Es un aplicativo periférico que sirve para planificar tareas de procesamiento Bach, visualización de archivos log del sistema y configuración del monitoreo de la aplicación. Para más información, consultar el Thuban Server





Beg5.png





DocIntro: es la herramienta de captura de datos de Thuban®. Se encarga de recolectar información en el Sistema de archivos del cliente, darle un formato específico e ingresarla al repositorio de imágenes. Para mayor información ver DocIntro




Beg6.png





Workflow: permite crear, manejar y manipular procesos de negocio complejos bajo tecnología Jbpm.





Beg7.png





Admin: permite administrar usuarios, grupos, clases documentales, bandejas, seguridad y todo tipo de parámetros de configuración de Thuban®. Para otras consultas, ver Thuban Admin







Los dos proyectos más representativos de la arquitectura de Thuban® son:

THUBAN ENGINE



Es el encargado de definir los contratos de servicios y la lógica de negocio. También abarca un set de utilidades Core y el manejo de Excepciones. Define las versiones de Spring y Hibernate que utilizan cada uno de los aplicativos Thuban®.


THUBAN TOOLKIT





Conjunto de utilidades para la capa de presentación. Define la versión de ZK Framework que utilizan los aplicativos Thuban®.





Como se mencionó antes, el equipo de desarrollo utiliza Maven para la gestión de librerías. Por lo tanto, cada proyecto tiene asociado su correspondiente archivo POM. La forma de incorporar librerías al Classpath de la aplicación es definiendo las dependencias en su POM correspondiente.

Entonces, cualquier aplicativo que quiera utilizar los servicios de Thuban® deberá incorporar la dependencia thuban-engine en su descriptor de proyecto:


    <dependency>
     <groupId>com.latintech.thuban</groupId>
     <artifactId>thuban-engine</artifactId>
     <version>5.8.0</version>
   </dependency>


De igual manera, cualquier proyecto que utilice interfaces de usuario necesitará incorporar la dependencia thuban-toolkit en su POM:

   <dependency>
     <groupId>com.latintech.thuban</groupId>
     <artifactId>thuban-toolkit</artifactId>
     <version>5.8.0</version>
   </dependency>

Estándares de desarrollo

Engloba un conjunto de términos, conceptos y técnicas aceptadas por el equipo de desarrollo de Thuban®.


Servicios

Thuban® utiliza el Core Container de Spring para la gestión de servicios, manejo de transacciones, establecimiento del pool de conexiones, etc. Como explicamos previamente, Spring monta sus bases en dos patrones de diseño: Inyección de Dependencias (DI) e Inversión de Control (IoC).

Los servicios son definidos en un archivo de configuración llamado services-application-context.xml, que se encuentra dentro de Recursos en ThubanEngine. Ahí se definen las llamadas a servicios y datos de la aplicación. Un servicio estará compuesto por una llamada similar a la siguiente:


<bean id="adminService" class="com.latintech.thuban.services.ThubanAdminServiceImpl">
 <property name="userDAO" ref="userDAO"/>
 <property name="groupDAO" ref="groupsDAO"/>
 <property name="sqlDAO" ref="sqlDAO"/>
 <property name="groupMembershipDAO" ref="groupMembershipDAO"/>
 <property name="userVarDAO" ref="userVarDAO"/>
 <property name="rightCodesDAO" ref="rightCodesDAO"/>
 <property name="securityService" ref="securityService"/>
 <property name="groupRightDAO" ref="groupRightDAO"/>
 <property name="classesDAO" ref="classesDAO"/>
</bean>


Esto supone:


- Crear un DAO y referirse a él en el archivo dao-application-context.xml como se indica a continuación:


  <bean id="userDAO" class="com.latintech.thuban.dal.UserDAO">
<property name="sessionFactory" ref="hibernateSessionFactory"/>
</bean>


- Definir una Interface para nuestro servicio, por ejemplo: AdminService.java

- Implementar dicha interfaz en ThubanAdminServiceImpl.java y definir los setters para cada uno de los DAOs que utilizaremos. Por ejemplo:


 public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}



A partir de ahora, estamos en condiciones de utilizar el servicio. Al definir la interface AdminService.java nos aseguramos de que cualquiera de sus implementaciones ofrezca el listado de servicios definido por la interfaz (comportamiento). Desde un punto de vista más técnico, el compilador verificará que cualquier servicio que implemente la interfaz respete el formato por ella definido. De no ser así, se indicará una falla de compilación.

Los servicios se alojan excluyentemente en el proyecto ThubanEngine y deben ser definidos bajo el paquete com.latintech.thuban.services para garantizar la transacción de la base de datos. La definición en el archivo de configuración es:

  <aop:config>
 <aop:pointcut id="servicesOperation" expression="execution(* com.latintech.thuban.services.*.*(..))"/>
     <aop:advisor advice-ref="txAdvice" pointcut-ref="servicesOperation"/>
  </aop:config> 


NOTA: La forma de invocar y utilizar cada servicio será explicada en un apartado posterior.


Otro punto importante es la convención de nombres que se utiliza para definir servicios. Se deben establecer nombres que sigan las siguientes características:


- Estén expresados en Inglés de forma clara y concisa. Por ejemplo:

getUser(Integer userId)          SI     	getUserByHisId(Integer Id)         NO


- Evitar nombres complejos que pueden ser explicados por javadoc en la interface del servicio:

retrieveLastObjectFromRepositoryWithLazyEval(Integer id)    NO 

Puede ser cambiado por:

getLastObjectFromRepository(…)
getLastObject( … )


- Con un javadoc del tipo:

/**
* Recupera el último objeto del repositorio de Thuban con
* Inicialización Lazy.



Otro punto importante es la generación de comentarios que no aportan información relevante y que —peor aún— pueden llegar a confundir. La utilización de comentarios (fuera de javadoc) orienta al desarrollador, de forma tal que cualquier persona que tome el código fuente —incluso el mismo programador— pueda entender fácilmente el flujo de ejecución leyendo el código y los comentarios, si es que existe algún tipo de complejidad en el procesamiento.


Los comentarios del tipo:

// devolvemos el usuario procesado return usuarioRecuperado;


No son bienvenidos y no aportan al entendimiento del código.

Interfaz de Usuario

Beg10.png



Las interfaces de usuario (en Inglés: User’s interface ó UI) se construyen en ZK con extensión ZUL. Cada proyecto tiene sus propias interfaces, definidas en la carpeta Secure del proyecto. Todas estas interfaces están protegidas por el FilterChain y se debe acceder con autenticación mediante login.



Por convención, el desarrollo se basa en el patrón MVC (Modelo Vista Controlador).






Controlador

Cada vista tiene asociada un controlador. En ZK existen varias formas de implementación de controladores, pero esto no significa que todas ellas sean correctas. Uno puede verse tentado de escribir algo como:

 <window id="yourWindow" use="com.latintech.thuban.ui.YourUI">


El componente Window es un tanto especial en ZK. Se conoce como SpaceOwner (internamente este componente implementa una interface de ZK llamada IdSpace).

Beg11.png




Según este ejemplo, si “A” es un SpaceOwner, controlará el espacio de IDs que incluye los componentes “B” y “D”. En cambio, si “C” es otro SpaceOwner controlará el espacio de IDs que incluye al componente “E”. Ahora bien, como “A” y “C” son dos SpaceOwners diferentes pueden existir componentes dentro de su espacio de domino que tengan el mismo ID.







Por tanto, el siguiente ejemplo es absolutamente válido:

<window id="A">
<label id="B"/>
<window id="C">
<label id="B"/>
</window>
</window>


Luego de conocer un poco más una Windows, podemos ver que más allá de que sea un componente especial dentro del universo ZK, no deja de ser un componente y es incorrecto tratarlo como un controlador.


Pros:

- Es fácil de entender y funciona con sólo agregar algunos métodos nuevos a la Window.

Contras:

- El controlador tiene que extender de un componente que reside en la vista.


Una segunda aproximación —y la más correcta de todas— consiste en utilizar un Composer. Éste permite definir uno o varios controladores para nuestra pantalla. Por lo tanto, la definición anterior podría ser alterada de la siguiente manera:

<window id="yourWindow" apply="com.latintech.thuban.ui.MyComposer">
public class MyComposer extends GenericAutowireComposer {
 private Listbox list ;
 private Textbox text ;
   public void doAfterCompose(Component comp) throws Exception {
           super.doAfterCompose(comp);
   Hacer lo necesario para inicializar la pantalla.
                                     }
}


Existen varios tipos diferentes de Composers. El más completo de todos es el AutoWireComposer. Éste permite eliminar las referencias a componentes de la vista utilizados para acceder a ellos mediante la forma tradicional (por medio de una Window por ejemplo):

this.getFellow("texto")


Por la definición de un atributo interno del Composer con el mismo nombre que el ID representativo del ZUL. Por ejemplo:

private Textbox texto;


Teniendo en cuenta que existe un componente en nuestra vista identificado como:

<textbox id="texto"/>


Este Composer inyecta el componente directamente utilizando el concepto de Inversión de Control. Por eso no debemos preocuparnos por recuperarlo manualmente cada vez que lo necesitamos.


Pros :

- El controlador no tiene que extender de un componente de la vista haciendo más puro el manejo de eventos.

- Permite escribir varios Composers para una misma vista.

Manejo de Eventos

Una forma de mejorar el rendimiento de nuestra aplicación es puliendo el manejo de eventos de nuestros componentes. La forma de hacerlo es:

- Cada componente puede disparar eventos, por lo que se puede invocar un método de su controlador de la siguiente manera:

<combobox id="combo" onClick="myWindow.loadSomething()"/>


Sin darnos cuenta, estamos influyendo notoriamente en el rendimiento de nuestra aplicación. En este caso, BeanShell resuelve el evento en el contexto del componente (en este ejemplo, un combobox) y al verificar que no corresponde a su contexto, lo deriva a su parent (la Window). Todo esto consume ciclos de procesamiento.


- Lo ideal sería invocar directamente nuestro Controlador de la siguiente manera:

<combobox id="combo" forward="onChange=onLoadSomething"/>

Aquí, nuestro componente invoca directamente al Controlador, ganando ciclos de procesamiento extras y agilizando la llamada. Lo único que queda por hacer es agregar el prefijo “on” a nuestros métodos de tal manera que si teníamos nuestro método loadSomething() deberíamos llamarlo onLoadSomething().

Identificar componentes

Otro punto importante a la hora de escribir código legible es nombrar correctamente los atributos de nuestras interfaces de usuario. Veamos algunos ejemplos:

<combobox id="seleccioneAlMenosUno"/>


Si bien es práctico para la persona que escribe el código, porque conoce todos los componentes de la UI que está construyendo, es realmente difícil de localizar para alguien externo que lo lee por primera vez. Por el contrario, si se escribe el código anteponiendo un prefijo que indique el tipo de componente, seguramente se provee ayuda referencial al lector, sin que éste tenga que rastrear la definición propiamente dicha del componente para conocerla:

<combobox id="cmbSelectOne"/>


Por ejemplo, para algunos componentes los nombres sugeridos son:

Componente Sugerencia
Combobox cmb
Textbox txt
Checkbox chk
Radio rad
Listbox lst
Grid grd
Groupbox grp

Manejo de Excepciones

Una excepción es un evento que ocurre durante la ejecución de un programa y detiene el flujo normal de la secuencia de instrucciones. En otras palabras, una excepción es una condición anormal que surge en una secuencia de código durante su ejecución.

Las excepciones en Java están destinadas a la detección y corrección de errores, al igual que en el resto de los lenguajes que las soportan. Si hay un error, la aplicación no debería terminar su ejecución inesperadamente. Se debería lanzar una excepción que capturase y resolviera la situación de error; o poder ser tratada finalmente por un gestor por defecto u omisión.

En Thuban® se han definido un conjunto de excepciones para utilizar en cada una de las capas y parametrizar los errores en función de su causa y/o tipo. Estas excepciones se clasifican en diferentes grupos que permiten un mayor o menor grado de personalización mediante mensajes de error predefinidos. Dentro de estos grupos, se destacan las excepciones orientadas al usuario, los errores inesperados o problemas detectados en subsistemas o conectores.

La gestión de excepciones proporciona un mecanismo poderoso para controlar cualquier tipo de incidente que pueda llegar a suceder en la infraestructura de Thuban®. Permite manipular errores y/o problemas inesperados debido a las características dinámicas y complejas de la arquitectura, logrando un refinamiento de código, legibilidad y un alto grado de mantenibilidad.


Una clasificación básica, que debería tener presente todo aquel interesado en utilizar excepciones en Java, remite a la definición de dos grandes grupos de excepciones a tener en cuenta:


- Checked Exceptions (excepciones controladas): Son errores previstos, controlados en el código que permiten al sistema recuperarse.

- Unchecked Exceptions (excepciones no controladas): Son excepciones no previstas ni controladas que pueden provocar inconsistencias de datos y la finalización inesperada de la aplicación. Esto se conoce como Runtime errors (Errores en tiempo de ejecución).



El proyecto Thuban® Exceptions engloba la definición de cada una de las excepciones utilizadas en el marco de la arquitectura de Thuban® y la definición y manejo de errores (internalización). El proyecto divide las excepciones en tres tipos:

- core: excepciones de carácter general que definen el comportamiento de las excepciones particulares definidas en cada una de las capas de la arquitectura Thuban®.

- services: grupo de excepciones específicamente definidas para cada uno de los servicios de dicha arquitectura. Permite una rápida identificación de los errores y/o problemas que hayan ocurrido durante la ejecución de un servicio particular.

- services-custom: excepciones particulares utilizadas en servicios y/o DAOs que abarcan casos específicos que requieren la identificación personalizada del problema que le dio origen.


Cada una de ellas utiliza una codificación especial que sigue un patrón preestablecido para informar el error. Como primera medida, se establece en ThubanConst la constante que define el código de error:

<source lang="xml">/** Error interno del servidor. */ public static String E100_1001= "E100-1001"; </source>


A continuación se define la entrada en el archivo de propiedades (por ejemplo excepciones_thuban.properties) en conjunto con el mensaje asociado:

<source lang="xml">E100-1001= Error interno del servidor.</source>


La jerarquía de excepciones en Thuban® se muestra en el siguiente gráfico:

Beg12.png


- ThubanException: define el comportamiento genérico para todas las excepciones dentro de la arquitectura de Thuban®. Maneja la internalización y los códigos de error.

- ServiceException: excepción generada por la capa de servicios que hereda el comportamiento de ThubanException.

- ConfigException: excepción que se genera ante la presencia de una configuración incorrecta de la aplicación y que seguramente conllevará problemas de funcionamiento.

- DataAccessObjectException: excepción de uso exclusivo en DAOs. Tiene la misma estructura interna que UserServiceException, puesto que puede dar origen a errores que serán capturados y tratados por dicha excepción.

- UserServiceException: excepción orientada a usuarios de cualquier índole, desde usuarios de aplicación hasta subsistemas que consumen los servicios, que parametriza el mensaje de error de acuerdo con un nivel de severidad. Es posible identificarlo y tratarlo de diversas maneras.

- UnexpectedErrorException: representa todos aquellos errores de conexión y comunicación, los errores ocurridos en tiempo de ejecución, etc. que limitan la ejecución normal de la aplicación. No tiene parametrización.


- SubsystemException: excepción generada en un subsistema utilizado dentro de un servicio. Es parametrizable mediante el mensaje de error original que generó la causa.

- Excepciones personalizadas: define el conjunto de excepciones que cubre problemas particulares que no se pueden generalizar con otra excepción de nivel superior. Por ejemplo CouldNotFindResourceException

- Excepciones por servicios: comprende el conjunto de excepciones definidas por cada servicio para personalizar los problemas/errores e identificar las inconsistencias en la intercomunicación de los mismos. Por ejemplo DocumentServiceException / ResourceServiceException.