3

在应用程序中,我们已将其建模Company为实体和Address值对象:

public class Company : Entity  {
    public Address PrimaryAddress { get; set; }
    public Address SecondaryAddress { get; set; }
}

public class Address : ValueObject {
    public string ZipCode { get; private set; } // etc.

    public Address(string zipCode) {
        ZipCode = zipCode;
    }
}

在这里,Address没有身份并且是不可变的。为了更新PrimaryAddress公司,我将其替换为新Address对象。

但是,在进一步发现该域后,我们发现一家公司可能拥有可变数量的地址。将它们表示为单独的属性不再可行。所以我们重构了Company

public class Company : Entity  {
    public Address[] AddressBook { get; set; }
}

我们现在有一个问题是如何更新公司的Address. 我们现在关心地址的身份,但仅在 Company 的上下文中

重构之后,我们最终得到:

public class Company : Entity  {
    public Address[] AddressBook { get; set; }

    public void UpdateAddress(Address newAddress) {
        var oldAddress = AddressBook.FirstOrDefault(a => a.Id == newAddress.Id);
        if (oldAddress != null)
            oldAddress = newAddress;
    }
}

public class Address : ValueObject {
    public Guid Id { get; private set; }
    public string ZipCode { get; private set; } // etc. 

    public Address(Guid id, string zipCode) {
        ZipCode = zipCode;
        Id = id;
    }
}

// usage
var company = repo.Load<Company>(companyId);
var address = new Address(model.Id, "12345"); // uses id of address we are replacing

company.UpdateAddress(address);
repo.Save(company);

为了更新地址,我们使用它来定位它,并将其Id替换为具有相同ID 的新地址对象。

  • 因此 Address 仍然是一个值对象吗?
  • 我对更新的地址使用相同的ID 是否正确,或者根据定义(作为值对象)我们应该替换Id。
  • 如果地址仅在公司实体的上下文中具有身份,我们是否应该在我们的模型中明确这一点,也许生成一个仅在实体内部唯一的 ID(可能使用实体的 ID 作为计算的一部分)?
4

1 回答 1

5

因此 Address 仍然是一个值对象吗?

我会说不,只要你给 Address 一个身份,它就不再是一个值对象。这意味着您不再只关心它的属性,而是开始重视应用程序中的地址生命周期,跟踪其状态的变化等。

我对更新的地址使用相同的 ID 是否正确,或者根据定义(作为值对象)我们应该替换 Id。

我不会重用地址 ID。从域的角度来看,当公司搬迁时,地址本身不会发生变化。该地址仍将有有效的门牌号和建筑物。由该身份定义的地址仍然存在,您甚至可以想象为其他公司重用它。因此,当公司搬家时,只需更改 Company 和 Address 之间的关联以指向具有新 ID 的新地址。

如果地址仅在公司实体的上下文中具有身份,我们是否应该在我们的模型中明确这一点,也许生成一个仅在实体内部唯一的 ID(可能使用实体的 ID 作为计算的一部分)?

仅仅因为您觉得需要在公司内部挑选出不同的地址并不意味着您必须给它们一个 Id 并使它们成为实体而不是值对象。例如,如果您想对公司内部的地址进行排名、定义主地址等,您可以使用值对象完美地做到这一点。地址值对象将保持不变,您可以只在 Company 中拥有一个索引集合、一个 PrimaryAddress 字段等。

于 2012-04-12T11:44:52.033 回答