关于服务端开发,你还在使用哪些过时的技术?

背景

随着对功能需求越来越多,越来越智能和错综复杂,业务逻辑应该越清晰简单快捷,然而大部分的开发者还停留在上个世纪一样没有走出来,把简单的业务流程交错,导致代码重用率低,很难开发出强大功能的应用来。

开发效率低且增加需求后无法继续做下去,几乎成为业界普遍现象。仅因为把简单的事情复杂化了。


那么作为新时代的开发者,应该使用什么样的架构和开发模式呢?

摈弃旧技术,使用新技术

一、使用MVVM,而不是MVC

MVC模式 是视图V、模型M、控制器C,控制器C的作用是选择数据模型M绑定指定到视图V渲染给前端用户看。
MVVM模式 是模型M、视图V、视图模型VM,视图V和模型M通过绑定器进行通信。而视图模型VM决定了视图呈现的方式。

很多人说:“我了解MVVM啊,我也在用MVVM,而不再是MVC了”
但是很多人在开发服务端的思维模式,依然不是前后端分离的接口模式,而是MVC模式,比如说还在使用控制器C和模型M,仅仅是单纯的视图V分离出来。如果说这也算是前后端分离了,那确实是,但是不难发现开发并没有简单,反而更复杂了,仅仅是单纯的让前端人员的工作量变多了而已。


那要怎样才是充分发挥MVVM模式的优点?
首先,服务端应该仅仅是提供M,也就是数据,不应该做其他的控制。如果说前后端分离了,那么服务端的开发模式应该是ACM,而不是CM,更不是CMS(控制器C + 模型M + 服务S)

注解:服务S是许多开发者在对外部API和复杂模型的处理。

在前后端分离的开发模式下,服务端需要专注的仅仅是数据交互的问题,也就是前端和数据库端之间的通讯。

说白了,服务端就只是负责对数据增删改查和通知的工作。
这样不仅通讯更加快捷,而且编写起来也相对简单。所以服务端最重要的就是数据M。
如果需要给服务端采用一种开发模式,那么就应该是ACM。


那么服务端为什么要采用ACM模式呢?什么又是ACM模式?
ACM模式 是接口A、验证C、模型M,接口A负责统一接收和响应前端消息。验证C负责校验调用接口时传递的参数和前端身份权限验证,M则负责处理数据,也就是数据的增删改查。

提供一个API接口,最重要的是接口传参的安全问题

备注:如果是分布式结构(例如GRPC),那么web端的验证C负责身份权限验证,应用端的验证C仅负责校验传递的参数。

真正的前后端分离,服务端应该是仅提供web API给前端,前端通过调用不同的web API和传递不同的参数来实现对数据的交互。


二、使用脚本语言开发,而不是编译语言

作为一名经过了php、易语言、C#、python、nodeJS的开发者,开发使用的编程语言选择可以说是深有体会,在客户端的软件开发方面,我们可以选择Objective-C、C++、C#、java,这样可以确保我们的开发应用编译加壳后可以不被其他人破解、反编译,而且运行速度较快。

但是在服务端开发时,我们必须要选择脚本语言php、python或nodeJS,因为服务端不比客户端,如果服务端的功能出现问题,再重新打个包上传上去会很麻烦,万一打错了一个版本,或者有BUG没有修复,那么就不得不重新再打个包,这样在已运行的线上时极为不利的,尤其是电商、游戏服务端,说是要临时关闭服务可能丢失大量用户群体。

很多人说:“我们公司的服务端也是用脚本语言开发的” ,但是你公司开发的服务端有没有充分发挥脚本语言开发的优点呢?


三、使用低耦合、可同步的开发方式

脚本语言开发的优点是:无需编译,开发速度快,易维护、易部署,低耦合,可同步操作。
但是却很多人把易维护、易部署、低耦合应搞成了难维护、难部署,高耦合,无法同步操作。

比方说,一个nodeJS + Koa的服务端,硬改成了路由R + 控制器C + 模型M + 服务S,通过路由R脚本文件关联所有路由路径和控制器,那么每次增加一个功能,就需要修改R文件,在该文件引入新的控制器脚本C并为它绑定路由,这样不仅极为不方便,而且不容易溯源。
更无法同步操作,比方说有开发者甲和乙两人同时给该服务端添加新功能,这是一种常见的协作方式,但是两个人在开发时都需要修改路由R脚本文件,这时,如果Git或SVN就会导致冲突,所以极为不便。正确的做法应该是遍历引入目录下的指定后缀名文件,例如:*.api.js,然后脚本文件中独立注册路由,这样不仅耦合度低,而且不需要某块功能或路由时,直接删除即可。

也有人说:这样会不会好查看路由和业务脚本的关系?比方说,我有50个路由和50个业务要实现,总之就是很多路由,那么这样会不会不好找?


四、充分发挥目录结构和命名的特长,而不是随意起名

如果想知道一个路由的对应哪个功能模块,可以使用路由机制自带的函数查看,每个路由机制都可以查看所有路由。但是在定义目录结构和给文件起名时,最好还是与业务和数据表名相关的。
例如:数据表名cms_article_channel ,是内容管理系统文章频道表,那么在创建目录时应该路由设置为/cms/article_channel,然后在article_channel目录下放置main.api.js文件。
然后把文章频道相关的增删改查函数都写在main.api.js文件中。
通过main.api.js文件统一注册文章频道的增删改查路由。

为了更方便查询,还可以统一命名增删改查等,例如add增、del删、set改、get查、upload上传、download下载、load载入、save保存、update更新、install安装、uninstall卸载、clear清空。

那么要查询文章频道的路由路径为/cms/article_channel/get
其对应的脚本文件就是/cms/article_channel/main.api.js
其对应的函数就是get

这样不仅容易溯本寻源,还能提高路由检索速度,和人找到响应模块的速度。
并且,如果对一块业务使用统一的路由规则,那么要这对块业务做监听拓展也将十分容易。
例如要统计某篇文章的被访问次数,那么可以挂载到/cms/article/目录下名为before.api.js函数中,然后加载路由所有before.api.js文件时优先加载,只要不做响应即可。
除此之外,还可以before.api.js还可以改变请求参数,做格式转换等。同理,如果要对某一块业务返回数据格式做转换或请求成功的次数做统计,只需要写在after.api.js脚本下。


五、使用低耦合度的插件机制,而不是把功能某个部分混在一起

在编译语言开发时,为了解决开发时需要重启、关闭的问题,于是想出来热拔插的概念,也就是需要的时候安装、不需要的时候卸载的插件机制,这样不仅将功能独立,降低耦合度,对于后期拓展业务,也是极为方便。

但是在脚本语言开发时,很多人没有引用插件机制的概念,还把本应该耦合度低的开发方式硬生生的变成高耦合度的开发方式。比方说之前所说的把所有路由卸载一个脚本里面,而不是遍历目录或文件检索路由的方式,也不是通过插件机制注册的方式,弄得一个脚本语言开发服务端,反倒需要重启服务端才行。

脚本语言开发的服务端如果需要重启,那么还不如编译型语言开发的服务端,因为编译型语言开发的服务端虽然不好维护,但至少性能上不输给脚本语言。

对于模块化开发,很多人只是用到了引入模块功能,而没有用到卸载模块功能。其实,脚本语言的模块也是可以动态卸载的,对此我们需要充分利用它的卸载功能。
在程序设计上,首次启动我们要遍历一次路由文件,然后对某个路由下相关的脚本改变时,通过API接口传递指令的方式进行卸载、重新引入模块。

备注:也有部分前沿的开发者使用监听文件变化的方式,个人建议开发阶段可以使用监听方式,部署上线时使用API方式。API方式存在被刷风险,需要做权限验证,而监听方式更耗内存,因此各有利弊。


六、充分发挥弱语言不用定义类型的优势,而不是定义成强语言

除了以上开发,还有的就是硬给弱语言定义了数据类型,引用了什么模块使得跟强语言似的,但是这样不仅编写不方便,而且增加了维护成本。
许多开发者还容易对弱语言和强语言有误解,弱语言的优势是不用定义类型和数据模型,使用更为方便,坏处是类型判断时可能因为 == 和 === 问题导致出错,但是如果硬要把数据定义成强语言,那么就犯了个很大的错误,例如从msyql数据库查询一条数据,是什么类型的就会返回什么类型的值,如果还需要给这个值做定义一个强模型,那么在业务需求变更时,就必须要重新修改业务脚本和模型。

而如果使用模型生成数据库的功能模块,更有可能导致数据库中的数据丢失。因此不建议给弱语言定义模型,即使是像python这样的强语言脚本,也可以是查询回的数据就是什么类型,不需要再定义。
至于模型和数据库的字段问题,应该是直接在数据增加字段,一般情况下,增加的字段如果不需要作为查询条件,可以不用更改模型。


七、使用脚本 + 配置文件,而不是把所有东西都写在脚本里面

传统的开发是把路由路径、用户权限验证、传递参数验证、SQL查询方式统统都写在了一个脚本里,这样不仅代码零乱,业务逻辑不清晰,而且管理起来极为不便。

对于脚本,只需要做业务逻辑,可以把路由接口、参数的格式规范、返回的格式规范,SQL操作方式都用json文件放置。命名及如下:

api.json 放置路由信息,路由路径、标题、用户身份权限
param.json 放置传递参数的名称、标题、类型、格式、长度
sql.json 放置对增删改查的sql语句拼接片段和方式

这样,我们就可以通过遍历的方式首先载入所有api.json信息,然后加载指定的路由脚本文件和其他配置信息,这样不仅业务脚本更简约,让开发者思路更清晰明了,还更容易实现强大的功能。
并且有了api.json和param.json文件,就等于有了API文档,只需要一个api接口和页面将其呈现出来即可。


八、充分发挥query传参和body传参的特点

在前端和服务端交互时,有query和body两个位置可以传参,但是没有多少人充分发挥它们的特点。例如:增删改查,
许多人指知道在删查的时候用query传参,在增改的时候通过body传参,但是最佳的传参方式应该是通过增改时可以通过query+body传参。
修改时,服务端通过query判断哪些数据要被修改,然后通过body来确定修改哪些字段的值并赋值。
而当没有query的情况下,那么服务端就可以判断为是增加一条数据。
这样的好处是前端可以传递条件批量修改数据,同时跳转路由页面的时候,直接把url中的query部分传给服务端。那么在前端的后台管理的列表页和表单增改页就能充分发挥效果,并且前后端都更加省事。


九、使用事件机制和生命周期,而不是将所有业务写在一起

正如之前你所说的路由文件命名,有main.api.js、before.api.json、after.api.js,这就是一个最基础的生命周期。就如现实一般,一个事情发生前,发生时,发生后分别对什么产生了影响。

那么除此之外,还有什么呢?准确点说,大自然界的是机制是什么样的?服务端的事件机制就应该是什么样的。
一个事件发生的全过程应该是经过三个阶段、分别是验证阶段check、行为阶段action、渲染阶段render,check阶段判断一个事情是否满足触发条件,是否会发生,行为阶段是确定了该事件会发生什么,而渲染阶段则是该事情的发生传达给人们什么。
一个事情的发生和传达给人们的信息可能是不同的。例如一个人买了本田车花销20万,而传达给别人时可能只剩下某某人买了辆本田车。
所以,渲染阶段负责的是过滤或补充数据,以及确定返回的数据内容格式,常见的格式有json、xml、html、form-data。


总结

作为人工智能和大数据的新时代的服务端开发者,需要掌握最前沿的开发技术,用最轻量+优雅的开发框架和开发模式来编写程序,才能做出最佳性能的服务端。并且在新时代下的开发者,一定要有协同开发的概念,要充分发挥分工合作的开发特点,做好代码可重用、低耦合度的高效开发思想。

你可能感兴趣的:(开发技巧)