Este artigo foi traduzido por máquina.

Cutting Edge

Objetos e a arte de modelagem dos dados

Dino Esposito

 

Dino EspositoMuitos dos aplicativos de hoje são criados ao redor de um modelo de dados único, normalmente são transferido para um armazenamento de dados por meio de uma ferramenta de mapeador de objeto relacional (ORM). Mas às vezes — por vários motivos diferentes — você pode precisar de mais flexibilidade, que requer vários modelos. Neste artigo, discutirei algumas estratégias que você pode usar para lidar com essas situações e desenvolver mais aplicativos em camadas e robustos.

Usar diferentes modelos claramente faz todo o aplicativo mais complexo, mas é uma espécie de complexidade necessária, positiva que faz com que todo o projeto mais gerenciáveis. Noções básicas sobre quando um modelo de dados simplesmente não couber todos os casos de uso é o desafio para o arquiteto.

Diferentes partes de um aplicativo de software podem ter seu próprio modelo de dados. A maneira na qual você representar dados em nível de interface do usuário é diferente da interface na qual você organizar os dados na camada intermediária, e ele pode ser até mesmo diferente de como os dados fisicamente são mantidos no armazenamento de alguns dados.

Mas, por muitos anos, os desenvolvedores utilizavam apenas um modelo de dados, independentemente da parte do aplicativo envolvido. Muitos de nós cresceram com bancos de dados relacionais e suas técnicas de modelagem relacionados. Era natural gastar muito esforço em elaborating um modelo baseado em regras de normalização e relações. Todos os dados armazenados em um banco de dados relacional, em seguida, foram extraído e movimentadas usando estruturas de memória, semelhantes a um banco de dados na memória. Conjunto de registros é o nome desse padrão de dados genéricos (consulte bit.ly/nQnyaf); o ADO.NET DataSet foi uma excelente implementação dela.

A abordagem baseada em tabela progressivamente foi empurrada para o canto pela complexidade crescente dos aplicativos. Ferramentas ORM surgiram por dois motivos pragmatic principais. Primeiro, trabalhar com objetos é mais fácil do que lidar com super-arrays genéricas de dados como, por exemplo, um conjunto de registros. O segundo motivo é a produtividade. O objetivo de um ORM está dando um modelo de objeto e mapeando-as para um esquema relacional. Usando um ORM, essencialmente feitas no modelo de objeto se parecer com o banco de dados real para os olhos do aplicativo.

Como você projeta esse modelo? E você deve realmente usar apenas um modelo para cada aplicativo? Vamos descobrir.

Um modelo sempre não serve para tudo

O recente lançamento do Entity Framework (EF) 4.1 incluído o suporte para programação "Código primeiro", que, como o nome implica, permite Microsoft.Os desenvolvedores do NET Framework adotar uma abordagem de código primeiro para modelagem de dados. Basicamente, isso significa que você começar escrevendo as classes de objeto de CLR antigo simples (POCO) que modelam o domínio do aplicativo. A segunda etapa consiste em mapear essas classes para algum armazenamento persistente e tendo a ferramenta ORM (o EF) cuidam dos detalhes de persistência. O ORM expõe uma linguagem de consulta (LINQ to Entities), semântica transacional (os objetos xxxContext o EF) e criar um básico, ler, atualizar e excluir planos de API que oferece suporte à simultaneidade, carregamento lento e busca (CRUD).

Portanto, você tem o modelo, e você sabe como mantê-los e como consultar as informações dele. Este é um modelo que você pode usar em qualquer lugar em seu aplicativo? Mais especificamente, este é um modelo que você efetivamente pode trazer para a camada de apresentação? Esse é um ponto fraco realmente onde teoria e prática diferem substancialmente, contexto é o rei e a incerteza (quando não é realmente confusão) reigns. Deixe-me a oferecer um exemplo concreto vinculado à página ASP popular.Tecnologia de NET MVC. A única razão que estou usando o ASP.NET MVC, em vez de, digamos, Silverlight, é que o ASP.NET MVC tem o modelo do word no nome do (a m no MVC) — e eu perguntado muitas vezes em classes e conferências sobre a localização exata do "modelo" em um aplicativo ASP.Aplicativo NET MVC.

Hoje, mesmo após três versões, muitos tutoriais sobre ASP.NET MVC insistir em usando apenas um modelo para consultas, atualizações e apresentação. Muitos tutoriais também mantêm a definição do modelo dentro do projeto principal. Ele funciona, então, onde do problema? O problema não está com a solução, que funciona, é eficaz e é algo que eu geralmente usou sozinho e pretende continuar usando. Na verdade, há um conjunto de mundo real, mas simples e vida relativamente curta aplicativos (não apenas as demonstrações e tutoriais), que podem ser desenvolvidos com padrões simples. O problema de usar apenas um modelo é com a mensagem, ela transmite para os principais clientes dos tutoriais: os desenvolvedores que desejam para aprender uma tecnologia. Ter apenas um modelo em um só lugar sugere é o preferencial (se não recomendado) maneira de fazer as coisas. Ele é, em vez disso, apenas um caso especial — um cenário muito simple e favorável. Se o cenário real, na verdade, você trabalhará na corresponde àquele, está mais finos. Caso contrário, você está preso e pronta para crescer sua primeira "big bola de lama" muito maior.

Uma arquitetura geral mais

Vamos começar usando nomes um pouco diferentes. Vamos chamar o modelo de dados que você manter o modelo de domínio e os dados da chamada você gerencia no modo de exibição do modelo de exibição. Devo mencionar que modelo de domínio não é exatamente um termo neutro em software, como ela se refere a um modelo de objeto projetado de acordo com um número de regras adicionais. No escopo deste artigo, não estou usando o significado que resulta da metodologia me orgulhando até hoje DDD (Design). Para mim, aqui, o modelo de domínio é simplesmente o modelo de objeto que você persistir —modelo de entidades pode ser outro equivalente — e menos confusa — termo.

Você usar as classes no modelo de entidades no back-end do aplicativo; Você pode usar as classes no modelo de exibição na camada de apresentação. Observe, contudo, que no ASP.NET MVC, a camada de apresentação é o controlador. O controlador deve receber dados prontos para a interface do usuário. Os componentes de camada intermediária recebem e retornam os objetos do modelo de exibição e internamente usam objetos de entidade. Figura 1 mostra a web de dependências em um projeto típico de várias camado.

Connections Among Layers
Figura 1 conexões entre camadas

A apresentação (isto é, a classe code-behind ou controlador) faz referência a lógica do aplicativo, ou seja, um componente que implementa casos de uso do aplicativo. A lógica do aplicativo tecnicamente pertence à camada de negócios ou nível e casos muito simples pode ser mesclada com a apresentação. Este é o que acontece em alguns tutoriais que são muito simples de realmente sente a necessidade de isolar a lógica do aplicativo em sua própria camada ou mal projetado e divisão lógica de aplicativo entre a apresentação e a camada de acesso de dados (DAL).

O conjunto de lógica de aplicativo implementa o padrão de camada de serviço e separa duas camadas de interface: apresentação e dados. A lógica do aplicativo faz referência o modelo de entidade (as classes de domínio) e a DAL. A lógica do aplicativo coordena a DAL, classes de domínio e serviços para buscar o comportamento esperado. A lógica do aplicativo se comunica com a camada de apresentação por meio de objetos do modelo de exibição e se comunica com a DAL através de objetos de domínio. A DAL, por sua vez, referencia o modelo e o assembly ORM.

Algumas palavras sobre o Entity Framework

Vamos examinar essa arquitetura, supondo que o EF como o ORM. O EF não é simplesmente um ORM, mas como seu nome sugere, faz o trabalho típico de um ORM, além de oferecer uma estrutura para criar um modelo. Boa idéia, mas ele não deve ser esquecido que podemos estiver espalhados pela duas camadas distintas — a DAL e negócios. As classes são os negócios; o mecanismo de persistência é a DAL. Para o EF, o mecanismo de persistência (o assembly ORM) é system.data.entity e suas dependências, incluindo a classe ObjectContext. Em outras palavras, a menos que você use classes POCO e código primeiro, você irá provavelmente acabará com um modelo de domínio que tem uma dependência de ORM. Um modelo de domínio deve usar POCO — ou seja, entre outras coisas, ele deve ser um assembly independente. Um thread interessante sobre este tópico existe no estouro de pilha em bit.ly/mUs6cv. Para obter mais detalhes sobre como dividir as entidades do contexto em que o EF, consulte o ADO.Entradas de blog da equipe líquido, "Explicação passo a passo: POCO modelo para a Entity Framework" (bit.ly/bDcUoN) e "EF 4.1 modelo & O banco de dados primeira passo a passo"(bit.ly/hufcWN).

Partir dessa análise, parece que o atributo POCO é essencial para as classes de domínio. POCO, claro indica uma classe com nenhuma dependência fora de seu próprio assembly. POCO é sobre a simplicidade e nunca é errado. Não vai os meios de maneira POCO tendo formulários de acoplamento forte entre camadas. Acoplamento forte não é poisonous e não matar você instantaneamente, mas pode levar seu projeto para uma morte lenta. Confira a minha coluna sobre desastres de software da edição do mês passado (msdn.microsoft.com/magazine/hh394145).

Qual é o modelo?

Quando você cria um modelo de objeto, você pode criar uma biblioteca de classes. Você pode organizar seu modelo de objeto de acordo com a um número de padrões, mas basicamente tudo se resume ao escolher entre uma abordagem orientada a tabela e uma abordagem orientada a objeto.

Como você planejar suas classes? Que recursos eles apresentam? Em particular, suas classes devem estar cientes do banco de dados? Eles devem incluir lógica (ou seja, métodos) ou ser limitado a apenas expor propriedades? Há dois principais padrões, você pode consultar: registro ativo e o modelo de domínio.

No padrão de registro ativo, as classes são modeladas rigorosamente tabelas de banco de dados. Na maioria das vezes, você tem uma classe por tabela e uma propriedade por coluna. Mais importante, as classes são responsáveis por sua própria persistência e sua própria lógica simples, um mínimo de domínio.

De acordo com para o padrão do modelo de domínio, suas classes são destinadas a fornecer uma visão conceitual do domínio do problema. Essas classes não têm nenhum relacionamento com o banco de dados e os métodos e propriedades. Por fim, essas classes não são responsáveis por sua própria persistência. Se você optar por uma abordagem de modelo de domínio, persistência tem que ser delegada a uma camada distinta — a DAL. Você pode escrever essa camada, mas ele não seria tão divertida. Uma DAL well-done para uma biblioteca projetada de acordo com o padrão do modelo de domínio é quase a mesma como uma ferramenta ORM. Então por que não usar uma das ferramentas de ORM existentes?

Especialmente se você usar o gerador de código automática, o EF apresenta que um modelo de objeto constituído de classes que possuem somente as propriedades. O padrão usado certamente não registro ativo, mas classes não ter nenhum método por padrão. Felizmente, classes são marcados como parciais, que torna possível a forma até um muito mais rico modelo de domínio adicionando lógica por meio de classes parciais. Se você escolher a abordagem de código primeiro, em seguida, está inteiramente responsável por escrever o código-fonte das classes do início ao fim.

Classes em um modelo de objeto que costumam ser apenas propriedades de recurso conhecido como um modelo de domínio anêmica.

Repositórios

Uma boa prática que está ganhando popularidade bem-merecida é quebra automática de código de acesso a dados em classes de fachada conhecidos como repositórios. Um repositório consiste em uma interface e uma classe de implementação. Você geralmente possui um repositório para cada significativas classe no modelo. Uma classe significativa em um modelo de objeto é uma classe que controla sua própria persistência e significa em seus próprio no domínio sem dependendo de outras classes. Em geral, por exemplo, cliente é uma classe significativa, enquanto OrderDetails não, é porque você sempre usará os detalhes do pedido se você tiver um pedido. No DDD, uma classe significativa é considerada ser uma raiz agregada.

Para aprimorar o design, você pode estabelecer uma dependência entre a lógica do aplicativo e a DAL através das interfaces do repositório. Repositórios reais, em seguida, podem ser injetados na lógica do aplicativo conforme apropriado. Figura 2 mostra a arquitetura resultante onde a DAL baseia-se em repositórios.

Using Repositories in the DAL
Figura 2 usando a DAL repositórios

Repositórios permitem injeção de dependência na DAL porque você pode desconectar o módulo atual que fornece lógica de persistência e substituí-lo com seu próprio facilmente. Isso é certamente vantajoso para a capacidade de teste, mas ele não está limitado à. Uma arquitetura baseada em repositórios permite que a simulação da DAL e testar a lógica do aplicativo no isolamento.

Repositórios também representam um ponto de extensibilidade excelente para seus aplicativos. Ao substituir o repositório, você pode substituir o mecanismo de persistência de forma transparente para o restante das camadas. O ponto aqui não é, de forma muito sobre a alternância de, digamos, Oracle para SQL Server, porque esse nível de flexibilidade já é fornecido pelas ferramentas ORM. O ponto aqui é ser capaz de alternar entre a implementação atual da DAL para algo diferente, como uma nuvem API, Dynamics CRM, uma solução NoSQL e assim por diante.

Quais repositórios não devem ser

Um repositório é parte da DAL; como tal, ele não deveria para saber sobre a lógica do aplicativo. Isso pode ser uma instrução muito óbvia, mas um tipo de diagrama de arquitetura que vejo com muita freqüência hoje em dia é baseado na apresentação e repositórios.

Se sua lógica real é fina e simples — ou é essencialmente CRUD — então este diagrama é mais do que OK. Mas e se não for o caso? Nesse caso, você precisa, sem dúvida, um lugar no meio onde você implantar a lógica do aplicativo. E, acredite, que já vi apenas alguns aplicativos que estão apenas CRUD em minha carreira. Mas provavelmente apenas não sou um homem sorte …

Esclarecendo disfarce

Resumindo, hoje em dia aplicativos tendem a ser criado em torno de um modelo de dados que uma ferramenta ORM, em seguida, persiste ao armazenamento de alguns dados. Isso é bom para o back-end do aplicativo, mas não se surpreenda muito se a interface do usuário requer que você lide com agregações significativamente diferentes de dados que não existem apenas no modelo original. Esses novos tipos de dados que existem para o único propósito da interface do usuário devem ser criados. E eles acabam formando um modelo de objeto totalmente paralela: o modelo de exibição. Se você reduzir esses dois modelos para apenas uma, em seguida, tudo isso de maneira stick para que e ser feliz. Caso contrário, espero que este artigo Esclarecida alguns pontos obscuros.

Dino Esposito é autor de "Programming Microsoft ASP.NET MVC3 "(Microsoft Press, 2011) e co-autor do"Microsoft.NET: Arquitetando aplicativos corporativos "(Microsoft Press, 2008). Residente na Itália, Esposito é um palestrante sempre presente em eventos do setor no mundo inteiro. Você poderá segui-lo Twitter no twitter.com/despos.

Graças aos seguintes especialistas técnicos para revisão deste artigo:Andrea Saltarello eDiego Vega