Maven: Parent, Module y BOM (Bill of Materials)

Aunque últimamente ando con gradle y en gradle he resuelto el tema que comento aquí, quería ver si podía hacer algo similar con maven.

¿Cual es el tema?

Imagina que tienes un «producto» SW en tu empresa, algo como el control de una flotilla de camiones, que vendes a distintos clientes que tienen camiones y necesidad de controlar su flotilla. ¿Y por qué «producto» entre comillas?. Aunque tu producto está guay, cada cliente siempre quiere algunas funcionalidades adicionales que tu producto no tiene, o modificación de las que ya existen y la política de tu empresa es hacerle caso al cliente.

Así que tienes tu proyecto organizado en un montón de proyectos maven (o gradle):

  • Uno o más proyectos maven con el «core» de tu producto donde está lo que sabes que siempre va a ir a cualquier cliente.
  • Varios proyectos maven con «plugins» con funcionalidad adicional que puedes añadir o no a tu core según el cliente los pida o no.
  • Varios proyectos maven con librerías tuyas propias de utilidades, relativas a o no a tu producto. Por ejemplo, si tu producto lee de alguna forma los GPS de los camiones para saber por dónde andan, puedes tener varias librerías para leer distintos modelos de GPS.

Ahora imagina que tienes que trabajar en tu producto para hacerle modificaciones al cliente «Fulanito Logistic» que quiere determinados plugins, alguno más que tienes que desarrollar, te ha pedido además algo que te interesa meter en el core porque lo ves útil para siempre, etc.

Y encima, tienes otro proyecto en paralelo para «Menganito Logistic» que quiere otros plugins distintos y también quiere ciertas modificaciones, pero que mira tú que cosas, no son las mismas que quiere «Fulanito Logistic».

¿Cómo montas esto en tu IDE favorito? ¿Y tu compañero que está trabajando para la otra compañía?

Pues bien, inicialmente, montábamos todo (core, todos los plugins y todas las librerías), pero eso hace que el proyecto crezca cada vez más, se haga más inmanejable y los compilados sean cada vez más costosos. Además, empiezan a proliferar en el código como como «if es para fulanito ….», o algo más elaborado porque tenemos bastante friki como anotaciones en las clases estilo @Menganito.

Así que al final, montamos algo un poco más complejo, pero que permite que nuestro IDE y nuestros jenkins cojan solo lo que es necesario en cada caso.

En algún sitio de la estructura de git, metemos un pom.xml parent con las cosas que son comunes en nuestro producto. Por ejemplo, dependencyManagment con las versiones de spring-framework, junit, slf4j/logback, etc. También  properties que necesitemos, etc, etc.

En la misma estructura de git, tenemos un directorio plugins y debajo de el un proyecto maven para cada plugin. Justo debajo de plugins, tenemos un pom.xml con module para cada plugin, algo así

plugins/pom.xml
plugins/plugin1/pom.xml
plugins/plugin2/pom.xml

Cada plugin tiene como padre al plugins/pom.xml y el plugins/pom.xml tiene a su vez como padre al parent común que tenemos por ahí.

plugins/pom..xml tiene como module a todos los plugins y al core de nuestra aplicación. Este pom.xml es el que montamos en el IDE si estamos trabajando en el producto en general y no para un cliente concreto. Además, es el que metemos en jenkins para asegurarnos que los plugins y el core siempre son compatibles.

Por otro lado, para trabajar para un cliente concreto, creamos en el mismo git un directorio proyectos con dos subdirectorios, menganito y fulanito. Todos con su pom.xml de forma similar al de plugins

proyectos/pom.xml
proyectos/menganito/pom.xml
proyectos/fulanito/pom.xml

proyectos/pom.xml tiene como padre al padre común que habíamos hecho por ahí y menganito/pom.xml y fulanito/pom.xml tienen como padre a proyectos/pom.xml

A su vez, menganito y fulanito pom.xml tienen «module».que con path relativo, incluye los plugins necesarios para ese cliente concreto, así como el core. Tambien, debajo de menganito y fulanito se crean subproyectos con código que es específico para ese cliente y que no tenemos previsto reutilizar más.

El que trabaje para menganito, monta en su IDE el menganito/pom.xml y así solo tiene el core, los plugins específicos y el código específico para menganito, ganando tiempo de compilado, menos complejidad de clases/proyectos en el IDE, etc. También esto facilita el hacer el zip/instalado específico, vía maven, para este cliente concreto. Y un jenkins que solo compila lo de ese cliente.

En parent y modules con maven tienes un ejemplo y detalles de como montar todo esto.

Entradas relacionadas:

1 comentario en “Maven: Parent, Module y BOM (Bill of Materials)

  1. Se parece bastante a lo que hace Jira, y algunos otros proyectos que soportan plugins y usan maven.

    Igual la arquitectura de cómo se manejan los plugins en un sistema, siempre es complejo. Cada plugin, puede ser un proyecto independiente, que sólo depende del «plugin base». Luego se compilan y publican (en Nexus/Artifactory). Los sistemas para los clientes, tendrán dependencias a los plugins que usen. En este caso, cada plugin, cada sistema cliente, y el sistema base, son proyectos totalmente independientes.

    Si además se necesita carga dinámica de los plugins, hay mecanismos como OSGi, los cuales me traen muy malas experiencias. En lo posible, trato de evitarlo. Creo que en Eclipse, una de las implementaciones más usadas de OSGi, se llama Equinox, y todo el IDE y sus proyectos, está montado alrededor de eso.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.