新闻中心

EEPW首页 > 嵌入式系统 > 牛人业话 > <读书笔记> 代码整洁之道

<读书笔记> 代码整洁之道

作者:时间:2016-08-01来源:网络收藏

  二、关于函数的一些规则

本文引用地址:http://www.eepw.com.cn/article/201608/294841.htm

  1、短小

  函数的第一规则就是短小。

  长度以20行封顶为最佳。

  if,else,while语句的块应该只有一行,这样不但能保持函数短小,还能增加可读性。

  函数的层级不应该多于两层,这样才容易理解和阅读。

  2、只做一件事

  函数应该只做一件事,做好这一件事。

  判断函数是否只做了一件事的方法就是看其是否能够拆出一个函数,该函数不是单纯的重新诠释其实现。

  3、每个函数一个抽象层级

  要确保函数做做一件事情,函数中的语句都要在同一抽象层级上。这是保持函数短小的要诀。

  4、函数参数

  最好少于3个,0个和1个最佳,3个以上请使用结构体代替。

  输出参数比输入参数更加难以理解,读函数时,习惯于认为信息通过参数输入函数,通过返回值输出。

  给函数起个好名字,使其能够很好的解释函数的意图、以及参数的顺序。比如assertExpectedEqualsActual(expected,actual)就容易理解和记忆。

  5、无副作用

  副作用指的是被其隐藏起来的事情,比如开机检查密码函数,如果调用前密码未经初始化,就会出错,就隐藏了其时序性耦合的要求。应该在其函数中增加初始化密码的功能,尽管违反了只做一件事的。

  6、分割指令与查询

  函数修改某对象的状态或者获取该对象的参数,应该分为两个函数实现。

  比如函数设置某个指定属性,如果成功就返回true,失败返回false,用例如下:

  if(set("username","unclebob"))...

  这样的语句理解上面有歧义,set是动词,但是在上下文中感觉像形容词,从读者角度看,这句语句的意思是问username的属性是否已经设置为unclebob?还是询问username的属性是否成功设置为unclebob?因此最好改为如下所示:

  if(attributeExists("username"))

  {

  setAttribute("username","unclebob");

  }

  7、使用异常代替返回错误值

  直接返回错误鼓励了在if语句中把指令当做表达式使用,会导致多层次嵌套结构。如果返回异常代替错误码,错误处理代码就可以从主路径代码中分离出来,得到简化

  8、不要重复

  重复的代码可维护性差,如果算法修改,所涉及的地方都要更新,代码臃肿,还会增加放过错误的可能!

  如果一个算法在不同函数中重复出现,则需要使用一个独立的函数修复它。

  面向对象和面向组件编程也多多少少都是消除重复的策略。

  9、结构化编程

  只要保持函数短小,偶尔出现return、break、continue语句没有什么坏处,甚至比单入单出更具表达力。

  goto语句只在大函数中才能用到,因此尽量避免使用。

  10、如何写出短小的函数

  写代码和写文章一样,先写出初稿、再细细打磨,直至达到心中的样子。

  初写的函数,一般都是冗长而复杂,有太多缩进和嵌套循环,名称随意性大,代码有重复。通过分解函数、修改名称、消除重复,然后遵循本章的规则,重新组装函数,就可以写出短小精炼的函数。

  三 关于注释的规则

  1、注释不能美化糟糕的代码

  带有少量注释的整洁而有表达力的代码,要比带有大量注释的零碎而复杂的代码像样的多!

  与其花时间写注释,不如花时间清理早搞定糟糕的代码。

  代码在变动、演化,而很不幸,注释不是总随之变动,时间越久,注释离代码的本意就越久。只有代码是唯一真正准确的信息来源。。

  2、用代码阐述

  使用代码本身解释其行为。

  比如//Check to see if the employee is eligible for full benefits

  if((employee.flags &HOURLY_FLAG)&&(employee.age > 65))

  通过创建与注释所言同一事物的函数即可。

  if(employee.isEligibleForFullBenefits())

  3、好注释

  法律信息,比如公司代码规范要求写的有关法律的注释,版权声明等。

  提供信息的注释,更好的方法是使用函数名称传达信息。

  对意图的解释:注释不仅提供了有关实现的有用信息,而且还提供了某个决定后面的意图。

  阐释:把晦涩难懂的参数或者返回值翻译为可读形式的注释是有用的。

  警示:用于警告其它程序员会出现某种后果的注释也是有用的。

  4、坏的注释

  喃喃自语式:只是觉得因为过程需要就增加的注释。

  多余的注释:本身并不能比代码提供更多的信息,就是多余。

  误导性注释:含义不精确或者容易引起误导的注释。

  循规性注释:每个函数或者每个变量都要有注释的规矩是全然可笑的,只会搞乱代码。

  日志式注释:在有源码控制系统的今天,这种冗长的记录只会让模块变得凌乱不堪,应该删除

  废话注释:对显然之事喋喋不休,毫无新意。看代码的人员,也几乎对其视而不见。因此用整理代码的决心替代废话的冲动,会使你成为更优秀的程序员。

  可怕的废话:在知名开源库的J**adoc中,也可以看到复制黏贴错误,意思就是变量不一样,注释却一样。

  位置标记:少用标记栏,比如//Action//////////////////////////////,特定函数放在这个下面,多数时候是在不必要。

  括号后面的注释:尽管对于多层嵌套有帮助,但是更应该使用短小、封装的函数,如果你想标记右括号,其实应该做的是缩短函数。

  归属与署名:源码控制系统很善于记录是谁在何时改动了什么,没有必要用小小的签名搞脏代码。比如注释/*Added by Rick*/

  注释掉的代码:直接把代码注释掉是讨厌的做法,别人可能认为其一定有原因才留在这里不敢删除,最后注释掉的代码像渣滓一样堆在那里,别这么干!

  信息过多的注释:别再注释中增加历史性话题或者无关的细节描述。

  不明显的联系:注释的作用是解释未能自我解释的代码,如果本身还需要解释就没有必要了。

  函数头:短函数不需要太多注释,只需要写一个好名字就比注释强得多!

  四 关于代码格式的规则

  你应该保持良好的代码格式,选用一套管理代码格式的简单规则,然后贯彻实施。如果在团队中工作,则团队应该一致同意采用一套简单的格式规则,所有成员都要遵从。使用能帮你应用这些格式规则的自动化工具会很有帮助。

  1、格式的目的

  原始代码修改很久之后,其代码风格和可读性仍会影响到可维护性和扩展性。

  代码格式关乎沟通,而沟通时专业开发者的头等大事!

  哪些代码格式方面能帮助我们沟通呢?

  2、垂直格式

  垂直尺寸

  单个文件的长度尺寸与可理解性相关,统计数据表明,用大多数为200行到500行的单个文件可以构造出出色的系统,短文件通常比长文件容易理解!

  函数布局

  函数名称应该足够告诉我们是否在正确的模块中,源文件顶部应该给出高层次的概念和算法,细节应该向下逐次展开,直至源文件中最低层的函数和细节。就像报纸一样,标题统领提纲概要,内容逐次展开细节。

  空行

  在包声明、函数之间、代码块之间应该使用空行隔开,这条简单的规则极大的影响到代码的视觉外观。空白行作为一条线索,标示出独立的概念。

  靠近 如果说空白行隔开了概念,靠近的代码则暗示了他们之间的紧密联系。因此关系紧密的应该互相靠近.

  垂直距离

  全局变量声明应该放到文件第一个函数声明前,局部变量声明放到函数顶部。相关函数应该放在一起,调用者放在被调用者上面,这样就能轻易找到被调用函数,极大增强模块的可读性

  3、横向格式

  行宽

  一行代码应该多宽?统计数据表明,70%的代码行少于60个字符,代码行应该尽量短小,死守80字节有点僵化,但是不要超过100字符或者120字符。简单的规则是无需向右拖动滚动条,就可以看到全部代码。

  水平区隔与靠近

  在运算符号两端(乘号除外,因其优先级较高,多数格式化工具都忽视优先级)、函数名和右括号之间之间,函数参数之间增加空格!

  水平对齐

  经验表明一组类声明中的变量名、或者赋值语句的右值对齐没有什么实际作用,因此左端对齐,使用同样的空格区分规则即可。

  缩进

  有缩进的代码结构,阅读时可以很容易查找新的声明、变量、类和函数块,否则就需要折腾一番才能明白,程序员应该依赖缩进模式(在python中强制使用缩进表示for循环的范围,C语言中使用大括号,但是也要依赖缩进增强可读性)。

  空范围

  有时while或for语句的语句体为空,如下所示.右端的分号很难看见,容易让人迷惑。

  while(dis.read(buf,0,readBufferSize) != 1);

  因此最好改为如下格式

  while(dis.read(buf,0,readBufferSize) != 1)

  {

  }

  团队规则

  在团队中,各成员应该采用一致的代码格式,如果各自风格不同,会增加项目代码的复杂度。

  五 单元测试

  过去10年来,编程专业领域进步很大,特别是敏捷和(测试驱动开发)运动鼓舞了很多程序员编写单元测试。要我们在编写生产代码之前先编写测试,其还有三大定律:

  定律一:再编写不能测试通过的测试驱动前,不可编写生产代码

  定律二:只可编写刚好无法通过的单元测试,不能编译也不算通过

  定律三:只可编写刚好足以通过当前失败测试的生产代码。

  这些定律要求测试与生产代码一起编写,测试代码先写,这样写程序,测试将覆盖所有生产代码。

  1、保持测试的整洁

  测试代码和生产代码一样,需要被思考、设计和照料,像生产代码一样整洁

  正是单元测试让你的代码可扩展、可维护、可复用。如果没有测试,每次修改都可能带来缺陷,无论架构如何有扩展性,设计划分如何好,如果没有单元测试,你的改动都可能带来不可预知的缺陷。

  2、整洁的测试

  整洁的唯一要素的就是可读性,在单元测试中,可读性比生产代码还重要。如何做到可读性?就是要明确、简洁和具有足够的表达力。

  测试要采用构造-操作-检验模式,每个测试均要可以清晰的拆分为三个环节,第一个环节构造测试数据,第二个环节操作测试数据,第三个环节检验操作是否得到期望的结果。

  3、每个测试一个断言

  单个测试函数有且仅有一个断言是个好准则。

  每个测试做测试一个概念,如果一个测试测量三件事情,可能会导致遗漏。

  4、整洁的5条规则

  快速(fast),测试应该快速运行,你才能想要频繁运行它,如果不频繁运行,就不能尽早发现问题。

  独立(Independent),测试应该互相独立,从而可以单独运行每个测试。

  可重复(Repeatable),测试应该在任何环境中重复通过,否则当前环境具备时,你也会无法运行测试。

  自足验证(Self-Validating),测试应该有布尔值输出去,无论如何不应该查看日志文件来确认测试是否通过。

  及时(Timely),测试应该及时编写,如果在生产代码之后编写测试,你会发现代码难以测试。


上一页 1 2 下一页

关键词: 代码 TDD

评论


相关推荐

技术专区

关闭