Boas práticas para implementar mapeadores em um aplicativo multicamadas

5

Quando você está trabalhando com um aplicativo multicamadas, muitas vezes você tem a tarefa de converter objetos em uma camada em objetos em outra camada. Isso poderia converter objetos de banco de dados em objetos de domínio, objetos de serviço em objetos de domínio, objeto de domínio em modelos de exibição, etc.

Eu já vi isso sendo feito de várias maneiras, incluindo:

  1. Conversão in-line
  2. Criando uma classe de tradutores com métodos auxiliares estáticos
  3. Usando métodos de extensão para simplificar a conversão
  4. Substituindo operadores de transmissão
  5. Criando classes de mapeamento sepear para cada tradução possível
  6. Utilizando soluções como o automapper

Qual seria a maneira "correta" de lidar com isso? O aplicativo com o qual eu trabalho atualmente utiliza classes de mapeamento separadas para cada tradução possível, e embora tenha benefícios de testabilidade, estamos usando a injeção de dependência e temos que passar todos esses mapeadores como dependências no construtor.

Alguém descobriu uma maneira melhor de fazer isso?

UPDATE

Estou usando a pilha .NET aqui (EF + Business Layer + MVC)

    
por Sebastian K 04.02.2013 / 04:07
fonte

3 respostas

1

Não tenho certeza sobre a melhor maneira de implementar o mapeamento objeto-objeto, mas você pode preferir confiar em uma biblioteca especialmente criada para resolver isso. Meu projeto também é baseado na pilha do .NET e o Automapper ( link ) funciona muito bem. Está disponível via NuGet.

    
por 06.02.2013 / 01:04
fonte
1

O AutoMapper é uma solução comum para isso, no entanto, prefiro codificar manualmente os mapeamentos. Eu normalmente tenho uma classe estática com métodos de extensão que mapeia para e de DTOs.

[DataContract]
class UserDto
{
 [DataMember]
 public string Name { get; set; }

 [DataMember]
 public DateTime BirthDay { get; set; }
}

class User
{
  public string Name { get; private set; }
  public DateTime BirthDay { get; private set; }
}

static class ContractMappings
{
   public static UserDto ToDto(this User user)
   {
     return new UserDto
     {
       Name = user.Name,
       BirthDay = user.BirthDay
     };
   }
}

Cada projeto nos limites do aplicativo terá uma classe ContractMappings que contém mapeamentos para todos os contratos associados a esse projeto. Se esta classe ficar muito grande, pode ser um sinal de que os limites do projeto são inválidos.

Mapeamentos codificados manualmente permitem um maior grau de flexibilidade, o que pode ser uma vantagem e uma desvantagem.

No caso de ViewModels, geralmente, o ViewModel aceita um objeto DTO ou domínio em seu construtor. Se o ViewModel é usado para criar um DTO ou atualizar um objeto de domínio, eu coloco o método de atualização diretamente no ViewModel para manter o maior grau de coesão.

    
por 08.02.2013 / 01:56
fonte
0

A resposta é a solução que melhor resolve seu domínio de problema. Abaixo está outra solução que você não mencionou.

Use o mesmo tipo para todos os modelos. A maioria dos objetos que você está usando para armazenar dados pode ser vista como um hashmap ou um dicionário. O nome da propriedade é a chave e o valor retornado é o valor. O Clojure é um excelente exemplo de uma linguagem que suporta essa linha de pensamento com o uso de palavras-chave. Palavras-chave são uma palavra ou fase que começam com dois pontos e podem ser usadas como um identificador descritivo. No Clojure, um mapa é uma função que pode pegar uma chave como argumento e retornar seu valor pareado.

(def my-data-model { :name "Joe" :age 25 })
(my-data-model :name) => "Joe"

Se o seu modelo de domínio se parece com isso:

(def domain-model { :id 1 :value "my data" })

Seu modelo de visualização pode ser a mesma coisa com o par: id / value id removido. Com essa abordagem, todos os seus "modelos" são do mesmo tipo e não há necessidade de tradução entre eles.

    
por 04.02.2013 / 05:27
fonte