BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Artigos Como a Expedia está se livrando dos transformadores de Java Beans

Como a Expedia está se livrando dos transformadores de Java Beans

Favoritos

Pontos Principais

  • Dedicar algumas horas de trabalho à Inovação pode encorajar os desenvolvedores a expressarem seu potencial, criando soluções que seriam úteis em suas atividades diárias
  • Criar código open source, produtos ou soluções que solucionam um problema comum podem ajudar outras pessoas
  • Paixão é o ingrediente chave para software de qualidade
  • O BULL fornece uma aceleração útil da fase de desenvolvimento reduzindo a possibilidade de introduzir erros
  • Em cenários do mundo real, o BULL não introduz nenhuma degradação de performance

Em uma arquitetura em camadas, na qual você está criando níveis de abstração encapsulando as mudanças para objetos de dados e propagando estes para outras camadas, o processo de mapeamento de objetos pode ser tornar obrigatório e incômodo.

O mapeamento de objetos de dados tem sido tradicionalmente feito pela codificação manual de transformadores que copiam os dados entre as entidades (ou Java Beans).

Essa tarefa pode exigir incontáveis horas e milhares de linhas de código mapeando de e para objetos de dados diferentes dependendo do número de ítens que é necessário transformar.

A quantidade de trabalho necessário é substancial, especialmente quando a quantidade de casos de testes é levada em consideração.

Esse tipo de código para essas conversões é muito chato de escrever e extremamente propenso a erros, então por que não fazê-lo automaticamente?

O problema

Por sorte, existem muitos frameworks de mapeamento disponíveis na web que podem fazer isso por nós, então estamos salvos!

Mas, o que acontece quando os seus Java Beans são imutáveis de acordo com as práticas de segurança comumente recomendadas? A consequência disso é que não existe nenhum framework disponível que seja capaz de transformar os seus objetos de uma maneira simples.

A solução

Uma biblioteca que pode transformar automaticamente todos os tipos de Java Beans, incluindo os Imutáveis, mutáveis e mistos pode nos poupar um monte de trabalho e o BULL faz isso.

Os benefícios

Para melhor ilustrar os benefícios de ter essa biblioteca, vamos observar um exemplo: imagine que você está trabalhando em uma aplicação multi-camadas, construída como a seguir:

O FooController contém uma API Rest que recupera o request como entrada e envia uma resposta depois de executar um conjunto de operações

Para obter uma resposta, o FooController precisa pegar os dados de request/response (mapeados por objetos de domínio similares a este) movendo através das três camadas, então precisamos implementar, para cada uma delas: um Transformer (mais seus testes), que copia e modifica, se necessário, os dados de um objeto para o outro na próxima camada.

Resumindo, para cada camada, vamos precisar de 20 classes dividas como a seguir:

  • 1 Classe de Serviço
  • 1 Teste da Classe de Serviço
  • 6 Objetos de Domínio
  • 6 Transformadores
  • 6 Testes de Transformadores

Multiplicando pelas 3 camadas nos dá um total de 60 classes.

Agora vamos analisar o mesmo cenário utilizando o BULL:

Agora a situação parece bem diferente: as classes de transformadores não são mais necessárias e o total de classes que precisamos para todas as 3 camadas foi reduzido para apenas 24, e no geral temos 60% menos código. Isso implica no seguinte:

  • Menos tempo de desenvolvimento (redução de custos direto);
  • Possibilidade de introdução de erros reduzida;
  • Código que é mais fácil de manter.

O que o BULL pode fazer

O BULL foi construído tentando fazer o seu uso o mais fácil possível, de fato, para transformar um objeto é necessário apenas uma linha de código:

ToBean toBean = new BeanUtils().transform(fromBean, ToBean.class);

hoje em dia, alguns dos recursos disponíveis são:

  • suporta cópia de beans imutáveis;
  • suporta cópia de beans mutáveis;
  • suporta cópia de beans híbridos (alguns campos privados, outros não);
  • suporta cópia de Java beans sem getters e setters;
  • suporta Validação através de annotations (Bean validation);
  • suporta cópia com tipos primitivos do Java;
  • suporta cópia com tipos Java Collection;
  • suporta cópia de atributos aninhados em mapas;
  • suporta cópia com Arrays contendo tipos primitivos e não primitivos;
  • suporta cópia com mapeamento de nomes das propriedades;
  • suporta cópia recursiva;
  • suporta transformação de campos através de funções lambda.

A lista completa de funcionalidades, sempre atualizada e incluindo exemplos, está disponível aqui.

Transformação na vida real

Nós sabemos que na vida real é raro precisarmos apenas copiar as informações entre dois Java Beans quase idênticos, geralmente o que ocorre é:

  • o objeto destino tem uma estrutura totalmente diferente do objeto origem;
  • precisamos efetuar alguma operação no valor de um atributo específico antes de copiá-lo;
  • os atributos do objeto destino precisam ser validados;
  • o objeto destino tem um atributo adicional além do objeto origem que precisa ser preenchido com alguma informação oriunda de uma origem diferente.

Como podemos resolver isso? Bem, BULL te dá a possibilidade de executar qualquer tipo de operação em um atributo específico!

Aproveitando-se de expressões lambda o desenvolvedor pode definir seu próprio método que será aplicado ao valor antes de copiá-lo.

Vamos explicar isso melhor com um exemplo:

Dada a seguinte classe origem:

public class FromFoo {
  private final String id;
  private final String val;
  private final List<FromSubFoo> nestedObjectList;
  
  // all args constructor   
  // getters
}

e a seguinte classe destino:

public class MixedToFoo {
  public String id;
 
  @NotNull
  private final Double val;
  
  // constructors
  // getters and setters
}

e assumindo que o campo val precisa ser multiplicado por um número aleatório no nosso transformador, temos 2 problemas:

  1. O campo val tem um tipo diferente do objeto origem, de fato um é String e outro é Double
  2. Precisamos instruir a biblioteca como nós podemos aplicar nossa função matemática

Bem, isso é bem simples, você precisa apenas definir sua própria Expressão Lambda que faz isso:

FieldTransformer<String, Double> valTransformer =
     new FieldTransformer<>("val",
                      n -> Double.valueOf(n) * Math.random());

A expressão será aplicada ao atributo com nome: “val” no objeto destino.

O último passo é passar essa função para a instância de BULL:

beanUtils.getTransformer()
      .withFieldTransformer(valTransformer)
      .transform(fromFoo, MixedToFoo.class);

No que diz respeito à “validação de atributos”, é até mais simples, pois você precisa apenas anotar o seu campo com uma validação existente em javax.validation.constraints (ou definir uma customizada) e pronto.

Como chegamos lá?

Como costumávamos implementar toneladas de Transformadores de Java Beans que, muito frequentemente, requerem mais tempo de implementação do que funcionalidades básicas nas quais estamos realmente trabalhando, decidimos começar implementando algo que pudesse acelerar nosso processo de desenvolvimento e que pudesse ser útil para todos aqueles que estivessem lidando com o mesmo problema.

Graças à cultura da companhia Hotels.com, tivemos meio-período por semana para investir em projetos de inovação. Aproveitar a oportunidade para implementar este e outros produtos, agora está mostrando seu benefício. Nesse caso em particular, reduzimos acentuadamente o tempo de desenvolvimento de diversas funcionalidades que nós trabalhamos.

Por que Open Sourcing

  1. O OSS (Software open source) também tem viabilidade a longo-prazo. É criado e suportado por uma comunidade global de empresas e desenvolvedores independentes, muitos deles vivem com valores open source como colaboração e voluntariado.
  2. O OSS é mantido por uma comunidade de desenvolvedores. As mesmas empresas que os utilizam estão constantemente revisando código OSS que eles mantêm, assim como milhares de desenvolvedores independentes trabalhando nos projetos em todo o mundo. O resultado é um grande processo de revisão de código que garante segurança e responsabilidade.
  3. O OSS tem valores fortes - e, na maioria das vezes, as empresas e desenvolvedores de OSS possuem valores semelhantes - eles são defensores de mais participação da comunidade, colaboração e voluntariado. Eles acreditam em trabalhar juntos para criar produtos gratuitos e de alta qualidade, acessíveis tanto para empresas como para organizações sem fins lucrativos. Esta crença enfatiza a missão das melhores empresas e desenvolvedores de software livre. Isso os motiva a criar novos recursos e contribuir com entregando esses recursos de volta para a comunidade. Como resultado direto, os projetos populares de OSS são frequentemente a tecnologia de ponta.

Links Úteis

Conclusões e principais argumentos

  1. Dedicando algumas horas do expediente na empresa à Inovação pode encorajar os desenvolvedores a expressarem seu potencial, criando soluções que devem ser úteis em suas atividades diárias. Essa biblioteca é um grande exemplo, pois foi implementada durante essas horas, e agora está permitindo que a Expedia economize tempo e dinheiro.
  2. Tornar o código open source, produtos ou soluções que solucionam um problema comum podem ajudar outras pessoas que com certeza irão apreciar e provavelmente se sentirão mais encorajadas a colaborar nas melhorias, fazendo o software cada vez melhor.
  3. Paixão é o ingrediente chave para software de qualidade, dado que na maioria dos casos isso vai tomar um bom tempo, mas no final pode compensar os esforços.
  4. O BULL fornece uma aceleração útil da fase de desenvolvimento (em cenários similares ao descrito acima) reduzindo a possibilidade de introduzir erros
  5. Em cenários do mundo real, o BULL não introduz nenhuma degradação de performance.

Sobre o Autor

Fabio Borriello é mestre em Ciências em Engenharia de Computação e possui Pós-Graduação em Tecnologias Web. Ele é um Engenheiro de Software J2EE talentoso e apaixonado, com experiência comprovada em análise e design orientados a objetos e possui uma excepcional visão de todas as facetas do Ciclo de Vida de desenvolvimento de software, da análise e design à implementação e manutenção. Cada vez que ele precisa enfrentar algo novo, representa para ele um desafio e uma boa ocasião para aprender algo novo.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT