如何更新域模型中的审计字段?

时间:2013-12-09 10:23:48

标签: domain-driven-design

我想扩展这个问题When to update audit fields? DDD

在我的域模型中,这可能不适合它,但我们有CreatedBy和ModifiedBy的属性,两者都是User,两个值对象。

我是DDD的新手并且对哪个层负责更新这些属性感到困惑......数据?域?或申请?

在上面链接的问题中,他们提到使用事件来更新这些属性......那么假设这些字段在域上是可更新的吗?

以下是我班级的一个例子......

public class SpritePalette
{
    private readonly SpritePaletteColors _colors;

    public string Id { get; private set; }
    public string Name { get; private set; }
    public SpritePaletteColors Colors { get { return _colors; } }
    public bool IsPublic { get; private set; }
    public User CreatedBy { get; private set; }
    public DateTime CreatedDate { get; private set; }
    public User ModifiedBy { get; private set; }
    public DateTime ModifiedDate { get; private set; }

    public SpritePalette(
        string name)
    {
        this.Name = name;
        this.IsPublic = false;

        _colors = new SpritePaletteColors();
    }

    internal void UpdateId(string value)
    {
        Validate.IsNotEmpty(value, "Id is required.");

        this.Id = value;
    }

    public void UpdateName(string value)
    {
        this.Name = value;
    }   

    public void MarkAsCreated(User value)
    {
        this.CreatedBy = value;
        this.CreatedDate = DateTime.UtcNow;
    }

    public void MarkAsModified(User value)
    {
        this.ModifiedBy = value;
        this.ModifiedDate = DateTime.UtcNow;
    }

    public bool HasColor(string color)
    {
        return _colors.HasColor(color);
    }

    public void AddColor(string color)
    {
        _colors.AddColor(color);
    }

    public void RemoveColor(string color)
    {
        _colors.RemoveColor(color);
    }

    public void UpdateIsPublic(bool value)
    {
        this.IsPublic = value;
    }
}

我雇佣了两个方法,一个用于将模型标记为已创建,一个用于更新CreatedBy和CreatedDate,另一个用于将模型标记为已修改。

对于DDD,这是否可以接受?处理这些更新审计属性的更好方法是什么?有更好的方法,即使用事件吗?

我承认这有点主观,但感谢任何人都可以提供的任何帮助!

2 个答案:

答案 0 :(得分:1)

使用"框架"

的解决方案

一个。使用额外参数公开每个构造函数和命令方法。 像:

public SpritePalette(
    string name, User user)
{
    this.Name = name;
    this.IsPublic = false;

    _colors = new SpritePaletteColors();
    createdBy(user)
}

public void UpdateName(string value, User user)
{
    this.Name = value;
    modifiedBy(user);
}

internal void modifiedBy(User value)
{
    this.CreatedBy = value;
    this.CreatedDate = DateTime.UtcNow;
}

在这种情况下,每次应用程序层操作域模型时,都会更新审计字段。但是当应用程序层调用以下几个命令方法时,这可能看起来很简单:

//application layer
public void update(String name, String description, ....other attributes,User user) [
    //retrieve SpritePalette
    SpritePalette.updateName(name, user);
    SpritePalette.updateDescription(description, user);//passes user again
    //other command methods invocation   //passes user again & again
}

B中。公开额外的审计字段更新方法。

像:

 //application layer
public void update(String name, String description, ....other attributes,User user) [
    //retrieve SpritePalette
    SpritePalette.updateName(name);
    SpritePalette.updateDescription(description);
    //other command methods invocation   
    SpritePalette.modifiedBy(user);
}

但我有时害怕忘记调用这个modifiedBy()方法。

没有"框架"

的解决方案

也许我们应该使用另一组模型。如果我们将更新行为建模为事件怎么办?核心域不需要审计字段。查询要求通常需要审核字段,例如"我想看看谁修改了这个东西"。

让我们分开:

class UpdateNameEvent {
    string SpritePaletteId;
    string name;
    User user;
    Date when;
}

class SpritePalette{
    on(UpdateNameEvent event) {
         this.Name = event.name();//no user involved
    }
}

 //application layer
public void update(String name, User user) [
    //retrieve SpritePalette
    var event = new UpdateNameEvent(name, user);
    SpritePalette.on();
    //other command methods invocation   
    events.save(event); //save the events
    repository.update(SpritePalette);
}

public List<SpritePaletteEvent> list(string id) {
    return events.list(id);
}

答案 1 :(得分:1)

在您上面链接的问题中,CreatedByUpdatedBy是域层的一部分,因为实际的域会议实际上是由某人安排的。

在您的设置(精灵)中,CreatedByUpdatedBy似乎不太可能是底层图形域的一部分。因此,CreatedBy / UpdatedBy属性仅用于簿记/审核,因此是纯粹的应用程序级别问题,应仅在应用程序级别处理。在Java中,您通常会通过某些Interceptor更新这些标志,但我不确定如何在C#中执行此操作。也许可以更新存储库中的这些字段(通过让应用程序在工作单元或类似工具中注册当前用户)。