A Impedância, o Mapeamento Objeto Relacional e Implementações – Parte I

Boa Noite Pessoal,

Após uma correria danada para fazer as provas 70-453 e 70-454 e fazer minha apresentação no SQL Server Day estou aos poucos retomando minhas atividades. Ainda quero voltar a postar nos fóruns de SQL Server do MSDN e Technet, mas uma coisa por vez, pois, esse fim de ano está muito corrido e ainda tem algumas pendências de SQL Server para resolver. Hoje falarei um pouco sobre modelagem de dados, especificamente sobre implementações relacionadas às aplicações que estão imersas no paradigma da orientação a objeto e os dados que estão armazenamentos em bancos de dados cujo o Engine continua sendo relacional.

A orientação a objeto provê diversos benefícios em relação a sua predecessora (a análise estruturada) tais como encapsulamento, polimorfismo, herança, etc. Essas características proporcionam soluções muito mais fáceis de manter e resilientes a alterações de negócio. A representação através da orientação a objeto traduz os objetos do mundo real da forma como eles realmente são em oposição a representação de funcionalidades como era na análise estruturada. Se por um lado as aplicações são beneficiadas por uma abordagem orientada a objeto, a persistência dos dados nos bancos relacionais demanda uma atenção muito maior, pois, a tradução entre esses dois mundos não é direta. Essa realidade divergente é conhecida como "Incompatibilidade de Impedância" (ou simplesmente Impedância), embora o termo "Mapeamento Objeto Relacional" seja o mais utilizado.

Os bancos de dados relacionais possuem algumas alternativas clássicas para lidar com a Impedância e prover o mapeamento objeto relacional. Alguns fabricantes oferecem recursos proprietários diferenciando-se uns dos outros, mas nessa primeira parte do artigo apresentarei apenas soluções mais triviais e independentes do SGBD em questão. Para exemplificar as alternativas existentes, apresentarei uma situação fictícia (embora se enquadre perfeitamente em muitas organizações) abordando um diagrama de classes simplificado e suas implementações em bancos de dados relacionais. O que prentendo destacar refere-se especificamente a situações que envolvam herança. Antes de propriamente apresentá-las, já adianto que na disciplina de modelagem de dados, raras as alternativas que podem ser tidas como "sempre corretas" uma vez que a elaboração de um modelo sempre terá uma dose de subjetividade do administrador de dados, vantagens e desvantagens bem como regras de negócio que diferem bastante em cada organização. A realidade a ser apresentada não é diferente.

Uma situação de negócio

A empresa FKW Soluções é uma empresa em ascensão e contínuo crescimento. Em virtude de seu mercado de atuação ser altamente dinâmico e volátil, a FKW conta com vários tipos de colaboradores em sua força de trabalho. Inicialmente havia na empresa apenas profissionais da casa (chamados de efetivos), mas com o tempo estagiários, terceirizados, consultores externos somaram-se ao capital humano da FKW. Um sistema de gestão de pessoas foi desenvolvido para auxiliar a administração desses profissionais. A lista de características desses tipos de colaboradores é listada na tabela abaixo:

Colaborador Características
Efetivo Matrícula, Nome, Gerência, Cargo, Número do PIS
Estagiário Matrícula, Nome, Gerência, Cargo, Curso, Faculdade, Previsão de Término
Terceirizado Matrícula, Nome, Gerência, Cargo, Empresa Contratante, Data da Contração
Consultor Externo Matrícula, Nome, Gerência, Cargo, Projeto, Especialidade

As descrições dos termos utilizados são relatadas a seguir:

  • Matrícula: A matrícula do colaborador na FKW 
  • Nome: O nome do colaborador
  • Gerência: A área da empresa onde o colaborador está alocado
  • Cargo: O cargo atualmente exercido pelo colaborador
  • Número do PIS: O número do profissional efetivo no Programa de Integração Social
  • Curso: O curso universitário que o estagiário atualmente está matriculado
  • Faculdade: A faculdade a qual o estagiário está matriculado
  • Previsão de Término: A previsão de término de curso do estagiário
  • Empresa Contratante: A empresa a qual o colaborador terceirizado se encontra
  • Data da Contratação: A data na qual o colaborador terceirizado foi contratado na empresa contratante
  • Projeto: O projeto no qual o consultor externo foi alocado
  • Especialidade: A área de especialidade do consultor

Uma descrição genérica de cada tipo de colaborador pode ser realizada logo abaixo:

  • Efetivos: são colaboradores que trabalham na empresa através de contrato de trabalho (CLT).
  • Estagiários: são colaboradores universitários que trabalham período parcial ou integral na empresa.
  • Terceirizados: são colaboradores que estão trabalhando na empresa através de um contrato de alocação de mão de obra por uma outra empresa (Outsourcing).
  • Consultor Externo: são colaboradores que estão na empresa por um período determinado e normalmente em um projeto específico.

Algumas descrições auxiliares são expostas para evitar confusões:

  • A características "cargo" para estagiários não será simplesmente estagiário. Um estagiário que faça o curso economia, pode por exemplo ter o cargo de estagiário em investimentos no mercado financeiro ou estagiário em orçamento empresarial
  • A data de contratação para terceirizados foi incluída para evitar que empresas terceiras que ganhem um contrato simplesmente incluam um profissional sem histórico nessa empresa

Em uma situação real diversas outras características seriam listadas, mas para manter a simplicidade e a didática desse exemplo, o artigo irá limitar-se às expostas até aqui. Do ponto de vista de modelagem de dados e objetos, outras entidades naturalmente apareceriam como "Cargo", "Gerência", "Faculdade", "Empresa Contratante", etc. Vou desconsiderá-las nesse exemplo.

Diagramas e Representações

Do ponto de vista de aplicação, a implementação OO é bem direta. Como os colaboradores compartilham características em comum, pode-se definir uma classe abstrata com essas características. Diz-se que a classe é abstrata porque todo colaborador tem que se necessariamente um efetivo, um estagiário, um terceirizado ou um colaborador externo já que todos os tipos de colaboradores na força de trabalho foram detalhados e não há a possibilidade de um colaborador que não se enquadre em nenhum desses tipos. Após a definição da classe abstrata (que nesse caso é uma superclasse), são derivadas as classes mais específicas (subclasses) na ordem 1:1 em relação aos tipos de colaborador. Considerando somente os atributos da classe, o diagrama para essa situação é representado pela figura abaixo:

Para aqueles que prefiram um modelo conceitual na notação do Peter Chen, a representação desconsiderando os atributos é exibida na figura abaixo:

A notação de Peter Chen mostra que no diagrama um colaborador especializa-se em efetivo, estagiário, tercerizado ou consultor externo. As letras T e D são extensões ao modelo e significam que a especialização é total, ou seja, todo colaborador tem que ser um dos quatro tipos e que a especialização é disjunta, ou seja, o colaborador só pode ser um e unicamente um dos quatro tipos especificados. Os atributos foram desconsiderados por razões óbvias já que essa notação acaba "poluindo" a visualização quando considerados os atributos.

Alternativas de mapeamento

Considerando que o repositório de persistência será um banco de dados relacional e que mapeia-se aqui em um nível lógico, ou seja, desconsiderando-se as implementações específicas e particularidades de um ou de outro SGBD, as alternativas para modelar os colaboradores resumem-se em apenas três.

  • Mapeamento de uma tabela por hierarquia ou herança
  • Mapeamento de uma tabela por classe concreta
  • Mapeamento de uma tabela por classe especificada

O mapeamento em uma uma única tabela

Nessa alternativa todos os atributos de todas as classes são diretamente mapeados para uma única tabela que normalmente recebe o nome da superclasse.

Em uma única tabela ficam concentrados todos os atributos de profissionais efetivos, estagiários, terceirizados e consultores externos.

A principal vantagem dessa implementação é a simplicidade. Quando um colaborador vier a mudar de cargo (um estagiário que venha a ser contratado), basta atualizar os novos atributos e se a regra de negócio exibir, remover os valores dos atributos do cargo anterior. Como os dados estão todos em uma única tabela, as tarefas de junção com outras tabelas é bem simples. A inserção, atualização e exclusão de dados também será focada em uma única tabela. Relatórios que façam menção a colaboradores (como uma lista de colaboradores por gerência) também são bem fáceis de serem elaborados embora haja a necessidade de tratamento de colunas nulas.

As principais desvantagens dessas implementação são as regras de validação nas operações de cadastro, a "explosão" de atributos e o espaço utilizado.

O atributo Faculdade, por exemplo, refere-se somente aos estagiários. De acordo com a implementação estabelecida, consultores externos não possuem esse atributo. Se não houver nenhum mecanismo de validação, a tabela permite que um consultor externo possua uma faculdade e isso pode levar a problemas de consistência. Se houver um registro com os atributos número do Pis, projeto e especialidade, não será possível estipular se o colaborador é um profissional efetivo ou um consultor externo. A presença de uma coluna "Tipo de Colaborador" pode contornar esse problema, mas ainda assim a inconsistência se mantém. Todo cadastro de novos colaboradores deverá ter regras específicas para evitar que atributos de subclasses diferentes sejam preenchidos. Se novos atributos como semestre ou número de créditos forem adicionados para os estagiários, todas as regras de inserção e atualização terão de ser revistas de forma a impedir que um efetivo tenha esses atributos preenchidos.

A presença de todos os atributos de todas as classes pode implicar em limitações de implementação. Alguns SGBDs tem limites na quantidade de colunas possíveis e ainda que esses limites dificilmente venham a ser transpostos, não é muito performático uma tabela com muitas colunas, pois, implica em

Como a especialização é disjunta, ou seja, um colaborador só pode ser de um único tipo, todos os demais atributos deverão ser nulos. Quando um estagiário é cadastrado, os atributos Número do PIS, Empresa Contratante, Data da Contratação, Projeto e Especialidade ficarão nulos. Situações similares ocorrem quando um terceirizado ou um efetivo são cadastrados. A presença de tantas colunas nulas incorre em overhead adicional e desperdiço de espaço principalmente para tipos de tamanho fixo.

O mapeamento de uma tabela por classe concreta

Essa alternativa cria uma tabela para cada subclasse envolvida. Cada uma das tabelas criadas recebe o nome da subclasse correspondente e os atributos da subclasse são diretamente mapeados para as colunas da respectiva tabela. Os atributos da superclasse são repetidos em cada uma dessas tabelas.

Os dados genéricos de colaboradores como matrícula, nome, gerência e cargo são repetidos para cada tabela e os dados específicos de cada subclasse estão em sua tabela respectiva. Como existem quatro tipos de colaborador é necessário quatro tabelas para realizar essa representação.

A administração de espaço é uma das principais vantagens dessa implementação. Embora a "duplicidade" das colunas entre as tabela dê uma idéia de desperdício de espaço, vale lembrar que o que está duplicado são as colunas e não os dados. A consulta de lista de empregados por gerência irá exigir a união de todas as tabelas, mas dispensa o tratamento de colunas nulas.

A codificação das instruções de inserção, alteração e exclusão também são bem simples, pois, todos os dados necessários estarão em uma única tabela facilitando a implementação e a manutenção.

O controle da integridade representa um dos principais desafios nesse tipo de implementação. Como as tabelas são distintas, como assegurar que uma mesma matrícula não irá representar um estagiário e um efetivo ? E no caso de um colaborador vir a efetuar um treinamento ? Se aparecer uma entidade "treinamento" qual das "matrículas" deveria se relacionar ? A da tabela efetivos, a da tabela estagiário ? Esse pode representar um certo entrave, uma vez que há certa dificuldade na representação da classe abstrata

O mapeamento de uma tabela por classe envolvida

Essa alternativa emprega a criação de uma tabela por classe envolvida independente da sua capacidade de ser instanciada, ou seja, classes abstratas e concretas serão mapeadas.

A vantagem mais evidente dessa implementação é a coerência com a orientação a objeto. Ela é a que melhor traduz o ambiente OO para o ambiente relacional. Como os atributos estão mapeados por classe o controle de redundância é garantido sem a necessidade de se armazenar atributos nulos o que é refletido em desempenho e economia de espaço.

A presença de tabelas adicionais incorre em desvantagens natas. O cadastro de cada colaborador envolverá operações em duas tabelas (a de colaboradores e a do tipo requerido) o que torna as operações de inserção, alteração e exclusão um pouco mais onerosas do ponto de vista de desempenho e manutenção. A divisão dos dados por várias tabelas provoca a necessidade de juntá-las através de JOINs o que também significa menos desempenho em relação ao uso de uma única tabela.

Conclusão

As três alternativas apresentadas podem efetuar o mapeamento objeto relacional (MOR) de uma herança. Existem prós e contras além de várias variações proprietárias de implementação. As alternativas foram expostas e analisadas sobre várias aspectos, mas de forma nenhuma o assunto se esgota aqui. Nos próximos artigos irei expor a realidade apresentada a evoluções de negócio que podem fazer com que uma ou outra escolha adequada mostre-se inadequada. Futuramente demonstrarei algumas implementações proprietárias que contornam várias das limitações levantadas.

Cabe ressaltar que nenhuma das três alternativas é adequada para todas as situações e que de forma nenhuma uma alternativa pode ser considerada sempre "correta" em relação às demais e que da mesma forma nenhuma delas pode ser tida necessariamente como "errada". A representação a ser transposta para o modelo pode ser melhor favorecida por uma determinada alternativa, mas de forma nenhuma é possível estipular uma melhor alternativa que se enquadre em todos os casos.

[ ]s,

Gustavo

5 Respostas para “A Impedância, o Mapeamento Objeto Relacional e Implementações – Parte I

  1. Gustavo parabéns para artigo!Realmente falta na net um artigo sobre modelagem do mesmo genero desse. Fico agora esperando a segunda parte juntamente com a demonstração da modelagem utilizando os recursos proprietários.

  2. Olá Daniel,De fato eu sentia muita falta de algo desse tipo na NET. Quando o OO começou a ganhar força eu vi um monte de artigos similares, mas muitos com uma certa superficialidade. Os bancos evoluíram e as opções de mapeamento também, porém os artigos não. Resolvi reunir uma série de conhecimentos de um e de outro e deu no que deu…A parte II já está pronta e está disponível no link http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!814.entry. A parte III está em andamento, não sei se chegarei à parte IV.Fico feliz com o feedback. Espero que as demais partes sejam igualmente proveitosas.Abs,

  3. Gustavo,"O controle da integridade representa um dos principais desafios nesse tipo de implementação. Como as tabelas são distintas, como assegurar que uma mesma matrícula não irá representar um estagiário e um efetivo ?"Esse mesmo problema de integridade mencionado na opção de tabela por classe concreta, pode acontecer no modelo tabela por classe envolvida. Pois Eu poderia inserir uma mesma matricula para o estagiário e o efetivo, ou estou enganado ?Essa consistência eu teria que fazer na regra de negócio ?Sérgio Resende

  4. Olá Sérgio,Se você utilizar uma tabela por classe concreta, a consistência das matrículas ficará por sua conta (possivelmente com triggers). Se utilizar a uma tabela por classe envolvida a matrícula será sempre uma só (a de colaborador no caso). A matrícula de colaborador fará os relacionamentos. É menos provavél que a presença da mesma matrícula nas tabelas de estagiário e efetivo lhe cause problemas, pois, possivelmente as consultas SQL irão filtrar pela coluna cargo da tabela colaborador (que será um estagiário ou um efetivo e não os dois simultaneamente). Ainda assim, se julgar necessário o controle adicional ficará por conta da aplicação ou de outra implementação (triggers possivelmente).[ ]s,

  5. Pingback: APS1 – Mapeamento objeto-relacional | QuatiNetwork

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s