防御性编程

2021/9/27 11:40:44

本文主要是介绍防御性编程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章转自豆皮范儿——防御性编程

引子

一个测试工程师走进一家酒吧,要了一杯啤酒;

一个测试工程师走进一家酒吧,要了一杯咖啡;

一个测试工程师走进一家酒吧,要了-1杯啤酒;

一个测试工程师走进一家酒吧,要了一份asdfQwer@24dg!&*(@;

一个测试工程师走进一家酒吧,什么也没要;

一个测试工程师走进一家酒吧,又走出去又进来又出去又进来又出去,最后在外面把老板打了一顿;

一个测试工程师走进一家酒吧,要了NaN杯Null;

一个测试工程师冲进一家酒吧,要了500吨啤酒;

一个测试工程师把酒吧拆了;

一个测试工程师化装成老板走进一家酒吧,要了500杯啤酒并且不付钱;

一万个测试工程师在酒吧门外呼啸而过;

测试工程师们满意地离开了酒吧。

然后一名顾客点了一份炒饭,酒吧炸了。

今天的主题就是 如何避免酒吧爆炸 防御性编程

防御性编程(Defensive programming)是防御式设计的一种具体体现,它是为了保证,对程序的不可预见的使用,不会造成程序功能上的损坏。 它可以被看作是为了减少或消除墨菲定律效力的想法。

保护我们的代码远离来自“外部”的无效数据,无论这个“外部”的概念被定位为什么。

以前端为例,大概包括以下方面

  • 后端接口

  • 字段变化、增减

  • 数据结构变化

  • 各种nullundefined之类的

  • 网络环境造成的问题

  • 用户输入和操作

  • 输入预期之外的内容

  • 非常规操作,如快速点击

  • 非常规环境,如慢网速环境

  • 模块/组件以外的数据
  • ...

防御场景举例(以JavaScript为例)

空值造成的相关问题

Uncaught TypeError: Cannot read property 'b' of undefined

Uncaught TypeError: fn is not a function

要时刻注意外部变量是否有值,下面是处理空值的几种方法

  1. 初始化值
// 逻辑或(||)操作符,会在左操作数为 假值 时返回右侧操作数。

const newData = data || {}

// 空值合并运算符(??) 是一个逻辑运算符。当左侧操作数为 null 或 undefined 时,其返回右侧的操作数。否则返回左侧的操作数。

const newDataAlt = data ?? {}

console.log(data.id)

  1. 使用 函数默认参数

函数默认参数在没有值或undefined被传入时使用默认形参

function divideBy(a, b = 1) {

return a / b;

}

divideBy(10, 2); // 5

divideBy(5); // 5

  • 注意 null或其他falsy值是被认为有值的
  1. 可选链操作符?.(Optional chaining)

如果链条上的一个引用是nullish (nullundefined),.操作符会引起一个错误,?.操作符取而代之的是会按照短路计算的方式返回一个undefined

if (this.props.data && this.props.data.list && this.props.data.list[0]) {

console.log(this.props.data.list[0])

// blabla...

}

// 使用 optional chain

if (this.props.data?.list?.[0]) {

console.log(this.props.data.list[0])

// blabla...

}

异步操作

setTimeout、异步请求等非同步代码的callback,需要特别注意异步操作前后的状态变化

  • 要注意dom元素是否一直存在,组件是否unmount,特别是有对canvas的操作的时候

  • 每个异步操作过程中的状态,页面上要有相应的loading

  • 初始化的loading

  • 按钮点击(防重复点击)

  • 网络较差的时候容易暴露loading相关的问题

JSON

Uncaught SyntaxError: Unexpected token } in JSON at position 13

处理json的时候,一般都要使用try catch捕捉错误

const json = '{"a":1,"b":2}';

let result;

try {

result = JSON.parse(json);

} catch (e) {

// handle error

}

其他语法错误

Uncaught SyntaxError: Invalid or unexpected token

  • 目前项目中均使用eslint,简单的语法错误可以自动提示而避免
  • this.someMethod或者this.state.someState的拼写错误,eslint无法查出来

外部攻击的防御

XSS

Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。

CSRF

Cross-site request forgery(跨站请求伪造)简称CSRF 或者XSRF, 其原理是攻击者构造网站后台某个功能接口的请求地址,诱导用户去点击或者用特殊方法让该请求地址自动加载。攻击者盗用了你的身份,以你的名义发送恶意请求。

对防御式编程采取防御的姿态

是不是防御式代码越多越好呢? No

  • 过度的防御式编程会使程序会变得臃肿而缓慢,增加软件的复杂度。

要考虑好什么地方需要进行防御,然后因地制宜地调整进行防御式编程的优先级。

  • 通用性防御措施 优于 细节性的防御

例如对于网络请求,一般是统一处理超时、鉴权、各种错误code,而不是在业务层个别处理

  • 根据使用场景,调整防御力度

如项目内部使用的utils函数和公开发布的package,后者防御要求更高

字节跳动数据平台前端团队,在公司内负责大数据相关产品的研发。我们在前端技术上保持着非常强的热情,除了数据产品相关的研发外,在数据可视化、海量数据处理优化、web excel、WebIDE、私有化部署、工程工具都方面都有很多的探索和积累,有兴趣可以与我们联系。



这篇关于防御性编程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程