代码风格
代码风格 代码风格 代码风格最早出现的,也较为传统的是KR 风格。所 谓 KR 即指《The C Programming Language》一书的作 者 Kernighan 和 Ritchie 二人, 这是世界上第一本介绍 C 语言 的书,而 KR 风格即指他们在该书中书写代码所使用 的风格。 KR 风格在处理大括号时, 使用了一种较为紧 凑的格式,将左括号留在前一行的末尾,并尽可能地压缩· 目录 1 基本的代码风格 2 代码风格的必要性 3 换行的讲究 代码示例 1-1: 寻找最佳的断行位置 代码示例 1-2: 代码示例 1-3: 代码示例 1-4: 代码示例 1-5: 每行只写一条语句 分行定义变量 4 避免代码过于拥挤 使用空行分隔代码块 使用空格降低代码密度 5 符号两侧添加空格的基本规则: 单目运算符 在双目、三目运算符 括号 不要使用连续的两个或多个空格 6 如何缩进 嵌套或包含关系引起的缩进 因换行而产生的缩进 使用空格还是 Tab键 7 大括号 大括号的位置 空的大括号结构 仅包含单个语句的结构体 1 基本的代码风格编辑 假设我们写的是文章而不是程序,那么你一定觉得诸如文章 应该分为若干个自然段、每段开头空两格之类的规则是理所 当然的。如果段落的开头不空两格,或者干脆把整个文章写 成单独的一段,仔细想来似乎也不会影响文章实质内容的表 达。既然如此,我们为什么还要在形式上下功夫呢?设想一 下,如果你手中的这本书既无章节也无目录,正文中的不同 内容都使用同样的字体字号印刷,几百页纸从头至尾洋洋洒 洒如念经般地“一气呵成” ,你还有耐心看下去吗? 这是一个人人都能理解的道理,可是当文章变成程序的时 候,就不是每个人都能想得通的了。不仅仅是初学者,甚至 一些熟练的开发人员,也会写出凌乱不堪的代码。许多人一 定有过这样的经历:一年半载之后,自己原来写的程序就完 全看不懂了。 如果这段程序只是为了交作业, 或者临时一用, 那还可以不去追究,但如果这是一个商业软件,现在需要根 据客户的要求进行修改的话,工作量可就大了——你不得不 先花时间把你原来的思路看懂。 肯定会有人反驳:代码是给机器运行的,又不是给人看的, 写那么好看有什么用? 他的话只对了前半句:代码确实是给机器运行的,可是机器 总共才需要看它几分钟?你花一个月编写的程序,机器顶多 两三分钟就编译好了——在这两三分钟之前,这代码不都是 你在看吗?开发软件编写代码不是一朝一夕的事情,更多的 情况下,一个软件的开发要经历很长的时间,并且常常由多 人合作完成。一个庞大的软件项目,可能会动用上千名程序 员工作数年!如果把代码写得连自己都看不明白,怎么与别 人交流?同一个开发团队内,一定要保持良好且一致的代码 风格,才能最大化地提高开发效率。 2 代码风格的必要性编辑 有的初学者会问:我现在只是一个人写程序,并不需要和其 他人合作,这些条条框框还有什么必要吗? 要知道,团队协作只是一个方面。我经常遇到这类情况,一 些初学者拿着他的程序来说: “这个怎么不能编译?”我帮 他把代码整理了半天,发现有一个地方丢了半个大括号。如 果他写程序的时候能够稍加注意一些的话,相信此类错误完 全可以避免。保持良好的编程习惯,能够避免的错误还远不 止这些。 如果说程序代码中对算法的清晰表述是通过长期训练而获 得的,那么本章要介绍的这些方法则无需伤神,你不必对代 码做任何实质性的改动,只需要添加一些空行与空格,就可 以使其可读性大大提高——这些规则就像写文章应该分段 一样简单, 只要愿意遵守, 那么别人在第一眼看你的代码时, 必能感觉到你那良好的编程修养,即所谓“见字如见人” 。 3 换行的讲究编辑 虽然你完全可以在 C# 里将所有的代码都连在一行里书写, 但想必没有人愿意这么做,谁也不会自己折磨自己的眼睛, 何况大多数鼠标对于上下翻页的支持都比左右翻滚好得多。 我相信,这也是大多数人接受将每条语句分行书写的原因, 很少有人会怀疑这一点的合理性。例如下面这行代码,虽然 结构很简单,但是它实在太长了,所以被分成了两行: 代码示例 1-1: 由于代码过长而进行断行 bitmap = new Bitmap(size.Width, size.Height, System.Drawing.Imaging.Pixelat.at32bppArgb); 这一点我相信大家都能理解并愿意遵循,然而问题的焦点并 不在于要不要换行,而在于在什么位置换行。 寻找最佳的断行位置 写程序不能像写文章那样,什么时候顶到了边界就换,而必 须按照其语法规则,在可以换行的位置断开。例如,对于包 含一个超长表达式的语句来说,我们可以在某两个表达式项 之间将其断开,如下 所示: 代码示例 1-2: 通过断行使代码更加清晰 if (f == Imageat.Jpeg.Guid || f == Imageat.Tiff.Guid || f == Imageat.Png.Guid || f == Imageat.Exif.Guid) { supportsPropertyItems = true; } else { supportsPropertyItems = false; } 原本一个很长的条件表达式,通过在“||”运算符处换行,显 得更加的清晰。有一点需要我们注意的是,当我们进行折行 时,要将折行位置处的分隔符(如前一例中的逗号,这一例 中的“||”运算符等)留在上一行的行末,给人以“此行并未 结束”的直观印象。这就好像在英文书写中,如果你需要将 一个单词拆开,就需要在前一行末尾加上连字符,以表示那 个单词并没有结束。 可以看出,换行在防止代码超出屏幕边界的同时,还影响着 代码的表达。因此如何选择合适的换行位置也是很有讲究 的。有的时候,我们并不一定非要在临近右边界的时候才去 换行,如果存在更为合理的分法,就应当采用,例如下面的 情况: double containerAspectRatio = (double)container.ClientWidth / container.ClientHeight; 按理说这样的断行并没有什么问题,它在表达式的两项之间 断开,并将运算符留在了上一行的行末。但是,我相信如果 换一种断行方式的话,能够更加清楚地表达出原来的逻辑: 代码示例 1-3: 寻找最佳的断行位置 double containerAspectRatio = (double)container.ClientWidth / container.ClientHeight; 如此一来,这个除法算术表达式就显得较为完整,相比前一 种写法而言更能体现其内在的逻辑关系。通常我们会选择整 个表达式中最高的关系层次进行断行,例如上述代码中的 “赋值号”和“除号”都是可以考虑的断行点,但相比较而 言,除号连接的这个算术表达式只是整个赋值表达式的右半 部分,如果在除号处断行,那么不但整个表达式会被截断, 连局部的这个除法表达式也会被截断;反之,我们选择在赋 值号处换行,可以保持除法表达式的完整,最大限度地减少 换行对语句整体结构的破坏。 同样的道理,为了将逻辑体现得更为清