Java é simples: você que burocratiza seus projetos

Sempre me incomodou bastante toda esta história de que Java é uma linguagem verbosa e sistemas feitos nesta são complexos. Então resolvi escrever este post pra mostrar alguns erros cometidos por desenvolvedores que, realmente, tornam não a linguagem verbosa, mas sim seus projetos verdadeiras máquinas “burrocráticas”.

Este é um primeiro post sobre alguns erros que encontro: é capaz de surgirem outros em um futuro próximo.

Pra quê interfaces?

Este é um ponto que fica muito claro quando você programa algum tempo em plataformas como Grails, Ruby on Rails ou Node.js e, em seguida, pega um projeto de revitalização de legados feitos em Java. Lemos em diversos livros ou palestras o seguinte princípio:

“Programe para uma interface, não para uma implementação”

O princípio está corretíssimo, mas a pergunta fundamental que o motiva não é feita: pra quê preciso de uma interface? Respondo: para representar uma abstração, ou seja, aquilo que é essencial no serviço e compartilhado por todas as suas diferentes implementações.

Portanto, se só existe uma implementação de uma classe no sistema por que você precisa criar uma interface? Não há o que abstrair daí.

Dica um: crie interfaces apenas se existir mais de uma implementação do serviço cuja funcionalidade você deseja abstrair.

DAOs desnecessários quando se está usando um ORM

É outro erro que encontro com frequência: imagine que seu sistema possua doze classes de domínio, todas elas persistidas contra uma mesma base de dados (relacional ou não). Um padrão comum que observo é a geração abusiva de objetos e classes no sistema:

  • Uma interface para representar o DAO para cada entidade.
  • A implementação do DAO para aquela interface
  • Todos os DAOs são executados contra a mesma base de dados
  • O DAO expõe algumas consultas, mas estas em sua esmagadora maioria (quando não todas) são usadas por uma única classe do sistema..

Levando em consideração que o papel do DAO é acessar e escrever dados em um repositório de dados, e existe uma ferramenta chamada ORM, acho interessante levantar sempre algumas perguntas:

  • Dentro de um futuro próximo você se vê trocando seu SGBD por alguma tecnologia ou fornecedor completamente diferentes?
  • Seu projeto precisa lidar com diferentes tipos de persistência de acordo com o ambiente no qual é implantado?
  • Se você usa um ORM (como Hibernate, EclipseLink ou JPA) para todas estas classes de domínio, e todas são persistidas contra o mesmo repositório de dados, realmente preciso ter implementados N DAOs apenas para persistir o estado destas?
  • Se só há uma implementação do DAO, preciso realmente de uma interface?
  • As consultas expostas por seu DAO são usadas por mais de um componente do sistema?

Minha sugestão aqui é simples: os ORMs já nos oferecem um DAO genérico por padrão (pense no Entity Manager do JPA): tire proveito disto. É exatamente o que Grails faz e, como vejo há quase uma década, funciona muito bem! Nós não escrevemos DAOs em Grails: nossos serviços usam apenas as consultas que realmente precisam e, quando há uma consulta compartilhada, a expomos ao restante do sistema através de uma função.

Se você tem um serviço responsável por gerenciar a lógica de negócio que envolve uma ou mais classes de domínio, e também possuí um ORM que já lida bem com o processo de persistência, pra quê ficar criando DAOs que expõem consultas usadas por um único ponto do sistema para todo o resto?

Solução simples: escreva seu serviço com um conjunto de métodos públicos bem definido que exponha aos clientes do mesmo apenas o que deve ser visto (isto se chama encapsulamento). Se ele precisa interagir com o banco de dados, use este DAO genérico fornecido pelo ORM internamente em seu serviço e evite com isto criar uma série de componentes que apenas irão aumentar a quantidade de código que você precisará gerenciar no futuro.

Concluindo

Neste post expus apenas duas situações que vejo repetidas vezes em projetos Java e que podem facilmente ser evitadas. Entendo perfeitamente o que motiva a ocorrência destes erros: você quer fazer bem feito mas não refletiu a respeito das boas práticas que muito provavelmente lhe foram impostas e não apresentadas.

_ Ah… mas e se no futuro meu sistema precisar de…
_ Bom: se você sabe o que vai ocorrer, você não tem um “e se”, mas sim um “vai”, então aplique.
_ Mas o futuro é imprevisível, preciso me preparar para ele.
_ Bacana: que então você tenha uma base de código menos complexa pra poder se adaptar mais rápido a ele.

24 thoughts on “Java é simples: você que burocratiza seus projetos

  1. Certeiro. Isso ocorre porque design patterns foram hype alguns anos atrás. Estava todo mundo aplicando porque era a tendência, mas ninguém sabia dizer direito por quê.

    Responda

  2. Acho que as interfaces facilitam muito quando os objetos precisam ser usados como mocks em testes.
    Quando uso um ORM somente crio DAO’s se preciso fazer SQL queries direto. Assim consigo descrever no DAO que tipo de busca está sendo feita. Mas o DAO também não precisa de muita firula. Elr pode ser simples.

    Responda

    Kico (Henrique Lobo Weissmann) Reply:

    Oi Enio, no caso de testes unitários é mais interessante usar algo como Mockito (http://www.mockito.org).

    Vou ver se escrevo algo a respeito dele aqui. :)

    Responda

    esp Reply:

    Opa,
    eu uso muito o Mockito. :)

    Mas é bem mais fácil trabalhar com mocks baseados em interfaces que os que são baseados em implementações.

    A interface também deixa claro quais os métodos relevantes oferecidos pelo seu serviço.

    Responda

    Kico (Henrique Lobo Weissmann) Reply:

    Sim, mas no caso do teste, quando você está criando um mock, te interessa um ou outro método apenas pois normalmente seu teste é de caixa branca.

    Então acaba que o Mockito vai te atender até melhor pois vai estar explicitando no seu teste exatamente o comportamento que quer.

    Responda

  3. A própria especificacao J2EE deixa tudo mais complicado/overengineering do que tem que ser (embora esteja bem lentamente melhorando), mas felizmente frameworks como o dropwizard/play provam que java pode ser simples, cool e produtivo.

    Responda

    Kico (Henrique Lobo Weissmann) Reply:

    Oi Mariane, bem observado e me fez lembrar de um livro excelente: não sei se já leu (é bem antigo).

    Se chama “Java EE without EJBs” do Rod Johnson. Naquela época ele já dizia isto e com isto criou o Spring. http://www.amazon.com/Expert-One-One-Development-without/dp/0764558315

    Responda

    Mariane Machado Reply:

    Nao conhecia esse livro nao, vou dar uma olhada.

    Responda

  4. Como se cria mocks em testes unitários em sem interfaces?

    Responda

    Kico (Henrique Lobo Weissmann) Reply:

    Excelente pergunta: seguem duas soluções.

    1) Você pode simplesmente criar uma subclasse (solução problemática)

    2) Você pode usar Mockito (http://mockito.org) que funciona muito bem, é fácil de usar e não pesa quase nada na hora de escrever seus testes.

    Responda

    esp Reply:

    Opa, o mockito não suporta por padrão mocks de métodos finais por exemplo.

    Com o Mockito, é bem mais fácil trabalhar com interfaces.

    Responda

    Kico (Henrique Lobo Weissmann) Reply:

    Opa,

    pra testes sabe o que é ainda mais interessante que Mockito? Groovy. Tá aí inclusive uma boa ideia de post aqui pro blog hein? :)

    Como Groovy é dinâmico, você consegue fazer este tipo de coisa de uma forma muito mais simples sem precisar de interfaces, se preocupar com métodos finais, etc.

    Responda

    Cassio Dias Reply:

    Neste caso power mockito resolve.

    Responda

  5. Concordo com ambas as colocações, Henrique. Mas sendo crítico do Java como você sabe que sou, não vejo a verbosidade da linguagem nesse tipo de abordagem. Isso que você questionou acontece em muitas linguagens. C# não escapa disso também. Depende apenas de quem implementa. Creio que a crítica à verbosidade esteja em questões como a ausência de propriedades, as exceções checadas, a maneira de se trabalhar com listas, e outras pequenas questões que vem sendo resolvidas nas últimas versões da linguagem, mas que demoraram demais para aparecer e acabaram de certa forma levando à necessidade do uso excessivo de padrões.
    Coisas como os métodos de extensão no C#, por exemplo, permitiram que o trabalho com listas e ORMs se tornasse bastante simplificado. Infelizmente, quando as primeiras novidades que reduziam a verbosidade da linguagem começaram a surgir no C# 2 e 3, a maioria das vezes, se não sempre, inspirado em outras linguagens, o que vi na comunidade Java foi um sentimento de nariz torto, de ‘jamais vou aceitar ter essa invenção da Microsoft na minha linguagem’ e com isso a evolução do Java se atrasou tanto. Cheguei a ver pessoas argumentando que deveriam usar outra palavra reservada, que não fosse ‘var’ para inferência de tipos APENAS para não usar a mesma palavra usada pelo C#. Por falar nisso, inferência de tipos, por mais banal que possa parecer, tornou o C# 2000% menos verboso e ainda não vi isso no Java. Em suma, a verbosidade do Java ao meu ver está em pequenos grãos, que de um em um alimentam uma granja inteira.

    Responda

    Léo Reply:

    Interessante seu ponto, Rafael.
    Porém tenho um pensamento um tanto contrário tanto quanto seu ponto de comparação em, por exemplo, Java e C# e ao ponto do Henrique sobre a verbosidade.
    Concordo que a linguagem Java não tem uma evolução como a C#, porém acredito que não deveria ter mesmo, visto que o Java não tende a ser algo ‘cool’, mas sim ser ‘Enterprise’, tipo mudar o menos possível e tornar-se o mais ‘maduro’ possível (não que não mudar seja amadurecer, porém vejo que empresas grandes que usam Java falam muito sobre isso). Para o cool nós temos o Scala e o Groovy, por exemplo. Para quem quer se sentir melhor trabalhando com Java, temos o Spring, que já ajuda bastante, agora se quer ser feliz mesmo, Spring com Groovy ou Scala com akka… coisa linda :)

    Responda

    Rafael Romão Reply:

    Entendo seu ponto de vista, Léo, mas o objetivo das mudanças no C# não é ser cool, e nem é algo feito de modo descontrolado. O objetivo é justamente aumentar a produtividade mantendo a segurança e compatibilidade. C# é tão enterprise quanto Java nesse sentido, tanto que as mudanças vêm mas vêm a conta gotas. E de fato também vem no Java, mas, ao meu ver, de modo bem menos satisfatório. Generics em Java é medonho, outras mudanças parecem mais gambiarras que features. Infelizmente a concepção inicial do Java deixou a linguagem tão engessada que fica difícil alterar seus principais pontos fracos sem que fique no mínimo estranho. C# se beneficiou disso, pois usou o Java, e muitas outras linguagens, como rascunho. Por isso digo que Java teve seu papel histórico, mas se for visto como bala de prata, não vai sair boa coisa. Como com qualquer linguagem.

    Responda

    Léo Reply:

    Concordo Rafael, a grande sacada do C# é essa mesmo, e concordo também que o Java é engessado a ponto de possibilitar novas mudanças, e concordo mais ainda que Java não é bala de prata, só discordo sobre o fato de que C# ser Enterprise assim como o Java, justifico isso com o fato de que o Java sempre trabalhou com especificações e demora muito para descontinuar algumas tecnologias/abordagens, o C# até pouco tempo atrás poderia utilizar WebForms ou MVC, e só, agora com o OpenSource há outras opções, porém (me corrija se estiver errado) não trabalham baseados em especificação, e isso para o Enterprise é ruim (digo em relação a experiência de projetos ditos “Enterprise” que eu já trabalhei)

    Responda

    Rafael Reply:

    Minha resposta foi postado no comentário abaixo, por engano.

    Responda

  6. Em .NET só mesmo a CLR e o C# em si seguem especificações ECMA. O restante, ou vem da nave mãe, o que tem tanta força ou mais que as especificações, pois trata-se de uma implementação oficial, entregue e garantida pela Microsoft, ou vem da comunidade open source, caso do Nancy, por exemplo. Quanto ao ASP.NET Web Forms, a questão é justamente esta. Ele ainda é suportado e evolui, ainda que o ASP.NET MVC seja a opção mais recomendada na maioria dos casos. Resumindo, o ‘enterprise’ no mundo .NET é garantido pela Microsoft, não por uma especificação aberta, uma vez que normalmente há uma, e uma única, implementação oficial. Para quem não tem problema em estar preso às plataformas oficialmente suportadas pela Microsoft, C# é tão enterprise quanto Java.

    Responda

    Léo Reply:

    É, então, quem não vê problema em estar preso às plataformas oficialmente suportadas pela Microsoft? Pensando corporativamente, e algo que eu tenho visto a anos trabalhando na área: se é ‘Enterprise’ grande maioria prefere apostar na Stack da Oracle (e.g: Weblogic, Oracle, SOA Suite, Java e etc), hoje sei de algumas destas empresas começaram a adotar .Net em novas soluções, porém eu acho dificil mudarem… sendo que geralmente eles pagam pelo pacote completo da Oracle, né?
    Aproveitando, não conheço, mas a Microsoft hoje possui alguma ferramenta que seja semelhante ao SOA Suite da Oracle?
    Mas pegando o gancho sobre tecnologias Microsoft, eu pessoalmente não sou fan de C# pelo fato de que tenho gosto pelas linguagens da JVM (é só gosto), como Groovy, Scala e Clojure, porém algo que a Microsoft tem feito muito bem ultimamente e eu tenho achado Foda é o Azure.

    Responda

    Rafael Reply:

    Quem não vê problema em confiar no stack Microsoft? Os mesmos que a deram o império que ela tem hoje como clientes.
    Sobre SOA, há o BizTalk.
    Gosto bastante de Scala, e simpatizo com Groove. Mas não curto muito a JVM.
    Sobre Azure, gosto como IaaS, como PaaS já prefiro plataformas abertas, como o Cloud Foundry ou o ecossistema que vem se construindo em torno do Docker.

    Responda

    Léo Reply:

    Eu conheço vários que não confiam, quando falamos em ferramentas para desenvolvimento e infraestrutura de rede, porém são os mesmos que adotam Windows em todas estações de trabalho, porém isso para mim é Cultural, e a fama da Microsoft no mundo corporativo se iniciou por ai: Windows e Office.
    Eu gosto muito da JVM, qual o motivo de você não curtir? Acho legal pois além das linguagens que podemos utilizar há vários projetos legais, como o Reactor, o Netty, Akka, Play, Vertx e tantos outros.

    Responda

    Rafael Romão Reply:

    Pra quê você foi perguntar? rs. Não gosto do modo como as coisas evoluem em torno da JVM, não gosto de ter que desmarcar o ASK toolbar sempre que atualizo o plugin que também não gostaria de ter que instalar para acessar meu banco, não gosto do modo como as referências são gerenciadas, da obsessão por especificações e padrões, da multitude descontrolada de frameworks e implementações de frameworks que fazem no fim a mesma coisa e da ausência de uma implementação oficial confiável de tais especificações/frameworks. Não gosto dos muitos problemas que já tive, como usuário, de software Java, em especial com configuração e instalação. Enfim, não vale a pena discutirmos isso. Como você disse, gosto é gosto, além de ser influenciado por questões culturais. E isso ao meu ver é o principal fator. Eu comecei em Delphi, parti pro Java, me apaixonei, me desiludi, parti pro .NET, mas nunca me afastei muito do mundo Windows/Microsoft. Já quem já começou em ambientes Java e Linux, por exemplo, dificilmente aprovará uma solução Microsoft. O importante é sabermos identificar o valor de cada tecnologia e quando ela é ou não apropriada. Dificilmente será apenas o fato de ser Oracle ou Microsoft definirá isso. Hoje mesclo java e outras tecnologias não Microsoft nas soluções que arquiteto, não tenho problema nenhum nisso, desde que seja a alternativa que irá me atender melhor diante da situação.

    Responda

    Mariane Machado Reply:

    .Net não pegou mais pq ficou mto tempo sem funcionar no linux (acho que hj em dia funciona ne?)

    Responda

Leave a Reply

Your email address will not be published. Required fields are marked *