番外篇:后端程序的特殊性在哪里

文章目录

    • 程序数据的特殊性
      • 场景一:外部数据
      • 场景二:内部数据
      • 场景三:软件一般意义上的场景
    • 程序场景的特殊性
    • 针对程序结构的必要说明
    • 针对应用场景的特殊性

程序数据的特殊性

从抽象层面来看,前端是数据的展示层,后端是数据的提供者。而数据的来源,主要分为两大块:程序内部数据和外部数据。内部数据指的就是程序自身运行进程中保存在内存的数据,外部数据指的就是程序从其他地方获取到的数据。外部数据一般来源为:

  • 数据库
  • 第三方缓存
  • 第三方服务

如果从程序设计角度来看,大家公认的程序本身可以分成两部分:数据结构 + 算法。对于后端来说,又可以分为三个场景。

场景一:外部数据

在该场景中,数据结构就是数据表的设计,包括:关系型数据表及非关系型数据存储的设计;而算法就是如何操作这些数据。该场景下,数据结构的设计是最关键的。

场景二:内部数据

在该场景中,数据结构就是实现一项功能所涉及到的类之间的结构。即通过定义每个类的成员变量和方法,规划类之间的组合继承等关系来实现数据结构的整体设计。
而算法,则是实现一个功能时内部对象之间交互的流程,通常可以使用UML的时序图表现。
该场景下,二者平衡。

场景三:软件一般意义上的场景

即软件开发人员通识的算法与数据结构的概念。系统中涉及到一些特殊功能项的时候,会采用特殊的处理方法来实现优化的目的。该场景下,偏向于算法设计。

后端程序与其他应用程序最大的区别之一就在于后端更偏向场景一,即外部数据非常重要,所以在一定程度上来说是面向数据库编程。

程序场景的特殊性

后端每个API都是可以出现并发场景的,即一个API可能被多个应用同时访问,并且这个访问量可能会变得很大。不像APP、web等客户端程序,虽然会遇到并发问题,但不是核心。

基于性能的考虑,如果频繁创建的大的对象,由于对象占用的是堆内存空间,而堆内存空间正是垃圾回收器的主要处理点。在并发数高的场景下,会导致频繁执行全量垃圾回收操作,即内存频繁出现大块的搬运处理,最终表现就是API响应卡顿或者内存溢出导致服务器挂掉。

正是由于存在上述的特殊性,使得后端程序在设计时会优先考虑避免大对象的频繁创建,也就是最好只创建一次,通过复用该对象实现业务处理(这里,大和频繁是两个重点)。那么这一方案引出了两个关键点:

  1. 大的对象本身不能保存状态,否则会出现并发数据共享的问题;如果加锁处理,会严重影响程序性能(并发数高的情况下)。
  2. 针对这类对象,保证运行期间只创建一次,即类似于单例模式实现,这点Spring已经提供支持,这也是为什么Spring托管的对象默认都是单例的。

这也就是为什么目前开发后端项目时,开发人员所熟知的Controller、Service、Dao这三层结构的类,他们的实现类都只创建一个对象,并且不保存状态(即不存在保存数值的成员变量)的一个重要原因。

至于这三层结构的划分,则是基于后续体量大的一种考虑方案,并不是最优解,但是最常见的分层。

针对程序结构的必要说明

基于上面两个解释,总体来看:
将程序的核心层级划分为常见的三层,并且保证每个类都是单例类(Spring 已经帮我们实现了)。

针对一般性的CURD操作,只要保证数据表设计良好即可。设计良好意味着三个方面:实用性、扩展性和性能优化。

针对复杂的业务设计,就要考虑类之间的耦合性、扩展性等。并且,会频繁创建并且不需要保存状态的类能设计成单例类(加上 @Component注解)就设计成单例的。

当然,上述只是理想下的实现,涉及到实际业务还是要符合实际的复杂情况。

针对应用场景的特殊性

为了保证连贯性有必要补充说明一下后端应用场景的特殊性。后端所提供的服务具有两大特性:

  • 持续服务不间断
  • 不论服务多少客户,对外表现都是相同的

由这两个基本点出发,引出了服务端的一系列问题:要想保证不间断服务,必须通过各种层面的冗余措施来提升系统的可靠性;要想保证性能平稳,即对外表现稳定,那么就要结合实际场景针对不同子系统设计压力处理的方案。而服务整体的可用性,则需要监控系统和测试系统以及发布系统等提供保障。

所以,我们一般设计从三个角度出发:

  • 软件本身的设计
  • 系统的设计
  • 项目整体的设计

文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览92065 人正在系统学习中

来源:oatlmy

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2019年9月8日
下一篇 2019年9月8日

相关推荐