BISVO
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.
- Conter um construtor publico padrão - isto é, um construtor que não receba nenhum parâmetro.
- 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 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..
![]() |
|
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.