success

Costumo dizer que existe uma ação no processo de modelagem capaz de transformar totalmente a forma como o software vai lidar com o ciclo de vida de um objeto dentro da solução, procure alterar o assessor de público para privado em todas as propriedades de uma classe.

listagem 1

Depois da ação exibida na listagem 1, tudo será diferente porque os meios necessários para se contornar o assessor privado da entidade ajudam a conduzir o desenvolvedor para um caminho totalmente diferente, e isto ficará mais evidente logo a seguir. Agora temos um problema, existe uma entidade que não pode ter seu estado alterado de forma alguma, então o próximo passo é fazer com que seja possível atribuir valores para que o estado da entidade seja alterado e para isso inserimos um construtor a classe Pessoa.

Como pode ser observado na listagem dois, agora temos uma Entidade que possui um construtor padrão que permite a alteração do estado no momento que a entidade é criada. Nossa entidade continua sem nenhum comportamento nem validação, mas agora ela apresenta uma espécie de contrato, que obriga o cliente a informar um conjunto de dados para que uma instância seja criada. Vamos olhar agora para as propriedades da Entidade Pessoa, o construir da classe deixa claro que temos um grande problema pois a quantidade de informação necessária para se criar uma Pessoa é grande.

Ao todo temos 11 propriedades na Entidade pessoa e todas elas primitivas, ou seja, sem nenhum comportamento ou funcionalidade. Como vimos nas seções anteriores, podemos facilmente entender como Objeto de Valor a característica que só tem valor para o sistema enquanto propriedade, e armazenam valores que dão característica a uma entidade, ou seja, temos vários exemplos de Objetos de Valor na entidade Pessoa então vamos começar remodelando o CPF.

Não queremos armazenar um único CPF no banco de dados, e permitir aquel aquele CPF seja gerenciado ou recuperado sozinho, a informação só faz sentido quando acompanhada de outros dados, no caso, o CPF só faz sentido quando ele é parte de uma Entidade, pois sozinho o CPF não agrega conteúdo a nada. Vamos então criar uma classe que represente o CPF, e que valide o seu estado para não deixar que um valor inválido seja armazenado.

Como podemos observar na listagem 3, agora temos uma classe que valida se o valor informado está válido, e dispara uma exceção de negócio quando alguma regra é violada, neste caso estamos preocupados com a validade do cpf, e para cada um dos fluxos de exceção determinados nós disparamos um erro. Com a classe Cpf agora podemos também elaborar testes para determinar se o resultado é válido, isso é demonstrado na listagem a seguir.

Agora temos o CPF transformado em um Objeto de Valor dentro da entidade Pessoa, e podemos garantir que o estado da propriedade será válido e não resultará em inconsistências na aplicação. Outra propriedade que ganhamos ao deixar de utilizar o campo primitivo na Entidade, é que podemos adicionar mais comportamentos, por exemplo, podemos desejar imprimir o valor do CPF com máscara de formatação, ou sem a máscara, dependendo da apresentação desejada. Podemos facilmente adicionar estes métodos a classe CPF.

Da mesma forma, podemos escrever um teste para garantir que não ocorram erros na formatação de apresentação.

O que fizemos até agora foi criar um Objeto de Valor que representa a propriedade CPF, adicionamos comportamentos de apresentação do valor quando necessário, o estado jamais é alterado tornando o CPF imutável após criado, e todas as validações necessárias para garantir a integridade do estado são executadas dentro do construtor da classe, no momento da inicialização, e temos testes para garantir os comportamentos desejados.

Avaliando o papel da tecnologia na solução

yeah

O mesmo exercício feito com CPF é necessário para todas as demais propriedades, transformando-as em Objetos de Valor ricos. Vamos analisar novamente as propriedades da Entidade Pessoa.


Listagem 7 - Propriedades da entidade Pessoa

Três propriedades da entidade são referentes ao mesmo conceito, o de endereço, e as propriedades são Logradouro, EstadoLogradouro e CidadeLogradouro. Podemos criar uma classe Endereço que tenha como papel validar e agrupar os dados estritamente relacionados ao mesmo conceito. Telefones e Email são propriedades que referem-se ao contato da Entidade, podemos aplicar o mesmo raciocínio para modelar um Objeto de Valor para Contato e também para DadosComplementares, que são as propriedades RG, DataNascimento e NomeMae e podemos inserir também o Endereco e Contato aqui uma vez que também podem ser modelados como dados básicos de uma pessoa. Dessa forma nossa entidade Pessoa fica como apresentada a seguir:


Listagem 8

Como podemos observar na listagem 2, agora a entidade Pessoa passou de 11 atributos para apenas 4, as informações ainda estão todas presentes mas melhor organizadas. Agora uma dúvida que fica em aberto é: Por que não adicionamos as propriedades de Nome e CPF aos dados complementares, ou a qualquer outra estrutura? Entidades precisam muitas vezes ser recuperadas utilizando algum filtro, ao determinar as propriedades de uma Entidade devemos buscar deixar somente aquelas que possuem maior peso na hora de aplicar algum filtro para busca dos registros.

Apesar de todas as outras propriedades serem passíveis de uso como filtro na recuperação de dados, Cpf e Nome são os mais comuns, por este motivo vamos manter estas duas propriedades no primeiro nível da entidade para dar destaque, e manter o agrupamento restante para manter a coesão.

Devemos ter a capacidade de identificar valores que são iguais, e para isso existe a necessidade de sobrescrever o método Equals herdado de object. No C# assim como outras linguagens, o uso da propriedade Equals resulta em uma comparação total de todas as propriedades do objeto alvo com o objeto origem, e este é um comportamento que desperdiça recursos de hardware e não leva o negócio em consideração, por exemplo, podemos determinar que duas Pessoas são iguais meramente comparando o Cpf.

Ainda falta refatorar o aspecto mais importante de uma entidade, a sua identidade. O recomendável é que o primeiro passo no processo de criação de uma entidade é é modelagem de sua identidade, e principalmente escolher o mecanismo mais eficiente para a sua geração. Existem diversas técnicas que podem ser utilizadas como por exemplo o uso de um UUID (Universally unique identifier), Guid ou até mesmo a combinação que envolva alguma lógica relevante para o domínio, como guid-nomeDaEntidade.

Geralmente esta informação é utilizada pelo sistema, mas caso exista a necessidade de exibir ao usuário esta informação a criação de nomenclaturas que podem ser abreviadas e transformadas em um dado amigável pode ser interessante.

Vamos então criar uma classe chamada PessoaId que tem como função ser a chave primária da entidade Pessoa.


Listagem 9 - Criando o PessoaID

Em seguida podemos alterar nossa entidade para utilizar a identidade criada na listagem 3.


Listagem 10 - Adicionando identidade a Pessoa

A listagem 3 mostra que utilizamos como identidade um Guid que tem a capacidade de gerar valores únicos com possibilidade de duplicação absurdamente pequeno. Para encerrar nossa revisão da Entidade pessoa vamos refletir sobre como acontece a persistência da Entidade e dos Objetos de Valor contidos nela. A maior lição de todas é: Jamais deixe que a ferramenta restrinja a modelagem do negócio, ou seja, o Framework de ORM, linguagem, arquitetura de Servidor, nada disso pode limitar a solução de negócio do cliente.

Vamos abordar melhor como o Entity Framework pode ser utilizado nesta solução.
Como encarar o papel da tecnologia na solução

Como sei que várias dúvidas surgem quando tentamos combinar as idéias discutidas ao longo dos últimos 6 posts, e algumas ferramentas do nosso dia a dia, como ORM’s modernos como EntityFramework, Hibernate e afins, este é um pequeno adendo para discutirmos um pouco melhor o papel das diferentes ferramentas que podem ser utilizadas na nossa solução.

O que está ao alcance de nossas mãos é buscar constantemente por novas ferramentas a serem adicionadas na nossa caixa de utilidades, para quando necessário extrair o que há de melhor em cada tecnologia.

Dois dos maiores frameworks ORM em uso atualmente são o Hibernate (que possui uma versão para .net chamada nHibernate) e o Entity Framework. Os dois oferecem suporte para persistir o modelo que estamos propondo. Hoje iremos abordar o uso do Entity Framework para esta atividade.

Quando pensamos que entidades devem nascer e morrer dentro do domínio, a intenção é que nenhum agente externo consiga alterar propriedades de modo a tornar o estado inconsistente, e para isso a construção de entidades ricas é uma das ferramentas utilizadas dentre diversas outras que compõe domínios ricos que sejam modelados com DDD ou quaisquer outras técnicas de modelagem. Quando pensamos na persistência, não existe nada que obriga entidades a serem os modelos de persistência, assim como nada obriga que uma entidade seja utilizada como retorno para uma chamada proveniente de um cliente.

O que fazemos em geral é criar uma classe que vai abstrair os dados requisitados pelo cliente, é comum denominarmos estes objetos de DTO (Data Transfer Object). Se o uso de DTO’s já é comum para representação de dados para o cliente, por que não utilizar-se DTO’s para persistência, e definitivamente separar toda uma camada de integração/infraestrutura do objeto do domínio? Poderia-se criar por exemplo um PessoaDTO que pode ser utilizado para a persistência no banco, e este pode receber toda a carga de infraestrutura que os ORM’s exigem para fazer os mapeamentos com o banco.

A tradução de entidades para DTO’s pode acontecer utilizando algum framework de mapeamento de objetos como o AutoMapper para .net. DTO’s em geral representam alguma visualização, então uma aplicação poderá ter diversos DTO’s cada um representando uma necessidade de consumo de dados do cliente, assim como DTO’s que representam dados a serem persistidos.

Agora caso a entidade seja utilizada na persistência, deve-se manter em mente que não podemos infectar o domínio com dependências de bibliotecas de terceiros, devemos sempre manter o domínio íntegro. Assim, podemos utilizar a API fluent do entity framework para isolar a camada de persistência e configurar quaisquer mapeamentos necessários na infraestrutura.

O EF (Entity Framework) permite o mapeamento de tipos complexos para colunas específicas, a listagem 11 mostra como mapear a propriedade NomeMae do objeto de valor DadosComplementares a coluna DadosComplementares_NomeMae da tabela TB_PESSOA.


Listagem 11 - NomeMae como enriquecida

O mesmo deve ser feito para todas os demais objetos da classe Pessoa. Existem restrições com relação ao uso e ao comportamento, mas em geral para a maioria dos casos esta solução vai atender, não é o objetivo deste artigo abordar a fundo nenhuma tecnologia e podemos explorar mais opções em um artigo futuro caso necessário, mas lembre-se, saber extrair o melhor das ferramentas presentes no seu “cinto de utilidades” é importantíssimo para jamais limitar a solução do cliente. Com todas as propriedades mapeadas, podemos facilmente inserir uma pessoa no banco, com todas as validações necessárias em uma entidade rica.


Listagem 12 - Configurando repositório


Listagem 13 - Resultado banco

O código para o projeto utilizado pode ser encontrado no github, e estou sempre disponível para dúvidas no e-mail doug.ramalho@roadtoagility.net.

Sugestões e críticas são mega bem vindas!

Créditos
Success: Photo by rawpixel.com from Pexels
Yeah: Photo by Kaboompics .com from Pexels

Tags: | | | | | | | | | | | | | | |

Sobre o Autor

Douglas Ramalho
Douglas Ramalho

Pesquisador apaixonado por filmes, música e bits, muitos bits. Sou um profissional viciado em tecnologia, com 11 anos de experiência em TI e um caminho repleto de suor, sangue e bugs. Gosto não apenas de estudar, mas também de promover o conhecimento, dessa forma meu objetivo é compartilhar toda a minha experiência para que possamos evoluir juntos, e também ajudar outras pessoas neste processo, para que em um grande grupo de apaixonados possamos elevar o nível de excelência a um patamar ainda maior.

0 Comentários

Deixe um comentário

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

Solicitar exportação de dados

Utilize este formulário para solicitar uma cópia dos seus dados neste site.

Solicitar remoção de dados

Utilize este formulário para solicitar a remoção dos seus dados neste site.