全栈开发

返回目录

前后端分离与全栈架构

好的程序员能够独立的解决某个技术难题,主动的关心项目进度与潜在瓶颈,能够负责模块小组,合理地分配任务,与项目经理、产品经理、美工、测试、服务端的同事高效包容地沟通。而衡量好的架构师的标准则是整个项目的工程化程度。众所周知,现在前端进入了一种爆炸期,各种技术框架百花齐放,各种应用场景天差地别,前端工程化个人感觉不仅仅是选定某个技术框架、选定代码规范、选定测试方案等等,工程化的根本目标即是以尽可能快的速度实现可信赖的产品。尽可能短的时间包括开发速度、部署速度与重构速度,而可信赖又在于产品的可测试性、可变性以及 Bug 的重现与定位。笔者感觉遇见的最大的问题在于需求的不明确、接口的不稳定与开发人员素质的参差不齐。先不论技术层面,项目开发中我们在组织层面的希望能让每个参与的人无论水平高低都能最大限度的发挥其价值,每个人都会写组件,都会写实体类,但是他们不一定能写出合适的优质的代码。另一方面,好的架构都是衍化而来,不同的行业领域、应用场景、界面交互的需求都会引发架构的衍化。我们需要抱着开放的心态,不断地提取公共代码,保证合适的复用程度。同时也要避免过度抽象而带来的一系列问题。当我们落地到前端时,笔者在历年的实践中感受到以下几个突出的问题:

  • 前后端业务逻辑衔接:在前后端分离的情况下,前后端是各成体系与团队,那么前后端的沟通也就成了项目开发中的主要矛盾之一。前端在开发的时候往往是根据界面来划分模块,命名变量,而后端是习惯根据抽象的业务逻辑来划分模块,根据数据库定义来命名变量。最简单而是最常见的问题譬如二者可能对于同意义的变量命名不同,并且考虑到业务需求的经常变更,后台接口也会发生频繁变动。此时就需要前端能够建立专门的接口层对上屏蔽这种变化,保证界面层的稳定性。

  • 多业务系统的组件复用:当我们面临新的开发需求,或者具有多个业务系统时,我们希望能够尽量复用已有代码,不仅是为了提高开发效率,还是为了能够保证公司内部应用风格的一致性。

  • 多平台适配与代码复用:在移动化浪潮面前,我们的应用不仅需要考虑到 PC 端的支持,还需要考虑微信小程序、微信内 H5、WAP 、 ReactNative、Weex 、 Cordova 等等平台内的支持。这里我们希望能够尽量的复用代码来保证开发速度与重构速度,这里需要强调的是,笔者觉得移动端和 PC 端本身是不同的设计风格,笔者不赞同过多的考虑所谓的响应式开发来复用界面组件,更多的应该是着眼于逻辑代码的复用,虽然这样不可避免的会影响效率。鱼与熊掌,不可兼得,这一点需要因地制宜,也是不能一概而论。

前后端分离

前后端分离的问题,不仅仅是技术上的选型问题,还涉及到整个团队在认知、职责、流程上面重新定义的问题,这也是为什么前后端分离概念看起来简单易懂,但真正团队在落地的时候却有诸多水土不服。笔者认为前后端分离最早可以追溯到 Roy Thomas Fielding 在博士论文 Architectural Styles and the Design of Network-based Software Architectures架构风格与基于网络的软件架构设计)中提出的所谓表述性状态转移(Representational State Transfer, REST )架构风格;该论文描述了指导 REST 的软件工程原则和选择用来支持这些原则的交互约束:

  • CS 架构:客户 - 服务器约束背后的原则即是关注点分离(Separation of concerns , SOC),通过分离用户接口和数据存储这两个关注点,我们改善了用户接口跨多个平台的可移植性;同时通过简化服务器组件,改善了系统 的可伸缩性。然而对于 Web 来说,最重要的是这种关注点的分离允许组件独立地进化,从而支持多个组织领域的 Internet 规模的需求。

  • 无状态:从客户到服务器的每个请求都必须包含理解该请求所必需的所有信息,不能利用任何存储在服务器上的上下文,会话状态因此要全部保存在客户端。其优势在于不必为了确定一个请求的全部性质而去查看该请求之外的多个请求,减轻了从局部故障中恢复的任务量,并且允许服务器组件迅速释放资源,在云端部署时能够完成弹性伸缩。其缺陷在于增加了在一系列请求中发送的重复数据(每次交互的开销),可能会降低网络性能;并且将应用状态放在客户端还降低了服务器对于一致的应用行为的控制。

  • 缓存:缓存约束要求一个请求的响应中的数据被隐式地或显式地标记为可缓存的或不可缓存的。如果响应是可缓存的,那么客户端缓存就可以为以后的相同请求重用这个响应的数据。

  • 统一接口:REST 架构区别于其他基于网络的架构风格的核心特征即是强调组件之间要有一个统一的接口,通过在组件接口上应用通用性的软件工程原则,整体的系统架构得到了简化,交互的可见性也得到了改善。实现与它们所提供的服务是解耦的,这促进了独立的可进化性。

  • 分层系统:分层系统风格通过限制组件的行为(即,每个组件只能 “ 看到 ” 与其交互的紧邻层),将架构分解为若干等级的层。通过将组件对系统的知识限制在单一层内,为整个系统的复杂性设置了边界,并且提高了底层独立性。

  • 按需代码:通过下载并执行 applet 形式或脚本形式的代码,REST 允许对客户端的功能进行扩展。这样, 通过减少必须被预先实现的功能的数目,简化了客户端的开发。允许在部署之后下载功能代码也改善了系统的可扩展性。通过在组件接口上应用通用性的软件工程原则,整体的系统架构得到了简化,交互的可见性也得到了改善。实现与它们所提供的服务是解耦的,这促进了独立的可进化性。

笔者认为对于前后端分离的理念有重要启发意义的即是 CS 架构与无状态这两个约束,传统的 BS 开发中因为使用了 Cookie-Session 这种存储模式,将数据的传输在服务端与客户端透明化;虽然方便了我们在服务端使用,却也导致了强耦合

服务端模板渲染(Aspx 、 JSP、PHP )、客户端渲染(ExtJS )与服务端渲染(ServerSide Rendering )这三类

笔者认为的前后端分离架构下的团队组织方式如下:

BFF 与 GraphQL

One of the basic problems with conventional REST is the failure of the client to demand a personalized data set. In addition to that, running and controlling multiple endpoints is another difficulty as clients are mostly needed to request data from diversified endpoints.

全栈工程师