我们处于开发周期(asp.net mvc applciation)的某个阶段,我们需要对现有的命令和事件进行更改(比如添加/删除一些属性等)。
我一直在努力寻找一种在系统中引入命令/事件版本控制的方法。我已经在google / stackoverflow等上阅读了很多帖子,但我还是要看一个实现它的代码示例。在版本控制时是否应该遵循推荐的模式。如果是,任何示例/片段?
编辑:这是我用这个
走了多远所以,如果我有一个活动
public class OrderSubmittedEvent : IDomainEvent
{
public int OrderId { get; private set; }
public OrderSubmittedEvent(int orderId)
{
OrderId = orderId;
}
}
如果我必须添加一些属性,我将上面的事件重命名为
public class OrderSubmittedEvent_V1 : IDomainEvent
{
public int OrderId { get; private set; }
public OrderSubmittedEvent_V1(int orderId)
{
OrderId = orderId;
}
}
并引入另一个与我的原始事件同名的事件,但添加了属性,如此
public class OrderSubmittedEvent : IDomainEvent
{
public int OrderId { get; private set; }
public OrderSubmittedEvent(int version = 1, int orderId = 0, string customerName =
"Joe blogs", string address = "Earth")
{
OrderId = orderId;
CustomerName = customerName;
Address = address;
CurrentVersion = version;
}
public static int LatestVersion
{
get { return 2; }
}
public int CurrentVersion { get; set; }
public string CustomerName { get; set; }
public string Address { get; set; }
}
我仍然需要继续更改发布此事件的代码,以包含新属性的值。
在重播我的活动时,我让我的活动通过IEventUpgrader 首先验证事件是否是可用的最新版本。因为类型将始终是事件类型,所以此检查基于属性“LatestVersion”和“CurrentVersion”
每个人都会想到这种方法?
下一个待办事项
谢谢
答案 0 :(得分:7)
通常您只需要对事件进行版本控制,您可以忽略这些命令,因为您不会将它们存储在事件存储中。
实现版本控制的方法很少..我的方法非常简单:
[Obsolete]
public class CompanyCreated
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public class CompanyCreated_V2
{
public Guid Id { get; set; }
public string CompanyName { get; set; }
public string TaxNumber { get; set; }
}
当您从事件存储中读取事件时,您需要处理事件从旧事件到新事件的转换。
另外,你需要知道你永远不会删除任何旧的事件类,因此我将它们装饰为Obsolete,让其他开发人员知道不要使用该事件。
答案 1 :(得分:4)
如果您只是添加&删除属性,可能不需要版本事件;只需忽略已删除的序列化属性,并为添加的属性使用合理的默认值。
答案 2 :(得分:1)
不可否认,我没有机会尝试以下方法,但我希望从第一天开始对版本进行烘焙:
由于完整的类型名称是相关的,我会选择命名空间。
namespace Primary.Messages.V1
{
public class CompanyCreated
{
public Guid Id { get; set; }
public string Name { get; set; }
}
}
namespace Primary.Messages.V2
{
public class CompanyCreated
{
public Guid Id { get; set; }
public string Name { get; set; }
public string TaxNumber { get; set; }
}
}
这些可以在不同的集合中,你可以将旧的标记标记为过时的(如Sarmaad所建议的那样)。可能旧版本不一定是过时的。
有什么想法吗?
答案 3 :(得分:1)
对于混合事件和命令,我会保持谨慎。他们有不同的目的并解决不同的问题。
要更好地理解我的意思,请这样思考 命令更像是RESTful API,客户端与服务器之间的通信。 事件搜索更多是一种存储数据的方式。
两者都需要版本控制,以通过不变性提供向后兼容性,但这又是出于不同的原因。因此,实现和异常是不同的。
我绝对会推荐一本书getScaledMinimumScalingSpan()
,以便为事件源系统的版本控制提供更多信息。
有关命令的更多信息,请查看Event Versioning by Greg Young,尤其是CQRS series。
答案 4 :(得分:0)
我完全没有理由,同时考虑为什么需要事件版本控制的问题,更具体地说是在答案中建议的方式?
我只能想到两个用例
1-目前正在使用的事件类已弃用,不再需要。 然后可以随时在git中跟踪该类。那么为什么要通过保留死类来打扰和复杂活动代码?
2-业务需求已更改,现在您需要保留基本事件,但您还需要另一个具有某些参数差异的类似事件。 这可以通过多种方式解决,例如装饰器模式可以在很大程度上帮助处理这种变化 或者,新事件可能代表一个独特的域概念,而不是试图强迫概念进入现有模型,最好在语义上更加命名并以这种方式使用它。