Domain Pollution Resolution 域污染解除

2023-11-10 07:59

本文主要是介绍Domain Pollution Resolution 域污染解除,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Domain Pollution Resolution
域污染解除

0. Domain 名词解释
首先说明一下 Domain 在本文中的意思。
<<Domain Driven Design>> 一书,令 Domain 这个词很火。引起了广泛争论:哪些Logic 应该放在 Business Service Layer, 哪些应该放在 Domain Object里面。这类争论纷纷扬扬,最后通常都上升到哲学高度,世界观高度,认知心理学高度。如果不幸发展到极端情况,双方很可能开始相互质疑对方的智商和对世界的基本理解能力。
这个层次的Domain 纷争,不是本文所关心的话题。
我一向认为,设计能够满足如下的条件,就可以称为是一个好的设计:能够使用多态性,代替Hard-Coded if else switch 等逻辑分支;新需求来的时候,不需要在旧代码里面添加if else switch等逻辑分支,而只需要加入一个新的Class;尽量避免 Package, Class 级别的交叉引用。

本文所关心的Domain 是一个更高的层次,类似于DSL, Domain Specific Language 里面的Domain的意思。
本文主要讨论如下议题:

HTML是否只应该用来表示结构?
HTML是否应该包含逻辑?
HTML是否应该包含服务器端脚本逻辑?比如,JSP, Velocity, Freemarker.
HTML是否应该包含浏览器端脚本逻辑?比如,Java Script.

Java 代码中是否应该输出HTML标签?比如,Taglib, Tapestry Page Component, etc?
Java 代码中是否应该使用框架特殊的HTML View Model? 比如,XMLC, Wicket, Echo, etc.

HTTP Web Server本来的设计宗旨是无状态,支持大用户量,多连接。目前的server side的page flow, web flow, continuation, 力图使得HTTP Web Server保持用户的流程状态。这种做法是否应该推荐?

SQL是一种可读性很好,应用广泛的一种DSL。如何动态拼装SQL,一直是一个难以解决的问题。
是否应该在Java 代码中嵌入SQL?
是否应该在Java 代码中使用 Criteria API?
是否应该在SQL Template中加入动态语言脚本逻辑?比如 iBatis 使用XML if otherwise, OR Bridge中使用velocity?
HQL, OQL在SQL中引入了OO语言的特性,似乎操作的是对象数据库,而不是关系数据库。这种做法是否应该推荐?

Hibernate 动态期间篡改用户代码的做法,是否应该推荐?
JDO静态期间篡改拥护代码的做法,是否应该推荐?

Dynamic Proxy, CGLib等动态篡改用户代码的做法,是否应该推荐?
Reflection绕开了 Java 的类型检查机制,是否应该推荐?
Thread Local是一种隐式契约,相当于绕开了显式契约(方法签名method signature),这种做法是否应该推荐?

这些属于开发模式、代码风格方面的问题,正如所谓Code Smell的感觉一样,也避免不了主观的成分。所以,下面的陈述并非论断,而只是“在我看来”。

1. HTML Template Layer
HTML应该尽量只用来表示结构,排除所有逻辑。
JSP, Velocity, Freemarker等服务器端脚本逻辑,属于Java Code或者Script Code对HTML的污染。
不仅应该排除JSP, Velocity, Freemarker等服务器端脚本逻辑,而且应该排除浏览器端脚本逻辑,比如Java Script.
当然,这里不是说,不用Java Script,而是说,不要把Java Script放在HTML里面。把Java Script放在一个单独的.js文件里面,在HTML中引入,并使用CSS把HTML Element 和 Java Script Event Handler 联系起来。
这方面的资料有:
Unobtrusive Javascript
http://www.onlinetools.org/articles/unobtrusivejavascript/
http://www.kryogenix.org/code/browser/aqlists/
http://www.bobbyvandersluis.com/articles/goodpractices.php

如何排除HTML中的Server Side Logic呢?
Ajax!
Ajax fans一定反应迅速,给出答案。
没错。Ajax可以做到。Ajax的主要问题在于使用和掌握难度。
除了Ajax呢?
有几个选择,XMLC, Jivan, fastm, Wicket, Echo等。(and Tapestry?)

fastm是我做的一个模板层,具体内容可以在此下载。
https://fastm.dev.java.net/files/documents/1911/25042/fastm1.0c.zip

fastm采用 XML Comment 作为文档结构标记。注意,是结构标记,而不是逻辑标记。不含有for if else。
可见,fastm并不是毫无污染,只是没有逻辑污染。fastm只在HTML中添加了自定义的结构标签,也勉强算没有违背HTML只用来表示结构的原意。
Ajax, XMLC, Jivan 的HTML很干净,而且对HTML 结构的控制能力很强,能够用代码动态控制布局。fastm也能够动态控制布局。Site mesh, tiles taglib, jsp, velocity, freemarker等做不到。
fastm 里面的例子中,包括一个分页的例子,和一个动态组装SQL的例子

2. Java Web Layer
Taglib, Tapestry Page Component, Echo, Wicket等在Java 代码中输出HTML标签,这也是一种,而且要求在Java 代码中使用框架特殊的HTML View Model,比如Table, List, Label, Formbean 等View Object。使用了这些框架,Java 代码的编译就需要依赖于这些框架了。
这相当于HTML标签对Java 代码的污染。
JSP, Velocity, Freemarker都不存在这种情况。Java 代码只是提供POJO,然后 HTML里面的Server Side Script使用这些POJO.
fastm不支持逻辑,所以这个方面弱一些。fastm要求Java Code把if, else 等逻辑分支变成一个Map 结构。由于Map属于java的基本类,所以,fastm也不需要在Java code中使用任何特殊的框架相关的view model。
3. Web Layer - Stateless or Stateful
与其在服务器端支持 page flow, web flow, continuation,那不如在浏览器端支持状态。这种场合下,我觉得,正是使用Ajax的最佳场所。
我倾向于这样的设计,服务器端尽量无状态,如果确实需要状态,那么尽量在浏览器段保持状态。
lightweb是我做的一个Web框架。
https://lightweb.dev.java.net/files/documents/4371/25044/lightweb0.9b.zip

主要的特点是,URL-Centric, 鼓励无状态的Service Oriented设计。支持三种Service模型,
Action (like WebWork Action),
Controller (like Spring MVC Controller),
Channel (like Struts Action Dispatcher),

lightweb支持多级模块寻找,使用几条匹配规则,代替庞大的Site Map 配置文件。
lightweb查找View的时候,不是根据Site Map 文件里面的那种小型状态机的配置(success -> showIt.jsp; fail-> this page), 而是直接资源定位。lightweb继承了fastm的观点,把template看作资源,而不是一段运行脚本。

Lightweb设计为IoC友好。在各个环节都暴露出插件接口。程序员可以自己选择IoC策略。可以采用一般的做法,用一个IoC container集中管理,比如,Spring IoC, Pico, Nano等;也可以分散到各子模块,进行管理;也可以分散到每个Action Validator里面管理。

4. ORM Layer
Hibernate 动态期间篡改用户代码,JDO静态期间篡改用户代码。
令我想起黑客,木马,夹带,偷梁换柱等。这属于语义上的Pollution。就是说,从原有的Source看起来,Domain Object并没有那样的行为,运行起来却有那样的行为。
iBatis采用reflection,确实干净。但是,性能、功能上又不够强大。某些功能的实现,确实需要代码生成。
lightor是我做的一个ORM框架。
https://lightor.dev.java.net/files/documents/4370/25043/lightor0.5a.zip

lightor也需要代码生成。区别在于,lightor不修改任何代码,只是产生新的Mapper代码。Domain Object运行的时候,还是你原来的Domain Object。这就避免了语义的污染。
lightor生成的Mapper代码,可以编译期类型检查,可以阅读,跟踪,调试。这些生成的代码,也都遵循本文的原则。Java 代码里面不含有SQL片断,SQL都存在于单独的资源文件中。
(另外,不采用CGLib,也是为了实现的简单)
lightor直接使用Native SQL。Lightor的目的不是屏蔽关系数据库,而是恰好相反。lightor的目的是,帮助程序员更清楚地认识关系数据库,SQL,JDBC。lightor和JDBC不冲突,可以一起使用。
lightor努力的第一个主要方向就是效率。大数据量查询和处理的效率。
据我所知,目前只有lightor才支持大数据量批量处理,因为只有lightor不惜降低ORM的身份和封装层次,能够接受ResultSet作为参数。
lightor的缓存策略比Hibernate更前进了一步,把query cache 和 ID Cache集成在一起。以便得到更好的控制。并且,把缓存API暴露给程序员,以便智能的控制某个特定的缓存。

5. SQL
HQL, OQL在SQL中引入了OO语言的特性,似乎操作的是对象数据库,而不是关系数据库。
我感觉,这是一种语法层次上的Domain Pollution。OO语法对SQL语法的污染。
正如感觉LinkQ是数据库查询语法对OO语法的污染。
Java 代码中使用 Criteria API,也属于数据库查询领域对OO领域的污染。

SQL是一种可读性很好,应用广泛的一种DSL。
我的看法是,尽量把完整的SQL放到单独的资源文件中,可以直接Copy到SQL Client就可以运行。特殊优化过的Native SQL,也是同样的地位。
HQL, OQL阻碍了用户对SQL进行特殊优化。

如何动态拼装SQL,一直是一个难以解决的问题。
直接在Java 代码中嵌入SQL,肯定不行。前面说了,Java里面最好不要有SQL片断,最好放到另外的资源文件中。
在Java 代码中使用 Criteria API? 前面也否定了。
在SQL Template中加入动态语言脚本逻辑?比如 iBatis 使用XML if otherwise, OR Bridge中使用velocity?
这种方法还是不错。不过仍然在SQL里面引入了脚本逻辑。
我也没有好的做法。我采用fastm来处理。在SQL里面引入结构标记。这也相当于污染。因为SQL和HTML不同。SQL不是描述结构的,而是一门DSL。
这种做法的一个好处是,整段SQL还是可以Copy到SQL Client里面,稍微修改一番,就可以直接运行。

6. A Demo Forum
farum是我做的一个简单的forum demo. 使用了fastm, lightor, lightweb, 也尽量体现我前面提出的原则。
https://farum.dev.java.net/files/documents/4372/25045/farum0.5a.zip

我觉得,使用一门语言,应该尽量发挥它的特长,而不是针对它的短处,修修补补。
Java作为静态类型编译语言的好处,就是编译期类型检查。那么如何发挥这个优势?前面说的Mapper源代码生成,就是一种尝试。
另外,其它的类似的胶水粘合部分,比如,IoC, Validation等,都可以进行这方面的尝试。目前,farum就是采用这样的做法,自己写的Validator Source进行validation, value setting, service implementation injection等工作。
farum没有使用Dynamic Proxy, CGLib等动态篡改用户代码的做法。
尽量不使用Reflection,因为Reflection绕开了 Java 的类型检查机制。与其使用reflection,真不如使用动态脚本语言。
当然,reflection是非常难以避免的。farum也少许使用了reflection。
Thread Local是一种隐式契约,相当于绕开了显式契约(方法签名method signature)。WebWork的一些用法,Spring Framework的Open Session In View,等都是采用了Thread Local。
farum没有采用Thread Local,而是采用了另一种方法实现了Open Session In view。而且如果缓存命中,甚至不需要从connection pool中获取Connection。

总结
<<Web开发构想>>一文中,我提出了,理想中的Web开发架构是这样的:
开发速度快,运行速度快,结构清晰优雅。
具体到每一层。
Web框架层主要追求 开发速度快。
O/R层主要追求 运行速度快。
页面资源层和页面模板层主要追求 结构清晰优雅。

下面就是我对这些理想的初步实现。
还远远达不到完美的程度,而只是朝这个方向努力。

Template Layer
fastm
https://fastm.dev.java.net/files/documents/1911/25042/fastm1.0c.zip

Web Layer
lightweb
https://lightweb.dev.java.net/files/documents/4371/25044/lightweb0.9b.zip

ORM Layer
lightor
https://lightor.dev.java.net/files/documents/4370/25043/lightor0.5a.zip

A forum demo using fastm + lightor + lightweb
farum
https://farum.dev.java.net/files/documents/4372/25045/farum0.5a.zip

这篇关于Domain Pollution Resolution 域污染解除的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/381382

相关文章

apk反编译修改教程系列-----修改apk 解除软件限制功能 实例操作步骤解析_6【二十五】

目前很多软件都需要票票才可以使用完全的功能。纯免费的功能性app已经很少见了。 今天继续以一款app为大家来演示如何去除软件的限制功能。教程的目的主要是学习反编译的基础修改方法,了解app的修改步骤以及基础的入门修改常识。每个使用修改方法不一定适用于所有app。只是给你另外的思路与步骤参考。 反编译工具:MT**绿色版 演示apk;**清单 app

maven学习笔记【解除js等文件的锁定】

默认情况下,jetty服务器运行期间是无法修改JS,CSS等静态文件的,必须要先关闭jetty服务器,再修改,再启动,如果经常修改静态文件,这是相当麻烦的. 其实是需要把jetty的webdefault.xml文件中的useFileMappedBuffer节点改为false即可 但是最近在项目中使用maven,jetty也作为maven插件使用,根本没有jetty的配置文件.其实jett

GCDAsyncUdpSocket 使用时出现错误 Domain=NSPOSIXErrorDomain Code=13 Permission denied

完整的错误描述为: Domain=NSPOSIXErrorDomain Code=13 "Permission denied" UserInfo={NSLocalizedDescription=Permission denied, NSLocalizedFailureReason=Error in send() function.} 原始代码是这样的: clientBroadcast

svg无功补偿装置脉冲封锁怎么解除

SVG(Static Var Generator,静态无功发生器)脉冲封锁是一种保护机制,用于防止装置在异常情况下继续运行,从而避免对电力系统造成进一步的损害。如果SVG进入脉冲封锁状态,通常需要执行特定的步骤来解除封锁并恢复正常运行。以下是解除SVG脉冲封锁的一般步骤: 1. 检查故障原因 故障诊断:首先,查看SVG的故障记录或报警信息,确定导致脉冲封锁的具体原因。常见的原因包括过电流、过电

最佳MyBatis 根据表结构自动生成代码, domain, dao, mapper 文件

摘要: 接触mybatis时间不是很长, 但是感觉也还容易上手, 好处发现也很多, 觉得还挺方便, 这段时间又学习一下MyBatis自动生成代码. 觉得在效率上更好了, 所以分享一下自动生成代码的步骤. 首先, 看看我的项目的包结构, 用的IDEA13.1,gradle包管理工具, ...其他的就没什么可说的; 今天, 主要讲 generator 里面的东西; mysql的jar包是

BM3D--Image Denoising by Sparse 3-D Transform-Domain Collaborative Filtering

系列文章目录 文章目录 系列文章目录前言稀疏三维变换域协同滤波图像去噪摘要1 引言2 分组和协作过滤A.分组B.按匹配分组C.协同过滤D.基于变换域收缩的协同过滤 3 算法结论 前言 论文地址 如果下载不了可以从 https://download.csdn.net/download/m0_70420861/89708940 获取 参考博客 :图像去噪算法:NL-Me

最新版本typora下载安装(保姆级教程)、文本编辑器typora解除破解(包括新旧版本)

首先针对旧版本,原本只需要替换 app.asar 文件即可。具体的操作步骤可以见这篇文章:旧版本解除步骤 问题:评论反应,说方法不行,仍激活破除不了,而且还导致软件使用不了,于是这里介绍新的方法(针对新版本) 新旧版本区分:值得是破解的新旧方法,而不是绝对意义上的新旧版本 建议使用新版本:比如这里以 1.7.x 为例(其余高版本激活方法一样) 一、下载 1、Typora 官网下

Failed resolution of: Lcom/growingio/android/sdk/agent/VdsAgent;删除growingio引发的问题

删除了 growingio之后 项目一直报这个错误 Failed resolution of: Lcom/growingio/android/sdk/agent/VdsAgent; 真是讨厌 解决方案 在as 的 Terminal 分别执行这两个命令 ./gradlew cleanBuildCache  ./gradlew clean 如果在使用上面两个命令的时候出现 权限拒绝

【论文】A Collaborative Transfer Learning Framework for Cross-domain Recommendation

Intro 业界常见的跨域建模方案主要分为两种范式[22][32][5][36][17][14][20]:1) 将源样本和目标样本进行联合和混合,然后执行多任务学习技术,以提高在所有域中的性能;2) 使用混合或数据丰富的源域数据预先训练模型,然后在数据不足的目标域中对其进行微调,以适应新的数据分布。在第一种方法中,通过不同类型的网络设计来学习特定域特征和域不变特征,其中域指标通常用于识别域。在微

数据分析-第三方库(工具包):Numpy【使用ndarray对象处理多维数组】【比Python原生list运算效率高:①内存块风格;②支持并行化运算;③底层用C编写,内部解除了GIL(全局解释器锁)】

一、Numpy优势 Numpy运算速度上的优势Numpy的数组内存块风格Numpy的并行化运算 1、Numpy介绍 Numpy(Numerical Python)是一个开源的Python科学计算库,用于快速处理任意维度的数组。 Numpy支持常见的数组和矩阵操作。对于同样的数值计算任务,使用Numpy比直接使用Python要简洁的多。 Numpy使用ndarray对象来处理多维数组,