开发者

Repository and Service Design question

开发者 https://www.devze.com 2022-12-20 18:42 出处:网络
We are trying to find out the best practice when using DDD and we are having some discussions on what makes the most sense or is the \"right way\".

We are trying to find out the best practice when using DDD and we are having some discussions on what makes the most sense or is the "right way".

Note: All code is pseudo code.

Conceder the following:

public interface IDomainEntityAService
{
    void CreateMyObject(DomainEntityA myobject);
    DomainEntityA RetrieveDomainEntityA(long someId);
    //Other operations that handle the business logic dealing with MyObject
}

We also have another service that uses portions of IDomainEntityAService to facilitate a specialized need.

public interface IDomainEntityBService
{
    DomainEntityB GetDomainEntityB();
}

where OtherInformation contains the following:

public class DomainEntityB
{
    public string Name { get; set; }
    public IList<DomainEntityA> DomainEntityAList { get; set; }
}

Now comes our question. We are looking into using a repository to persist OtherInformation like the following:

public interface IDomainEntityBRepository
{
    void Add(DomainEntityB information);
    DomainEntityB Get(long someId);
}

Since we wish to keep things as DRY as possible we would ideally want to reuse the logic of IDomainEntityAService to retrieve the list of DomainEntityAList for DomainEntityB. Which one makes the most sense?

A) have a reference to IDomainEntityAService in the IDomainEntityBRepository e.g.

public class SqlDomainEntityBRepository : IDomainEntityBRepository
{

    public SqlDomainEntityBRepository(IDomainEntityAService domainEntityAService, Database database)
    {

    }

    public void Add(DomainEntityB information)
    {
        //save DomainEntityB to SQL
    }
    public DomainEntityB Get(long someId)
    {
        //Get OtherInformation.Name from SQL
        //use domainEntityAService.Get() to populate the list of DomainEntityAList
        //return DomainEntityB
    }
}

B) IDomainEntityBRepository only handles the SQL stuff and we use the service layer for IHaveOtherInformation to populate the list of MyObjects

public class DomainEntityBService : IDomainEntityBService
{
    public DomainEntityBService(IDomainEntityAService domainEntityAService, IDomainEntityBRepository repo)
    {
    }
    public DomainEntityB GetDomainEntityB()
    {
        var domainEntityB = _repo.Get(someId);
        domainEntityB.DomainEntityAList = _domainEntityAService.GetAll(someId);
        return domainEntityB;
    }
}

C) We make a specific DAL object for OtherInformation and we use the service layer to compose an instance of OtherInformation

public class DomainEntityBDAL
{
    public string Name { get; set; }
    public IList<int> DomainEntityAListIds { get; set; }
}

We then would have a repository to retrieve the OtherInformationDAL and then the code would look like the following:

public class DomainEntityBService : IDomainEntityBService
{

    public DomainEntityBService(IDomainEntityAService domainEntityAService, IDomainEntityBRepository repo)
    {
    }
    public DomainEntityB GetDomainEntityB()
    {

        var domainEntityBDAL = _repo.Get(someId);
        DomainEnt开发者_如何学GoityB result = new DomainEntityB() { Name = domainEntityBDAL.Name };
        foreach (var id in domainEntityBDAL.DomainEntityAListIds)
        {
            result.DomainEntityAList.Add(_domainEntityAService.Get(id));
        }
        return result;
    }
}

D) Wow we are completely off base do this instead!!!

I hope this makes sense and thanks for your help.

Edit Notes:

Maybe an english description can help describe my question better. We have DomainEntityA which is an aggregate root. There is a corresponding service to handle all logic that deals with DomainEntityA.

Now we also have DomainEntityB which is an aggregate root. However DomainEntityB has a list of DomainEntityAs. DomainEntityAs can live by itself, however DomainEntityB can not live without a list of DomainEntityAs

How would we load up the list of DomainEntityA items in DomainEntityB and maintain all the logic for DomainEntityA.

Reuse DomainEntityAService in DomainEntityBService?

Create a separate DomainEntityARepository in the DomainEntityBService?

We currently use EntLib but are looking more on information on design then the DAL implementation.


How about you instead use a general interface that lets you plug in the type? Like so:

public interface IRepository<T>
{
    T Get(object id);
    void Save(T value);
    void Update(T value);
    void Delete(T value);
    IList<T> GetAll();
}

Whatever implementation you use should be able to read the type and know how it fits into the database. That is the repository pattern in a nutshell. If you're not completely set on Entlib, explore NHibernate. I've found that it complements the repository pattern well. I've written extensively on this topic on my blog, so you can go there if you want to know more.


I'm making the assumption here that you're going to be storing to a database.

The answer to this depends quite heavily on what you're using as your persistence engine. If you have hand rolled your own persistence then C is not an option because you're going to see N+1 Queries. B would most likely be my first choice because it offers the most code reuse with, hopefully, non-awful performance.

Having said that if you're using something like NHibernate I'd recommend NOT using the repository pattern and instead

  • Encapsulating complex queries as objects (which can then be unit tested).
  • Use the session directly

I hope this helps!

0

精彩评论

暂无评论...
验证码 换一张
取 消