viv*_*vek 6 oop domain-driven-design
最好的例子是User需要持久化的实体.我有以下候选人为用户分配唯一标识符:
举一个详细视图的简单示例,我们经常有一个用户的详细显示some/path/users/{user_id},如果我们将emailId保持为唯一ID,那么用户可能有一天会更改其电子邮件ID并将其中断.
哪种方法可以更好地识别同一个实体?
名为 UUID。
UUID,因为它为标识符提供了一个很好的可预测结构,而不会引入任何语义含义(如您的电子邮件 ID 示例)。想想代理键。
命名为UUID,因为您希望生成的 id 具有确定性。确定性意味着可重现:您可以将系统移至测试环境,并重放命令以检查结果。
它还为您提供了一种检测重复工作的额外方法 - 如果重复创建用户命令(例如:用户 POST 两次相同的 Web 表单),您的系统会发生什么。有多种方法可以在中间层中防止这种情况发生,但是在持久层(也就是在您的记录系统中)中覆盖这一点的一个非常简单的方法是对 id 设置唯一性约束。因为第二次运行该命令会产生一个具有相同 id 的“新”用户实体,持久层将反对重复,您可以从那里处理事情。
因此,即使所有中间保护层在重复命令之间的间隔期间重新启动,您也可以获得幂等命令处理。
命名的 UUID 为您提供了这些属性;例如,您可以根据实体类型的标识符和命令的 id 构建 uuid(重复的命令在重新发送时将具有相同的 id)。
如果您保证该属性永远不会分配给其他人,您可以使用用户的临时属性(如电子邮件地址)作为您命名 uuid 的种子的一部分。您确定不会将 vivek@stackoverflow.com 分配给其他用户吗?那么它就不是一个好用的种子。
如果命令重复,后端键分配将不会检测到冲突 - 您需要依赖其他一些状态来检测冲突。
系统时钟不是一个好的选择,因为它使重现相同的 id 变得困难。如果您可以在测试环境中将更新复制到本地时钟,则系统时钟的本地副本可以工作。但是,如果时间还不是您的域模型的一部分,那么这是您不想要的一大堆额外工作。