DDD разделяет сущность между двумя совокупными корнями - PullRequest
0 голосов
/ 30 сентября 2019

Я работаю с двумя различными совокупными корнями: пост и вопрос. У них обоих есть Категория.

До сих пор я реализовал ее как общую сущность (что я не уверен, является ли правильный дизайн в DDD).

public class Post
{
    public Guid Id { get; private set; }

    public Category Category { get; private set; }

    public string Title { get; private set; }

    public string Body { get; private set; }
}

public class Question
{
    public Guid Id { get; private set; } 

    public Category Category { get; private set; }

    public string Title { get; private set; }

    public string Body { get; private set; }
}

public class Category
{
    public int Id { get; private set; }

    public string Name { get; private set; }

    public string Key { get; private set; }
}

Примечание. Мне известно, что я впадаю в примитивный антиназор одержимости, и у меня есть планы по реорганизации примитивов в ValueObjects.

После прочтения этого поста DDD: Поделиться сущностью с несколькими агрегатными корнями Я думаю, что, возможно, мне следует преобразовать категорию в ValueObject (с несколькими полями).

Теоретически Category может быть сущностью с собственным жизненным циклом, но реальность такова, что я не добавляю, не удаляю, не обновляю категории.

Можно ли использовать общую сущность в DDD? ? Или мне лучше использовать ValueObject?

Ответы [ 2 ]

2 голосов
/ 30 сентября 2019

Давайте сначала разберемся с одним агрегатом: Пост

Теперь, чтобы ответить на ваш вопрос:

Можно ли использовать общую сущность в DDD? Или лучше использовать ValueObject?

Это зависит от того, что вы будете делать с Категория .

Сценарий 1:

У вас есть функция (или страница) в вашем приложении, чтобы показать все сообщения категории. Я хотел бы пойти со следующим дизайном:

public class Category
{
    public int Id { get; set; }
    //this is my in-memory database. Use repository and service to adjust yours
    public static List<Post> Posts;

    public Category()
    {
        Posts = new List<Post>();
    }

    public void AddPost(Guid id, string title, string body)
    {
        var post = new Post(id, title, body, this.Id);
        //saving the post into in-memory. Perhaps you can check some business logic inside Post entity
        Posts.Add(post);
    }

    // You can retrieve all posts of a single category
    public IEnumerable<Post> GetAllPosts()
    {
        return Posts.Where(x => x.CategoryId == this.Id);
    }
}

public class Post
{
    public Guid Id { get; private set; }
    public string Title { get; private set; }
    public string Body { get; private set; }
    public int CategoryId { get; private set; }

    public Post(Guid id)
    {
        Id = id;
    }

    public Post(Guid id, string title, string body, int categoryId)
    {
        //I prefer to pass guid into domain from external services.
        //Using this way, your service will have the id to return to upper layers.
        //Alternatively you can create new guid here on your own
        Id = id;
        Title = title;
        Body = body;
        CategoryId = categoryId;
    }

    // you can retrieve a post detail
    public Post GetPost()
    {
        return Category.Posts.FirstOrDefault(x => x.Id == this.Id);
    }
}

Я вижу только один агрегированный корень в этом сценарии: Категория .

Сценарий 2:

У вас есть страница сообщений, оттуда пользователи могут просматривать подробные сообщения. Кроме того, у каждого сообщения есть категория, которая будет показана где-то на этой подробной странице. Вы можете иметь следующий простой дизайн:

public class Post
{
    public Guid Id { get; private set; }
    public string Title { get; private set; }
    public string Body { get; private set; }
    public string CatKey { get; private set; }

    public Post(Guid id)
    {
        Id = id;
    }

    public Post(Guid id, string title, string body, string catKey)
    {
        //I prefer to pass guid into domain from external services.
        //Using this way, your service will have the id to return to upper layers.
        //Alternatively you can create new guid here on your own
        Id = id;
        Title = title;
        Body = body;
        //I don't even bother with category id. This is a simple value object, you can store all of your categories
        //into a hashtable of key-value
        CatKey = catKey;
    }

    // you can retrieve a post detail
    public Post GetPost()
    {
        //get your post detail from repo
    }
}

Надеюсь, что вы можете принять решение сейчас.

1 голос
/ 03 октября 2019

Главный вопрос Entity vs ValueObject: нужно ли по-разному отслеживать два экземпляра категории с одинаковыми значениями? Классическим примером является долларовая банкнота - в большинстве случаев серийный номер (ID) не имеет значения, и один доллар совпадает с другим (ValueObject). Однако, если ваш домен собирает редкие счета, это изменится.

Я подозреваю, что не в вашем случае, поскольку кажется, что Категория действительно состоит только из имени и ключа. Если категория сообщения изменяется, нужно ли отслеживать, какой была предыдущая категория?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...