Empacotamento Java

Há tempo sem escrever aqui por causa da correria. Dia desses, estava conversando com um amigo de trabalho e entramos no mérito do empacotamento dos sitemas em que estávamos trabalhando. Na ocasião, o assunto era DDD, mas acabamos caindo no assunto packages. A maioria dos sistemas em que eu trabalhei usa aquela divisão de responsabilidades do tipo DAOs, services e controllers na qual, teoricamente, a DAO toma conta das suas entidades (entidades ORM), os serviços encapsulam a lógica de negócio e os controllers atuam como – rufem os tambores – controladores de fluxo.

Minha opinião é que esse tipo de divisão é assim: DAO: tabelas relacionais representadas em objetos Java; Services: lógica estruturada usando classes e objetos; e contollers: onde vai todo o resto. Mas isso é assunto para outro dia.

É muito comum, nesse tipo de divisão – que também é chamada de package-by-layer – utilizar um pacote com.acme.model (ou entity) para colocar as entidades, com.acme.service para colocar os serviços e com.acme.controller para colocar os controllers, sob a justificativa de que isso mantém os artefatos bem separados caso o sistema venha a escalar.

Não!

Gosto de pensar em pacotes como pequenos módulos – package-by-feature – se você tem um módulo de gerenciamento de usuários, nada mais justo do que manter os respectivos artefatos (entities, DAOs, services e controllers) dentro do pacote com.acme.usuario. Não é?

Pense bem, isso cria uma boa alternativa pra você utilizar o modificador package-private ou default (só contextualizando que estamos falando sobre Java). Dessa forma, você pode garantir, por exemplo, que objetos do seu módulo Usuarios só sejam instanciados dentro dos limites do seu próprio pacote. E isso é só um dos exemplos.

Para deixar mais claro, quero dar uma “introspectada” no empacotamento de uma das APIs do Java: o java.util, responsável por prover, dentre outras, as implementações de coleções (famigerada Collections API). Se você reparar, não há divisões internas do pacote no que tange lists ou sets nem mesmo para a própria raízes das coleções, como as interfaces Collection e Map. Está tudo imediatamente abaixo de java.util:

java.util.packagingE aí, pra reforçar o que eu disse há pouco, a prória implementação da interface Entry da classe HashMap faz uso do package-private, que eu comentei há pouco:

static class Entry implements Map.Entry { ... }

Vantagens do empacotamento da perpectiva de features

Então resta enumerar as benesses de se empacotar seu software do prisma package-by-feature. Essas são só as que eu julguei legais de elencar aqui, as demais vou deixar como links no final do post.

Coesão

Vai te fazer pensar melhor sobre os limites do seu software – isso no DDD é chamado de Bounded Contexts – e acredite, vai diminuir a quantidade de artefatos que você terá que escrever. Na divisão por camadas, é muito comum que, ao codificar suas camadas em pacotes diferentes, você automaticamente comece a escrever artefatos desnecessários como por exemplo, de uma relação Usuario @OneMany Conta, você acabe escrevendo um UsuarioDAO e um ContaDAO. É um exemplo miserável, eu sei, mas já vi muito. Conta, de uma perpectiva de empacotamento por feature, poderia ser transparentemente e  automaticamente internalizada pelo módulo de usuários.

Navegação

No que tange a navegação, empacotar por feature também te deixa mais confortável para encontrar os artefatos que você deve alterar. É comum, por exemplo, que alterações nas entidades propaguem alterações por todas as outras camadas. Manter tudo junto vai aliviar seu estresse quando você tiver que sair procurando onde mais estão os fragmentos do seu módulo.

Testes

Eu duvido que você já não tenha se deparado com uma situação em que teve que modificar a visibilidade de algum aterfato só para conseguir testá-lo – eu conheço o dilema sobre “testar ou não testar privados”, mas acontece que você vai cedo ou tarde se deparar com isso . Então, empacotar por feature também vai te beneficiar nesse sentido, uma vez que ao invés de publicar os atributos ou comportamentos da sua classe, você pode simplesmente deixá-los privados ao nível do pacote.

Nomenclatura

Aumenta significativamente o escopo dos nomes que você pode empregar em seu código. Pense assim, uma vez que o pacote compõe o nome (unique name) das suas classes, você poderia simplificá-los:

  • com.acme.usuario.Usuario.java
  • com.acme.usuario.Dao.java
  • com.acme.usuario.Service.java
  • com.acme.usuario.Controller.java
  • com.acme.usuario.Exception.java

Sei que tem gente que vai infartar ao ler isso, mas não deixa de ser uma possibilidade.

E você, como empacota?

Fontes:

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s