热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

程序设计实践----编程风格

程序设计风格的原则根源于由实际经验中得到的常识,它不是随意的规则或者处方。代码应该是清楚地和简单的——具有直截了当的逻辑、自然地表达式、通行的语言使用方式、有意义的名字和有帮助作用

     程序设计风格的原则根源于由实际经验中得到的常识,它不是随意的规则或者处方。代码应该是清楚地和简单的——具有直截了当的逻辑、自然地表达式、通行的语言使用方式、有意义的名字和有帮助作用的注释等,应该避免耍小聪明的花招,不使用非正规的结构,一致性是非常重要的东西。

1.1名字

       什么是名字?一个变量或函数的名字标识这个对象,带着说明其用途的一些信息。一个名字应该是非形式的、简练的、容易记忆的,如果可能的话,最好是能够拼读的。许多信息来自上下文和作用范围(作用域)。一个变量的作用域越大,它的名字所携带的信息就应该越多。全局变量使用具有说明性的名字,局部变量用短名字。根据定义,全局变量可以出现在整个程序中的任何地方,因此它们的名字应该足够长,具有足够的说明性,以便使读者能够记得它们是干什么用的。给每个全局变量声明附一个简短注释也非常有帮助。

        人们常常鼓励程序员使用长的变量名,而不管用在什么地方。这种认识完全是错误的,清晰性经常是随着简洁而来的。

        现实中存在许多命名约定或者本地习惯。常见的比如:指针采用以p结尾的变量名,例如nodep;全局变量用大写开头的变量名,例如Global;常量用完全由大写字母拼写的变量,如C O N S T A N T S等。有些程序设计工场采用的规则更加彻底,他们要求把变量的类型和用等都编排进变量名字中。例如用p c h说明这是一个字符指针,用s t r T o和s t r F r o m表示它分别是将要被读或者被写的字符串等。至于名字本身的拼写形式,是使用 n p e n d i n g或P e n d i n g还是n u m _ p e n d i n g,这些不过是个人的喜好问题,与始终如一地坚持一种切实际的约定相比,这些特殊规矩并不那么重要。

        函数采用动作性的名字。函数名应当用动作性的动词,后面可以跟着名词:

        now = date.getTime();

        putchar('\n');
对返回布尔类型值(真或者假)的函数命名,应该清楚地反映其返回值情况。下面这样的语句

        if(checkoctal(c))...

是不好的,因为它没有指名是么时候返回真,什么时候返回假。而:

       if(isoctal(x))...

就把事情说清楚了:如果参数是八进制数字则返回真,否则为假。

1.2  表达式和语句

         名字的合理选择可以帮助读者理解程序,同样,我们也应该以尽可能一目了然的形式写好表达式和语句。应该写最清晰的代码,通过给运算符两边加空格的方式说明分组情况,更一般的是通过格式化的方式来帮助阅读。这些都是很琐碎的事情,但却又是非常有价值的,就像保持书桌整洁能使你容易找到东西一样。与你的书桌不同的是,你的程序代码很可能还会被别人使用。

        用加括号的方式排除二义性。括号表示分组,即使有时并不必要,加了括号也可能把意图表示得更清楚。在上面的例子里,内层括号就不是必需的,但加上它们没有坏处。熟练的程序员会忽略它们,因为关系运算符(<<= == != >= > )比逻辑运算符(& &和| |)的优先级更高。

1.3 一致性和习惯用法

      为了一致性,使用习惯用法。和自然语言一样,程序设计语言也有许多惯用法,也就是那些经验丰富的程序员写常见代码片段的习惯方式。在学习一个语言的过程中,一个中心问题就是逐渐熟悉它的习惯用法。

       常见习惯用法之一是循环的形式。而习惯用法的形式却是:

       for (i = 0; i

            array[i] = 1.0;

       这并不是一种随意的选择:这段代码要求访问n元数组里的每个元素,下标从0到n-1。在这里所有循环控制都被放在一个f o r里,以递增顺序运行,并使用+ +的习惯形式做循环变量的更新。这样做还保证循环结束时下标变量的值是一个已知值,它刚刚超出数组里最后元素的位置。熟悉C语言的人不用琢磨就能理解它,不加思考就能正确地写出它来。

        对于无穷循环,我们喜欢用:

       for (; ;)...

      但while(1)...

也很流行。请不要使用其他形式。

         缩排也应该采用习惯形式。  

        一致地使用习惯用法还有另一个优点,那就是使非标准的循环很容易被注意到,这种情况常常预示着有什么问题:

1.4 函数宏

      老的C语言程序员中有一种倾向,就是把很短的执行频繁的计算写成宏,而不是定义为函数。完成I / O的g e t c h a r,做字符测试的i s d i g i t都是得到官方认可的例子。人们这样做最根本的理由就是执行效率:宏可以避免函数调用的开销。实际上,即使是在C语言刚诞生时(那时的机器非常慢,函数调用的开销也特别大),这个论据也是很脆弱的,到今天它就更无足轻重了。有了新型的机器和编译程序,函数宏的缺点就远远超过它能带来的好处。 

        函数宏最常见的一个严重问题是:如果一个参数在定义中出现多次,它就可能被多次求值。如果调用时的实际参数带有副作用,结果就会产生一个难以捉摸的错误。

       给宏的体和参数都加上括号。如果你真的要使用函数宏,那么请特别小心。宏是通过文本替换方式实现的:定义体里的参数被调用的实际参数替换,得到的结果再作为文本去替换原来的调用段。

        C++ 提供的在线函数既避免了语法方面的麻烦,而且又可得到宏能够提供的执行效率,很适合用来定义那些设置或者提取一个值的短小函数。

1.5 神秘的数

      神秘的数包括各种常数、数组的大小、字符位置、变换因子以及程序中出现的其他以文字形式写出的数值。

字形式写出的数值。
       (1) 给神秘的数起个名字。作为一个指导原则,除了0和1之外,程序里出现的任何数大概都可以算是神秘的数,它们应该有自己的名字。在程序源代码里,一个具有原本形式的数对其本身的重要性或作用没提供任何指示性信息,它们也导致程序难以理解和修改。下面的片段摘自一个在2 4×8 0的终端屏幕上打印字母频率的直方图程序,由于其中存在一些神秘的数,程序的意义变得很不清楚:



        在这段代码里包含许多数值,如2 0、2 1、2 2、2 3、2 7等等。它们应该是互相有关系的……但是……它们确实有关系吗?实际上,在这个程序里应该只有三个数是重要的:2 4是屏幕的行数;8 0是列数;还有2 6,它是字母表中的字母个数。但这些数在代码中都没出现,这就使上面那些数显得更神秘了。

通过给上面的计算中出现的各个数命名,我们可以把代码弄得更清楚些。我们发现,例如数字3是由( 8 0-1 ) / 2 6得到的,而l e t应该有2 6个项,而不是2 7个(这个超一( o ff - b y - o n e )错误可能是由于写程序的人把屏幕坐标当作从1开始而引起的)。通过一些简化后,我们得到的结果代码是:


        现在,主循环到底做什么已经很清楚了:它是一个熟悉的从0到N L E T的循环,是一个对数据(数组)元素操作的循环。程序里对d r a w的调用也同样容易理解,因为像M A X R O W和M I N C O L这样的词提醒我们实际参数的顺序。更重要的是,现在我们已经很容易把这个程序修改为能够对付其他的屏幕大小或不同的数据了。数被揭掉了神秘的面纱,代码的意义也随之一目了然了。

        把数定义为常数,不要定义为宏。C程序员的传统方式是用# d e f i n e行来对付神秘的数值。C语言预处理程序是一个强有力的工具,但是它又有些鲁莽。使用宏进行编程是一种很危险的方式,因为宏会在背地里改变程序的词法结构。我们应该让语言去做正确的工作 。

       与此类似的还有另一个问题,那就是程序里许多上下文中经常出现的0。虽然编译系统会把它转换为适当类型,但是,如果我们把每个0的类型写得更明确更清楚,对读程序的人理解其作用是很有帮助的。例如,用(v o i d *) 0或N U L L表示C里的空指针值,用‘\ 0’而不是0表示字符串结尾的空字节。

         利用语言去计算对象的大小。不要对任何数据类型使用显式写出来的大小。例如,我们应该用s i z e o f(i n t)  而不是2或者4。基于同样原因,写s i z e o f(a r r a y [ 0 ] ) 可能比s i z e o f(i n t) 更好,因为即使是数组的类型改变了,也没有什么东西需要改变。利用运算符s i z e o f常常可以很方便地避免为数组大小引进新名字。

1.6 注释

       最好的注释是简洁地点明程序的突出特征,或是提供一种概观,帮助别人理解程序。注释应该提供那些不能一下子从代码中看到的东西,或者把那些散布在许多代码里的信
息收集到一起。当某些难以捉摸的事情出现时,注释可以帮助澄清情况。如果操作本身非常明了,重复谈论它们就是画蛇添足了。

        否定性的东西很不好理解,应该尽量避免。

        无论产生脱节的原因何在,注释与代码矛盾总会使人感到困惑。由于误把错误注释当真,常常使许多实际查错工作耽误了大量时间。所以,当你改变代码时,一定要注意保证其中的注释是准确的。

        学生常被告之应该注释所有的内容。职业程序员也常被要求注释他们的所有代码。但是,应该看到,盲目遵守这些规则的结果却可能是丢掉了注释的真谛。注释是一种工具,它的作用就是帮助读者理解程序中的某些部分,而这些部分的意义不容易通过代码本身直接看到。我们应该尽可能地把代码写得容易理解。在这方面你做得越好,需要写的注释就越少。好的代码需要的注释远远少于差的代码。

1.7 为何对此费心

        这里最关键的结论是:好风格应该成为一种习惯。如果你在开始写代码时就关心风格问题,如果你花时间去审视和改进它,你将会逐渐养成一种好的编程习惯。一旦这种习惯变成自动的东西,你的潜意识就会帮你照料许多细节问题,甚至你在工作压力下写出的代码也会更好。






推荐阅读
  • 本文详细介绍了C语言中的指针,包括其基本概念、应用场景以及使用时的优缺点。同时,通过实例解析了指针在内存管理、数组操作、函数调用等方面的具体应用,并探讨了指针的安全性问题。 ... [详细]
  • 本文详细介绍了C语言的起源、发展及其标准化过程,涵盖了从早期的BCPL和B语言到现代C语言的演变,并探讨了其在操作系统和跨平台编程中的重要地位。 ... [详细]
  • 本文介绍了多个关于JavaScript的书籍资源、实用工具和编程实例,涵盖从入门到进阶的各个阶段,帮助读者全面提升JavaScript编程能力。 ... [详细]
  • 在Java中,this是一个引用当前对象的关键字。如何通过this获取并显示其所指向的对象的属性和方法?本文详细解释了this的用法及其背后的原理。 ... [详细]
  • 本文深入探讨了HTTP请求和响应对象的使用,详细介绍了如何通过响应对象向客户端发送数据、处理中文乱码问题以及常见的HTTP状态码。此外,还涵盖了文件下载、请求重定向、请求转发等高级功能。 ... [详细]
  • PHP 过滤器详解
    本文深入探讨了 PHP 中的过滤器机制,包括常见的 $_SERVER 变量、filter_has_var() 函数、filter_id() 函数、filter_input() 函数及其数组形式、filter_list() 函数以及 filter_var() 和其数组形式。同时,详细介绍了各种过滤器的用途和用法。 ... [详细]
  • 本文探讨了如何使用自增和自减运算符遍历二维数组中的元素。通过实例详细解释了指针与二维数组结合使用的正确方法,并解答了常见的错误用法。 ... [详细]
  • Python处理Word文档的高效技巧
    本文详细介绍了如何使用Python处理Word文档,涵盖从基础操作到高级功能的各种技巧。我们将探讨如何生成文档、定义样式、提取表格数据以及处理超链接和图片等内容。 ... [详细]
  • 本文介绍了一种解决二元可满足性(2-SAT)问题的方法。通过具体实例,详细解释了如何构建模型、应用算法,并提供了编程实现的细节和优化建议。 ... [详细]
  • Python入门:第一天准备与安装
    本文详细介绍了Python编程语言的基础知识和安装步骤,帮助初学者快速上手。涵盖Python的特点、应用场景以及Windows环境下Python和PyCharm的安装方法。 ... [详细]
  • Java 数组及其常用操作
    本文详细介绍了 Java 中的数组类型、定义方法以及常见操作,帮助开发者更好地理解和使用 Java 数组。 ... [详细]
  • Python 学习是否需要先掌握 C 语言?
    Python 是一门非常适合编程入门的语言,很多人疑惑是否需要先学习 C 语言才能更好地掌握 Python。本文将详细探讨这个问题,并为初学者提供专业的建议。 ... [详细]
  • Ihaveastringwithquotesaroundthepathasfollows:我在路径周围有一个带引号的字符串,如下所示:C:\ProgramFiles(x ... [详细]
  • 本文探讨了Java编程的核心要素,特别是其面向对象的特性,并详细介绍了Java虚拟机、类装载器体系结构、Java类文件和Java API等关键技术。这些技术使得Java成为一种功能强大且易于使用的编程语言。 ... [详细]
  • 异常要理解Java异常处理是如何工作的,需要掌握一下三种异常类型:检查性异常:最具代表性的检查性异常是用户错误或问题引起的异常ÿ ... [详细]
author-avatar
mobiledu2502855653
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有