面向错误编程

背景

公司有一个应急系统,管理各种类型的应急策略,前端代码质量一言难尽。最近有新需求,领导要求梳理主机异常应急策略,为此我们给系统添加一种新的策略类型——主机异常应急策略。

后端加上新类型后,您猜咋滴?前端好几个页面白屏了!只要数据里有新类型的策略就会!

我看了看代码,您猜咋滴?问题出在策略类型标签上:类型字段后端为英文常量,前端将其展示成一个中文标签。由于类型有好几种,前端用一个字典来映射渲染函数,代码大致如下:

1
2
3
4
5
6
7
const strategyTypes = {
  Link: () => <Tag color="magenta">链接</Tag>,
  CheckList: () => <Tag color="orange">确认表</Tag>,
  Card: () => <Tag color="green">应急卡片</Tag>,
  Routine: () => <Tag color="cyan">常规应急操作</Tag>,
  Host: () => <Tag color="red">主机异常策略</Tag>,
};

这倒无可厚非,采用字典这种配置化的数据结构,添加新类型时只需加上对应配置项即可。

问题出在数据渲染环节上,策略类型是表格中的一列,列配置如下:

1
2
3
4
5
6
{
  title: '类型',
  dataIndex: 'Type',
  key: 'Type',
  render: (type: string) => strategyTypes[type](),
}

render 函数负责根据 type 类型字段,渲染出对应的组件。它先以策略类型为键从字典中取出渲染函数,然后调用渲染函数。结果后端添加了新类型支持,前端的配置字典忘了更新,取出的渲染函数是空的,于是乎抛异常!

这其实是一个很低级的错误,任何数据都必须检查是否为空,并妥善处理。借助可选链操作符可以轻松实现这点:

1
(type: string) => strategyTypes[type]?.()

这个 render 函数先根据 type 字段从字典中取出渲染函数,渲染函数非空时才调用,否则直接返回 undefined 。在 React 中,undefined 被视为空节点,不会渲染出来。这样一来,就算配置字段漏了新策略类型,也只是不显示,页面不会直接挂掉!

说到底,编程是一项面向错误的工作,要时时刻刻跟非预期的情况作斗争,不能想当然。因为,我们需要面向错误编程,未雨先绸缪:

  • 这个数据可能为空吗?如果数据为空,我的程序会挂吗?
  • 这个网络请求可能失败吗?如果请求失败,我的程序会怎样?
  • 如果用户不按常规出牌,点了另一个按钮,我的程序会怎样?
  • etc

订阅更新,获取更多学习资料,请关注我们的公众号:

【随笔】系列文章首发于公众号【小菜学编程】,敬请关注: