C# - Usando uma Entity Base Class


Hoje veremos o conceito de Entity Base Class e sua utilização na linguagem C#.

A idéia de criar uma classe base para compartilhar recursos comuns entre várias entidades de domínio é um princípio do Domain Drive Design ou DDD, e, é uma boa ideia, pois permite reunir a lógica comum em um só lugar.

Se você não conhece este conceito deixe-me apresentá-lo com um exemplo bem simples.

Vamos criar uma aplicação Console do tipo .NET Core no VS 2019 Community chamada C_EBaseClass1.

Vamos focar no modelo de domínio onde temos definidas as seguintes classes:

Nota: Vou simplificar a definição das entidades pois o objetivo é mostrar o conceito da Entity Base Class

Abaixo temos a definição de cada uma dessas entidades do modelo de domínio:

public class Cliente
{
   public Guid Id { get; set; }
   public string Nome { get; set; }
   public string Endereco { get; set; }
}
 
public class Pedido
{
  public Guid Id { get; set; }
  public Guid ClienteId { get; set; }
  public DateTime Data { get; set; }
}
 
public class Item
{
   public Guid Id { get; set; }
   public Guid PedidoId { get; set; }
   public Guid ProdutoId { get; set; }
}
 
public class Produto
{
   public Guid Id { get; set; }
   public string Nome { get; set; }
   public decimal Preco { get; set; }
}
 
 
public class Categoria
{
    public Guid Id { get; set; }
    public string Descricao { get; set; }
}

Observe que todas as entidades possuem em comum a definição da propriedade Id que é usada para identificar a entidade de forma única. O tipo usado aqui pode variar mas vamos adotar para este exemplo o tipo Guid para todas as propriedades Id.

Aqui podemos criar uma Entity Base Class ou uma classe base de entidade onde vamos definir a propriedade Id que é comum a todas as entidades e a seguir faremos com que as entidades herdem dessa classe base.

Como não desejamos que a classe base possa ser instanciada a Entity Base Class deverá ser uma classe abstrata.

Vamos criar uma classe chamada EntityBase conforme o código a seguir:

    public abstract class EntityBase
    {
        protected EntityBase()
        {
            Id = Guid.NewGuid();
        }
        public Guid Id { get; protected set; }
    }

Na definição da nossa Entity Base Class - EntityBase -  temos que:

Com isso podemos simplificar o código das entidades fazendo-as herdar da classe EntityBase:

public class Cliente : EntityBase
{
   public string Nome { get; set; }
   public string Endereco { get; set; }
}
 
public class Pedido : EntityBase
{
  public Guid ClienteId { get; set; }
  public DateTime Data { get; set; }
}
 
public class Item : EntityBase
{
   public Guid PedidoId { get; set; }
   public Guid ProdutoId { get; set; }
}
 
public class Produto : EntityBase
{
   public string Nome { get; set; }
   public decimal Preco { get; set; }
}
 
public class Categoria : EntityBase
{
    public string Descricao { get; set; }
}

E apenas para mostrar que funciona vamos criar uma instância da classe Cliente e atribuir valores às propriedades Nome e Endereco:

   class Program
    {
        static void Main(string[] args)
        {
            Cliente cli = new Cliente();
            cli.Nome = "Pedro da Silva";
            cli.Endereco = "Rua projetada 100";
            Console.WriteLine($"{cli.Id} - {cli.Nome} - {cli.Endereco}");
            Console.ReadKey();
        }
    }

Note que ao criar a instância da classe o valor para Id será gerado no construtor da classe base.

Executando o projeto teremos o resultado:

É para isso que serve uma Entity Base Class e é assim que são utilizadas.

Você poderia pensar em usar uma interface como tipo de uma Entity Base Class. 

Nesta abordagem podemos criar uma interface IEntityBase assim:

   public interface IEntityBase
    {
        Guid Id { get; }
    }

Mas seria essa abordagem uma boa ideia ?

Não, usar interfaces não seria uma boa ideia e vejamos porque:

1- Interfaces não permitem reunir nenhuma lógica, temos que implementar essa lógica e isso leva a duplicação de código. No nosso exemplo teríamos que criar a propriedade Id em todas as entidades repetindo justamente o que queríamos otimizar;

2- Usar interface não expressa o relacionamento da propriedade entre as entidades do domínio, pois quando uma classe implementa uma interface faz uma promessa sobre algumas funcionalidades;

3- As entidades do domínio devem estar conectadas à entidade base por uma relação 'é um' o que uma interface não proporciona;

Por esses motivos a melhor escolha é usar uma classe abstrata e não uma interface.

E estamos conversados.

"Porque pela graça sois salvos, por meio da fé; e isto não vem de vós, é dom de Deus.
Não vem das obras, para que ninguém se glorie;"
Efésios 2:8,9

Referências:


José Carlos Macoratti