HTML5技术

领域驱动和MVVM应用于UWP开发的一些思考 - durow(2)

字号+ 作者:H5之家 来源:博客园 2015-10-31 09:17 我要评论( )

基础层这个是MVVM中没有明显说明的。如果我们把领域层的模型看作MVVM中的Model那么基础层是直接可以拿来用的,不存在任何冲突。在尝试将MVVM和领域驱动结合后大概是下图这种感觉,表示层只依赖于应用层。 0x04 关于

基础层这个是MVVM中没有明显说明的。如果我们把领域层的模型看作MVVM中的Model那么基础层是直接可以拿来用的,不存在任何冲突。在尝试将MVVM和领域驱动结合后大概是下图这种感觉,表示层只依赖于应用层。

 

0x04 关于Repository

之所以把Repository拿出来单独说,就是因为领域驱动最开始吸引我的就是Repository很好的解决了MVVM中没有涉及到并且长期困扰我的数据持久化的问题。此外另一个原因是看到很多文章讨论Repository应该属于哪一层的问题,这其中包含了Repository接口的定义和实现等。这里我也谈一下我个人的一点看法。

从领域驱动设计的四层架构中我们可以看到,领域层是依赖基础层的,而基础层并不依赖领域层,因为如果有两层是互相依赖的,那么分层就毫无意义了。这种依赖的具体表现是什么呢?最具体的表现就是基础层和领域层分别存放在不同的程序集中,领域层程序集引用基础层程序集,基础层可以在没有领域层的时候编译通过。基于这个结论来看Repository,Repository接口的定义和实现都是依赖于领域层实体模型的,这个是无法避免的,所以Repository无论接口的定义还是实现都应该放在领域层。实际上从访问数据库读取数据到最终转化为对象列表,这个过程跨越了基础层和领域层,这个过程中包含着两个关键动作,第一个是从数据库中读取数据库数据,第二个是把原始数据映射为领域层实体对象。其中第一个动作属于基础层,第二个动作属于领域层。具体到代码我个人的理解就是在领域层中不应该出现任何SQL语句以及明显的数据库相关的东西(例如SqlConnection)。根据这个理论来举例,读取Users表中的内容并获得User对象列表。在基础层中提供针对数据库的通用的操作,操作返回ADO对象,不依赖于领域层:

public DataTable GetUserTable() { const string SQL = “SELECT * FROM Users”; Using(var con = new SqlConnection(ConnectionString)) { var cmd = new SqlCommand(sql,con); var da = new SqlDataAdaptor(cmd); var dt = new DataTable(); da.Fill(dt); return dt; } }

在领域层中定义Repository接口并实现,返回领域层对象User

public IEnumerable<User> GetAll() { var dt = GetUserTable(); foreach(DataRow row in dt.Rows) { User { Name = row[“name”].ToString(), ID = (int)row[“id”] } } }

这样领域层单项依赖基础层。

之前看到有文章讨论把Repository接口定义放在领域层,接口实现放在基础层,这个是不符合领域驱动的四层架构设计的。因为基础层中对Repository的实现依赖了领域层。但如果不纠结于这个四层架构,或者说在实际项目中领域层和基础层不需要分别放到单独的程序集中,这么做也是可以的,而且这么做领域层会显得更“纯净”,毕竟从数据库到实体的映射不能算业务逻辑。还是那句话,模式和设计是一种通用的指导方向,最终还是要服务于特定场景,没有绝对的对错,只有合适不合适。

0x05 引入ORM后的问题

ORM的作用就是把具体的数据库操作从业务逻辑中抽取出来,编写业务逻辑时不需要再考虑具体的数据库操作,把基础层和领域层的功能封装到了一起,这和Repository作用十分类似,可以说ORM是Repository的一个子集。这看上去似乎是很好的,在数据库操作时直接使用ORM来代替Repository就可以了。但实际中存在的最大问题是ORM返回的实体对象是对数据库表的抽象,一般是POCO对象,而Repository中返回的领域层对象是聚合根,聚合根和ORM返回的实体对象不一定是完全对应的,而且领域层对象是充血的。在某些情况下ORM返回的实体对象可以直接拿来作为领域层对象使用,这自然是好的,但当不能直接使用时就需要转换为领域层对象或对ORM返回的实体对象进行功能上的扩展。

0x06 以上理论在UWP中的实践

思考了一大堆理论连我自己都信了,但实践才是检验真理的唯一标准。所以我打算新建一个测试用的UWP应用检验一下。记得学习MVVM那会,要用MVVM开发我一般会新建一个项目,然后建三个文件夹:View,Model,ViewModel,但为了能充分体验那种低耦合和单项依赖的感觉,我曾在一个解决方案中建了三个项目,分别叫View、ViewModel和Model,其中View引用ViewModel,ViewModel引用Model(虽然在View最后生成的文件夹中我们看到了Model的dll,但View并不直接依赖Model)。项目是不能互相引用的,也就是单向的依赖。所以这次在检验自己理论时,我仍然用了这个方法,根据领域驱动四层架构的依赖关系,在一个解决方案中建了四个项目:View(表示层),ViewModel(应用层),Domain(领域层),Infrastructure(基础层),其中Domain中有个Model文件夹存放领域模型,也是MVVM中的Model。VS解决方案中项目的排列是按照字母顺序的,所以项目存在的顺序并不代表他们之间的依赖关系。

 

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 从USB驱动器运行Windows 10 - SmallProgram

    从USB驱动器运行Windows 10 - SmallProgram

    2017-03-11 09:01

  • vue系列之MVVM框架 - zhaobao1830

    vue系列之MVVM框架 - zhaobao1830

    2017-02-16 13:00

  • MVVM - 王小帅0401

    MVVM - 王小帅0401

    2016-12-07 17:00

  • Vue.js 和 MVVM 的小细节 - 一像素

    Vue.js 和 MVVM 的小细节 - 一像素

    2016-11-08 14:00

网友点评