热门标签 | 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语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了基于c语言的mcs51单片机定时器计数器的应用教程,包括定时器的设置和计数方法,以及中断函数的使用。同时介绍了定时器应用的举例,包括定时器中断函数的编写和频率值的计算方法。主函数中设置了T0模式和T1计数的初值,并开启了T0和T1的中断,最后启动了CPU中断。 ... [详细]
  • 本文介绍了在Windows系统上使用C语言命令行参数启动程序并传递参数的方法,包括接收参数程序的代码和bat文件的编写方法,同时给出了程序运行的结果。 ... [详细]
  • C语言判断正整数能否被整除的程序
    本文介绍了使用C语言编写的判断正整数能否被整除的程序,包括输入一个三位正整数,判断是否能被3整除且至少包含数字3的方法。同时还介绍了使用qsort函数进行快速排序的算法。 ... [详细]
  • C语言常量与变量的深入理解及其影响
    本文深入讲解了C语言中常量与变量的概念及其深入实质,强调了对常量和变量的理解对于学习指针等后续内容的重要性。详细介绍了常量的分类和特点,以及变量的定义和分类。同时指出了常量和变量在程序中的作用及其对内存空间的影响,类似于const关键字的只读属性。此外,还提及了常量和变量在实际应用中可能出现的问题,如段错误和野指针。 ... [详细]
  • 恶意软件分析的最佳编程语言及其应用
    本文介绍了学习恶意软件分析和逆向工程领域时最适合的编程语言,并重点讨论了Python的优点。Python是一种解释型、多用途的语言,具有可读性高、可快速开发、易于学习的特点。作者分享了在本地恶意软件分析中使用Python的经验,包括快速复制恶意软件组件以更好地理解其工作。此外,作者还提到了Python的跨平台优势,使得在不同操作系统上运行代码变得更加方便。 ... [详细]
  • 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
    本文旨在全面介绍Windows内存管理机制及C++内存分配实例中的内存映射文件。通过对内存映射文件的使用场合和与虚拟内存的区别进行解析,帮助读者更好地理解操作系统的内存管理机制。同时,本文还提供了相关章节的链接,方便读者深入学习Windows内存管理及C++内存分配实例的其他内容。 ... [详细]
  • 本文讲述了作者从最初对软件工程的选择迷茫到逐渐喜欢并坚持学习的经历。作者在大学期间通过学习专业课和参与项目开发,不断挑战自己并取得成就感。虽然曾考虑过转专业和复读,但最终决定坚持学习软件工程,并为自己的未来努力奋斗。作者还提到了大学生活与自己最初的预期不同,但对此并没有太多抱怨。 ... [详细]
  • 本文介绍了GTK+中的GObject对象系统,该系统是基于GLib和C语言完成的面向对象的框架,提供了灵活、可扩展且易于映射到其他语言的特性。其中最重要的是GType,它是GLib运行时类型认证和管理系统的基础,通过注册和管理基本数据类型、用户定义对象和界面类型来实现对象的继承。文章详细解释了GObject系统中对象的三个部分:唯一的ID标识、类结构和实例结构。 ... [详细]
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社区 版权所有