这篇文章主要讲解新手向的问题提问及描述实践,从一篇英文翻译而来。

什么是 SSCCE

SSCCEShort, Self Contained, Correct (Compilable), Example 的缩写。

如果对代码有问题并且想要寻求帮助,准备一个简短、自成一体、准确的示例(SSCCE)是很有必要的。但是什么是SSCCE?

实际上,从名字上就能看出。让我们看一下每一部分。准备给他人看的内容应该是:

  • 简短的 - 例子尽量短小,不要让审阅者无聊
  • 自成一体的 - 确保一切想要的东西都包括进去了
  • 准确的 - 复制,粘贴,(编译,)就能看到所指的内容
  • 示例 - 展现我们正要解决的问题

简短的

这取决于讨论组或论坛上。就一个公共的论坛来说,大多数的阅览者大约只会阅读100行左右的代码,而有200-300行的代码就会产生抱怨情绪。

精简的技巧

如果一个GUI界面有40个按钮,但是与问题毛关系也没有,还留着它们干啥。如果这些按钮全都与问题相关(移除按钮问题也就消失了),依次放回一两个按钮,如果问题出现了,保留这一两个按钮即可。

导致数组或表格出问题的可能有一百多条数据,但是同样的,如果能从两三条条目中看出问题,那么精简一下只保留这些条目。

如果问题出现在GUI界面层,精简所有后端的逻辑(JavaScript或Java等)。另一方面,如果一个应用有一个界面,但是问题出现在逻辑上,可以把GUI界面精简到最小版本。

如果在别人看来精简了大量的代码,那么你可能精简了你认为与问题不相干的代码,但在解决问题上却是有用的。

问题解决了吗?

通过明确的指出问题出在哪里,你就向解决问题上迈出了重要的一步。这个过程突出显示一个问题的起源,而这个过程恰恰可以帮助解决问题。你可以更仔细的摘出这一部分,并在此过程中发现问题。

即使你不能明确问题为什么发生,你仍然迈出了重要的一步:确定问题所涉及的代码(至少一部分)。

如果代码已经精简成问题的简要例子,那么它就可以呈现给别人;如果还没有,将问题的代码放回来,继续精简其它部分,直到代码精简完毕。

自成一体的

最重要的是确保给他人的代码可以“复制,粘贴,编译,然后运行”,就帮助了解问题来说这是行之有效的方法。

这意味着当这些代码被复制、粘贴然后编译,他们自己就能运行并看到结果。这可以认为是问题的一个示例。

如果你能做到这一点,那么极有可能得到帮助。

怎样弄一个自成一体的例子

如果代码进行了文件I/O操作,把问题中与输入/输出无关的文件I/O操作用虚拟数据结构来代替。

如果问题出在输入上,文本输入_就会_被用到,那么准备一个简短的例子,这个例子可以复制到实际的数据文件中。

如果问题只发生在加载阶段,那么插入代码来模拟加载过程。如果一个布局问题只发生在特定情形下,找到切实可行的方法来_迫使_这些问题复现。

显然,就发布到论坛上来说,有些东西是不能包含到例子里的,诸如“数据库”。但是更多时候你需要一点横向思维,想出一个方法来取代在展示问题上你认为“重要”的东西。

横向思维的一个例子是“图像”。与代码问题相关的图像看起来可能很难被替换。但是有一个小技巧就是链接到网络上的图像,这个图像展示了相同的问题。如果可能的话,尽量使任何基于图像的Web网络在字节大小上“少”一点。

正确性

如果我的例子是正确的,那我还需要在这里做什么?

(笑)不,在这一方面不是什么“正确”的意思。在这篇文章中,正确性(或可编译性,尤其涉及到计算机源代码而言)意味着确保例子适合公认的标准或协议。

为了实现这一目标,有必要来:

  • 行宽。示例中一行的宽度保持在62个字符以内。(但是不要删除所有的行缩进!)新闻阅读器通常在72个字符左右强制另起一行(为了确保稳定性字符可能会更少)。有时候,换行符不会导致任何问题,但是更多时候会有问题,这意味着行与行要重新整合,来确保可以出现预期的结果。
    大多数代码编辑器都会在编辑区顶端显示行宽。
  • 如果有的话请使用命名习惯。大多数人愿意帮助那些在提示中使用大小写字母,或用来描述命名的代码,这样可以略读代码以快速的确定问题。如果按照读者的习惯,就可以帮助他们更好的了解代码。
  • 确保示例是_正确的_。无论是示例可以编译清楚,或者能出现需要解决的确切错误信息。

更多的提示:

  • 将所有的资源(CSS/JS/Java源代码、图像等)放到同一个文件夹,这样可以更容易管理,并且也很容易找到。
  • 从Java源代码中删除package语句。
  • 将Java的public类降级到默认级别。如果语言指定在每个源代码文件中只能有一个public类,那么就要降级所有其他的类到默认级别。这样可以让示例在不用分成单独的文件就可以编译。
  • 验证器如果可行,可以来验证示例。

示例

一定要确定发表的代码真的表现出了问题!

已经在这个例子上纠结了一小时,或者有一天了吧。可能看起来像是永远。那么现在,就是一个很好的时间用来休息一会儿,后退一步,海阔天空。

_重整电脑也是如此。_别忘了在必要的时候重启电脑。

现在打开出现问题的网页或程序。当初的问题还在那儿吗?

也许99%会是这样解决的(或者少使用较不可靠的操作系统)。

现在,如果问题依然存在,那就发表你的示例吧。

示例 - 加分点

我们希望给这些人一美元,那些询问一个网页或样式表、一些JavaScript代码或者一个Java Applet小程序但没有给出链接的人。我们并不需要提供和维护这个文档,做这些还不如去沙滩享受阳光浴、体验异域风情、喝着异国风味的鸡尾酒。

为什么人们会错过这样的机会?很少有东西能像链接那样诱人。对于一个经验丰富的论坛版主,有一个链接会像一个写有“喝掉我”这样模糊的讯息的瓶子那样诱人,也可以比作异国风味的鸡尾酒。

三个臭皮匠,顶个诸葛亮。一群人有助于发现并解决手头的问题,也会解决_兼容性问题_(这可能就是问题的原因)。

网络上标准

当处理与互联网相关的事情时,这里存在另一个“疑难杂症”。互联网或与其相关的一些事情上,都会有些放荡不羁。每个标准后面都会有候补标准。对于每个规则往往有至少三个例外。

首先,浏览器的工作方式不同。这里不是指IE和Netscape的不同,也不是指旧浏览器和新浏览器的不同。而是,举个例子来说,是Macintosh下的“Internet Explorer 5”和Windows下的“Internet Explorer 5”(显著)的区别。

在网页设计讨论组寻求帮助的人们往往很惊讶的听到,他们经历的网页问题却没有在使用不同浏览器的那些人哪里表现出来。

Java Applets

更复杂一点的,有更多问题的,还要数网页中有个Applet的时候了。上述提到的浏览器往往会形成不同(通常不好的)HTML和样式表,如何将Applets与浏览器结合的很好,这将是另一个问题。这里只是举个例子。

很长一段时间,微软在Internet Explorer上运行Java的_早期版本_(JVM 1.1版本)。之后发生了一些事情,微软将_最新的Java_引擎嵌入到它的浏览器中。不就之后,他们又开始提供_没有JVM_的IE版本了。

含有Applets可能会出现并发症,但庆幸的是当在互联网环境下,这很容易检查出来。点击几下,在星球另一边的人就能从他们自己浏览器的Java控制台上看到输出,有些时候也能看到Applet正常的工作。

如果一个Applet在你这里能正常工作,在其他人那里却出问题了,这可以帮助你快速所别问题的范围,一般是HTML、Applet标签、或者(完全没有安装)浏览器的JVM插件。

何必如此?

这是一个很好的问题。为什么要做这些事情?

也许会有人能从你给的描述中明白你所描述的问题。也许这只是数以千计的人无意当中发现的一件事情。

如果你已经检查了FAQ、google过论坛、阅读了XXX指导手册,那么你会发现答案不会那么容易浮现出来。你_必须_深入做这些事情,难道不是吗?

如果浪费了公共论坛其他会员的时间和带宽,就可能会被群起而攻之。

在讨论组有过贡献的人给予很宽泛的建议。这些建议有时候会奏效,有时候不会,但无论哪种方式,意见都是免费的。

贡献者这样做有多种多样的原因,其中一条是,当他们可以将自己所知道的与自己领域相关的一部分知识传递给正在学习的人,这样所带来的成就感。

不幸的是,如果一些人问一些包含在基础教程却还需要别人喂养的问题,这个迹象表明,提问者并没有强烈的欲望想去学习那些他自己应该去学习的内容。

如果这里有一段你想写的代码,你可以有很多途径来完成或者让其他人帮你修改一下。对于金额不多的时候,你可以找一些基于互联网的外包公司来完成(做完)大多数的IT工作。这些本来就是这些外包公司正在研究的。

自由论坛就是用来学习的。

话说回来:

让我们假设你的确在学习,你有一个庞大的、复杂的系统,系统中有一个偶然的、不可预知的错误,然后你搜索了FAQ和论坛、研究了说明书或文档,但是却没有找到一个答案。

向讨论组描述问题的时候放松宽泛一点,也许这样可以消除一些基本问题上的误解。

我们并不打算为了解决每一个单独的问题都用上SSCCE。也并不是说某些例子需要这样做或者必须那样做。

然而,它将使人们获得帮助,最终会增加找到解决方法的机会。

参考文献