为 Web 应用程序设计交互式错误处理

用户与 Web 应用程序交互时,总是不可避免地会发生错误。您的应用程序必须确保所输入的数据是有效的,如果不是,应用程序必须明确地告诉用户数据无效的原因,并使用户能够轻松修正问题。同时利用客户端和服务器端错误处理策略,确保数据的有效性,并为用户提供友好的错误追索功能。

可用性大师之一 Jakob Nielsen 有一句话列入了十大可用性启示,那就是 “错误预防:比良好的错误消息更好的就是防患于未然的谨慎设计”。 确实,在 Nielsen 充满蓝色和紫色链接的完美世界中,我赞同这种说法。但在现实世界中,错误总会发生,必须加以处理。通过了解频繁出现错误的环境,开发人员可以用最好的方法设计应用程序的最终错误交互和可视化反馈,以帮助用户解决错误。协调的错误处理策略结合了客户端和服务器端解决方案,能够最好地维护应用程序处理的完整性,同时保证最高效地指导用户完成错误解决,并返回最初的工作流。在这篇文章中,我们将探讨一些实践技巧,帮助您将此类错误处理策略整合到您自己的基于 Web 的应用程序中。

犯错是人之常情

在人工智能领域中取得重大突破之前,应用程序一直要求用户通过一种定义非常良好的方式与之交互。对于每一个应用程序,用户都必须在一个有效交互的有限集之内进行通信。任何超出此有限集的交互都会导致错误的出现。

应用程序应尽可能地为用户提供更高的自由度。例如,标准日期格式是 DD/MM/YYYY,但用户应该也能使用像 DD-MM-YYYY 或 DDMMYYYY 这样的格式。只要应用程序可以将输入解析为惟一的有效值,就应该接受输入,您不必彻底地将人类用户约束在应用程序所偏好的格式中。然而,在迎合用户的模拟思维方面,应用程序的数字处理只能达到这个程度。

遗憾的是(恩,我认为从大范畴来看,应该说 “幸运的是”),人类用户不会自然而然地被约束在固定的交互操作集中。为用户提供三个复选框供其选择,他们最终会选中所有七种可能的组合,而不管哪种组合是系统视为有效的。在应用程序的操作更倾向于人类思维方式之前、或者在人类按照应用程序的开发方式安排一切之前,这种人机通信中的根本分歧将始终存在。在可以预见的未来,用户仍会不断触发应用程序错误。

噢,我是不是没有提到,错误也会来自于最终彻底失败的应用程序?令人讨厌的 500 Internal Server Error 听起来是不是很熟悉?

 




回页首


有错误,改正它!

最糟糕的错误消息就是那些根本不存在的消息。再差的错误消息也好过没有任何提示。但对于一条错误消息来说,必须具备几个基本组件才是有效的。在用户的交互导致错误时,一个设计良好的应用程序会提供三个错误处理组件:

  1. 发出警告:引起用户注意。出现错误。
  2. 问题在这里:解释出错原因。
  3. 尝试这种方法:给出可行解决方案建议,为用户展示问题所在。

一条错误消息的可视化设计属性 —— 其颜色、字体大小、位置 —— 可以清晰地将它与应用程序用户界面的其他部分区分开来,引起用户的注意。人们通常认为,红色、粗体、显示在页面顶端是错误消息的标准属性。此外,感叹号也经常被用作表达重要性的图形化符号。图 1 中的错误消息正展示了所有这些属性。


图 1. 错误消息

在通过这些可视化提示吸引用户的注意力之后,消息还必须明确、简洁地描述引发错误的问题。所表达的内容和表达方式 同样重要。

要有效地与用户通信,应用程序必须能讲用户的语言。应用程序和用户是两种差异很大的实体,因此,必须加以转换,以使两者间的通信更加有效。应用程序知道某些地方发生了错误,它必须将这一事实传达给用户。遗憾的是,尝试传达此类信息的错误消息往往令人迷惑,其中包含着一些不完整的句子和含义模糊的代码。读到这样一条消息时,您可能会想这恐怕只有机器人才能读懂吧。由于错误消息的主要受众是非技术型最终用户,因此应将消息从机器人式、代码式、技术式、技客(geek)式语言转换为简单易懂的英语。

这并不是说,永远不要在错误消息中包含像错误代码这样的信息。与此不同,如果能够证明此类信息对于错误的解决是有帮助的,就可以在恰当的上下文中加以解释(例如,用户可能在寻求技术手册或帮助台的协助时引用错误代码)。不要简单地显示 “ERROR 6534”,而是可以在错误消息中解释 “拨打分机 555 向帮助台咨询此问题时,请引用错误号 6534”。

错误消息要明确而简洁地解释出错原因、改正方法,不要留给用户去猜测。在一条错误消息中,礼貌大有帮助。不要去责备用户。使错误消息保持客观,阐述问题本身。例如,一条糟糕的错误消息可能是这样:“您在 123A 字段中输入了异常的字母字符。” 而更好的错误消息应该是这样:“邮政编码字段中包含一个无效字符。这里只能输入数字。一个有效的邮政编码示例是 90210。”

通过利用应用程序的交互特性,您可以准确地展示出现问题的位置。以可视化提示高亮显示字段标签和/或出错的字段,例如颜色、字体处理等,示意图是最有效的。清单 1 展示了如何以 CSS 实现它。更加有效的就是将响应的错误消息链接到出错字段的一个页面定位点处,并将将焦点设置为该字段,如 清单 2 所示。


清单 1. 通过 CSS 类高亮显示错误

				
<!-- CSS classes -->
.errorLabel {
	color: red;
	font-weight: bold;
}
.errorField {
	border: 1px solid red;
}

<!-- Applying the CSS classes to field labels and fields  -->
<td class="errorLabel">Zip Code:</td>
<td><input name="zipCode" type="text" class="errorField" /></td>




清单 2. 将一条错误消息链接到特定字段

				
<!-- Error Message Text  -->
The <a href="#zipCode">zip code</a> field contains an invalid character. 
Only numbers may be entered. An example of a valid zip code is 90210.

<!-- Error Field  -->
<td><a name="zipCode">Zip Code:</a></td>
<td><input name="zipCode" type="text" /></td>

 

更为高级的错误消息能够提供附加的分层消息,例如到可应用的 Help 系统模块的直接链接,以及结合关键术语(例如字段名)的术语表定义,在鼠标悬停在其上时显示。鼠标悬停帮助如清单 3 和图 2 所示。


清单 3. 使用 <title> 标记,添加在鼠标悬停时显示的附加信息

				
<!-- Error Message Text  -->
The <a href="#zipCode" title="A zip code is a code of digits added to a postal 
address to aid in the sorting of mail. Zip code must be entered as 5 digits.">
zip code</a> field contains an invalid character. Only numbers may be entered. 
An example of a valid zip code is 90210.



图 2. 使用 <title> 标记设置的附加信息




回页首


同时利用客户端和服务器端错误处理

现在您了解了错误是在什么时候发生的,应用程序必须明确而简洁地为用户解释出错原因、出错位置以及改正方法。但您不能忽视错误响应策略中的一个关键元素 —— 错误发生的时间。对于绝大多数 Web 应用程序来说,这个时间 通常是默认的,也就是用户向服务器提交有问题的页面的时刻。以这样一种方式制约错误响应会导致次优的用户体验。

在考虑何时提供错误消息时,有一些因素会发挥作用。两个主要的响应时期是:页面提交之后,或在用户的焦点离开字段时立即响应。服务器端验证通常采用前者,而客户端验证往往采用后者。两种解决方案的融合能够同时实现两者的优势。

在用户的焦点离开字段时立即进行验证时,省略了到服务器的一次往返传递,从而节约了用户的时间。如果用户输入无效的数据片段,应用程序可立即提示用户,在用户提交页面之前改正问题。如果您的应用程序只使用服务器端验证,那么就需要进行一次额外的服务器往返传递,要占用 3 到 6 秒的时间。跨许多个数据元素来看,这样的延迟是累加的。

立即验证还可帮助用户解决问题。由于应用程序会立即抛出错误响应,用户可以更轻松地在焦点转移到其他字段之前改正问题。例如,如果用户在快速浏览一个多页打印表单时输入了一个邮政编码,而错误地输入了六位数字而不是五位,那么他可以快速返回打印表单查看,并更正问题。由于错误被立即捕获,用户不必重新回头在应用程序屏幕和打印表单上寻找要更正的信息。

对于具有海量数据条目的场景来说,客户端验证用处不大。在这种情况下,客户端验证对于高重复性、流线型的工作模式是有干扰的。在这种场合下,应严格保持在服务器端进行验证。

由于您仅能给用户的计算机带来有限的逻辑,客户端验证确实有自身的局限性。对您要求用户下载的数据量设定合理的限制,以用户群的连接度量为基础(例如,拨号、高速等等)。复杂的条件验证通常需要采用服务器端验证的方式,原因在于执行这种验证所需的代码数量。举例来说,如果所输出数据的有效性取决于之前根据特定业务规则输入的数据,而其中的逻辑过于复杂,客户端无法处理。只要将所有的客户端验证代码放在有个外部的 .js 文件中,用户就只需要下载这个文件一次。在初始下载之后,客户的计算机通常会缓存文件。部分适于进行基本格式的客户端验证的内容包括日期、邮政编码、社会保险号码、电话、传真、信用卡号码和电子邮件字段。高级的综合验证(blanket validation)也很常用,例如用于检查字母或数字字符、字段长度和无效符号的验证。

安全性是另外一项至关重要的考虑事项。您的应用程序放在客户本机上的任何内容都不是安全的。如果您的应用程序需要在高度保密的情况下完成所有验证,那永远不要在客户端进行验证。同样,以黑客技术处理自己的定制页面,以便能够在绕开所有客户端验证的情况下提交数据,因此您不能完全依赖客户端验证。

客户端验证能够提供更好的用户体验。如果要提供完整、安全的验证,最好将所有验证都规划为在服务器端进行。可以这样看待两种验证,小区大门处的一名保安和您自己的家庭安全系统。有保安(客户端验证)是一件好事,他能带来一种安全感,还能提供其他一些帮助(比如指路等等),但您不会希望单独依靠这位保安来满足您的安全需求。您的个人家庭安全系统(服务器端验证)才能够真正地为您带来根本的安全。

 




回页首


结束语

利用客户端验证,您可以增强用户体验,而服务器端验证能够真正维护应用程序输入数据的完整性。尽管都是验证输入数据,但它们解决的是两种截然不同的问题。客户端验证为用户提供了一种更为有效的方式,使他们可以更正基本的数据录入错误。服务器端验证是根本性的验证,能够确保数据有效。无论您的应用程序采用怎样的方式捕获错误,重要的事情都是明确地将错误告知用户,解释出错原因,帮助他们更正错误。孔子曾经说过:“知错能改,善莫大焉。” 而构建 Web 应用程序时,您至少应使用户能够轻松地改正错误。


参考资料

  • 您可以参阅本文在 developerWorks 全球网站上的 英文原文
  • 关于在您的定制标记中尝试、捕获和改正错误条件的简要介绍,请阅读 Brett McLaughlin 撰写的 “JSP 最佳实践: 自定义标记中的错误处理”(developerWorks,2003 年 8 月)。
  • 了解基于 EJB 的系统上数据验证背后的某些概念,了解如何避免意料之外或无法理解的错误消息,请阅读 Brett McLaughlin 撰写的 “EJB 最佳实践: 数据验证出现在什么地方最合适”(developerWorks,2002 年 12 月)。
  • 在 Jakob Nielsen 的 Alertbox 专栏中了解他对如何 改善 404 错误消息 的见解(useit.com,1999 年 4 月)。
  • 浏览 Ask Eric 的所有问题与解答内容,这是由 Human Factors International 的 Eric Schaffer 博士撰写的。
  • 要开怀大笑(并了解如何不去 编写错误消息),请查看 Microsoft Crash Gallery,这里有大量的屏幕快照和照片。
  • 阅读 Martin Tsachev 撰写的 “Form validation on the client side”(Sitepoint,2002 年 9 月),这是一份关于客户端验证的出色简介。
  • WebSphere® Software Information Center 中阅读关于 JSP 页面错误处理的内容。
  • 要了解 graPHIGS API 的错误处理工具,请访问 IBM® eServer AIX® Information Center
  • 访问 developerWorks 的 Web 开发专区,获得专门讲解基于 Web 的解决方案的文章和教程。
  • 浏览关于上述和其他技术主题的 图书

你可能感兴趣的:(为 Web 应用程序设计交互式错误处理)