Design Pattern

Asked

Viewed 633 times

12

Good use the following design pattern:

Projeto

Where the Interface will communicate only with the application and this will communicate with the Repository. Thus the interface will have no restrictions and no knowledge of how the communication occurs with the database. In my case I use the Entity Framework, but in this scheme I can easily be using other communication methods.

The Application has two classes for each Domain class:

public class CartasAplicacao
{
    private readonly IRepositorio<Cartas> repositorio;

    public CartasAplicacao(IRepositorio<Cartas> repo)
    {
        repositorio = repo;
    }

    public void Salvar(Cartas carta)
    {
        repositorio.Salvar(carta);
    }

    public void Excluir(Cartas carta)
    {
        repositorio.Excluir(carta);
    }

    public IEnumerable<Cartas> ListarTodos()
    {
        return repositorio.ListarTodos();
    }

    public Cartas ListarPorId(string id)
    {
        return repositorio.ListarPorId(id);
    }
}

And:

public class CartasAplicacaoConstrutor
{
    public static CartasAplicacao CartasAplicacaoEF()
    {
        return new CartasAplicacao(new CartasRepositorioEF());
    }
}

In Repositorioef I do the following:

 public DbSet<SBE_ST_BannerRotativo> BannerRotativo { get; set; }
        public DbSet<Cartas> Cartas{ get; set; }

        public Contexto()
            : base("BancoDados")
        {
            Database.SetInitializer<Contexto>(null);
        }

And:

 public class CartasRepositorioEF: IRepositorio<Cartas>
    {
        private readonly Contexto contexto;

        public CorpoDocenteRepositorioEF()
        {
            contexto = new Contexto();
        }
        public void Salvar(Cartas entidade)
        {
            if (entidade.Id > 0)
            {
                var cartaAlterar = contexto.Cartas.First(x => x.Id == entidade.Id);
                cartaAlterar.Descricao = entidade.Descricao;
                cartaAlterar.Imagem = entidade.Imagem;
                cartaAlterar.Nome = entidade.Nome;
            }
            else
            {
                contexto.CorpoDocente.Add(entidade);
            }
            contexto.SaveChanges();
        }

        public void Excluir(Cartas entidade)
        {
            var cartaAlterar = contexto.Cartas.First(x => x.Id == entidade.Id);
            contexto.Set<Cartas>().Remove(cartaAlterar );
            contexto.SaveChanges();
        }

        public IQueryable<Cartas> ListarTodos()
        {
            return contexto.Cartas;
        }

        public Cartas ListarPorId(int id)
        {
            return contexto.Cartas.FirstOrDefault(x => x.Id == id);
        }
    }

Then to use in the Interface:

var bdcarta = CartasAplicacaoConstrutor.CartasAplicacaoEF();
bdcarta.Salvar(carta);

My questions are about what the pros and cons about this design model are. If there are other patterns that are "better" than this.

  • 1

    I believe that the tags [software-engineering] or [software-architecture] are more suitable than [design-Pattern]

  • @gmsantos, edited, thank you!

1 answer

8


I find separation unnecessary for your case at some points.

The separation in Dlls between Domain, Repository and Application is unnecessary because you said yourself that the Interface will communicate with the application, and the application will communicate with the Repository. As it is done, virtually all classes of all Dlls used for inter-layer communication need to be public, which only leaves the project more complex and unnecessarily exposed (high coupling, low cohesion).

In this case, the three layers can perfectly be in the same DLL, separated only by namespace:

  • Application.Core.
    • Application
    • Dominio
    • Repositorioef

This ensures that only Dominio and Aplicacao will be exposed to their interfaces, ensuring low coupling and high cohesion, as recommended in Software Engineering.

The existence of a repository ensures that the application will be properly isolated from the database, enabling you to even remove the Entity Framework and use other access technology and persistence in databases. Even better that each repository implements the interface IRepositorio, ensuring orthogonality in implementations. It would still be interesting to use a generic repository pattern, avoiding having to implement repository to repository (which is not necessary and goes against the good practice of Don’t Repeat Yourself). Here are good examples of how to do this.


EDIT

At requests by comment, I’m putting the implementation of a generic repository:

public class AplicacaoGenerica<T>
    where T: class
{
    private readonly IRepositorio<T> repositorio;

    public AplicacaoGenerica(IRepositorio<T> repo)
    {
        repositorio = repo;
    }

    public void Salvar(T entidade)
    {
        repositorio.Salvar(T);
    }

    public void Excluir(T entidade)
    {
        repositorio.Excluir(T);
    }

    public IEnumerable<T> ListarTodos()
    {
        return repositorio.ListarTodos();
    }

    public T ListarPorId(string id)
    {
        return repositorio.ListarPorId(id);
    }
}

public class RepositorioGenericoEF<T>: IRepositorio<T>
    where TEntity: class
{
    private readonly Contexto contexto;

    public RepositorioGenericoEF()
    {
        contexto = new Contexto();
    }
    public void Salvar(T entidade)
    {
        if (entidade.Id > 0)
        {
            contexto.Entry(entidade).State = EntityState.Modified;
        }
        else
        {
            contexto.Set<T>.Add(entidade);
        }

        contexto.SaveChanges();
    }

    public void Excluir(T entidade)
    {
        contexto.Set<T>().Remove(entidade);
        contexto.SaveChanges();
    }

    public IEnumerable<T> ListarTodos()
    {
        return contexto.Set<T>.ToList();
    }

    public T ListarPorId(int id)
    {
        return contexto.Set<T>.FirstOrDefault(x => x.Id == id);
    }
}

Therefore:

public class CartasAplicacao: AplicacaoGenerica<Cartas>
{

}

public class CartasRepositorioEF: RepositorioGenericoEF<Cartas>
{

}

I took this example as inspiration: http://www.tugberkugurlu.com/archive/generic-repository-pattern-entity-framework-asp-net-mvc-and-unit-testing-triangle

  • Gypsy, I did not understand the final part, of implementing repository to repository. I asked the question as I do currently.

  • You have implemented entity-specific logic Carta. A generic system would not require a specific implementation. It would be necessary to reimplement only cases that are the exception. If you have 20 entities, you will have to write 20 repositories. The idea is to write only one repository for the 20 entities.

  • It’s still not very clear to me. I could give an example?

  • @Diegozanardo I set an example for you.

  • Gypsy, I can’t do it...

  • @Diegozanardo Open another question, please, with the code that is giving problem.

  • @Ciganomorrisonmendez If you are separating by namespace only, how do you ensure that the 'Ui.Web' project will not have direct access to the repository?

  • @Brenosarkis Not referencing him directly.

  • @Ciganomorrisonmendez But if he’s in the same DLL as "Domain" for example, there’s no way I can guarantee it. Agree? (not wanting to involve the discussion about your team understand and know the limitations of each layer and 'use them for good')

  • But, honestly, you need all this care for a small project?

  • @Ciganomorrisonmendez This is a very difficult question... I just wanted to understand better really, thank you!

Show 6 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.