重审业务逻辑
用过MVC的童鞋都知道业务逻辑(Bussiness Logic),但是大多对这概念又是模棱两可,业务逻辑从来都是这样难以理解,谈论前后端分离之前这个概念非常有必要探讨一下!
在简单的CRUD的系统中,基本上都是对数据进行增删改查操作,并没有多少业务逻辑可言;但像银行系统对金融数据的操作就显得不那么简单了,以转账为例:A给B转帐转100元,简易代码如下:
if(A.balance - 100 >= 0){
A.balance -100;
B.balance +100;
}else{
//返回异常信息
}
这串代码已经不仅仅是对数据的增删改查了,它包含了一些业务规则,比如A的余额如果少于100,这个代码会返回异常信息提示"余额不足",类似于这种,一组和特定领域业务相关而又不可拆分的代码,可以看作业务逻辑的实现。所以转账是作为一部个不可拆分的整体提供给用户的,也就是说Business层是不可能给你提供一个"A.余额+x"这种接口的,如果你想转账,请用转账方法,方法里面怎么对数据操作,你无需关心,你也没法关心。
=====
这里注意强调一下:页面/渲染逻辑和业务逻辑的区别,页面通常需要多个数据用来展示,比如网上银行界面即显示用户名、余额和转账记录等,这些信息的组合称作页面/渲染/展示逻辑,并不等于业务逻辑,业务逻辑只应提供基本的业务数据而不应该和页面逻辑掺和起来,就拿这个例子来讲,页面的这些数据,service层会提供三个接口来支持页面数据的产出,但并不会给你拼到一块给你,拼接不同的业务信息组合成一个View Object只能是脱离于service之外的层处理,在此特地分清页面逻辑和业务逻辑的关系
前后端定义
既然是谈前后端分离,就必须,必须,必须先划出前后端的定义,要不然谈来谈去,最后大家敢情不是说的一块事。其实前后端的概念真是一人一个看法,有人觉得和浏览器相关的技术这帮就属于前端,牵扯到了java代码的就属于后端;也有人觉得前段不仅包括浏览器技术栈线,还包括后台像jsp等模板技术相关技术也属于前端,后端纯粹是service那块的技术。在这里我说下我的看法。
不同人对前后端的定义的不同是因为看待角度的不同,有人以工作职责分,有人以技术栈分;这里我觉得应该以业务逻辑为分割线去分!(明白为啥我一上来先说业务逻辑了吧·—·)
为什么我会以业务逻辑去分割前后端的定义,这么说吧,一个系统的展现形式可能会有很多种:Web、Web Service、桌面客户端等,他们无一例外都是和用户直接打交道的,像网上银行的Web网页、手机APP,他们采用不同的技术和交互实现了与系统的交互,而整个系统有一部分是不随展现形式而变的——业务逻辑代码,也就说转账这个业务无论是在Web还是App中,对数据的操作逻辑是不变的,所以我们很自然的就会形成一个分隔:
最基本的一部分是专注与实现业务逻辑代码的实现,是不随展现形式而改变的;另一部分是用来给用户展现的,可能随着技术潮流改变而改变(说不定过一段时间就出VR版的网银了,哈哈);我称前者为后端,后者为前端。也就是说所有针对业务逻辑去实现的部分是后端,用来展现数据和用户交互的部分属于前端。
=====
对应到传统的MVC上来,service层就是后端,而service依赖dao层,dao层也属于后端,而Controller既不属于前端也不属于后端,他只是作为Server对外提供的一层HTTP访问方式的接口,是后端的门口;而Browser的技术栈线全都属于前端,这里前端并仅不限于browser,任何用于实现特定显示方式的部分都属于前端:比如我为了更好的将数据拼接成组合渲染逻辑对象,可以再加一层nodejs作为中间层,当然这也是划为前端。如下图:
图1
前后端分离
何为前后端分离?前后端本来不就分离么?这要从尴尬的jsp讲起。分工精细化从来都是蛋糕做大的原则,多个领域工程师最好在不需要接触其他领域知识的情况下合作,才可能使效率越来越高,维护也会变得简单。jsp的模板技术融合了html和java代码,使得传统MVC开发中的前后端在这里如胶似漆,前端做好页面,后端转成模板,发现问题再找前端,前端又看不懂java代码...前后端分离的目的就是将这尴尬局面打破。
什么是前后端分离?前后端分离说白了就是把前端和后端分成两个工程,由不同的团队负责开发,这样从工程和职责的角度上都有分开,这样,后端偏向于提供单纯的API接口,前端就是调用API接口进行展示和业务调用。
这样不仅将页面渲染和业务逻辑从server剥离开来,将页面渲染放给前端,甚至放给浏览器;将业务逻辑放给后台专心搞业务,降低了他们之间的耦合性,而且从职责上进行了分明,更适合大项目和大团队管理和开发。
解决方案
我也提不出什么解决方案,比较有名的属淘宝UED的中途岛项目,我谈谈我大概的实现方案。
首先Server端是RESTful风格的,简单的只提供API的访问接口;Browser端进行对HTML的展示,配合ajax异步请求和Angular、React等前端成熟框架进行页面渲染;但browser自己势单力薄,所以要多出一层处理数据的nodejs(不限死nodejs),用来处理页面逻辑数据、session、渲染初始页面等工作,所以大致的原理图如图1所示。
总结
前后端分离可能并不适用于所有情况。软件开发嘛,都知道没有最好,只有最合适,能用比较合适的手段去实现软件的目标,也算功德圆满了。
我记得我们班里有次活动,有两个小伙子被挑出来做游戏,每个人原地转10圈,再转晕之后,面前有两台电脑,导师开口出题,要求一分钟用java敲出一个菱形图案,其中一个马上大脑急速转动,分析规律,屏幕上只见他熟练的for循环语句敲的飞快,虽然有些许卡住,但是就在他敲得起兴的同时,另一位采用system.out.print()的方式,快速的敲了个菱形图案出来,不过被老师制止:"必须用for循环!",这句话对我就触动挺深,做软件究竟是为了水平的提高,还是真正的实现需求?
以上也只是个人的一些心得和看法,有任何不妥和错误的地方欢迎指出。