加入收藏 | 设为首页 | 会员中心 | 我要投稿 辽源站长网 (https://www.0437zz.com/)- 云专线、云连接、智能数据、边缘计算、数据安全!
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

透过现象看本质: 常见的前端架构风格和案例

发布时间:2019-10-15 17:35:22 所属栏目:优化 来源:_sx_
导读:所谓软件架构风格,是指描述某个特定应用领域中系统组织方式的惯用模式。架构风格定义一个词汇表和一组约束,词汇表中包含一些组件及连接器,约束则指出系统如何将构建和连接器组合起来。软件架构风格反映了领域中众多系统所共有的结构和语义特性,并指导

如果开发过Express、Koa或者Redux, 你可能会发现中间件模式和上述的管道模式有一定的相似性,如上图。相比管道,中间件模式可以使用一个洋葱剖面来形容。但和管道相比,一般的中间件实现有以下特点:

  • 中间件没有显式的输入输出。这些中间件之间通常通过集中式的上下文对象来共享状态
  • 有一个循环的过程。管道中,数据处理完毕后交给下游了,后面就不管了。而中间件还有一个回归的过程,当下游处理完毕后会进行回溯,所以有机会干预下游的处理结果。

我在谷歌上搜了老半天中间件,对于中间件都没有得到一个令我满意的定义. 暂且把它当作一个特殊形式的管道模式吧。这种模式通常用于后端,它可以干净地分离出请求的不同阶段,也就是分离关注点。比如我们可以创建这些中间件:

  • 日志:记录开始时间 ⏸ 计算响应时间,输出请求日志
  • 认证:验证用户是否登录
  • 授权:验证用户是否有执行该操作的权限
  • 缓存:是否有缓存结果,有的话就直接返回 ⏸ 当下游响应完成后,再判断一下响应是否可以被缓存
  • 执行:执行实际的请求处理 ⏸ 响应

有了中间件之后,我们不需要在每个响应处理方法中都包含这些逻辑,关注好自己该做的事情。下面是Koa的示例代码:

  1. const Koa = require('koa'); 
  2. const app = new Koa(); 
  3. // logger 
  4. app.use(async (ctx, next) => { 
  5.  await next(); 
  6.  const rt = ctx.response.get('X-Response-Time'); 
  7.  console.log(`${ctx.method}${ctx.url} - ${rt}`); 
  8. }); 
  9. // x-response-time 
  10. app.use(async (ctx, next) => { 
  11.  const start = Date.now(); 
  12.  await next(); 
  13.  const ms = Date.now() - start; 
  14.  ctx.set('X-Response-Time', `${ms}ms`); 
  15. }); 
  16. // response 
  17. app.use(async ctx => { 
  18.  ctx.body = 'Hello World'; 
  19. }); 
  20. app.listen(3000); 

事件驱动

事件驱动, 或者称为发布-订阅风格, 对于前端开发来说是再熟悉不过的概念了. 它定义了一种一对多的依赖关系, 在事件驱动系统风格中,组件不直接调用另一个组件,而是触发或广播一个或多个事件。系统中的其他组件在一个或多个事件中注册。当一个事件被触发,系统会自动通知在这个事件中注册的所有组件.

这样就分离了关注点,订阅者依赖于事件而不是依赖于发布者,发布者也不需要关心订阅者,两者解除了耦合。

生活中也有很多发布-订阅的例子,比如微信公众号信息订阅,当新增一个订阅者的时候,发布者并不需要作出任何调整,同样发布者调整的时候也不会影响到订阅者,只要协议没有变化。我们可以发现,发布者和订阅者之间其实是一种弱化的动态的关联关系。

解除耦合目的是一方面, 另一方面也可能由基因决定的,一些事情天然就不适合或不支持用同步的方式去调用,或者这些行为是异步触发的。

JavaScript的基因决定事件驱动模式在前端领域的广泛使用. 在浏览器和Node中的JavaScript是如何工作的? 可视化解释 简单介绍了Javascript的执行原理,其中提到JavaScript是单线程的编程语言,为了应对各种实际的应用场景,一个线程以压根忙不过来的,事件驱动的异步方式是JavaScript的救命稻草.

浏览器方面,浏览器就是一个GUI程序,GUI程序是一个循环(更专业的名字是事件循环),接收用户输入,程序处理然后反馈到页面,再接收用户输入… 用户的输入是异步,将用户输入抽象为事件是最简洁、自然、灵活的方式。

需要注意的是:事件驱动和异步是不能划等号的。异步 !== 事件驱动,事件驱动 !== 异步

扩展:

  • 响应式编程: 响应式编程本质上也是事件驱动的,下面是前端领域比较流行的两种响应式模式:
  • 函数响应式(Functional Reactive Programming), 典型代表RxJS
  • 透明的函数响应式编程(Transparently applying Functional Reactive Programming - TFRP), 典型代表Vue、Mobx
  • 消息总线:指接收、发送消息的软件系统。消息基于一组已知的格式,以便系统无需知道实际接收者就能互相通信

MV*

MV*架构风格应用也非常广泛。我觉MV*本质上也是一种分层架构,一样强调职责分离。其中最为经典的是MVC架构风格,除此之外还有各种衍生风格,例如MVP、MVVM、MVI(Model View Intent). 还有有点关联Flux或者Redux模式。

家喻户晓的MVC

程序员透过现象看本质:常见的前端架构风格和案例

如其名,MVC将应用分为三层,分别是:

  • 视图层(View) 呈现数据给用户
  • 控制器(Controller) 模型和视图之间的纽带,起到不同层的组织作用:
  • 处理事件并作出响应。一般事件有用户的行为(比如用户点击、客户端请求),模型层的变更
  • 控制程序的流程。根据请求选择适当的模型进行处理,然后选择适当的视图进行渲染,最后呈现给用户
  • 模型(Model) 封装与应用程序的业务逻辑相关的数据以及对数据的处理方法, 通常它需要和数据持久化层进行通信

目前前端应用很少有纯粹使用MVC的,要么视图层混合了控制器层,要么就是模型和控制器混合,或者干脆就没有所谓的控制器. 但一点可以确定的是,很多应用都不约而同分离了'逻辑层'和'视图层'。

(编辑:辽源站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读