سؤال

I'm working with visual studio. The solution contains the 4 following projetcs :

DAL

Works with Entity framework + Repository pattern. It contains the DB classes + Repositorys.

BLL

It contains the DTO classes + Services. Services map the DTO classes with the DB classes. It references the DAL project.

IMessageRepository messageRepo;

public MessageService()
{
    this.messageRepo = new MessageRepository();
    AutoMapper.Mapper.Initialize(cfg => cfg.AddProfile<AutoMapperProfile>());
}

public MessageService(IMessageRepository repo)
{
    this.messageRepo = repo;
    AutoMapper.Mapper.Initialize(cfg => cfg.AddProfile<AutoMapperProfile>());
}

public List<DTO.Message> GetAll()
{
    List<DTO.Message> messages = ((System.Linq.IQueryable<DAL.Message>)messageRepo.GetAll()).ProjectTo<DTO.Message>().ToList();
    return messages;
}

Presentation

It references the BLL project and EntityFramework.SqlServer.dll.

MessageService ms = new MessageService();
List<Message> messages = ms.GetAll();

Bonus : Unit tests

It references the BLL project and the DAL project (It mocks the repositorys)

[TestClass]
public class MessageServiceTest
{
    Mock<IMessageRepository> messageRepo;
    MessageService messageService;

    [TestInitialize]
    public void SetUp()
    {
        // Create a new mock of the repository
        messageRepo = new Mock<IMessageRepository>();

        // Set up the mock for the repository
        messageRepo.Setup(x => x.GetAll()).Returns((new List<DAL.Message>
        {
            new DAL.Message { Id = 1, Content = "Hello world!", Date = DateTime.Now },
            new DAL.Message { Id = 2, Content = "I <3 U!", Date = DateTime.Now }
        }).AsQueryable());

        // Create the service and inject the repository into the service
        messageService = new MessageService(messageRepo.Object);
    }

    [TestMethod]
    public void TestGetAll()
    {
        // Act
        var messages = messageService.GetAll();

        // Assert
        Assert.AreEqual(2, messages.Count, "The messages count is not correct");
    }
}

I'm new to software architecturing. What are your thoughts on this architecture? Any improvements?

هل كانت مفيدة؟

المحلول

Your Service class is redundant. The Repository should return the 'real' object, not the EF object.

Do all your retrieval and mapping inside your Repository.

Your Unit test doesn't really test anything except your mock setup. Is it even possible for your mapping to fail?

I would skip the unit test on a repository and move right on to Integration tests; as its the SQL and object creation where you get the most bugs.

Entity Framework has a lot of issues as you scale up. If you hide it behind a repository you lose the (so called) benefits of things like IQueryable, lazy loading and the automatic creation and mapping to classes.

I would take it out and just use SqlClient and DataReader to manually populate your DTOs.

Its not clear if your DTOs are your models or if you have other models with logic that you populate using the DTOs. Or whether you are putting your models in a separate project? (which I would recommend)

Also you really should have a Database project with the database setup in it. Too often people skip this, creating the database manually and then when you want to deploy a new instance or add a table or something you have no source control and deployment path.

Overall you ask about your three layer design, but you have only shown the datalayer.

Ps. I would change all the Repository methods to async Task<>

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى softwareengineering.stackexchange
scroll top