网页样式编码
我一直在重读Jeff Atwood(《 Coding Horror》 )和Joel Spolsky(《 Joel on Software》 ),并讨论了编码风格标准。 它使我想起了我打算写“某天”的博客条目。
今天是“某一天”。
首先,我应该通过指出它来开个玩笑,因为这似乎是“权威指南”,因为似乎没有人认为他们只是有些想法,但对其他方法持开放态度。 每个人都有了答案。 但是,在这种情况下,重点在于确定标准的过程,而不是所选标准的确切细节。 我发现他们的论点令人信服,在应用它们之后我有个人经验,但是我永远不会说我有最终的答案。 技术改变了一切,例如现代IDE中的语法着色器。
现在是晚上10点,您的晚餐来自自动售货机
考虑在工作中执行任务。 现在是几奌? 还是在早上10点左右? 还是下午2点,当您可能有一点低迷的下午,但是午饭后仍然放松并专注于工作?
没人会想到晚上10点的生活,晚餐来自自动售货机,您根本不知道什么时候才能回家。 这是最容易犯愚蠢的错误而又很难发现它们的关键时刻! 好的标准可能不会阻止您犯一些愚蠢的错误,但是它们应该为错误的代码赋予明显的代码味道,使它们更易于查找。
始终牢记这一点–不应采用编码标准,对最小单元测试范围的要求等,因为有人认为该代码看起来应该漂亮,或者他们喜欢CI屏幕上的绿色。 之所以采用它们,是因为它们使在压力条件下更容易产生良好的代码。
为什么编码样式标准很重要
一句话回答: 专注 。
开发人员最关键的资源是焦点。 它是有限的,容易耗尽。 更糟糕的是,效果是非线性的。 专注,清晰的目标和无干扰的精神意味着您可以进入“流动”状态并取得令人难以置信的生产力。 这意味着您可以编写代码,同时考虑如何测试它以及如何减少将来要做的工作量。
但要添加令人惊讶的少量干扰-条件块末尾的空白行,感觉像是在楼梯上错过了一步(或者更糟的是,恐慌您不小心删除了一行代码)或类似的变量名( m_x和m_y ),您就被淘汰了。 您正在编写有效但不容易扩展的代码。 分散注意力,编写一些代码来复制标准库中已有的内容,或者忽略边框。
晚上10点范例
作为第一个示例,请考虑
if (name.isEmpty()) {
...
}
和
if (name.length() == 0) {
...
}
上午10点没有太大区别。 如果您很累,则首先要明确指出您正在检查一个空字符串。 第二个需要一点点的注意力,以查看您正在检查一个特殊值(零),它看起来不太相似(0 vs 8),并且您必须从测试(数字)到语义(这是一个空字符串)。
一条线不会产生太大的变化,而是在不到五分钟的时间内打十二遍? 每次叮叮可能只花费您0.2%的精力,但0.2%很快就累了。
一致性,一致性,一致性!
任何标准总比没有标准要好,但是完全接受它甚至更重要。 没有什么比击中没有遵循与其他所有事物相同模式的代码块更令人分心(即失去焦点)的了。
另一方面,缺乏一致性可以用来娱乐。 我曾经被聘用一份简短的合同来处理一些没有活跃开发人员的代码。 这本书显然是由三个人写的,每个人都有自己的风格,对彼此的尊重不大。 (在一个具有1万行代码的应用程序中,您实际上需要多少个链表实现?自然,它们对边界案例的处理会略有不同。)我向姐妹项目的一位同事提到了我对先前开发人员的观察,并认真对待了他,因为我能够形容一年前离开公司的人。
重要提示 :关键是一致性。 对于代码而言,始终遵循可怕的样式要比混搭样式好得多。
自动化
当您从不运行格式化程序时,标准没有任何意义。 您需要使其自动化。
现代IDE应该提供一种在保存文件时自动格式化代码的方法。 在Eclipse中,它位于“首选项”>“ Java”>“代码编辑器”>“保存操作”中。 我用它来保证我的文件总是正确格式化。 (如果要进行很多更改,我还将在编辑器中显式调用格式化程序。)
另一种方法是进行CI工作,以定期重新格式化所有内容。 它可以检出代码,重新格式化,运行测试,以及是否成功提交代码。 该操作可以每晚进行,但绝对应每周至少执行一次。
一种严重的错误方法是使用源代码管理系统中的钩子将代码格式化为检入格式。可以使用这些钩子来验证代码是否已正确格式化,如果不正确,则将其拒绝,但是您永远不希望源代码控制系统修改代码。
优化正确的事情
这是多语言站点的常见问题。 他们有一个编码样式标准,并将其应用于所有语言。
不不不!
记录单一样式可能会更容易一些,但请参阅我有关疲倦的开发人员的评论。 我应该能够看一眼代码,并立即告诉您它是否在C / C ++,java,scala,javascript中,无论我多么疲倦。 我不必查看所使用的功能/方法,也不必滚动编辑器,即使我的眼睛模糊,我也应该一目了然。
为什么这么重要? 考虑一下,内存管理。 C / C ++需要显式释放对象,而Java / scala则不需要。 (C ++析构函数可以提供帮助,但是您仍然需要显式地释放许多东西。)
晚上10点范例
这是一条细线,但请考虑两种样式:
void method() {
Book book = new Book();
if (test()) {
doSomething(book)
}
}
和
void method()
{
Book *book = (Book *) malloc(sizeof Book);
if (test())
{
do_something(book);
}
free(book);
}
通过不同的样式,我可以看到花括号并被下意识地提醒我应该先检查malloc(),然后再检查匹配的free()(如果找到)。 对于Java和C,使用相同的样式,我将需要更加仔细地寻找,尤其是。 使用不具有可见性修饰符的package-private方法。
当语法着色器使用不同的颜色时,它会提供更多帮助。
不要像1999年那样编码
在1999年,我使用了“ vi”,不得不跟踪所有内容。 尽管我知道其他人也这样做,但我从未陷入过像对对象字段使用“ m_”前缀这样的做法。 (“ m”代表会员)
在2014年,我们拥有IDE已有多年了。 这些带有几个重要的工具。
语法着色
通过语法着色,一目了然,值是类静态字段,类对象字段还是参数。 例如,在Eclipse中,静态字段为粗体,对象字段为蓝色,参数为黑色。 所有前缀所做的只是浪费一点点精力来确定该字段实际是什么,尤其是在没有类似命名参数的方法中。
比较
public double getNewX(double theta) {
return x*sin(theta) + y*cos(theta);
}
与
public double getNewX(double theta) {
return m_x*Math.sin(theta) + m_y*Math.cos(theta);
}
(我通过添加静态导入Math方法而作弊,但它遵循同样的精神!)
博客没有显示它,但是IDE可能会以不同的颜色显示'x','sin'和'theta'。 您将立即知道哪些是变量以及它们的声明位置等。
集成编译器警告
借助集成的编译器警告,我们立即被警告有问题的代码,例如
public void setName(String name) {
name = name;
}
有两个正确的实现。 由于前面提到的原因,我更喜欢前一种方法。
public void setName(String name) {
this.name = name;
}
和
public void setName(String name) {
m_name = name;
}
语言功能
最终,语言现在支持诸如“最终”和“常量”之类的关键字。 同样,可能需要一点时间来习惯它,但这将编译器警告提升为编译器错误。
Java:
public void setName(final String name) {
this.name = name;
}
C:
void setName(const char* name)
{
self.name = name;
}
彩色激光打印机
喷墨打印机非常适合照片。 基于复印机的打印机有利于提高速度。 但是,如果您是开发人员,则需要彩色激光打印机。 你永远不会回去。 文本很清晰(因此您可以区分'0'和'O'或'l'和'1')并且不会拖尾(因此您可以继续区分它们)。 它们也很便宜–大约6个月前,我以600美元的价格在家里购买了内存最大的双工HP……而Costco恼人的是,它以300美元的价格出售了类似的型号,现价150美元。 (他们可能正在清理库存以购买较新的型号。)
明显的缺点是墨粉成本-为我的打印机加墨将花费400多美元-但这是一种幻想,因为每页成本只是喷墨打印机成本的一小部分。 这只是刺痛,因为这是每年一次的费用(对我而言),而不是每月的费用。
今天,我的打印量要比十年前少得多,但是当我将其打印在优质纸上而不是单色在大容量复印纸上时,就变得与众不同。
遵守标准
最后,合理地严格遵循标准。 有两个原因。
历史上的原因是,已经存在了十年的标准在许多聪明人(很多人比您聪明)的帮助下得以幸存。 如果他们看不到他们的问题,那你为什么呢?
现代的原因是,开发人员应该阅读很多其他人编写的代码。 他们应该在关于Stack Overflow的搜索中,在DZone和Java Code Geeks上的文章中看到,同时在查看开源库以了解其他人如何解决了该问题。 记住重点-如果您消除了诸如不同样式之类的问题带来的摩擦,则集成新信息会更容易。
结论
对于Java而言,我个人更喜欢Apache标准-它是原始的Java标准,但是带有空格而不是制表符,并且行长为120个字符。 数组看起来像“ char []数据”。
对于C,我通常使用上面显示的样式。 开括号在他们自己的行上,数组看起来像“ char data []”。
如果自己动弹,则应自动执行繁重的工作。 没有80页的圣经! 不能自动化的内容应放在单个页面上,例如是否使用驼峰大小写(java)或下划线(C),是否使用匈牙利表示法等。请记住,您希望自己的语言具有独特的外观,是各自语言的标准配置(或几乎如此)!
最后,不要将编码样式标准与编码标准混淆。 您应该大量使用'final'和'const',因为它可以创建更好的代码,而不是因为它是标准样式。
旁注:匈牙利符号
推荐的必读内容: 使错误的代码看起来错误 。
在Windows世界中广泛使用的匈牙利表示法是错误的。 恶毒。 邪恶。 我撕开它的头,在它的坟墓上撒尿。
正如Joel所指出的那样,匈牙利的原始符号很有价值。 在Java世界中,使用它的一个好地方是处理用户提供的值时。 来自user(*)的任何内容都带有“ u”前缀,表示“不安全”。 任何经过消毒的东西都带有“ s”前缀,表示“安全”。 将此选项设为可选项很诱人,但是前缀“ s”会提醒您某些值可能不安全。 正常情况下使用驼峰式,因此为“ uName”,而不是“ uname”。 Perl用“污点”处理得很好。
(我一直在考虑使用批注在Java中做同样的事情,但是批注是基于类的,而不是基于对象的,因此我只能将类标记为不安全。仅实现标记器接口并没有真正的收获。)
对象值的“ m_”前缀? 我认为这是有用的,当人们第一次从C转向C ++时,我们的选择是在90年代中期使用 “ vi”或“ emacs”。 如今,面向对象的设计变得司空见惯,以至于我觉得这很混乱–类似于有人说“我想在2015年乘坐飞机前往阿拉斯加”或“我将于2012年开始在这里工作”。 但是, 除非您准备进行大量编辑, 否则这应遵循当地的约定。
(*“用户”包括数据库和文件。任何可由应用程序外部的人操纵的东西。)
翻译自: https://www.javacodegeeks.com/2014/02/the-definitive-guide-to-coding-style-standards.html
网页样式编码