Back-End

26 set, 2013

Como você organiza os sub-módulos Maven?

Publicidade

Sendo um programador itinerante, uma das coisas que eu observei ao longo dos anos é que cada projeto com o qual você se depara parece ter uma forma ligeiramente diferente de organizar seus módulos Maven. Não parece haver uma maneira convencional de caracterizar o conteúdo dos sub-módulos de um projeto, e nem muita discussão sobre isso. Isso é estranho, já que definir as responsabilidades dos seus módulos Maven me parece ser tão importante quanto um bom design de classe e técnica de codificação para o sucesso de um projeto. Assim, à luz dessa falta de sabedoria, aqui estão os meus dois centavos…

Quando você entra em um novo projeto, você geralmente encontrará uma convenção de layout que vagamente corresponde ao definido pelo manual Better Builds With Maven. O diretório limpo do projeto geralmente contém um arquivo POM, uma pasta src e vários sub-módulos, cada um em seu próprio subdiretório, como mostrado no diagrama abaixo:

maven 1

Se todos nós concordamos que essa é a maneira padrão de abordar o nível superior do layout do projeto (e eu já vi isso feito de forma ligeiramente diferente), então parece haver três diferentes abordagens na organização das responsabilidades de cada um dos sub-módulos de um projeto. Elas são:

  • Totalmente por acaso.
  • Por tipo de classe.
  • Por área funcional.

Eu não vou ficar nos projetos que são organizados aparentemente sem nenhuma estrutura ou ordem, exceto para dizer que eles provavelmente começaram bem organizados, mas não foram projetados bem o suficiente para suportar as mudanças forçadas sobre eles.

Ao dizer que sub-módulos de um projeto são organizados “por tipo de classe”, quero dizer que os módulos são usados ​​para agrupar todas as classes que englobam, mas não estão limitados a uma camada na arquitetura do programa. Por exemplo, um módulo pode conter todas as classes que compõem o serviço do programa, ou camadas de persistência, ou um módulo pode conter todas as classes da model.

Por outro lado, ao dizer que os sub-módulos de um projeto são organizados por área funcional, estou falando de uma situação em que cada módulo contém, tão perto quanto possível, uma fatia vertical da aplicação, incluindo model beans, service layer, controllers etc.

Se a verdade deve ser dita, então há uma série de maneiras de organizar sub-módulos do seu projeto. A maioria das configurações dos projetos é bastante plana na estrutura, que é o que eu demonstrei acima; no entanto, se você der uma olhada na palestra de 2009 de Erik Putrycz  – Maven – or how to automate java builds, tests and version management with open source tools, ele demonstra que você pode ter módulos dentro de módulos dentro de módulos.

A fim de explorar isso um pouco mais, eu vou inventar meu cenário absurdamente artificial habitual e, nesse cenário, você tem que escrever um programa para a prática odontológica de Welsh, de propriedade de um homem chamado Jones, também conhecido localmente como ‘Jones The Driller ‘. Os requisitos seriam bastante normais para a prática odontológica, e incluem lidar com:

  • Detalhes dos pacientes: nome, endereço, data de nascimento, número de telefone etc.
  • Prontuários médicos, incluindo tratamentos e resultados.
  • Compromissos.
  • Contabilidade, por exemplo, vendas, compras, salários etc.
  • Auditoria: como quem fez o que a quem…

Como uma solução para o problema de Jones The Driller, você propõe que vai escrever uma aplicação web multi-módulo baseada em Spring, MVC e tomcat que, quando montada, tem um design padrão ‘n’ tier de um banco de dados MySQL, uma camada de banco de dados, serviço de camada, um conjunto de controladores e algumas JSPs que compõem a view. Ao criar seu projeto, sua ideia é organizar os seus sub-módulos “por tipo de classe”, e você vem com a seguinte organização de módulo, mostrada abaixo mais ou menos em ordem de construção de dependência

  • dentists-model
  • dentists-utils
  • dentist-repository
  • dentists-services
  • dentists-controllers
  • dentists-web

…que em sua tela seria algo parecido com isto:

maven 2

Seu módulo dentists-model contém beans do projeto que o objeto da Model é utilizado a partir da camada de persistência até os JSPs. dentist-repository, dentists-services e dentists-controllers refletem as diversas camadas de sua aplicação, com o módulo dentists-web contendo todas as JSPs, CSS e outros apetrechos de view. Quanto a dentists-utils, cada projeto tem um módulo utils em que todas as classes são realmente úteis, mas as classes distintas acabam.

Enquanto isso, em um universo diferente, uma versão diferente do que você decide organizar os sub-módulos do seu projeto por área funcional, que vem com a seguinte composição:

  • dentists-utils
  • dentists-audit
  • dentists-user-details
  • dentists-medical-records
  • dentists-appointments
  • dentists-accounts
  • dentists-repository
  • dentists-integration
  • dentists-web

Nesse cenário, a ordem de construção é um pouco diferente; praticamente todos os módulos dependerão de dentists-utils e, dependendo de suas necessidades exatas de auditoria, a maioria dos módulos vai depender de dentists-audit. Você também pode ver nas imagens a seguir que a estrutura do pacote sub-módulo foi disposta em camadas e tipo dos limites em que cada módulo tem seu próprio modelo, repositório (que contém apenas definições de interface), serviços e pacotes de controller e que o layout de cada módulo é idêntico no mais alto nível.

maven 3

Outra discussão que temos aqui é a organização da estrutura de pacote do seu projeto, onde você pode fazer o mesmo tipo de pergunta: você organiza “por tipo de classe” ou “por área funcional” como mostrado acima?

Você deve ter notado que os módulos dentists-repository podem estar bem próximos do final do ciclo de construção, uma vez que apenas contêm a implementação das classes de repositório e não as suas definições de interface. Você também deve ter notado que os dentists-web são mais uma vez um módulo separado. Isso é porque você é um cara de negócios muito mais experiente e, ao manter JSPs etc. em seu próprio módulo, você espera mudar o design do seu aplicativo e vendê-lo para que outro dentista: Williams The Puller.

De uma perspectiva de teste, cada módulo contém os seus próprios testes unitários, mas há um módulo de teste de integração separado, que vai demorar mais tempo para executar pode rodar quando necessário. Em geral, há duas maneiras de definir testes de integração: em primeiro lugar, colocando-os em seu próprio módulo, o que eu prefiro; e, em segundo lugar, por meio de um teste de integração nomeando a convenção como somefileIT.java, e rodando todos os arquivos *IT.java para todos os arquivos *Test.java.

Seus dois seres idênticos propuseram duas soluções diferentes para o mesmo problema, então eu acho que agora é hora de dá uma olhada nos prós e contras de cada um.

Tomando “por tipo de classe” como primeira solução, o que se pode dizer sobre isso? No lado positivo, é bastante sustentável, já que você sempre soube onde encontrar o material. Precisa de uma classe de serviço? Então isso é no módulo dentist-service. Além disso, a ordem de construção é muito simples. A desvantagem é que a organização “por tipo de classe” é propensa a problemas com a intromissão de dependências circulares, e classes com responsabilidades totalmente diferentes são todas misturadas, dificultando a reutilização da funcionalidade em outros projetos sem desnecessariamente arrastar a coisa toda.

Então, quais os prós e contras da abordagem “por área funcional”? Na minha maneira de pensar, dada a estrutura de pacote de cada módulo, é quase tão fácil de localizar uma classe usando essa técnica, quanto utilizando a “por tipo de classe”. O real benefício do uso dessa abordagem é que é muito mais simples reutilizar uma área funcional de código em outros projetos. Por exemplo, eu trabalhei em vários projetos em diferentes empresas que implementaram auditoria várias vezes. Cada vez que eu ia implementar isso, eu costumava fazê-lo mais ou menos da mesma forma, então não seria bom apenas reutilizar a primeira implementação? Isso sem falar nas questões de propriedade de código … A mesma ideia também se aplica aos dentists-user-details; a exigência para gerenciar nomes e endereços se aplica igualmente bem para um site de vendas de calçados como para a prática odontológica. E o lado ruim? Uma das vantagens dessa abordagem é que os módulos são altamente desacoplados, mas por experiência própria, não importa o quanto você tente, você sempre acaba com mais acoplamento do que você gostaria.

Você já deve ter notado que ambas as propostas não são 100% puras, “por tipo de classe” contém um pouco de “por funcionalidade”, e “por área funcional” contém um pouco de “por tipo de classe”. Isso pode ser evitado, mas eu estou propositadamente sendo pragmático. Como eu disse anteriormente, você sempre vê um módulo utils em um projeto. Além disso, a criação de um módulo de banco de dados separado permite que você altere a implementação de banco de dados do seu projeto com bastante facilidade, o que pode tornar o teste mais fácil em algumas circunstâncias e, da mesma forma, um módulo web separado permite que você remodele o código, e você pode ter a sorte de vender o mesmo produto para vários clientes com a sua própria marca.

Finalmente, uma das verdades não escritas no desenvolvimento de software é que, uma vez que você tenha organizado seu projeto em seus sub-módulos, você raramente vai ter a oportunidade de reorganizá-los e melhorá-los: geralmente não há momento ou vontade política de fazer isso porque custa dinheiro; no entanto, deve ser lembrado que, em termos de Agile, a composição do módulo de projeto é, como o código, uma forma de dívida técnica que, se mal feita, também custa muito dinheiro. Parece, portanto, uma ideia realmente boa, com uma equipe, planejar completamente seu projeto antes de começar a codificar. Portanto, seja radical, faça algum projeto ou tenha uma reunião, você sabe que vai valer a pena no final.

***

Artigo traduzido pela Redação iMasters, com autorização do autor. Publicado originalmente em http://www.captaindebug.com/2013/01/how-do-you-organise-maven-sub-modules.html#.UhKHLRaxOON