BISVO

De BIS Wiki
Revisão de 17h42min de 12 de outubro de 2020 por Rodrigogml (discussão | contribs) (O Paradoxo do Equals)
(dif) ← Edição anterior | Revisão atual (dif) | Versão posterior → (dif)
Ir para navegação Ir para pesquisar

Todo a estrutura do BIS é baseada na manipulação dos objetos do tipo BISVO. Entender a base da estrutura do VO e seu funcionamento é o primeiro passo para desenvolver bem no BIS.

Introdução aos Objetos de Dados dos Patterns Java

Para entender o VO do BIS, vamos entender primeiro a definição dos objetos como definidos nas documentações dos patterns de desenvolvimento do Java:

  • Java Beans - O java Bean é uma classe simples utilizada apenas para carregar um conjunto de dados. Esta deve seguir as seguintes regras:
    • Conter um construtor publico padrão - isto é, um construtor que não receba nenhum parâmetro.
      O objetivo dessa regra é permitir que os frameworks possam instanciar o objeto facilmente, sem necessariamente conhece o objeto e saber que dados passar no construtor.
    • Seus atributos devem ser acessíveis através de métodos GET e SET. E preferencialmente ter seus atributos privados para evitar um acesso direto.
    • Sua classe deve ser serializável, isto é, implementar ou extender alguma classe que implemente a interface 'Serializable' do java.
      Isso permite que o objeto seja convertido em vários outros tipos de estrutura (como XML por exemplo) e salvos ou transmitidos para outros plataformas, frameworks, computadores, etc. e ser retornado em um objeto de forma fácil.
  • Value Object - O Value Object (VO) era um termo inicialmente utilizado para indicar um objeto capaz de guardar uma pequena quantidade de informação. Como o objeto/classe Integer ou String do Java. Além disso, um VO deveria ser imutável. Toda vez que seu dado precisasse ser alterado, o objeto deveria ser descartado e um novo construído, exatamente como as classes do Java citadas.
  • Data Transport Object - O Data Transfer Object (DTO) é o objeto capaz de carregar as informações através da rede, ou mesmo entre as camadas (sendo que as camadas podem estar em diferentes máquinas). Ou seja, o DTO é o objeto que carrega os VOs entre as camadas ou sistema distintos. Os DTO também são conhecidos só por TO (Transfer Objects).


A Mudança e o BIS

Com o tempo a utilização do termo VO passou a indicar objetos maiores capaz de guardar uma coleção de informações/atributos de um determinado objeto, bem como a serem transmitidos entre as camadas e rede. Ou seja, popularmente chama-se de VO os objetos acima chamados de DTO.

No BIS chamamos o objeto de VO e juntamos todas as funcionalidade em um objeto único! Assim, o VO do BIS é:

  • o objeto capaz de representar uma pessoa, uma venda, uma nota, um produto e assim por diante (como um VO ou Java Bean);
  • é utilizado e transferido desde a camada de persistência até a camada de apresentação (como o DTO);
  • tem as mesmas obrigações que o Java Bean (de construtor e acesso dos atributos por GET e SET, devendo estes métodos seguir a convenção de nomes definidos pela Sun);
  • devem obrigatoriamente estender a classe BISVO.

As vantagens de ter um único objeto, primeiro é não ter que implementar várias classes (um Bean, Um VO, um TO, etc) que representam a mesma coisa. Ganhamos no tempo de desenvolvimento, manutenção do objeto e de não ter que criar "conversores" que passam os dados de um objeto para outro.

As desvantagens é que passamos a ter limitações na criação dos objetos, como por exemplo, sendo o mesmo objeto usado em toda a aplicação, o objeto não pode simplesmente ganhar atributos por ser conveniente para a cada de apresentação ou para a camada de persistência. Em resumo, um BISVO deve conter apenas os atributos que realmente descrevem o objeto e nunca atributos convenientes ou temporários para exibição ou de processamento. (Nestes casos recomenda-se a criação de outro BEAN que encapsule o VO).


O Atributo Fixo ID

Uma das características do BISVO é já ter o atributo ID definido. O que faz com que todos os VO filhos ganhem o mesmo atributo ID.


Esse atributo ID funciona no sistema da mesma maneira que a Primary Key de um tabela de banco de dados. Na verdade, o ID é mesmo gerado pela camada de persistência e é utilizado para identificar o objeto no banco de dados. Na parte de Persistência esse tópico será melhor abordado.

Já no sistema, o ID do objeto tem algumas funcionalidade:

  • Para uma mesma classe de VO, o mesmo ID indica o mesmo objeto;
  • IDs diferentes indicam objetos diferentes;
  • ID nulo indica um objeto que nunca foi persistido.


O ID Nunca Pode ser Alterado
O ID de um objeto é criado pela camada de persistência, e depois será utilizado para identificar o objeto quando ele retornar para ser salvo. Trocar o ID fará com que a camada de persistência interprete como sendo outro objeto.

O ID é como o CPF de uma pessoa. Depois que foi registrado (no caso depois que foi persistido a primeira vez) ele nunca mais se altera até a morte (exclusão do objeto).


O Clone Recursivo

Os objetos do BIS implementam a interface 'Cloneable' do java.

Mas mais do que isso, ela fornece método para Clone Recursivo. O que isso faz? Enquanto o clone padrão do Java cria um novo objeto pai (o que se solicitou o clone) mas deixa todas as referências dos sub-objetos apontando para os mesmos objetos em memória do objeto original. O Clone Recursivo:

  • faz um clone completo do objeto criando completamente outras instâncias para todos os sub-objetos do VO.
  • duplica listas, hashs, arrays, e outros objetos de coleção, duplicando também seus conteúdos.
  • É capaz de detectar "loop", ou referências cíclicas entre os objetos e as recria mantendo as mesmas referências mas com objetos completamente novos. Os únicos objetos reaproveitados são os objetos imutáveis, como String, Integer, Long, BigDecimal, etc..


Limitação do Clone Recursivo
O método conhece alguns objetos de coleção mais utilizados no BIS, como ArrayList, LinkedList, HashMap, etc.. Caso seja utilizado algum tipo de objeto diferente dos comummente utilizados, o método precisa ser verificado e talvez ter o suporte à esses objetos acrescentado.

O Paradoxo do Equals

O BISVO e todos os seus descendentes devem manter a implementação do do equals inalterada para utilizar todos os serviços do BISFW. Muitos dos serviços que o BISFW oferece utiliza o a implementação do equals padrão (que verifica se é o mesmo objeto na memória) para garantir que não estamos em uma iteração infinita quando os VOs tem uma referência cíclica (como objetos da relação pai e filho).

O problema é que em algumas situações esse equals precisaria de uma implementação diferente. Um exemplo conhecido é a biblioteca utiliza na UI, o Vaadin.

Imagine o seguinte cenário:

  • temos uma tela de configuração de caixa e-mail padrão do sistema. Caixa pela qual o sistema enviará seus e-mails automáticos.
  • Agora imagine que ao abrir essa tela vamos exibir a lista de caixas disponíveis em uma tabela do Vaadin. E por óbvio, já vamos exibir selecionada a caixa atualmente configurada.

Os passos normais são, buscar no banco de dados a lista de caixas cadastradas e colocar na tabela. Em seguida buscar a configuração salva e chamar o comando tipo "setSelected(...)" na tabela que seja capaz de selecionar o objeto passado. O problema é que embora na lista tenha o objeto que desejamos selecionar o Vaadin vai procurar o objeto que mandamos selecionar ne lista de objetos existentes através do equals(). E nenhum será igual. Uma vez que o objeto na lista e o objeto da seleção foram buscados no banco de dados em momentos diferentes e são dois objetos distintos na memória, fazendo com que o equals retorne falso.

Por ser uma operação "dentro" do Vaadin, não temos como alterar o modo como ele compara o mesmo objeto. Para casos como esse a solução é encapsular o objeto dentro de outro e dentro deste implementamos o Equals da maneira como achamos conveniente. Como por exemplo comparando a classe e o ID dos objeto, uma vez que todos os objetos de mesma classe tem IDs únicos. Para essa solução conheça o GhostVO (GVO).

Para objetos não persistidos em banco de dados o equals precisa ser mais elaborado já que não teremos o ID definido.