论坛首页 Web前端技术论坛

降低前后台业务逻辑上的耦合度,前后台细粒度数据通讯的方法

浏览 10401 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-06-05  

题的提出 :

jCT模板属于前后台分离的设计.

对于前后台分离的设计.

S根据B提出的请求,发送原始数据,S不需要对表现层有任何控制,降低了B,S的耦合度.

这种降低了B,S的耦合度方法,本质上是降低了 数据内容 上的 耦合度 ,仅仅把表现层的控制数据分离出去了.

由于请求和数据直接影响到表现,表现 业务逻辑 的最直接体现,但是 这两个词不能画等号.因此我们用表现逻辑 这个词.暗示表现和业务逻辑是关联比较密切的.

表现逻辑 变化的时候,势必要 改变 后台数据内容 的组合结构,我们的问题就是

如何降低前后台 表现逻辑( 业务逻辑) 上的耦合度


附加举例 说明问题:

常见的页面上有多种访问(按日,月,年或分类)排名,如果我们要增加或减少一个排名规则的话,表现 是要改的,后台 数据内容 也要同期改,这就是耦合度高的问题.

当然,对于新增的表现,采取多次和后台通讯也是一种解决方法,不过这增加了通讯的次数.

我们要达到只需要 表现,不用改 后台 ,并且不增加通讯次数的目标.


问题分析 :

表现逻辑 最终体现在原始数据的变化上.

业务逻辑对数据的细粒度化是比较容易实现的,就是把数据的请求最小化,然后把多个请求 获得的数据组合输出就行了.这在设计中是常见的.最简单的就是按请求的次序 请求队列 ,输出关联数组结构 的数据就行了.

那要解决的问题就是,前台如何在一次通讯中发出 请求队列 ,后台如何正确解析 请求队列 的问题.


解决方案 :

这里我直接给出我的方案,

利用POST方法和GET参数的配合.

在实际使用POST和GET方法的时候我们通常是用参数名=值 ,这种值对 的形式提交,事实上http协议并没有限定死这种形式,我们这种形式对http协议来说只不过是一串字符串罢了.用ajax 方法提交数据的时候是可以直接传送以JSON形式 的数据的,这就是纯字符串了.JSON 对数据的表现能力是毋庸置疑的.经后台解析后才对象化的.

我们可以把 请求队列 JSON 形式与后台通讯,后台完成 请求队列 解析.当然对于ajax 来说使用POST 方法

无疑是很好的,因为POST 方法其实是兼容GET 的,ajax 请求中的url 参数就是GET 方法的实现.那GET参数 在这里有什么用途呢?共用参数 的传递(这个语言描述就到这里,做个应用的朋友应该已经明白了).

ajax POST的数据是JSON字符串格式,比如:

写道
{"login":{"name":"youname","pw":"123456"},"onlineusers":true}
 

我一直用PHP编程,php获得POST过来的JSON数据是很容易的

写道
$json=file_get_contents('php://input');
$json=json_decode($json,true);

 

到此 请求队列 的数据通信解决了,后台获取解决了,解析呢?这恐怕要和你的应用有关了.解决起来类似于如下结构

 

写道
$OUT=array();
foreach($requireQueue as $Q){
  switch($Q['REQUIRE']){
    case 'login':
      $OUT['login']=login();break;
    case 'onlineusers':
      $OUT['onlineusers']=onlineusers();break;
  }
}

 

 

switch..case 就是细粒度的实现了.可以看出,在业务逻辑确定的情况下,表现只需要改变请求的队列的组合 就可以一次通讯获取 数据 了.

 

==========ps============

很遗憾,由于人事变动,我不再参与www.91mh.net这个项目了,项目负责人又回到了古老的编程方法,这个网站已经不采用我的技术了,回头有新的站我再给出新的地址吧。

   发表时间:2008-06-07  
你好,关注你的jct有一段时间了。可以说我了解js template就是从jct开始的。而且从html注释入手的方法也是值得提倡的。我最近在开发一个java 的MVC框架(类似struts),其中有一种View可以在直接返回任何对象的json,非常适合js template的整合,所以最近一直在考虑是否整合一个js template,但是由于考虑到js template以下的局限性,一直迟迟没有决定:
1.把模板解析放到的浏览器中,如果客户端不支持js,就比较惨了,虽然现代的浏览器几乎都支持,而且用户没事一般也是开的,但是对于天生最求完美的程序员,这始终会是一个心病。
2.js开发比较繁琐,就算你解析引擎做到在好,还是需要写很多的js代码去读取json等操作,这对于一般的程序员是比较烦人的(也就是为什么google的GWT和 DWR 存在的理由,一般程序员喜欢在java中做事)。

我在设计的MVC框架,考虑如果集成js template 的话,要能够在服务器端自动或半自动生成模板解析的js代码,让程序员尽量的通过服务器端的方法来完成客户端js模板的解析工作,这听起来似乎有点矛盾。。。不知道你怎么看?或者说这里是不是存在一种新的web开发模式,但不仅仅是ajax+json+js template那么简单。

看了你这篇文章又让我吃惊了一下,确实,如果ajax中请求一个action队列,然后返回队列合并结果,这种模式可以有效的降低服务器action的颗粒度,也保证了action的重复运用,这就相当于把一个action到做一个组件或者一个方法,然后一个请求队列来了后调用分别的action在组合,返回给用户。这个实现在我现在的框架下可以很轻易地实现,更不不需要你说的那么麻烦的方法。在配合 json和js template。。我感觉似乎一种新的 模式即将出现。

在考虑是否与你的jct整合,javaeye上我一般不来,喜欢和你深入的交流.
0 请登录后投票
   发表时间:2008-06-08  
chanawudi 写道

1.把模板解析放到的浏览器中,如果客户端不支持js,就比较惨了,虽然现代的浏览器几乎都支持,而且用户没事一般也是开的,但是对于天生最求完美的程序员,这始终会是一个心病。


是的,客户端必须要有执行脚本的能力,其实我的最终目标里根本就是自己写一个客户端,他的意义就不说了。

chanawudi 写道

2.js开发比较繁琐,就算你解析引擎做到在好,还是需要写很多的js代码去读取json等操作,这对于一般的程序员是比较烦人的(也就是为什么google的GWT和 DWR 存在的理由,一般程序员喜欢在java中做事)。


有什么是不麻烦的呢?熟悉的东西都不麻烦,不熟悉的才麻烦,作为程序员是要学习多门语言的。js只不过是其中一种罢了。java也只是一种,想要只用一种语言搞定所有的事情是不科学的,因为语言也在发展,都在变。因此我们要学习不同的东西。

chanawudi 写道

我在设计的MVC框架,考虑如果集成js template 的话,要能够在服务器端自动或半自动生成模板解析的js代码,让程序员尽量的通过服务器端的方法来完成客户端js模板的解析工作,这听起来似乎有点矛盾。。。不知道你怎么看?或者说这里是不是存在一种新的web开发模式,但不仅仅是ajax+json+js template那么简单。


在服务器端来做模板本来就是常规的做法,但是我反对这种方法,因为这种方法把数据和表现耦合的太紧了,
解决耦合性问题是我做这些工作的基础。离开了这个基础我的方法就没有可取的地方了。

chanawudi 写道

看了你这篇文章又让我吃惊了一下,确实,如果ajax中请求一个action队列,然后返回队列合并结果,这种模式可以有效的降低服务器action的颗粒度,也保证了action的重复运用,这就相当于把一个action到做一个组件或者一个方法,然后一个请求队列来了后调用分别的action在组合,返回给用户。这个实现在我现在的框架下可以很轻易地实现,更不不需要你说的那么麻烦的方法。在配合 json和js template。。我感觉似乎一种新的 模式即将出现。
在考虑是否与你的jct整合,javaeye上我一般不来,喜欢和你深入的交流.


呵呵你的文字也是渐进式的表达你思想的变化。如果你实做这个的话,你会发现,只有把表现完全在客户端做才能发挥这种模式的好处。
因为我倡导jCT(应该说是前台模板)和细粒度action有一个原因就是:
WEB的开发,对于大多项目(中小项目),主要的工作量和难度是在前台表现上,而这个任务目前是由后台完成的,
而做后台的人大多都是项目中的领导,他们在工作的时候往往只是做很少的辅助工作(选择框架,制定规范,这是一种交叉的规范,涉及到B和S,反正都是在约束别人)来完成表现问题,而具体的实现还要靠前台html/css/javascript人员(我把html/css的开发者也叫做程序员,同样整理文档的文案人员也叫程序员,因为他们都写逻辑性很强的code),这种局面是不正确的。这些中方法只能给前台程序员更多的限制,不能随意写代码,不能提高他们的专业能力(因为受限)。所以我对这种开发模式的评价只有两个字:
专制

这种限制导致程序员生态的不平衡,后台程序员地位高高在上,虽然主要的工作量还在前台程序员那里。而且前台程序员不能自由的写代码,无法很好的提高。这明显是专制体制下导致的程序员阶级。

用了jCT和细粒度action,会发现后台超级简单,
好了前台程序员解放了,可以按自己的意愿写代码,提高自己的能力,待遇也要提高了。
虽然我是做后台的,但是同样我也解放了自己,我可以做更多其他的工作了,不用总是为别人制定规范了。

畅想一下,如果这种专制继续下去,不管语言如何发展,框架如何高能,都摆脱不了交叉规范的问题,程序员阶级势必存在。

最重要的,其实我真的一直在讨论的是一种模式,我不关系是不是什么新的,只要有效就行,对于这种模式的实现,我也仅仅是提供了一个很小的简短的工具和一个数据通讯的方法,在这种模式下具体的细节实现有很多方法,大家都可以实做一个。

0 请登录后投票
   发表时间:2008-06-08  
另外就是,新的jCT里面包含了一些更灵活的东西
0 请登录后投票
   发表时间:2008-06-08  
   或许是我现在做的都是小项目,对于你说的后台程序员高高在上制定规则的感触不是很多,我们在做项目的时候往往是后台程序员做到把服务器端模板写好(比如freemarker,没有css,有少量简单的js),然后把这个交给前台美工(在我们小组中,他们确实只是美工。。)。在这个过程中,你所谓的过多的沟通几乎没有,后台负责数据和模板制作(都是div),前台就写css和布局。我想很多小项目组都是这个流程吧。

  再反过来,如果按你的思路来,我们写完细颗粒action,然后让美工去操作这些json,虽然愿望挺美好,但是好像不太现实,首先对前台程序员的要求就提高不少,还有,如果在小项目中,这样反而增加了沟通,因为后台必须说明哪些action输出什么,而且有时候前台需要什么但是现在还没有这些action,那么就要告诉后台我需要什么,你给我弄个action,这难道不是增加沟通吗?

  你说设计的模式其实是很美好的,是很人性的,那个时候前台程序员也可以自由写程序,但是我们的老板不会这么想吧?老板要的是效率和成本。。。。

  再肯定下,你这种模式应该是可行的,但是如你那样完全通过解耦合,我始终觉得不是完美的解决方法,思索中。。。。。
0 请登录后投票
   发表时间:2008-06-08  
大项目我也没有做过。高高在上很简单,看工资,看谁主导项目就知道了。
我的团队中,美工是不会代码的,只是作图,写html/css的必须会javascript,他们属于程序员,
至于action多,增加了沟通的问题,实际情况是这样的。
首先所有的action应该都是和应用业务需求有关的,应该是在业务分析阶段就确定的。
以后有没有变化,项目组的人都应该了解这个内容,这个成本是无法下降的。
后台可以先输出模拟数据,这个很容易吧,再说实际上是后台好写,前台工作量大,后台总能先完成的。

效率问题我的几个项目里已经证明过了。在客户不停的改业务需求,改表现的情况下,通常是1,2个小时内就实现了他的变更需求。

完美我到不奢望,首先要达到自由。

还有就是我作为我们团队的领导人,有责任想办法提高他们的收入,多干活和提高自身水平是关键。
我现在的这个模式,为达到这个目的提供了一个基础。

由于这个模式也是最近我才确定的,所以也要多实践,前面实践的几个项目,都是边思考边实现的,很不成熟,现在思路基本成型了。我准备再次实做一个站,测试一下效率问题,
现在正在落实一些此模式下细节的思路,落实后,就可以开工了。
0 请登录后投票
   发表时间:2008-06-08  
achun 写道
另外就是,新的jCT里面包含了一些更灵活的东西
http://www.91mh.net/js/jct3.js
因为一些名字我还觉得不合适,没有更新,你可以测试一下。
参见一下变更的文章
jCT更新计划:inline,entry,outlet


好的。

另外,你有没有一个比较大的demo可以让我看看,或者说用这种模式开发的样例站,我要亲身体验一下。
0 请登录后投票
   发表时间:2008-06-08  
以前写的站就不提了,今天开始写了个新的站
http://www.16lo.com/
仅仅是输出了一行文字,不过整个流程已经明朗了。
0 请登录后投票
   发表时间:2008-06-08  
。。。。。好像没看懂。。。我js实在不行啊。。。
0 请登录后投票
   发表时间:2008-06-08  
chanawudi 写道
。。。。。好像没看懂。。。我js实在不行啊。。。


在firefox下用firebug配合查看

涉及的js文件


jquery-1.2.6.js ------- 这里面有一些hack 用 //achun 表明了,具体作用先抛开不讲
jquery-ajax-queue.js----ajax 队列插件
json.js-----------------JSON支持了
jct.js------------------我的jCT模板工具
lib.js------------------自己写的几个小函数里面有注释,注意一下几个方法


R
urlPath
processXDOC
serializeXML


app.js------------------自己写的适合具体应用的函数模块,注意一下几个方法
jsonQueue------------队列化的 ajax 请求,当然返回数据类型为JSON,


要注意的是这个使用options.callback作为处理接口的


$().ready------------这里就是开始了


这里面有一个契约编程,我一直在说分离,那么应该是前台主动向后台要数据,那么第一个POST数据就是

{entry:true}
 

也就是entry了,(我采用的队列使用值对里的KEY作为请求指示,用值做参数的,你不一定要这样),
后台看到entry的请求就知道了前台要程序的入口模板,所以返回了

{"entry":"/16lo/index.html"}
 

(KEY的一致性是我采取的方式,你不一定要这样)
前台就去调用/16lo/index.html文件,并用jCT解析执行.注意window.jct();这一句没有参数,看看
/16lo/index.html的内容就知道了(我把注释也加进去)

首先这是一个完整的html,这也就是jCT的特性 一致性 如果直接在浏览器地址栏输入 http://www.16lo.com/16lo/index.html 就会得到和结果一直的表现样式(当然我这个例子没有使用样式,不过很快你就会看到样式的)

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"  xml:lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Language" content="zh-CN" />
<title>快乐的春天</title><!--head段的title,link,style,script会被processXDOC正确的处理-->
</head>
<body>
<!--entry function(D){
	if(undefined==D) return jsonQueue({init:true},{callback:this});
	with(D)
-->
<!--outlet 
	$('body').html(__CTV__.join(""));
-->
<!--上面这两句就是jCT的entry和outlet语法了,说白了就是在模板里对页面上的数据获取和装配提供了支持,
里面的
if(undefined==D) jsonQueue({init:true},{callback:this});
是个小技巧,可以看出这个jCT实例其实被调用了两次,第一次是由$().ready里的window.jct();调用的,第一次由于没有数据所以不能正确表现,
所以利用if判断和{callback:this}参数在得到数据后进行第二次调用,也就是表现了。{init:true}当然就是向后台提出的请求了。
至于,$('body').html(__CTV__.join(""));就简单了,__CTV__是jCT实例执行后的结果,这里面就是把结果显示于body了
-->
+-init-+<!--这个简单就是后台打出的数据了-->
</body>
</html>
 

现在配合后台的php代码

foreach ($AQ as $Q=>$P){//$AQ是	$json=file_get_contents('php://input'); $AQ=json_decode($json,true);处理的来的。
	switch ($Q){
		case 'entry':
			se_Msg(se_webPath(dirname(__FILE__).'/index.html'));//entry入口模板文件
			break;
		case 'init':
			se_Msg('hello anmouse');//init的数据
			break;
	}
}

 se_Msg,se_webPath是我写的库函数,功能就简单了,

se_Msg--------负责输出JSON格式的数据

se_webPath--通过后台路径计算对应前台的路径

当然还有一些辅助性的处理没有给出,不过那不是重点,随应用的不同那些处理会不同的,关键的就都在这里了。

还有就是最初后台给出的html代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict

.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"  xml:lang="zh-CN">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta http-equiv="Content-Language" content="zh-CN" />

<style type="text/css">

	body{display:none}

</style>

<script type="text/javascript" src="/js/jquery-1.2.6.js"></script>

<script type="text/javascript" src="/js/jquery/jquery-ajax-queue.js"></script>

<script type="text/javascript" src="/js/json.js"></script>

<script type="text/javascript" src="/js/jct.js"></script>

<script type="text/javascript" src="/js/lib.js"></script>

<script type="text/javascript" src="/js/app.js"></script><title></title>

</head>

<body><p>搜索引擎支持</p></body></html>

 呵呵就是这样,主意里面默认body是display:none的,因为里面的

<p>搜索引擎支持</p>

不是让浏览器看的是专门对搜索引擎输出的数据(当然站建成后这些数据就具体了),也就是说通过在通讯的时候判断一些特殊的变量来区分浏览器和搜索引擎,php判断代码如下:

(说来失望,我这个前台模板的方案向很多朋友解释过,可是一听是对纯ajax支持才能发挥特点时就动摇了,因为ajax对搜索引擎支持的不好,我就奇怪了,程序员遇到困难就退缩,这.........,一怒之下,用了2个小时我就想到了解决方案,这不是很简单么!)

$JSON=count($_FILES)>0 || (isset($_SERVER['HTTP_X_REQUESTED_WITH']) and $_SERVER['HTTP_X_REQUESTED_WITH'] =='XMLHttpRequest') || isset($_GET['_']);

 $JSON为true就是浏览器,为false就是SE了,当然第一次不管是不是浏览器或者SE都要输出一次,

<p>搜索引擎支持</p>

这样的数据

 

最后就是由于我是利用XMLHttpRequest对象对模板进行解析的,但是可恨的IE有BUG必须要求Content-Type为application/xml,不支持application/xhtml+xml而且还不能在浏览器上直接渲染xhtml文件,只能用html文件(因为xhtml文件Content-Type为application/xhtml+xml),没有办法就hack了jQuery 的 ajax方法,

			if (s.dataType =='xml') {
				xhr.setRequestHeader("User-Agent", 'application/xml');
			}

 利用

User-Agent

告诉后台,我要返回Content-Type 为 application/xml,而不是text/html

我的web server用的是lighttpd,配套设置为

$HTTP["useragent"] =="application/xml" {
        setenv.add-response-header  = ( "Content-Type" => "application/xml" )
}

 当然用了mod_setenv

 

所有的要点都在这里了。

0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics