【问题标题】:Is it allowed to modify value of the Value Object on construction是否允许在构造时修改值对象的值
【发布时间】:2021-05-25 14:23:19
【问题描述】:

假设我希望后面的值对象包含始终大写的字符串值。在构造函数中使用toUpperCase() 是否有资格这样做?

class CapitalizedId(value: String) {
    val value: String = value.toUpperCase()
    // getters
    // equals and hashCode
}

【问题讨论】:

    标签: domain-driven-design value-objects


    【解决方案1】:

    一般来说,我认为在值对象的构造函数中执行如此简单的转换不会有问题。当然,构造函数的用户应该不会感到意外,但正如名称 CapitalizedId 已经告诉您,无论创建什么都将大写,所以从我的角度来看,这并不奇怪。我还在构造函数中执行有效性检查,以确保遵守业务不变量。

    如果您担心不在构造函数中执行操作,或者如果操作和验证变得过于复杂,您可以随时提供工厂方法(或者在 Kotlin 中使用 companion,我猜,不是 Kotlin 专家)包含所有繁重的工作(想想 LocalDateTime.of())和验证逻辑,并像这样使用它:

    CapitalizedId.of("abc5464g"); 
    

    注意:在实现工厂方法时,在这种情况下,构造函数应设为私有

    【讨论】:

    • 感谢关于工厂方法的好建议。我想我可以将构造函数设为私有或完全删除它。值对象当然不会被调用 CapitalizedId :) 但在我们普遍存在的语言中,假定该值对象始终包含一个大写字符串。
    • 是的,感谢您指出这一点,我忘了说,在这种情况下,应该另外将构造函数设为私有。我会在我的回答中更新它。我不太了解 Kotlin 的机制,但请注意,完全删除构造函数不会给您留下默认构造函数,该构造函数仍然允许初始化值对象,在这种情况下绕过您的业务逻辑进行创建和验证。
    【解决方案2】:

    是否有资格在构造函数中使用 toUpperCase() 这样做?

    是的,从某种意义上说,您最终得到的仍然是 ValueObject 模式的表达式。

    这与初始化程序应该初始化并且不包括其他职责的想法不一致。见Misko Hevery 2008

    这个具体的实现会是一个代价高昂的错误吗?应该不会

    【讨论】:

    • 这几乎肯定不会违反 Hevery 的文章,因为它所做的只是初始化一个字段。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    • 2011-08-15
    • 2014-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多