下面是一位同事对当前的产品开发框架提出的一些建议,以及我的回复。我觉得一些问题提得有一定的代表性,在征得本人同意后,将本邮件发布在博客中。
同时,也非常希望对框架、产品有好的建议的小伙伴,都可以给我发邮件:9474649 @ qq.com。
发件人: 胡庆访
发送时间: 2016-07-16 15:36
收件人: 杨盛元
主题: Re: 渣打银行项目,关于rafy框架,一点个人意见。
盛元:
由于最近工作时间的问题,一直没有回复你的技术建议,深感抱歉。
首先,非常感谢你提出的技术上的建议。我们非常期望项目组上的开发人员都能象你这样深入的思考,和产品组的研发人员一起探讨,提出更多的技术建议,一起让产品不断更新升级。
对于你邮件中提出的问题,我整理了一下。下面对它们进行一一的回复。
1、领域建模的意义。
答:“领域模型是辅助技术人员更容易理解业务的设计图。”这句是没有问题的。其实我们产品上的新模块开发也是这样去做的。其实在培训的视频中,已经说明了,虽然 Rafy 使用的是 CodeFirst 的开发模式 ,但是开发者的第一步应该是使用 UML 来进行领域建模,而非直接使用 Rafy 框架进行编码。先画图而不是先编码的方式的目的也是为了帮助开发人员去理解业务。使用 UML 的原因,也是因为这一步是与任何框架无关的。同时,这样也更进一步地确定出领域模型未来在程序中的表现形式。
2、三层变为两层的问题。
答:几层并不重要,重要的是关注点分离就好了。另外,Rafy 框架中的 Repository 代码是可以分开来放在单独的项目中的。
3、框架能否写 SQL 的问题。
答:Rafy 框架体系中包含一个 ORM 框架:Rafy 领域实体框架。任何 ORM 框架为了保证开发的灵活性,都会允许开发者去编写 SQL。但是 ORM 框架也不会建议开发者去编写原生 SQL。
4、“领域模型,只是辅助技术更好的理解业务的一种UML图,并不是用来引导项目技术架构的图。(简单点就是:技术什么都不用动,理解业务就好。)”
答:其实业务和技术之间存在着很大的鸿沟,Eric Evans 在提出 DDD 时,就是为了解决这个问题。而领域建模只是解决这个鸿沟的第一个步骤。有了领域模型图之后,如何使用技术来实现就是第二步。
开发者当然可以按照自己的理解,使用常用的架构模式来搭建自己的技术架构。
Rafy 领域实体框架的意义:在这种开发方法的基础上,把一个常用的领域驱动架构模式以框架的形式固化下来,辅助开发者快速实现领域模型图中的所有领域模型,并在这个架构上解决一系列技术问题。
其实,这就是框架带来的进步。例如 ASP.NET MVC 框架就是把 MVC 架构在 Web 开发场景中的架构模式固化下来的 Web 开发技术框架。那为什么我们不用 MVC 框架,而非要基于 ASP.NET WebForm 去实现自己的 MVC 框架呢?只有以下原因会促使你去这样做:老的框架无法解决你的问题、或者开发者认为自己可以开发出更优秀的框架。
5、TypeScript 学习成本较高的问题。
答:采用新生事物,都是要付出代价的。我们需要考虑的是:这个代价值得吗?对于 TS,我们得出的结论是:性价比很高。
6、EF 6 还是 Rafy 的问题。
答:Rafy 不单只是一个 ORM 框架。它是一个产品线的开发平台,为我们提供了除 ORM 外的许多框架:DDD、Plugin、SOA、MDA、PL,详见下文:《Rafy 框架设计理论》。
如果单纯从 ORM 的角度来对比 EF6 和 Rafy 的话,也有诸多优势,详见下文:《Rafy 框架发布》。
7、你建议使用代码生成器。
答:对于你使用的一站式代码生成的模式,是比较老的开发模式了。虽然是一个比较易用、方便的开发模式,但是这在代码的可重用性、可维护性、架构的传承性等方面都较差(见:《对代码生成器的简单思考》)。
代码生成器和框架作用在开发过程中的不同层次、不同阶段。二者需要配合使用。不需要开发者修改的代码,应该编写在框架内部;而开发者需要修改或者调整的代码,应该使用代码生成器生成在外部,方便二次修改。另外,为了减轻开发者的负担,应该把尽可能多地封装在框架中。就拿 EF 作为例子,实体的代码在框架之外,ORM 的逻辑在框架之内;这与更老的 TypedDataSet 的代码生成模式相比,优势太多。
Rafy 框架的开发模式的设计中,我们是非常重视代码生成器的,所以也是在提供框架的同时结合代码生成器在使用。例如:属性的生成是使用 VS 自带的代码段(轻量代码生成);实体文件的生成是使用项模板。这些代码生成功能都是结合在 VisualStudio 中的,给开发者的体验是连贯一致的,要比外部的代码生成功能好很多。
8、纯model表字段部份单独放在一个cs文件里标记上partial。
答:产品的开发模式上,吸取了你所提及的许多代码生成器开发模式的经验。Entity 与 Repository 的代码是可以分开放的。目前为了方便使用,放在了一起。二者的代码都分为开发者编写的代码和自动生成的代码。例如,实体的代码是分在两个文件中的,以 User 实体为例,一个文件是 User.cs,另一个则是 User.g.cs 文件中(自动代码生成)。
9、最好能再加一个viewModel文件夹,放视图数据模型。(项目里边有很多都是直接DataTable处理的)
答:建议很好。如果 ViewModel 较多的话,应该放在一个单独的文件夹中。不建议项目组使用 DataTable 作为 ViewModel。
10、后端返回统一一个模型 Result。
答:现在就是这样做的。
下面是同事建议的邮件内容:
发件人: 杨盛元
发送时间: 2016-06-13 15:05
收件人: 胡庆访
主题: rafy框架问题,主要针对领域模型(ddd)
在tp(vim)渣打银行这个项目中看框架,技术和业务实现部份感觉有很多缺陷。
我对领域模型的理解:首先对领域模型DDD,是领域驱动设计,它的起源由来是早期业务设计是由流程图+用例图,横纵向表达业务流程和项目中各业务需要的模块。
之后加入领域模型,是为了在业务和技术实现之间起到一个桥梁作用,让技术更方便理解业务。领域图就包含了 (数据字段,数据关系,业务主要方法)。
领域模型是辅助技术人员更容易理解业务的设计图。
在RAFY里,框架想要实现用技术代码直接实现DDD。这样得出的结果就是,业务数据模型+数据逻辑+业务逻辑。三种代码全部混合堆在一起。三层+Model的结构被做成了两层,应用层和混合层(业务逻辑,数据逻辑,数据模型)。像框架介绍里说处理聚合组合关系。这一类属于业务逻辑关系,并不像一对多,多对多这样硬性的数据结构关系。和数据层混合在一起也不合理。
在这个框架下还出现了在控制器下能够直接写SQL语句的情况。在开发人员水平参差不齐的情况下,这框架不够规范。
等一些别的问题。。。巴拉巴拉。
网上现在很多人把领域模型理解成“要求技术按照领域图,实现技术架构”。
而我觉得领域模型,只是辅助技术更好的理解业务的一种UML图,并不是用来引导项目技术架构的图。(简单点就是:技术什么都不用动,理解业务就好。该三层还是三层,或是别的更灵活的技术架构。)
如果有一天有个名词叫流程驱动设计,那么所有代码都要堆在一起了。
所以领域驱动设计DDD,只是业务设计上照顾技术。对设计的要求更高了,而不是针对技术架构。
我希望能用通用技术来开发项目,三层结构+Model,Orm改用entity(ef)。这样对开发人员的学习成本就底了,项目开发效率和质量应该更好。 同样可以做公司项目中的各种业务封装(工作流,固定字段,角色/权限等)。
另外:可以的话最好前端也能用通用常用的技术JS+JQUERY之类。TypeScript不是很成熟,对大众开发者有过多的学习成本和更少的可参考资料。
觉得我理解得不对,可以进一步交流。
发件人: 杨盛元
发送时间: 2016-07-06 14:10
收件人: 胡庆访
主题: 渣打银行项目,关于rafy框架,一点个人意见。
钉钉不方便。我说直接点。
ORM部份,其实我更希望用ef6,不过rafy已经跟项目和产品绑在一起了,就不提这个。
我长期积累的做项目的方案步奏是:
1:由数据库表/视图,自动生成Model,连带备注和所有字段。(将纯字段模型标记成partial,让此部份永远自动生成,人工不干涉,可靠性更高,而且不用再写数据字典)。
2:做模板。由模板+数据Model,直接生成页面。可以是.net,js甚至是android的。原理简单就是替换Txt中标签内容。
(各种增删改查,树形数据维护,报表等都可以做成代码模板。软件大部份页面都可以设计成一样的,只要数据结构一样)
这里指的是用model一次生成整个.cs和csview和js全部文件。不是代码片段。
(这招我已经用几年了,很方便,一个页面一秒钟完成。生成文件后,删除多余的自动生成代码,补上业务逻辑就行了。)
以上是整个的方案。rafy把Model的关联关系和字段映射写在一起。这招就行不通了。感觉很不方便。
能不能做这样的小调整,把纯model表字段部份单独放在一个cs文件里标记上partial。
最好能再加一个viewModel文件夹,放视图数据模型。在rafy里加个方法.ToModel<T>()数据转成对应视图模型的方法。现在项目里边有很多都是直接DataTable处理的。虽然要做ddd领域架构,但视图数据模型开发过程中是必然会有的。有个这种方法处理起来规范些。
前后端交互:
1: 在后端所有的Action返回统一一个模型如{success:data:,msg:,code:};
2: 这样在前端接收数据部份,就可以做一个封装统一处理。(如:code是异常的话,就弹出框。展示Msg内信息,正确就返回data数据跑前端业务逻辑)
以上这个框架里有一部份,我觉得还可以封装得更全一点。让后端统一返回模型,前端就能统一处理了。
我觉得这样可以在对框架不作大改动的情况下,项目开发会更方便些。
你参考下。