如何优雅做系统错误提示?

这里是Z哥的个人公众号

每周五11:45 按时送达

当然了,也会时不时加个餐~

我的第「149」篇原创敬上

大家好,我是Z哥。

不管是日常的工作中还是生活中,我们每天会用到很多软件系统。

不知道你有没有过这样的感受,当你使用软件遇到异常的时候,有时候软件给出的错误提示让人摸不着头脑。唯一的办法就是复制到搜索引擎搜一下,看看有没有哪个不幸的人与我遇到一样的问题。

所以,一个好的错误提示特别重要。它不但能让使用者明白当前到底发生了什么,甚至还能引导如何解决异常。达到这个程度的话自然可以大大提高系统的使用效率,也能间接降低己方商务人员或者产品经理的培训成本。

因此,作为程序员群体的一份子,在这里我想呼吁大家认真对待错误提示,特别是那些不是给“人”看的错误提示……

作为软件的创造者,我们虽然无法避免出现异常、出现bug,但是我们可以做到避免无意义的错误提示产生。

首先,一些常见的容易让人摸不着头脑的错误提示要先避免。比如,

  • 提交失败。

  • 数据读取失败。

  • ……

这类错误提示看上去准确表达了当前遇到的问题,实际上啥也没说。你想象一下,当我点击一个提交按钮之后,页面没有跳转而且还弹个框出来,哪怕里面什么字都没写,我能也猜到这里估计出错了。

但是具体错在哪?作为用户该如何处理?一概不知。

另外,还有一种常见的情况是,错误提示含有太多的技术术语,使用者根本不明白啥意思,也不关心这些。比如,

  • 远程服务响应超时。

  • 事务执行失败,XX保存失败。

  • ……

其实这还算好的,有的甚至把技术框架中返回的expcetion信息直接作为错误提示出来。这对用户看起来就是一堆乱码,他只会找你说“系统乱码了,帮我解决一下……”。

如果上面的景象就在你日常工作中发生,也不用不好意思,我们都是这么过来的。Z哥我自己以前也同样没意识到这个问题,经过了这些年的工作之后,我认为,编写正确的错误提示可以按照以下的思路来。

/01 不要提示用户不关心的信息/

首先来个排除法。

我们作为程序员经常需要通过一些技术性的线索来排查问题,特别是expcetion信息。但用户并不关心它们,而且他们无法对此类消息进行任何处理。

所以,这些信息记录到日志里就好,页面上无需给出这种用户不关心的信息。

/02 清楚表达问题原因/

让用户清楚的知道问题的原因,是他能否自行解决问题的基础。

比如,前面提到的“提单失败”的例子,你告诉他由于缺少XX信息导致提交失败,那么使用者自然会去想办法把缺少的信息给补上。

我还记得我之前用某个邮箱的时候,有封邮件发不出去,它总是提示我“邮件发送失败。”我真是服了,到底啥原因发送失败,后来经过自己不断的测试才知道是某个附件太大了导致发送失败。

/03 给出引导建议/

这点在一些企业内部使用的系统,以及一些toB的项目中特别重要。因为大多数系统使用者都只负责自己工作相关的部分,对其他的模块并不了解。所以,哪怕你将问题的原因表达的很清楚,但是他还是不知道该如何解决,只能寻求产品经理或者开发人员的协助。

比如,电商平台的客服在后台替用户修改订单收货地址的时候,发现某个地区下没有可用快递可选。如果你没有给出引导,诸如“联系XX人员进行设置。”之类的内容,那么他们只能来找你解决,无其他路可走。

如果想做得更好一些,针对某些场景可以直接放出下一步操作的连接,这样用户可以直接到达需要他进行操作的页面。

/04 提示内容尽可能简短/

文字一多,大多数人都不会逐字逐句看的,甚至有些人会完全不看。

Z哥工作中遇到过无数次这种情况。不管是错误提示还是操作提示,不管你写的多么详细、清楚,只要文字超过2行或者有几十个字以上,很多人看都不看直接截个图发给你,问你该怎么办?

听说有个美国机构做过相关的研究:

如果句子中的单词数不超过8个,读者可以理解其中的100%。

如果句子包含43个单词或更长的单词,则读者的理解力将下降到不足10%。

美国某研究机构

虽然这个研究说的是英文,但是中文也是类似的道理。不过我没找到这个研究的具体出处,不知道真假,但是我觉得这个结论还是很符合常识的。

以上这4点说起来简单,也很好理解,没什么新奇的。但是真正做的时候很多人就把它们抛之脑后了。

当然,比给出合理的错误提示更好的是,避免出现错误。所以你还可以更进一步,提前规避掉一些错误。

比如,

  • 为了避免日期选择超过有效范围,可以对有效范围外的日期设置为禁用状态。

  • 为了避免在信用卡卡号之类的文本框内输入数字以外的字符,做一下输入限制。

  • 为了避免在弱网络下页面无法正常加载而提示错误,可以做缓存,提前预存一些数据在本地。

  • ……

好了,总结一下。

这篇呢Z哥和你分享了我对软件系统抛出的错误提示的看法。我认为好的错误提示需要符合以下4点。

  1. 不要提示用户不关心的信息

  2. 清楚表达问题原因

  3. 给出引导建议

  4. 提示内容尽可能简短

如果可以的话,还可以通过做一些前置的限制约束来提前规避掉一些可能发生的异常。

希望对你有所帮助。

推荐阅读:

  • 怎么开会才不浪费时间?

  • 真的是计划赶不上变化吗?

原创不易,如果你觉得这篇文章还不错,就「在看」或者「分享」一下吧。鼓励我的创作 :)

如果你有关于软件架构、分布式系统、产品、运营的困惑

可以试试点击「阅读原文

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/308987.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

搭建一套ASP.NET Core+Nacos+Spring Cloud Gateway项目

前言伴随着随着微服务概念的不断盛行,与之对应的各种解决方案也层出不穷。这毕竟是一个信息大爆发的时代,各种编程语言大行其道,各有各的优势。但是有一点未曾改变,那就是他们服务的方式,工作的时候各司其职&#xff0…

如何在ASP.NET Core中集成ElasticSearch

本文来自:https://www.blexin.com/en-US/Article/Blog/How-to-integrate-ElasticSearch-in-ASPNET-Core-70图片我敢打赌,您肯定会被要求向Web应用程序中添加高级搜索功能,而且通常是全文的类似Google的搜索。在技术电子商务的开发过程中&…

了解下C#由转换二进制所引起的思考

【导读】最近遇到很有意思转换二进制的问题,有部分童鞋俨然已了解,可能也有一部分童鞋没碰到过也就不知情,这里我们来深入学习下转换二进制所带来的问题。在写此篇文章时,非常开心,收到再一次连任MVP的邮件&#xff0c…

如何利用.NETCore向Azure EventHubs准实时批量发送数据?

最近在做一个基于Azure云的物联网分析项目:.netcore采集程序向Azure事件中心(EventHubs)发送数据,通过Azure EventHubs Capture转储到Azure BlogStorage,供数据科学团队分析。为什么使用Azure事件中心?Azure事件中心是一种Azure上…

C++实现二叉树

代码如下: #include<iostream> #include <queue> #include <stack> using namespace std;class BinTree { private:class TreeNode{public:int data;TreeNode *left;TreeNode *right;TreeNode ():data(0),left(nullptr),right(nullptr){}TreeNode(int e):da…

MySql :Could not create connection to database server.

错误&#xff1a; Exception in thread “main” org.apache.ibatis.exceptions.PersistenceException:Error querying database. Cause:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. The error …

Vue 3拖更,尤雨溪介绍最新进展

Vue.js 作者尤雨溪近日介绍了 Vue 3 的最新进展。尤雨溪表示&#xff0c;由于在 Vue 3 上花费的大部分时间都投入到了设计和构建稳定的内核上&#xff0c;不过要让整个框架处于"ready"状态&#xff0c;不仅仅是内核的问题&#xff0c;还需要有兼容版本的支持库 &…

Mysql@和@@符号的详细使用说明

一、概述 是用户变量&#xff0c;是系统变量。 二、使用语法及实践 用户自定义变量 1、用户定义变量语法 SET var_name expr [, var_name expr] 如&#xff1a;set t1 100; 2、获取用户定义变量值方式&#xff0c;如&#xff1a; select t1 from dual; 如下图 系统变…

探讨NET Core数据进行3DES加密或解密弱密钥问题

【导读】之前写过一篇《探讨.NET Core数据进行3DES加密和解密问题》&#xff0c;最近看到有人提出弱密钥问题&#xff0c;换个强密钥不就完了吗&#xff0c;猜测可能是与第三方对接导致很无奈不能更换密钥&#xff0c;所以产生本文解决.NET Core中3DES弱密钥问题&#xff0c;写…

C++实现表达式树

代码如下: #include <iostream> #include <string> #include <stack> #include <queue> using namespace std;class Tree { private:class Node{public:char val;Node * left;Node *right;Node(char val):val(val),left(nullptr),right(nullptr){}Nod…

redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作

前段时间在做用户画像的时候&#xff0c;遇到了这样的一个问题&#xff0c;记录某一个商品的用户购买群&#xff0c;刚好这种需求就可以用到Redis中的Set&#xff0c;key作为productID&#xff0c;value就是具体的customerid集合&#xff0c;后续的话&#xff0c;我就可以通过p…

IDEA如何在包下建立子包

idea如何在包下建立子包 第一次在包下建立子包时候出现了问题 在java > springmvc包下再new上一个package controller的时候就会出现这个样子 如何解决 在IDEA2019 中的Show Options Menu下有一个Compacket Middle Packages将它关闭即可 解决成功

.NET Core微服务开发选项

微服务开发的关注点有哪些&#xff1f;微服务构最终的目标是实现业务的价值&#xff0c;交付&#xff0c;为了让开发人员更加关注业务开发和交付&#xff0c;微服务需要一些比较底层的基础设置&#xff0c;我们也称为微服务公共关注点。配置管理&#xff1a;对微服务可变参数进…

gRPC真要取代WebApi了,你还学得过来吗?

今年1月份微软曾宣布要实验性的对.NET支持 gRPC-Web&#xff0c;然后在6月份已经正式发布了。这些天尝试了下&#xff0c;真的很强大&#xff0c;不负责任的预言下&#xff0c;RESTful的时代即将过去&#xff0c;而gRPC要成为革命者&#xff01;先别急眼&#xff0c;下面我来详…

Spring5 jar包下载

下载地址 https://repo.spring.io/simple/libs-release-local/org/springframework/spring/ Spring5最新版本的下载 选择最新版本5.2.3 下载前两项&#xff0c;解压放入文件夹中 项目中导包 ps&#xff1a;我使用的开发工具是idea 第一步&#xff1a;在file中选择project st…

优化 Azure 成本,实现财务目标

点击上方蓝字关注“汪宇杰博客”原文&#xff1a;Omar Khan General Manager, Microsoft Azure翻译&#xff1a;汪宇杰导语我们的许多客户都面临着如何满足关键 IT 项目的资金需求的困难决策。我们在此共同帮助您实现财务目标。确保 Azure 工作负载的成本得到优化有助于释放资金…

采用config方式灵活配置我们的Quarz.net中的Job,Trigger

经常在项目中遇到定时任务的时候&#xff0c;通常第一个想到的是Timer定时器&#xff0c;但是这玩意功能太弱鸡&#xff0c;实际上通常采用的是专业化的第三方调度框架&#xff0c;比如说Quartz&#xff0c;它具有功能强大和应用的灵活性&#xff0c;我想使用过的人都非常了解&…

对于任给的一张无向带权连通图,求出其最小生成树(C++)

对于任给的一张无向带权连通图&#xff0c;求出其最小生成树。 题目要求: (1)编程创建一幅图 (2)输出创建的图 (3)编写Prim算法代码&#xff0c;实现图的最小生成树求解&#xff0c;且输出最小生成树 (4)编写Kruskal算法代码&#xff0c;实现图的最小生成树求解&#xff0c;且…

使用.Net Core实现的一个图形验证码

SimpleCaptcha是一个使用简单&#xff0c;基于.Net Standard 2.0的图形验证码模块。它的灵感来源于Edi.Wang的这篇文章https://edi.wang/post/2018/10/13/generate-captcha-code-aspnet-core&#xff0c;我将其中生成验证码的代码抽取出来进行封装得到了这个模块。下面介绍一下…