From ef46172a5e9a9f0a9e02a48cf3dac03e19ab76b4 Mon Sep 17 00:00:00 2001 From: Javier Moran Rua Date: Tue, 26 Jan 2010 20:21:55 +0100 Subject: [PATCH] ItEr45S06DocumentacionFormacionItEr44S07: Continuation of architecture section of development guide. --- .../guia-arquitectura.rst | 195 ++++++++++++++++-- .../guia-desenvolvemento/images/mvc_zk.png | Bin 0 -> 8448 bytes .../images/zk_architecture.png | Bin 0 -> 26877 bytes 3 files changed, 174 insertions(+), 21 deletions(-) create mode 100644 doc/src/technical/guia-desenvolvemento/images/mvc_zk.png create mode 100644 doc/src/technical/guia-desenvolvemento/images/zk_architecture.png diff --git a/doc/src/technical/guia-desenvolvemento/guia-arquitectura.rst b/doc/src/technical/guia-desenvolvemento/guia-arquitectura.rst index 499d93766..5d095aa35 100644 --- a/doc/src/technical/guia-desenvolvemento/guia-arquitectura.rst +++ b/doc/src/technical/guia-desenvolvemento/guia-arquitectura.rst @@ -5,31 +5,184 @@ Guía de Arquitectura Arquitectura basada en capas ============================ -Enumeracion das capas usadas na aplicación: +A aplicación Navalplan utiliza unha arquitectura de organización do código baseada en capas. Consiste en organizar o software nunha serie de divisións horizontais lóxicas. Estas divisións horizontais organízanse xerarquicamente de forman que descansa cada unha na capa que ten debaixo. Así ata a capa máis profunda. Nesta estruturación séguense os seguintes preceptos: + - Cada capa ten un conxunto de responsabilidades que corresponden a un determinado nivel de abstracción. + - Unha capa ofrece servizos a capa de nivel superior. + - Unha capa usa os servizos ofertados pola capa de nivel inferior. - * Capa de interfaz: - * Modulo de autenticacion. - * Interfaz WEB: - * Model-View-Controller - * Capa de servicios conversacionais: XXXModel - * Interfaz de servicios WEB. - * Servicios REST. - * Capa de loxica de negocio: Entidades e clases auxiliares de comportamento - * Capa de persistencia +As capas de que consta Navalplan son as seguintes: + - Capa de presentación - interfaz web. + - Capa de interfaz servizos web. + - Capa de lóxica de negocio. + - Capa de persitencia. -Tecnoloxías utilizadas e relacion con cada capa -========================================================= +A continuación se explicará brevemente cada unha destas capas. - * Framework Spring. Contedor de inyeccion de dependencias usado de forma transversal na aplicación para inyeccion de control -e para proporcion de varios servicios como: - * Xestion das transaccions en Hibernate e a sesión. - * Spring TestContext para traballar sobre JUnit. - * Framework ZK. Framework para facer interfaz web. +Capa de presentación - interfaz web +----------------------------------- + +A capa de interfaz web corresponde coa parte do programa que se encarga de implementar as páxinas HTML/Javascript que permiten aos usuarios realizar as operacións necesarias para planificar a empresa. + +Dentro da interfaz web se fai uso do patrón MVC (Model-View-Controller) para estruturar cada unha das pantallas. + +No patrón MVC distínguense 3 partes estruturais. + - **Vista (View)**. A vista inclúe os compoñentes software que se encargan de representar os widgets dos que se compón a + interfaz gráfica. No caso dunha aplicación de escritorio os widgets da vista se renderizan pintándose a través das librerías + gráficas do sistema operativo. No caso dunha aplicación como ésta, unha aplicación con interfaz web, os widgets se renderizan a + través de HTML/Javascript e esta renderización e levada a cabo polo navegador web do usuario que accede a aplicación. + - **Modelo (Model)**. O modelo encapsula por unha banda os datos que se xestionan a través da vista e ofrece o controlador + operacións para actuar sobre eles. Na arquitectura está representado por clases que teñen xestionado o seu ciclo de vida a través + do contedor de inxeción de dependencias que se usa *Spring framework*. Son clases conversacionais que rexistran o estado de + interacción do usuario cunha determinada pantalla na que esté operando. + - **Controlador (Controller)**. O controlador é o compoñente software - materializado en Navalplan nunha clase de orientación a + obxectos - que se encarga de atender as notificacións, peticións procedentes da vista e de solicitar ao modelo que realice as + operacións pertinentes acordes coas ordes que o usuario emite ao programa a través da interfaz. + +É unha capa que non ten ningunha por enriba, é dicir, interactúa directamente co usuario. + +Capa de interfaz de servizos web +-------------------------------- + +A capa de servizos web é unha capa paralela a capa de interfaz web que ofrece servicios web REST para ofrecer funcionalidades de exportación/importación de datos dunha instalación da aplicación co exterior. Conténplanse dous tipos de comunicacións a través de servizos web: + - **Integración con outras aplicacións**. Quedarían englobados aquí os ERP que desexen interactuar con Navalplan. + - **Integración con outras instalacións de Navalplan**. Dúas instalacións de Navalplan en sendas empresas permiten interactuar + para a subcontratación de pedidos e o reporte de avances dos mesmos. + + +Capa de lóxica de negocio +------------------------- + +A capa de lóxica de negocio atópase por debaixo da capa de interfaz web e dos servizos web. É unha capa que está constituida por clases que capturan as regras existentes no dominio da aplicación - planificación de empresas do naval -. Nela existen dous tipos de clases: + - **Entidades**. Son clases que representan conceptos que teñen persistencia no dominio. Quere dicir esto que representan datos + que se van almacenar. Ademáis, levan asociado comportamento que ten que ver cos datos que representa a entidade. + - **Clases de comportamento**. Nalgúns caso pode haber clases que teñen únicamente comportamento e non datos. Esto se deseña na + arquitectura cando se quere reutilizar o comportamento entre varias entidades ou cando desacoplalo da entidade proporciona maior + flexibilidade e esta é requerida. + +Aplícase, por tanto, na arquitectura o patrón de deseño *Domain Model* [1]_. Básicamente consiste en que sexan os obxectos do dominio os que capturen o comportamento de maneira que a reutilización deste comportamento se leva a cabo a través destes obxectos. Como estes obxectos son usados polas capas superiores e teñen o comportamento embebido neles conséguese esta reutilización independentemente do servicio no cal se usan. Esto evita que se cometan erros e se duplique código. + + +.. [1] Patterns of enterprise application architecture. Martin Fowler. + +Capa de persistencia +-------------------- + +A capa de persistencia atópase por debaixo da capa de lóxica de negocio e é a encargada da gravación das entidades na base de datos. Na aplicación utilízase unha solución ORM - Object Relational Mapping - para o mapeo das clases que representan os obxectos do dominio a súa representación en táboas de bases de datos relacionais. Esta solución ORM se encarga tanto de convertir a entidades as consultas que se lanzan sobre o sistema de persistencia como de facer a tradución das entidades ás filas correspondentes das táboas da base de datos. + +A solución arquitectónica usada na capa de persistencia permite que o programa se poida executar sobre diferentes bases de datos. + +Non se inclúen directamente sentencias SQL no código do programa, senón que en base a unha linguaxe propia do ORM se traducen as sentencias SQL adecuadas a cada sistema xestor de base de datos. + +O ORM utilizado é Hibernate. + +Tecnoloxías usadas e relación con cada capa +=========================================== + + +Spring Framework +---------------- + +Spring Framework principalmente é un framework que proporciona un contedor de inxección de depedencias que permite a implementación do patrón de deseño IoC [2]_. + +Resumidamente este principio de deseño permite desacoplar, é dicir, facer independentes, unhas parte dun programa de outras. Facendo independentes unhas partes de outras propicia que a arquitectura do programa permita cousas como cambiar unha determinada implementación por outra e que as cousas sigan a funcionar. Por exemplo, Navalplan permite a sustitución do ORM que implementa agora mesmo a persistencia, Hibernate, por outro ORM ou outra solución de almacenamento como usar directamente JDBC. + +A través do contedor de inxección de dependencias tamén se permite xestionar o ciclo de vida dos obxectos que se crean recorrendo ao contedor - *beans* de Spring -. Por exemplo, pódese configurar que un *bean* teña ámbito *Singleton* [3]_ ou ben que se devolva unha nova instancia da clase do *bean* cada vez que se solicita unha nova referencia ao contedor. + +Ademáis de cómo contedor lixeiro de inxección de dependencias Spring Framework úsase na aplicación con outras finalidades: + + - **Cómo xestor das transaccións para Hibernate**. Utilízase Spring para a xestión das transacción a través do ORM que se usa na + arquitectura Hibernate. De maneira declarativa a través de Spring se abren e xestionan as sesións de persistencia de Hibernate e + se manexan as transaccións das operacións coa base de datos. + - **Como planificador de tarefas**. Hai determinadas operacións que hai que executar periódicamente durante a execución da aplicación e, para elo, a través de Spring faise uso do *scheduler Quartz* [4]_. + - **Nos tests de unidade Spring TestContext**. Para a realización das probas de unidade úsase o framework *JUnit*. Agora ben, non se fai directamente senón a través da sección de Spring denominada como *Spring TestContext*. Con esta parte permítese utilizar *JUnit* de forma declarativa sen anotacións e, incluso, ser agnósticos de JUnit xa que permite que sexa sustituido por outro framework como *TestNG*. + +.. [2] Inversion de control +.. [3] Ver http://en.wikipedia.org/wiki/Singleton_pattern +.. [4] Ver http://www.opensymphony.com/quartz/ + +Framework ZK +------------ + +Na interfaz web para proporcionar a experiencia de usuario desexada elixiouse o uso do framework ZK. ZK é un framework Java/Javascript construido sobre a especificación de Servlets. Desta maneira, para desplegar a aplicación web necesítase un contedor de Servlets. + +ZK defínese como un framework orientado a eventos baseado en compoñentes que ten por obxectivo permitir a programación de interfaces ricos na web. ZK está composto por un motor AJAX orientado a eventos, un conxunto de compoñentes XUL [5]_ ou XHTML e unha linguaxe de etiquetas denominada ZUML - *ZK User interface Modeling Language* - que permite especificar como se compoñen as distintas páxinas dunha aplicación web mediante a escritura de ficheiros ZUML. + +A filosofía de traballo co framework ZK consiste en representar a aplicación a través de compoñentes ricos XUL e XHTML e en manipular +estes compoñentes a través da captura dos eventos que son disparados froito da interacción do usuario coa aplicación. Isto consiste en +trasladar o modelo de programación levado a cabo nas aplicacións de escritorio á web. AJAX é usado como medio de comunicación entre os +eventos lanzados froito da interacción de usuario e o contedor de Servlets. A utilización de AJAX por parte do framework para levar a cabo esta comunicación é transparente para o programador, o cal permite incrementar a produtividade ao verse o programador libre de non ter que xestionar todos estes eventos a través da tecnoloxía AJAX. Desta maneira, co framework ZK simplifícase o desenvolvemento de aplicacións ricas AJAX dos modos seguintes: + + - O motor orientado a eventos permite utilizar o modelo de programación intuitivo do escritorio e levalo a web. Os compoñentes XUL e XHTML proporcionan ao usuario bloques para a construción de interfaces web reutilizables e que fan esta labor vistosa e produtiva. + - A utilización do linguaxe de etiquetas ZUML permite ao desenvolvedor especificar como son as pantallas da aplicación web dunha maneira comparable a como se pode especificar como é unha páxina HTML estática. + +Ademais de presentar todas as vantaxes anteriores para o desenvolvedor de cara o resultado co usuario, unha característica que debe ser apreciada é a capacidade do framework de proporcionar interfaces ricas que, sen lugar a dúbidas, aumentan a experiencia do usuario en varios frontes: + + - Por unha banda, os compoñentes XUL e XHTML son compoñentes baseados en AJAX e con Javascript que manipula o DOM. Isto permite que os cambios que hai nunha páxina se efectúen manipulando o HTML e non tendo que recargar toda a páxina, o cal fai que o tempo de resposta e a experiencia do usuario mellore considerablemente. + - A través de Javascript tanto os compoñentes proporcionados polo framework, como os que pode implementar o desenvolvedor, poden proporcionar efectos e formas de interacción dinámicos que fan a experiencia máis produtiva e intuitiva. Por exemplo, pódese citar o efecto de arrastrar e soltar, elementos dinámicos á hora de despregar listados, mostrar elementos, etc... + - ZK está baseado en HTML e Javascript e soporta os principais navegadores do mercado. Debido a isto ten como vantaxe este framework que pode ser accedida a súa funcionalidade avanzada usando un navegador estándar. + +Esquema de funcionamento AJAX +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Agora explicarase moi brevemente a través dunha figura como ZK implementa o comportamento descrito, como transparentemente ao +usuario e coa utilización de Ajax leva o modelo baseado en eventos do escritorio á web. + +.. figure:: images/zk_architecture.png + :scale: 75 + :align: center + + Diagrama de arquitectura de ZK framework. + +Pódense observar no diagrama 3 partes: + - ZK Loader. É conxunto de Servlet Java que se encarga de responder as peticións normais HTTP do navegador web. + - ZK AU Engine. Conxunto de Servlets que se encarga de recibir/responder as peticións Ajax. + - ZK Client Engine. Código Javascript que se encarga de actualizar o DOM e capturar os eventos do usuario. + +O mecanismo representado é o seguinte: + 1. O ZK Loader interpreta unha petición entrante e xera a correspondente páxina HTML, incluíndo HTML, CSS, código Javascript usando compoñentes ZK no lado do servidor. + 2. O ZK Loader envía unha páxina HTML ao cliente e ao ZK Client Engine. O ZK Client Engine reside na parte do cliente para monitorizar os eventos Javascript enviados polo browser. + 3. Se calquera evento Javascript é lanzado, o ZK Client Engine envía estes eventos, a través de peticións Ajax, ao ZK AU Engine. + 4. O ZK AU Engine recibe as peticións AJAX, actualiza as propiedade dos compoñentes ZK e envía a resposta Ajax de volta a parte cliente. + 5. O ZK Client Engine recibe a resposta e actualiza os cambios indicados na árbore DOM do browser. + +O uso de ZK abrangue únicamente á capa de presentación - interfaz web - de maneira que é fai que a aplicación sexa independente deste framework en capas inferiores. + +Unha característica arquitectónica de ZK remarcable é que un framework centrado no servidor. Esta frase significa que os widgets que conforman as páxinas dunha aplicación web existen como obxectos na parte servidora (contedor de Servlets) e é o propio framework o que xestiona toda a complexidade de por en comunicación o navegador de usuario coa parte servidora. A captura de eventos no navegador, o seu transporte ata o servidor, a comunicación dos cambios que se fagan no servidor nun widget ata o navegador e a modificación do DOM para reflexar estes cambios é feito de forma transparente polo framework ZK. + +Esto fai que sexa fácil aplicar o patrón MVC, explicado con anterioridade. En particular ZK ocúpase exclusivamente da parte de vista e interven un pouco na parte do controlador. O programador toma o control dende o controlador ata o modelo. O diagrama seguinte explica como se materializa con ZK o patrón MVC. + +.. figure:: images/mvc_zk.png + :scale: 75 + :align: center + + Patrón MVC aplicado en ZK framework + +A parte de vista, a cargo de ZK, como se ve, está formada por dúas partes: A parte servidora, e a parte HTML/Javascript. A parte servidora está constituida por obxectos Java que representan os widgets presentes no navegador nunha determinada páxina e a parte de HTML/Javascript é a renderización do widget a través de elementos HTML e JS. + + +.. [5] XUL. XML-based User interface Language. Aplicación de XML para describir unha interfaz de usuario. É usada por Firefox. + +Timeplot +-------- + + + +TODO +---- + * Ferramentas externas: Cutycap + * JFreeChart. + * YUI. Libreria Javascript para compoñentes. + * JasperReports para informes. + * Jgrapht. Grafo de tarefas. * Servicios web REST. - * Apache CXF. Para - - - + * JAX-RS API. + * Apache CXF. + * Framework Spring security. Para autenticación. + * Hibernate Validator para validacións. + * Framework auxiliares: + * JODA + * Gettext para internacionalizacion. + * Apache Math. Relación das capas cos paquetes e módulos do proxecto ===================================================== diff --git a/doc/src/technical/guia-desenvolvemento/images/mvc_zk.png b/doc/src/technical/guia-desenvolvemento/images/mvc_zk.png new file mode 100644 index 0000000000000000000000000000000000000000..37fa664108c5994b5d8636270ac9ff1e1af7129e GIT binary patch literal 8448 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 literal 0 HcmV?d00001