破坏编码标准


35

软件公司实施了各种编码标准,其目的是提高代码可靠性,可移植性,最重要的是提高不同开发人员共同编写的代码的可读性。

两个著名的例子是MISRA C和为JSF项目开发的C ++标准。

在仔细指定单词“ must”,“ shall”,“ should”,“ might”等之后,这些通常采用以下格式:

例:

规则50:不应测试浮点变量的完全相等或不相等。

原理:由于浮点数容易出现舍入和截断错误,因此即使达到预期,也可能无法实现精确的相等性。

这些编码标准通常会限制从编译器的角度来看是合法的代码,但这些代码很危险或不可读,因此被认为“有害”。

现在让我们滥用它!

您被接受为公司小型标准化委员会的成员,该委员会旨在设计公司每个开发人员都必须使用的新编码标准。在其他人不知道的情况下,您秘密地在一个险恶的组织中工作,并且以破坏公司为己任。您必须为编码标准提出一个或多个条目,这以后会阻碍开发人员。但是,您必须小心,不要立即使其变得明显,否则您可能会冒不被标准接受的风险。

换句话说,您必须在编码标准中引入看起来合法的规则,并且很有可能被委员会其他成员接受。之后,项目启动和无数的工时投入的代码,你应该能够滥用这些规则(例如,通过一个技术性,或者通过非常字面解释),以将其他正常且高质量的代码标记为违反标准。因此,他们必须付出很大的努力来重新设计它,而规则会从现在开始阻碍它们。但是,由于规则在相当长的一段时间内一直处于活动状态,纯净的势头将使这些角色继续存在,并且存在重大冲突出于不同管理层之间利益关系的考虑,其他经理可能会保持规则有效(他们承认错误会很愚蠢!),从而阻碍了公司的发展!哇哈哈哈哈哈!

计分

从第一个有效条目开始大约2周后,获得最高票数的答案。我有一个很好的答案的主意,但几天后我将只发布它,因为其他人可能也有相同的主意,并且我不想从他们的快乐中抢走。当然,无论分数如何,我自己的答案都不会被接受。

鼓励选民根据漏洞的隐藏程度以及对开发人员的沮丧程度为答案打分。

条款和规则

  • 一条或多条规则必须看起来专业,就像上面的示例一样
  • 规则看起来应该是真实的(因此诸如所有变量必须至少包含一个下划线,一个大写字母,一个小写字母和两个数字之类的东西”是不可接受的。它们确实会阻碍开发人员,但很可能不会被开发人员接受。委员会),如果他们的优点不是立即显而易见的,则应给出充分的理由。
  • 以后您应该能够找到一种使用/滥用规则破坏开发人员的方法。您可能会滥用其他规则中的任何歧义,或者您可能会使用多个规则,这些规则本身无害,但一旦组合起来便是有害的!
  • 您应该在文章结尾处在剧透标签中发布有关如何滥用规则的说明
  • 使用的语言不能是深奥的语言。必须选择一种在实际项目中广泛使用的语言,因此首选具有类似C语法的语言(而不是像Golfscript这样的语言)。

4
Python,Ruby,Haskell,Makefile,XML等是许多实际项目中使用的某些语言,这些语言没有类似C的语法。
kennytm

7
这个问题似乎不是主题,因为它不是编程竞赛。
彼得·泰勒

5
@PeterTaylor:定义包括“编程难题”,这并不意味着答案必须是一段软件代码。在网站的定义中,没有任何地方写的只是“编程竞赛”。定义是:“代码高尔夫/编程难题/其他编程竞赛或挑战
vsz 2014年

7
@PeterTaylor对我来说就像一场编程竞赛。在警察和强盗挑战中,强盗也不编写代码(如果您的论点是强盗评论,那么请务必在建议将警察和强盗挑战分为两个独立问题的元文章中发表评论)
John Dvorak 2014年

5
我投票决定重新开放。似乎我们仍然有一些问题,我们无法就它们是否在主题上达成共识。这让我想起了与艺术相关的作品,该作品已经关闭,然后重新开放两次。我确实有这个问题的答案的想法,并且肯定与编程有关。这个问题甚至适合网站上的2个标签。
hmatt1 2014年

Answers:


40

C / C ++

规则1:不得使用八进制常量

理由:八进制常数可能会引起混乱。例如,随便看一下该行 const int coefficients[] = {132, 521, 013, 102};
可能会错过以下事实:数组中的数字之一以八进制定义。

如果您想变得更加邪恶,请添加以下内容:

规则2:十六进制常数只能在位操作的上下文中使用。

原理:如果常量代表数字值,则以十进制表示时更易读。十六进制常数应指示它代表位掩码,而不是数字值。

如何滥用它:

使用下面的简单程序,它将添加数组的前10个元素。此代码将不符合标准。

sum = 0;
for (i = 0; i < 10; i++) 
{
    sum += array[i];
}

注意,0按照定义,即是一个八进制常数。根据规则1,要求在整个代码中都将其写为0x00令人沮丧。按照规则2,更令人沮丧。


1
您可以链接到0一个八进制常量的编码标准定义吗?我认为这是因为它以character开头0。它将加强您的假想者的论点。
xnor 2014年


16

蟒蛇

规则1:必须使用-OO标志对所有代码进行字节编译,以优化字节码。我们需要优化的字节码以实现大小和效率!

规则2:测试必须针对将要投入生产的同一“工件”代码进行。我们的审核员需要这样做。

使用-OOremoves assert语句。结合规则2,这实际上禁止assert在测试中使用语句。玩得开心!


这也会删除文档字符串,这意味着您help()在REPL上一无所获,非正式的REPL测试仍在测试中。
凯文

不。如果编写适当的测试框架,它将使用unittestor模块,该模块实现自己的断言而不依赖于__debug__标志。但是,Doctests不会自动运行。鬼!
pppery

15

这是针对Node.JS项目的。

第3节-速度和效率至关重要

规则3.1:文件最大不得超过1kb。大于此大小的文件需要很长时间才能解析。

规则3.2:嵌套功能的深度不得超过3级。V8引擎必须跟踪许多变量,并且像这样的深层闭合使其工作更加困难,从而减慢了一般解释的速度。

规则3.3:避免require()变通。

规则3.3.1:任何模块require()d require()的深度都不得超过3。深require()链在内存使用和速度方面都是昂贵的。

规则3.3.2:核心模块在内部计数为一个require(),而不管它们多少次require()

规则3.3.3:外部模块最多计数2 require()秒。我们不能像核心模块那样宽容,但是可以假设模块作者正在编写高效的代码。

规则3.4:不惜一切代价避免同步呼叫。这些操作通常会花费很长时间,并且会阻止整个事件循环继续进行。

如何滥用它:

规则3.1和3.3不能很好地协同工作。通过require()在链中最多保留1kb和3 s,它们将很难获得成功。
规则3.2和3.4几乎不兼容。3.4禁止同步通话;3.2通过限制回调的数量使高级异步工作变得困难。
坦白说,规则3.4是遵循真实规则的规则。3.1、3.2和3.3是完全伪造的。


11

JavaScript(ECMAScript)

7.3.2:正则表达式文字

不得使用正则表达式文字。具体来说,源代码不得包含与下面定义的RegularExpression非终结符匹配的任何子字符串。

RegularExpression     :: '/' RegularExpressionBody '/'
RegularExpressionBody :: [empty]
                         RegularExpressionBody [any-but-'/']

[empty]匹配空字符串,[any-but-'/']匹配任何单字符字符串,但包含'/'(斜杠,U+002F)的除外。

基本原理

出于可读性原因,通常不建议使用正则表达式。通常,使用传统的字符串操作比通过使用正则表达式更容易理解代码。但是,更重要的是,许多正则表达式引擎提供了低于标准的性能。正则表达式还与JavaScript上下文中的安全性问题相关联。

但是,Organization™认识到正则表达式有时 完成这项工作的最佳工具。因此,RegExp对象本身是不被禁止的。

(语法摘录本身的语法(不是其定义的语法)与ECMAScript规范的语法相对应。当然,在假设规范的另一点上将更严格地定义它。)

诀窍

以下程序不符合要求:

// sgn(x) is -1 if x < 0, +1 if x > 0, and 0 if x = 0.
function sgn(x) {
  return x > 0?  +1
       : x < 0?  -1
       :          0
}

上面给出的RegularExpressionBody非终结符的生成显示了依靠显式递归来表达BNF中列表的一种通用方法。这里的技巧是,我“偶然地”允许将空字符串用作RegularExpressionBody,以使该字符串//在源代码中被禁止。但是,谁仍然需要单行注释?C89和CSS似乎做得很好,但只允许使用/* */块注释。


15
实际上,这还比这更邪恶:代码可能既不包含块注释,也不可能每个文件包含一个除法运算符。
Chromatix

哦,是的,你是对的。我什至没有想到这一点。:P
FireFly 2014年

5

C#

12.1禁止使用影响程序状态的静态方法

这是因为很难可靠地测试静态方法的结果,尤其是更改某些状态的方法。

12.2静态方法必须是确定性的

如果静态方法接受输入并提供输出,则每次使用相同输入调用静态方法时,结果必须相同。

为什么

C#程序的入口点是私有静态方法“ main”。第一条规则现在禁止这样做,因为该规则忘记声明只有公共,受保护或内部方法才应遵循此规则。如果真的需要测试,则只能使用公用方法遵循规则1。Main可能也会违反规则2,因为如果程序失败,则程序将给出错误代码,这可能与输入参数无关。例如,程序可能找不到文件,或者可能依赖于未正确设置的其他系统。


4

JAVA /春天

4.2在生产代码中使用反射

由于反射可用于访问源代码的其他受限制部分,因此严格禁止在生产代码中使用反射。

绝招

从技术上讲,Spring使用反射来实例化和管理其支持的对象。通过执行此规则,必须删除所有Spring实用程序。


3

网站编码

666.13不能使用UTF-8,而应使用UTF-7代替。
理论依据:UTF-7比UTF-8更有效率,尤其是在针对我们使用阿拉伯国家的用户时。

如何滥用它:

HTML5特别禁止使用UTF-7。这意味着,现代浏览器将不支持它。如果所有测试都是在IE 11之类的浏览器上完成的,那么为时已晚,没人会注意到这一点。


2

JavaScript按位运算符

1.9您不得使用乘法,除法或下限,除非它们的速度比按位对应的速度快得多。它们应分别用按位运算符<<,>>和~~代替。
基本原理:按位运算符效率更高。

如何滥用它:

在处理大量数字时,使用<<或>>而不是乘法或除法会引起麻烦。此外,它们忽略运算优先级和小数点。当您输入负数时,双波浪号将返回不同的值。


2
我认为已经很明显x = (x<<10) + (x<<8) + (x<<5) + (x<<4) + (x<<3) + (x)在所有方面(可能甚至是速度)都逊色x *= 1337,并且用位移位总和来代替除以2的非幂除数甚至更糟。
lirtosiast

@Thomas Kwa我适当地编辑了答案。感谢您指出这一点。我是按位运算符的新手。
Stefnotch

1

JavaScript(ECMAScript)

7.3.1:标识符约定

对标识符的限制取决于标识符的类型。标识符分为变量常量函数构造器类型 ; 见5.3。限制如下。

  • 变量: 第一个字符必须是小写字母字符。 驼峰式大小写(请参阅1.3)应用于分隔标识符中的单词。

  • 常量: 标识符必须仅包含大写字母字符和下划线('_',U+005F)。下划线应用于分隔标识符中的单词。

  • 功能: 功能必须遵循与标识符 类型相同的规则。

  • 构造函数: 第一个字符必须是大写字母字符。 驼峰式大小写(请参阅1.3)应用于分隔标识符中的单词。

基本原理

可读的标识符名称对于可维护性非常重要。将标识符限制为众所周知的约定还可以简化不同代码库之间的转换。这些特定的约定以Java™编程语言[1]的标准约定为模型。

诀窍

我很遗憾地通知jQuery团队,其“全局jQuery对象”的最常用名称与此名称约定冲突。幸运的是,他们已经想到了这一点,并且同时提供$jQuery作为引用同一对象的全局名称。我想,尽管如此,用户群可能并不热衷于从任何地方切换$jQuery任何地方。


2
»函数必须遵循与标识符类型相同的规则。«–您是指»作为变量类型«吗?
圣保罗Ebermann
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.