.NET:关于数据模型、领域模型和视图模型的一些思考
2013-07-04 00:35
411 查看
背景
数据模型、领域模型和视图模型是“模型”的三种角色,一些架构用一种类型表示这三种角色,如:传统三层架构。也有一些架构用两种类型表示这三种角色,如:结合ORM的领域驱动架构。非常少见的场景是用三种类型表示这三种角色,我只在个别领域这么弄过,如:工作流引擎。今天只说一个话题:是否有必要为视图模型引入独立的类型?还是用一种类型表达领域模型和视图模型这两种角色比较方便?引入一些词汇:
A方案:用一种类型表达领域模型和视图模型这两种角色,又叫公开领域模型到视图(Open Domain To View)。
B方案:为视图模型引入独立的类型,又叫使用数据传输对象(DTO)。
A方案
因为领域模型和视图模型是一个类型,所以领域模型会从UI进行重建,因为领域模型会从UI进行重建,而UI层是不能相信的,所以必须对领域模型进行验证(包含IsValid()方法),而且领域的很多方法都是修复领域模型的非法状态,如:重新计算订单总额、加密未加密的密码属性等等。代码示例
internal sealed class TestGridCommandHandler : ApplicationService, ICommandHandler<CreateTestGrid>, ICommandHandler<UpdateTestGrid>, ICommandHandler<DeleteTestGrid> { public void Handle(CreateTestGrid command) { var testGridService = this.Service<TestGridService>(); testGridService.Create(command.TestGridInfo); command.Id = command.TestGridInfo.Id; } public void Handle(UpdateTestGrid command) { var testGridService = this.Service<TestGridService>(); testGridService.Update(command.TestGridInfo); } public void Handle(DeleteTestGrid command) { this.Service<TestGridService>().Delete(command.Id); } }
注意看第二个方法,这里的command.TestGridInfo就是领域模型,从客户端重建后直接调用ApplicationService进行update,update负责修复模型状态、执行验证和处理乐观并发。
B方案
因为领域模型和视图模型是一个不同的类型,所以领域模型不会从UI进行重建,因为UI进行重建的只是视图模型, 所以要从数据库加载一份领域模型,然后将视图模型合并到领域模型中,这里的合并不是指用AutoMapper这样的合并工具,而是一种合理的合并过程(不能用反射绕过领域模型封装的逻辑),在这个合并过程,领域模型始终处于合法状态(也可以不合法,很多人都这么弄,保留IsValid()方法即可)。代码示例
internal sealed class TestOrderCommandHandler : ApplicationService, ICommandHandler<CreateTestOrder>, ICommandHandler<UpdateTestOrder>, ICommandHandler<DeleteTestOrder> { public void Handle(CreateTestOrder command) { var testOrderService = this.Service<TestOrderService>(); var testOrder = command.CreateTestOrder(); testOrderService.Create(testOrder); command.Id = testOrder.Id; } public void Handle(UpdateTestOrder command) { var testOrderService = this.Service<TestOrderService>(); var testOrder = testOrderService.Repository.Load(command.Id); testOrder.CheckOptimisticKey(command.TestOrderInfo.OptimisticKey); command.UpdateTestOrder(testOrder); testOrderService.Update(testOrder); } public void Handle(DeleteTestOrder command) { this.Service<TestOrderService>().Delete(command.Id); } }
注意看第二个方法,这里先用Repository从数据库返回一个领域模型,执行乐观锁检查,用视图模型修改领域模型(不是简单的反射),然后调用ApplicationService进行Update。
备注
只看代码大家可能觉得A方案比较简单,而B方案视乎有点脱裤子放屁的感觉,我之前都是用的A方案,开发效率确实高,但是应对比较复杂的逻辑就非常不爽了,具体为啥不爽我还没有想明白。我现在非常有信心用好任何一个方案,因为一个高人告诉我:关注代码细节胜于关注这些架构上的问题。
结合四色原型,我觉得可以这样弄:PPT和DES用A方案,MI用B方案。
相关文章推荐
- .NET:关于数据模型、领域模型和视图模型的一些思考
- 搜集的一些关于.NET模拟POST数据的资料
- 关于类的数据成员的访问权限设计的一些思考(转)
- 关于数据建模(面向ER)和领域模型建模(面向OO)在企业应用中的作用的讨论
- 关于领域驱动设计(DDD)中聚合设计的一些思考
- 关于领域驱动设计(DDD)中聚合设计的一些思考
- 关于类的数据成员的访问权限设计的一些思考
- 关于领域模型的几点思考和总结
- 关于数据建模(面向ER)和领域模型建模(面向OO)在企业应用中的作用的讨论
- 关于数据建模(面向ER)和领域模型建模(面向OO)在企业应用中的作用的讨论
- 【ThinkPHP】关于ThinkPHP关联模型和视图模型的一些心得 推荐
- .net使用mvc模式开发web应用 模型与视图间的数据处理
- 关于类的数据成员的访问权限设计的一些思考
- 关于数据建模(面向ER)和领域模型建模(面向OO)在企业应用中的作用的讨论
- 关于字典转模型的一些思考(持续更新中)
- 关于C++和C#的自定义数据类型转换的一些思考
- 关于数据建模(面向ER)和领域模型建模(面向OO)在企业应用中的作用的讨论
- DDD:贫血模型和领域模型的一些思考
- DDD:谈谈数据模型、领域模型、视图模型和命令模型
- 关于指令、数据、程序和进程的一些思考