Personal tools
gvSIG Desktop
gvSIG Desktop

Cached time 11/22/13 07:49:45 Clear cache and reload

 
Document Actions

Estructura de un proyecto en gvSIG

by Joaquin Jose del Cerro Murciano last modified 2010-08-31 14:00
Maven y eclipse
-----------------------------

Una de las características más interesantes de maven es su capacidad de trabajo con proyectos multimódulo y las facilidades que ofrece a la hora de ejecutar objetivos predefinidos para realizar ciertas tareas claramente definidas, como la compilación del código y su empaquetado. 

En su contra, la versión actual de Eclipse no incorpora los mecanismos necesarios para poder soportar los proyectos multimódulo, por lo que la integración con los mecanismos de maven resultan complejos y requieren el uso de determinados mecanismos y estrategias para conseguir simular dichos comportamientos.

Maven utiliza un Project Object Model (POM) para describir el proyecto de software a construir, la estructura del proyecto y sus submódulos, sus dependencias de otros módulos y componentes externos y el orden de construcción de los elementos. Haciendo uso de estas características definidas, se puede llegar a conseguir que eclipse emplee la información que en los POMs se detalla, para simular un comportamiento multimódulo.


Trabajar en eclipse con maven
-----------------------------

A la hora de trabajar con eclipse, tal y como se mencionaba anteriormente, habrá que tener en cuenta unas pautas que nos permitirán hace uso de las funcionalidades que maven nos ofrece. 

Lo primero que llama la atención es la nomenclatura de los directorios. Los nombres aplicados a los directorios no son casuales, y es que a través de ellos, se pretende simular la estructura jerárquica del proyecto. Para ello, el proyecto padre tendrá el nombre del *artifact_id* y, a partir de él, sus submódulos completarán su nombre con el del padre (es decir, si tengo el proyecto padre *org.gvsig.ejemplo*, el submódulo *Ejemplo1* deberá estar contenido en el directorio '*org.gvsig.ejemplo*/*org.gvsig.ejemplo.ejemplo1*', el *Ejemplo2* en '*org.gvsig.ejemplo*/*org.gvsig.ejemplo.ejemplo2*', si el *Ejemplo1* tuviera a su vez el submódulo *Ejemplo1a* estaría en '*org.gvsig.ejemplo*/*org.gvsig.ejemplo.ejemplo1*/*org.gvsig.ejemplo.ejemplo1a*', y así sucesivamente). Esto da pie a una estructura del proyecto en forma de árbol:

* *org.gvsig.ejemplo*

  * *org.gvsig.ejemplo.ejemplo1* 
  
    * *org.gvsig.ejemplo.ejemplo1.ejemplo1a*

  * *org.gvsig.ejemplo.ejemplo2*


Los nodos padre no son tomados como proyectos Java por eclipse, ya que simplemente son los contenedores de los submódulos. Estos proyectos contendrán el fichero POM con su definición y la descripción de los submódulos que lo conforman. De esta forma, se puede lanzar órdenes a módulo padre, para que se ejecute en él y en todos sus descendientes de manera automática (install, compile, etc.)

Por su parte, los nodos hijos (u hojas del árbol) sí que son proyectos Java, con su estructura habitual en proyectos de este tipo. Estos nodos pueden aprovechar la configuración del padre (dependencias, propiedades, atributos, ...) si especifica en su POM quién es su padre, simplificando su configuración.


Desarrollar un proyecto para gvSIG
---------------------------------------

Cuando vamos a desarrollar un proyecto para gvSIG deberíamos tener 
una separacion lo más estricta posible entre el API y la implementación de
ese API. Para llevar esto a cabo, y apoyándonos en la facilidad de maven
para gestionar proyectos multimódulo se ha confeccionado una plantilla base
para un proyecto de gvSIG. Esta plantilla nos orientará sobre cómo organizar
el proyecto, separando de forma estricta en varios proyectos de eclipse y
distintos jars la lógica de nuestra extensión, del interface de usuario
y a su vez, el API de la lógica de su implementación y el API del interface
de usuario de su implementación.

La estructura base de un proyecto de será:

* *library*

  * *tags* 

  * *branches*

  * *trunk*
  
    * *org.gvsig.example*
    
      * *org.gvsig.example.lib*
      
        * *org.gvsig.example.lib.api*

        * *org.gvsig.example.lib.spi*

        * *org.gvsig.example.lib.impl*

      * *org.gvsig.example.prov*
      
        * *org.gvsig.example.prov.provider1*

      * *org.gvsig.example.swing*

        * *org.gvsig.example.swing.api*

        * *org.gvsig.example.swing.impl*
      
      * *org.gvsig.example.main*

* *extensión*

  * *tags*

  * *branches*
  
  * *trunk*
  
    * *org.gvsig.example.app*
    
      * *org.gvsig.example.app.extensión*
      
En un primer momento, y viendo esta estructura, si lo comparabamos con 
lo que normalmente se venía haciendo en gvSIG antes de 2.0, parece una
estructura del proyecto bastante compleja, pero veamos con un poco
de detalle en que consiste esta.

Lo primero que observamos es que el proyecto está orientado como un 
proyecto de *SVN multimódulo* en comparación con lo que solíamos encontrarnos
en los desarrollos de gvSIG 1.X. Por un lado tenemos el desarrollo de la
parte de librería y por otro, el de la extensión o extensiones para gvSIG.
Esto se ha organizado así ya que normalmente los cambios en la lógica de 
nuestra extensión suelen llevar un ciclo de vida claramente separados de la
integración de estos en gvSIG. Una vez desarrollada la extensión es fácil que
de una versión a otra de gvSIG tengamos que hacer alguna modificación en la
parte de nuestro código que contiene la integración con gvSIG mientras que 
la parte de lógica no sufra cambios a no ser que se traten de correcciones
de bugs. Para conseguir esta independencia, el repositorio del SVN se separa
en dos grandes grupos:

* *library* 

  Contendrá la parte de lógica e interface de usuario que son independientes
  de gvSIG como aplicación. No quiere decir que no dependan de algunas librerías
  de gvSIG como la de acceso a datos, geometrías o mapcontext. SI necesitan
  depender de ellas puede hacerlo.
  
* *extensión*.

  Aquí estará la parte de nuestro código que tiene dependencias con la 
  aplicación gvSIG, andami y otras extensiones de gvSIG. Aquí estarán
  nuestras clases *Extension* así como la configuración de nuestro
  *plugin* para andami.

Vamos a ver ahora que nos encontramos dentro de *library*. Aquí residirán 

* *org.gvsig.example.lib*

  Nos proporcionará el API, SPI y la implementación de ese API.

* *org.gvsig.example.prov*

  En caso de que nuestra librería necesite trabajar con algún
  proveedor de servicios aquí estarán las distintas implementaciones
  de estos proveedores de servicios.
  
* *org.gvsig.example.swing*

  En caso de que nuestro proyecto suministre un interface de usuario
  para la parte de lógica, este lo ubicaremos aquí.
  La parte de *org.gvsig.example.lib* no debería contener dependencias
  con el interface de usuario. Este estará sólo aquí.
  
* *org.gvsig.example.main*

  Lo primero que podemos pensar es ¿ qué hace aquí un módulo *main*
  dentro de la librería ? Pues aunque parezca extraño tiene su utilidad.
  Se trata de un módulo destinado a proveer una aplicación de 
  prueba que permita arracar el interface de usuario y la lógica de
  la librería sin tener que arrancar un gvSIG para probarlo. Esto es
  muy útil de cara a poder realizar un desarrollo más ágil de nuestro
  proyecto y posponer la integración con gvSIG hasta que este esté
  en fases de desarrollo avanzadas.
  
Y por último nos encontramos con la separación en algunos de estos módulos
entre API, SPI e implementación. Esta separación podemos encontrarla
en *org.gvsig.example.lib* y *org.gvsig.example.swing*.

Supongamos que nos encontramos con el desarrollo de una extensión de 
análisis de redes en gvSIG. ¿ Con qué proyectos nos encontraríamos ?

En principio nuestro proyecto no precisa de proveedores de servicios 
especiales. Tiene una parte de lógica, y una parte de interface de usuario,
además del propio plugin para gvSIG. Tendríamos los siguientes proyectos:

* *org.gvsig.networkAnalysis.lib.api*

* *org.gvsig.networkAnalysis.lib.impl*

* *org.gvsig.networkAnalysis.swing.api*

* *org.gvsig.networkAnalysis.swing.impl*
      
* *org.gvsig.networkAnalysis.main*

* *org.gvsig.networkAnalysis.app.extensión*

Básicamente tendríamos estos seis proyectos, y cada uno de ellos generaría
su propio jar, acorde con el nombre del proyecto. Además de que cada uno
de los proyectos estará en su carpeta correspondiente, es importante
que tengan el nombre adecuado. Esto es así ya que al importar estos
proyectos dentro de eclipse, nos encontraremos con que el árbol de carpetas
es *aplanado*, pero gracias a la elección de los nombres de los proyectos
estos mantendrán su coherencia dentro de nuestro workspace.

Aunque parezca obvio, conviene recalcar que dependencias son aceptables entre
estos proyectos. Habrá un dependencia desde la implementación hacia el API, pero
no al revés. Así mismo, nuestro API debe ser conciso y completo. *completo* por que
el cliente de ese API no debe necesitar conocer de la implementación para poder 
usarlo, y *conciso*, por que no debe exponer los detalles de implementación; cuanto
menos exponga y más reducido se mantenga, más fácil y seguro será su mantenimiento.

Por otro lado, tenemos el interface de usuario. Este, sea la implementación o su API,
no deberá tener dependencias con la implementación de la librería, la lógica. Sólo
deberá depender de su API. 

Y por ultimo, la aplicación de pruebas y la extensión sólo deberan tener dependencias
con el API de la librería y el API del interface de usuario.

Hacer notar también, que en cada uno de los distintos niveles de carpetas encontraremos
ficheros *pom.xml*. Así tendremos un *pom* en *org.gvsig.example* que nos permitirá
hacer operaciones con todos los submódulos de nuestro proyecto, así como contener
la configuración general del proyecto. Por ejemplo, podremos construir
los proyectos de eclipse de cada uno de nuestros módulos directamente, atacando a este
*pom*. A su vez, *org.gvsig.example.lib* y *org.gvsig.example.swing* tendrán sus propios
ficheros *pom* con su configuración específica. Por último cada uno de los proyectos
*finales* tendrán su propio fichero *pom*. Cada uno de estos *pom* estará configurado
indicando como *pom* padre el de la capeta superior para heredar de él la configuración
comúm.


En varios momentos hemos estado hablando del API. Pero...

¿ qué entendemos por el API ? 

¿ Cómo lo definimos ? 

La pregunta no es tan obvia como parece. Cuando le pides a varios desarrolladores
que definan el API de un módulo no es normal que tengas resultados similares.
Así que en gvSIG ¿ qué esperamos cuando hablamos que hay una definición del API ?
Normalmente el API estará formado por un juego de interfaces java. Puede haber
alguna clase abstract que presenta una implementación por defecto para algo que
debe ser extendido por el consumidor de ese API, pero nunca contendrá una clase
con su implementación. La excepción a esto suelen ser las *excepciones*. Por su
naturaleza, las excepciones que dispara ese API estarán implementadas en el API.
Este juego de interfaces, se empaqueta en un proyecto y su jar y es la única
dependencia con el proyecto que debe de tener un consumidor de este.

A la hora de manejarnos con *swing* nos vamos a encontrar algunas variaciones.
Debido a la falta de interfaces en *swing* para manejar los componentes gráficos
cuando vayamos a definir el API de la parte de *swing* de nuestro proyecto
en lugar de usar interfaces, usaremos clases abstractas que extenderán los distintos
componentes *swing*, añadiendo métodos abstractos propios del dominio de nuestro proyecto.
Será normal encontrarnos clases abstractas que extiendan a JPanel, de forma que
estos definan los interfaces de usuario asociados a componentes de nuestro proyecto.


¿ Y qué tendremos en la implementación ?

Pues allí tendremos un juego de clases que implementan los interfaces definidos
en el API. Normalmente existirá un *manager* que hará las veces de punto
de entrada a las funcionalidades de nuestro proyecto, de factoría y configuración
de este.

Es conveniente repasar las herramientas que nos proporciona *org.gvsig.tools* para
la gestión de la separación entre API e implementación usando los *Library*, *Locators*
y *Manager*, y si nuestro proyecto va a precisar de *proveedores de servicios* las 
utilidades que existen para su gestión, de forma que cada proyecto no reinvente cada
vez como implementarlos y en todo gvSIG se traten de forma homogénea.

También deberemos tener en cuenta las recomendaciones a la hora de nombrar las
clases e interfaces. La estructura de proyecto descrita está pensada para adecuarse
a una nomenclatura como la descrita en el documento *Nomenclatura para clases e interfaces*. 
Así los interfaces
que encontremos en el API se nombrarán usando nombres significativos del dominio
de nuestra extensión, sin utilizar ningun tipo de prefijo o sufijo; mientras
que las clases que encontremos en el proyecto de implementación y aporten
la implementación de alguno de los interfaces del API se nombrarán anteponiendo
*Default* al nombre del interface que implementan.

Antes de abordar la creación de un proyecto gvSIG de acuerdo a la estructura
descrita es aconsejable repasar la documentación sobre `org.gvsig.tools.service`_
que describe con mas detalle las clases e interfaces a crear, y en qué subproyecto
de maven residen.


.. _`org.gvsig.tools.service` : v2_0/org.gvsig.tools/org.gvsig.tools.service

View source document

View source document Get permanent link


Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: