首页
学习
活动
专区
圈层
工具
发布

DDD实施
EN

Stack Overflow用户
提问于 2013-04-02 23:42:11
回答 7查看 1.7K关注 0票数 8

我是领域驱动设计的新手,我对一些概念有一些疑问(希望这是问这个问题的正确地方)。

我知道在DDD中我应该避免贫血模式,所以考虑到社交网络模式应该建立(保存)两个朋友之间的友谊吗?

我设想这样的情况,比如有一个类表示用户(使用类似Java的语法):

代码语言:javascript
复制
class User{
    String username
    List<User> friends
}

那么,它应该有一个增加一个朋友的方法吗?

代码语言:javascript
复制
class User{
    void friendship(User friend)
}

或者我应该用服务来做这件事?

代码语言:javascript
复制
class UserService{
     void friendship(User user, User user2)
}
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2013-04-02 23:55:25

我的想法是,这是关系数据库理论中所谓的“弱实体”的一个例子。Friendship可以仅由友谊中所涉及的两个User的标识符来标识,但也可以具有自己的属性,例如创建它的时间以及它是什么类型的关系。

我会将其作为自己的实体,并可能将其隐藏在由User对象公开的外观后面:

代码语言:javascript
复制
class User {
    protected List<Friendship> _friendships { get; private set; }

    public IEnumerable<User> Friends {
        get { return _friendships.Select( /* get other user */ ); }
    }

    public void AddFriend(User otherUser) {
        // check to see if friendship exists
        // if not, create friendship
        // do other friendshippy things

        // make sure the other user knows about our friendship 
        // and gets to do its friendshippy things
        otherUser.AddFriend(this);
    }
}
票数 6
EN

Stack Overflow用户

发布于 2013-04-03 08:19:12

我会用这样的方法

代码语言:javascript
复制
public sealed class Username : IEquatable<Username> { /* string wrap here */ }
public class User
{
    private readonly Username _username;
    private readonly HashSet<Username> _friends;
    public User(Username username)
    {
        if (null == username) throw new ArgumentNullException("username");
        _username = username;
        _friends = new HashSet<Username>();
    }

    public Username Name { get {return _username; } }
    public void Befriend(User user)
    {
        if (null == user) throw new ArgumentNullException("user");
        _friends.Add(user.Name);
    }

    public bool IsFriendsOf(User user)
    {
        if (null == user) throw new ArgumentNullException("user");
        return _friends.Contains(user.Name);
    }
}

注意,根据德米特定律,用户不公开任何集合。如果你真的需要它们,我会为朋友公开一个IEnumerable<Username>

此外,在DDD中,所有查询和命令都应该是泛指语言的一部分(这就是为什么我使用Befriend而不是AddFriend)。

但是,让我说一下,这看起来有点太CRUD了,不需要DDD。--如果你不需要(至少)一个领域专家来理解这个领域,那么你完全不需要DDD。如果您不需要DDD,它将成为项目中最昂贵的错误。

编辑

让我们假设领域专家说“友谊总是互惠的”(按照guillaume31's的建议):通过建模幂等命令,您可以非常容易地确保这样的业务规则。

代码语言:javascript
复制
public void Befriend(User user)
{
    if (null == user) throw new ArgumentNullException("user");
    if(_friends.Add(user.Name))
    {
        user.Befriend(this);
    }
}

您可以使用这样的属性来模型幂等命令,但有时需要进行更多的分析,以确保它们的参数和内部状态提供所需的一切。

票数 5
EN

Stack Overflow用户

发布于 2015-07-14 10:43:45

我想,友谊本身就是一个总根。可以在应用程序服务中直接创建它,也可以将创建委托给域服务。

如果用户特定的验证需要,域服务可以请求用户聚合进行验证。或者将两个用户聚合分派给友谊聚合创建者/构造函数。

然后,友谊存储库可以轻松地返回给定用户的朋友列表。

即使是友谊的集合也没有丰富的模式或行为;它有一个独立的一致性边界。

此外,如果我们使用事件源,我们可以监听friendshipCreated事件,并将情况通知两个用户。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15776418

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档