我想仅使用不可变对象构建我的域模型.但我也想使用具有val字段的特征并将一些功能移到特征中.请看下面的例子:
trait Versionable {
val version = 0
def incrementVersion = copy(version=version+1)
}
Run Code Online (Sandbox Code Playgroud)
不幸的是这样的代码不起作用 - 对于特性Versionable,复制方法是未知的.
我认为为每个特征和类生成复制方法会很好.这样的方法应该创建对象的浅拷贝,并使用与原始对象相同的类型返回它,并根据传递给方法的参数修改给定的字段.
所以在下面的例子中:
class Customer(val name: String) extends Versionable {
def changeName(newName: String) = copy(name = newName)
}
val customer = new Customer("Scot")
Run Code Online (Sandbox Code Playgroud)
customer.changeName("McDonnald") 应该返回一个对象实例 Customer(version = 0, name = "McDonnald")
和
customer.incrementVersion 还应该返回一个对象实例 Customer(version = 1, name = "Scot")
据我所知,目前Scala中缺少此类功能不允许使用不可变类和特征而不会污染具有特征字段的类构造函数.在我的示例中,我不想将参数命名版本引入Customer类,因为版本处理的功能我想要封装在Versionable特性中.
我知道案例类中复制方法的功能以及使用默认参数在类中编写自己的复制方法的能力 - 但我认为这个功能并不能解决我的问题,因为在特征中不可能使用这种复制方法.现有功能的另一个缺点是使用复制方法的父类返回父类而不是实际复制的对象类.
我的问题:
1)您是否知道如何以优雅的方式处理上述示例.我对Scala很新,所以也许已经有了很好的解决方案.在我看来,优雅的解决方案应具有以下功能:
不应该使用反射
不应该使用序列化
应该快
应该在编译时可以验证
2)您如何考虑编写编译器插件来为我上面的示例生成复制方法的代码?是否可以使用编译器插件来做到这一点?您有任何示例或提示如何做到这一点?
我的问题与CQRS(命令和查询责任隔离)和构建阅读模型(视图)的机制有关.据我所知,读模型是由事件处理程序构建的.这些处理程序(也称为非规范化程序)接收域事件并使用这些事件来构建不同的数据视图.
特定事件包含有关域模型中所做更改的信息.我认为这些信息在某些情况下不足以构建视图 - 即没有更改字段,在此类事件中没有更改实体等.
所以我的问题是:
是否允许负责构建读取模型的非规范化器不仅访问事件,还允许:
您对事件处理程序(非规范化程序)的允许依赖关系有何看法?
编辑:刚刚在上面的问题中添加了简单示例:
假设以下模型:
AR:ProductOffering*名称*描述*类别*价格
AR:客户*名称*类型*方法:buyProduct(productOffering),发出ProductPurchasedByCustomer事件
entity:ProductInstance*customer*productOffering
事件:ProductPurchasedByCustomer*customerId*productOfferingId
查看:ProductInventoryView*customerId*productOfferingId*customerType*productOfferingName*productOfferingCategory*price
如何仅使用ProductPurchasedByCustomer事件构建ProductInventoryView?如何编写denormalizer以查看有关customerType,productOfferingName等的信息?我应该从不同的视图中查找有关customerType和productOfferingName的其他信息吗?