基本上,用户想要更改其个人资料图片。
Web服务器收到针对/user/35435/profile/picture
的已发布图像,因此需要保存数据,并更新配置文件对象的LastModification
属性。
图像不会本地存储在Web服务器中,需要将其上传到其他位置(即:云存储)。
目前,每个操作都由Command或Query表示。命令在环境事务中运行(如SQL事务)。图像上传操作不是事务性的,但可以在出现错误时进行补偿操作(即:如果DB操作失败,则删除图像)。
在一个简单的实现中,创建一个包含当前日期和图像数据的命令。执行命令处理程序,它加载ProfileAggregate
聚合,并执行ProfileAggregate.updateProfilePicture(imageUploader, image, currentDate)
作为参数传递imageUploader
域服务。在方法内部,上载图像并更新配置文件。命令处理程序保存数据库中的更改并返回。
我不喜欢在图片上传期间保持交易的事实。我不喜欢在聚合中进行非域模型操作(如上传图像)(即使聚合在其他地方调用)。
这种交互是否应该像两个以串行方式执行的独立命令一样建模,或者只要在具体实现中没有依赖关系就可以将任何内容放在聚合中。
答案 0 :(得分:1)
您的命令处理程序可能位于您的体系结构的“应用程序层”中。因此,考虑到这一点,您会收到一个命令,并协调您的域/其他服务以满足它。
那就是说,我真的不喜欢两个不同的命令实现,从客户端的角度来看,他们只做一个动作。您可以创建一个代理命令(单个命令),并在其处理程序上生成两个命令(一个用于处理聚合,另一个用于处理上载)但这种方法将使您的API /模型在未来不那么直观。
我也不喜欢在Profile聚合中捆绑操作的上传部分,因为它似乎不是它的职责之一。
我在这里建议的是以下方法:
个人资料聚合应负责接受图片。因此,它的操作 updateProfilePicture 将简单地评估图片元数据(也许你有一个规则,图片必须具有一定的大小或针对某种算法进行验证,以试图找到裸露,这种东西)以及目标 Profile 的内部状态,以允许操作发生并使用 lastUpdated 属性或其他内容更新其内部状态。
ImageUploadService 将为您提供独立的功能,以接收图像并相应地存储它。
这两项操作都将独立进行,并最终通过消息传递保持一致。
因此,您的命令处理程序将:
当ImageUploadService完成接收图像后,它将向Profile域发送一条消息,报告上传成功/失败。然后:
答案 1 :(得分:1)
对您有帮助的主要问题是,当图像无法上传时,系统应该怎么做。我认为答案是您希望用户收到错误,系统(配置文件)应保持不变。
从Domain的角度来看,实际的图像上传/存储过程是无关紧要的。此操作实际上是基础结构的一部分,应该在命令发送到域层(到配置文件聚合)之前由应用层编排。这样,如果上载因任何原因失败,则不会发送该命令。
图像上传可以同步或异步完成;这取决于你的平台/编程语言/等,它是无关紧要的。关键是只有在图像上传成功后才将命令发送到Aggregate。该命令应包括ImageStorageId和可能的一些元数据(如文件名,文件大小,图像大小等)。
答案 2 :(得分:0)
我目前坚持在运行域命令之前处理文件上传。
除非域模型需要直接处理图像(或其他一些)文件,否则让所有基于文件的操作(包括上传和裁剪)远离它似乎是合理的。因此,如果您不分析模型中图像中的数据(例如,我不知道,人脸检测?),而只需要一些抽象的个人资料图像,则将元数据对象传递给模型。
如果域模型出现故障,它会调度一个事件,由应用程序处理并执行一些回滚逻辑。