Introdução

Uma das grandes vantagens do desenvolvimento Orientado a Objetos é a possibilidade de representar o domínio que está sendo modelado de maneira mais próxima do mundo real. No entanto, esta prática não é utilizada com tanta frequência quanto esperado, a maioria dos sistemas construídos em linguagens OO como Java ou C# ainda é composto de estrutura de dados e funções como coisas separadas.

Origens

Com o advento da programação estruturada passou-se a separar um programa em partes menores, módulos, e estas partes em outras ainda menores, funções ou procedimentos. As funções e procedimentos continham a lógica de negócio necessária para manipular as estruturas de dados, que são um agrupamento de dados logicamente relacionados (leia mais sobre este paradigma em Fantoches).

Com a chegada das tecnologias Orientadas a Objetos, os desenvolvedores tiveram que aprender um novo paradigma. No ritmo que as coisas funcionam em tecnologia não é surpresa que muitos destes aprendiam sobre classes e objetos enquanto desenvolviam os próprios sistemas.

Infelizmente esta pressa toda fez com que as linguagens OO funcionassem apenas como uma nova ferramenta para se fazer a mesma coisa. Quem programava em Pascal continuou programando em Pascal, só que utilizando Delphi. Quem programava em C continua escrevendo C, só que desta vez em Java. Existe um velho ditado em Ciência da Computação que diz: “Você pode escrever FORTRAN utilizando qualquer linguagem”.

Quando Tudo Já Está¡ Ruim…

No mundo Java EE esta situação foi piorada ao extremo pelos próprios fabricantes e evangelistas. Antes de Java EE se tornar toda uma plataforma de desenvolvimento foi criado o conceito de Enterprise Java Beans, componentes distribuídos que talvez tenham no curriculum o maior número de enganos históricos da indústria.

EJBs foram criados como uma plataforma de componentes distribuí­dos que levasse Java a concorrer com big players da Área como C++ e Ada. Acontece que muitos não entenderam o recado e EJBs foram tratados como a maneira de fazer aplicações corporativas em Java.

Um dos grandes problemas nesta abordagem é a maneira com que EJBs se dividem. Existem basicamente três tipos de EJBs: Session Bean, Entity Beans e Message-Driven Beans. Os dois primeiros são os relevantes nesta discussão, podemos ignorar o último. Entity Beans representam os dados em uma base de dados (quase sempre relacional). A tecnologia de mapeamento entre objetos e tabelas (Mapeamento Objeto-Relacional) do framework EJB até a versão 2.1 era precá¡ria e basicamente você teria um Entity Bean por tabela no banco de dados. Os Session Beans são os responsáveis por manipular os dados, sejam representados por Entity Beans ou não.

Para enfrentar as dezenas de problemas com esta arquitetura, a Sun lançou um catálogo de padrões chamados de Core J2EE Patterns. A maior parte deste catálogo se destina a lidar com problemas que EJBs causam, mas o nome “core” ajudou a difundir o mito de que Java EE era sinônimo de EJBs.

Eventualmente a comunidade de desenvolvedores percebeu que EJBs não é a solução para qualquer problema – na verdade é uma possível solução para uns poucos problemas e passou a desenvolver em um modelo mais simples, quase sempre utilizando apenas Servlets ou algum framework. O problema é que o modelo de programação criado para os EJBs, incluindo os padrões do catálogo da Sun, ainda são utilizados.

Transfer Objects/Value Objects

Um dos padrões deste catálogo era chamado de Value Object, ou VO. Posteriormente este objeto foi renomeado para Transfer Object por haver um conflito de nomes dele e outro padrão (interessante notar que a documentação oficial ainda faz uso do nome antigo nos diagramas) e porque trata-se de uma adaptação do padrão Data Transfer Object.

Um TO seria um objeto cujo objetivo é transportar dados entre um EJB e seu cliente, estando cada um em uma JVM diferente. Imagine que temos o cenário abaixo onde uma aplicação cliente recebe um objeto remoto do EJB:
Image:VOBOCenario.png


Toda vez que cliente chamar um método no objeto vindo do EJB é necessário fazer uma conexão na rede para pegar os dados deste do outro servidor:
Image:VOBOCenario-1.png
Estas conexões consomem recursos como Sockets, além de diminuir o desempenho da aplicação e aumentar o tráfego na rede. Para evitar este problema o EJB pode transferir todos os dados que o cliente vai precisar de uma só vez, em um só objeto. Este objeto é o Transfer Object:
Image:VOBOCenario-2.png
Como chamadas dentro de uma mesma JVM (que são o cenário mais comum) não possuem este custo agregado, não há porque utilizar TOs dentro de uma aplicação que não utilize chamadas remotas.

VOs e BOs: Modelo de Objetos Anémico

Num modelo orientado a objetos temos representações dos conceitos que estamos modelando na forma de classes, como mostrado abaixo.
Image:VOBODominio.png

Ao utilizar o modelo de programação inspirado em EJBs, devemos dividir nosso domínio em “classes de dados” e “classes de lógica”. As classes de dados recebem um nome terminando em VO (o correto seria utilizar o sufixo TO, mas vamos nos ater ao modo como é utilizado comumente), as classes de lógica em BO. O diagrama abaixo mostra este modelo.

Image:VOBOAnemico.png

Este é o modelo que Martin Fowler batizou com o padrão Anemic Domain Model (Modelo de Domínio Anêmico). Num modelo anêmico existem objetos que parecem modelar a realidade, como os VOs do modelo acima, mas na verdade não utilizam a característica básica de objetos que é manter dados e comportamento num mesmo componente: o tão falado objeto!

Problemas da Anemia

Um dos problemas principais deste modelo é, como Fowler aponta, que você paga o preço de ter um modelo rico (por exemplo é mais difícil mapear esta estrutura para um banco de dados) sem ter as vantagens deste. Um modelo rico traduz o mundo real para software da maneira mais próxima possí­vel, ao utilizar classes de dados separadas das classes de lógica esta vantagem é simplesmente jogada fora. No mundo real não existe lógica de um lado e dados de outro, ambos combinados forma um conceito.

Também a manutenção de um sistema construído desta maneira é problemática. O módulo (o BO) possui acoplamento muito alto com a estrutura de dados (o VO) e a mudança em um afeta o outro drasticamente. As setas no diagrama acima mostram como a dependência entre os módulos (já que não são objetos de verdade) aumenta drasticamente.

A coesão das classes de lógica (BOs) tende a ser baixa visto que agregam diversas funções relativas não só à  sua própria estrutura de dados como muitas vezes de outras. Bom notar que mesmo em Projeto Estruturado de Sistemas esta é uma divisão pobre de módulos.

Aumentando este problema, dificilmente um VO vai ser utilizado apenas por um BO (e se o for temos um problema grande de reusabilidade) e os demais BOs vão igualmente ter conhecimento sobre a estrutura de dados (VO), já que não existe um encapsulamento real do objeto. Assim, quando um destes VOs tiver sua implementação alterada temos que verificar os possíveis impactos em diversos BOs espalhados pelo sistema.

A falta de encapsulamento também faz com que os VOs possam estar em estado inválido. Todo Usuario no exemplo dos diagramas deve ter um login e uma senha, além de estar autenticado. O que acontece se um BO altera o login do usuário para null no meio da execução do programa? Não há proteção quanto a isso. Caso o Usuario fosse um objeto de verdade ele poderia se prevenir e não entrar em estado inválido.

Conclusão

Apenas deixar de utilizar EJBs não fez com que o uso de Orientação a Objetos se espalhasse na comunidade de desenvolvedores Java EE. A própria especificação EJB evolui e em sua versão 3.0 traz recursos para que sejam criados modelos ricos. Ainda assim a grande maioria das aplicações é construída de maneira procedural por pura ignorância ou indução da documentação existente.

Desenvolver sistemas envolve, antes de mais nada, conhecer a tecnologia utilizada. Não se pode tirar proveito de Orientação a Objetos se não se distingue o que é OO e o que é procedural.

Referências

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Preencha esse campo
Preencha esse campo
Digite um endereço de e-mail válido.
Você precisa concordar com os termos para prosseguir

Menu