另一个应用架构问题

时间:2011-07-21 09:14:19

标签: c# domain-driven-design n-tier-architecture ddd-service

我正在尝试一些DDD,我会尝试以最简单的方式描述我所做的事情。

核心项目
 核心项目包含实体,VO和域服务。例如,我有用户实体和 UserRelation 实体。我想我们都知道什么是 User 实体。 UserRelation 包含有关用户如何相互连接的信息,如follow和connect(双向跟随)。因此我使用无状态方法 UserDomainService ,如Follow(用户,用户)和Connect(用户,用户)。

public class User
{
    public string Name { get; set; }
    public string Username { get; set; }

    public void ChangeUsername(stirng newUsername)
    {
        ApplyEvent(new UserUsernameChanged(newUsername));
    }
}

public class UserRelation
{
    ctor(User1, User2, isBidirectional)
    public User User1 { get; set; }
    public User User2 { get; set; }
    public bool IsBidirectional { get; set; }
}

public class UserDomainService
{
    public UserRelation Follow(User user1, User user2)
    { 
        return new UserRelation(user1,user2,false);
    }
}

存储库项目

我正在使用NHibernate所以我决定不创建这样的项目。相反,我直接使用NHibernate。例如,在我的UI中,我从数据库中获取用户对象,更改它然后调用session.Save(用户)。

问题

如果我想按照以下方式进行操作,请执行以下操作:

  • 从DB
  • 获取一些信息
  • 从服务
  • 中调用Follow(user1,user2)
  • 将UserRelation对象保存到DB 最后,应用程序代码变得有点复杂。想象一下,如果我们想在2-3个地方使用这个代码,在某些时候我们必须重构它。

我的解决方案
我的解决方案是创建一个ApplicationService项目,该项目将执行脏工作并强制使用者使用ApplicationService而不是直接使用Entitties和Domain服务

public class UserApplicationService
{
    ctor(UserDomainService userDomainService){}

    User GetUser(Guid id)
    {
        return NhibernateSession.Get(id)
    }

    public void Follow(Guid user1Id, Guid user2Id)
    {
        var u1 = GetUser(user1Id);
        var u2 = GetUser(user2Id);
        var userRelation = _userDomainService.Follow(u1,u2);
        NhibernateSession.Save(userRelation);
    }

    public void ChangeUsername(Guid user, string newUsername)
    {
        user.ChangeUsername(newUsername);
        NhibernateSession.Save(user);
    }
}

此应用程序服务是好还是坏?正如您所看到的那样,新服务也可以作为存储库,因此我们可以创建一个UserRepository类,但现在让我们跳过它。困扰我的是两种方法中的参数。他们接受Guids,服务从数据库中检索用户。另一种选择是直接传递User对象。 ChangeUsername方法类似于User entity + persistence。

那你觉得这个怎么样?

2 个答案:

答案 0 :(得分:1)

我个人认为没有任何错误,事实上这就是我与之合作的公司所做的事情,只要你从该服务中抽象出数据访问,它就可以成为业务层的一部分,作为中介之间的中介。数据层和ui层,它可以避免重复自己,并确保为某个操作概述的任何规则都会触发。

答案 1 :(得分:1)

我的2美分。

DDD适用于大型项目。您不应该仅仅因为它是而将它应用于项目。通过查看NHibernateSession,我看到你可以通过id获取User。好吧,如果NHibernateSession负责你有哪些其他域对象?您没有存储库,为什么要强制DDD过热?

好的,继续前进,因为你有一个大型域名,我不清楚你为什么要创建一个新项目来托管 Follow 功能(那里的输入GUID没有任何问题)。 IMO 应用程序服务层不应该处理实体和infrustrucure,因为对于这个人来说它似乎太低了。应用程序服务层负责整个应用程序,而不是某些域对象的功能。我注意到你的_userDomainService似乎与你的情况更相关。如果移动关注功能没有多大意义,我会在域服务层创建另一项服务,称之为UsersManagerServiceUsersDomainService

最后,如果要实现存储库模式,请考虑使用通用存储库。