前段时间在看这本书, 看了一大半了, 很多东西讲的还是很有道理的, 这一系列文章作为笔记, 供自己今后翻阅.
1. 第二章 有意义的命名
1.1 名副其实的命名
名副其实说起来很简单. 但是这里需要强调. 给类,变量,方法选个好名字可能会花点时间, 但省下来的时间肯定会比花掉的多. 注意命名, 如果使用时候发现了更好的名字, 一定要及时替换掉. 这样做, 读你代码的人都会开心.
变量, 函数, 类的名称应该已经答复所有的大问题. 它应该告诉你, 它为什么存在, 它做什么事情, 应该怎么用. 如果名称需要注释来补充, 那就不算是名副其实.(这个问题, 我个人英文水平算不上特别好, 我觉得, 在方法名或者类名前面, 用中文描述下方法或者类的作用, 功能等, 看起来更加的直观一点, 可能英文为母语的程序猿并不需要这么做, 我的看法是, 重要的要用中文描述.)
1.2 避免误导的命名
程序猿必须避免留下掩藏代码本意的错误线索. 应该避免使用与本意相悖的词. 比如将一个放名字的label定义成: nameView, 就是误导的线索; 命名时候还要堤防使用不同之处较小的名称. 比如ESCreateAccountStep1Controller, ESCreateAccountStep2Controller, 这两个名字就是不好的命名, 稍不留神在代码中可能会引用到错误的类, 使用时候必须格外的小心.
以同样的方式拼写出同样的概念, 这才是信息. 拼写前后意义不同, 这是误导!
1.3 做有意义的区分
如果程序猿只是满足编译器或者解释器而写代码, 就会制造麻烦. 例如不同作用域重复命名的问题, 虽然语法是没有错, 但很多时候会产生意想不到的错误.
废话是另一种没有意义的区分. 比如variable永远不应该出现在变量名中. 比如有个类叫Product, 还有个类叫ProductInfo或ProductData, 这样名字虽然不同, 但是却没有任何意义. 这就是含糊不清的废话.
1.4 其它命名规范
- 使用读的出来的名字. 好的名字读起来像一句话, 读完就知道这个类或者方法是干什么用的, 见名知意.
- 可以的话, 就不要使用前缀. 前缀说白了就是没有意义的编码, 命名时候应该尽量避免使用编码.
- 避免思维映射. 就是说, 要编写别人能看得懂的代码, 比如一个变量名叫account, 代表意义却是性别, 这就是错误的思维映射.命名时候要使用其它程序猿都能够看得懂的名字.
- 不要耍帅扮可爱. 比如用whack()(美国俚语,劈砍)来表示kill(), 听起来倒是挺新鲜, 但是不明确, 不懂这些俚语的人, 乍一看完全看不懂. 命名宁可明确, 不为好玩.
- 别用双关词, 就是别用意义不明确的词.
- 可能阅读你代码的一定是程序猿, 所以尽情的使用专业术语吧, 命名成技术性的术语, 是比较靠谱的做法.
- 添加有意义的语境. 例如: addrFirstName, addrLastName, 这就是有意义的语境.而: firstName, lastName就是没意义的语境, 因为不能清楚的表达是什么的名字.
2. 第三章 函数
函数一节是书本中的第三章, 全面的讲解了如何写好一个函数, 个人觉得还是很不错了, 自从读了之后, 写代码时候就会下意识的注意某些问题, 避免某些问题.
2.1 短小
函数的第一规则是要短小, 第二规则是还要更短小
. 这是作者40年的经验告诉我们的结论, 我们写代码时候应该尽量减少一个函数的行数和每行代码的长度.
代码块和缩进. 一个函数不可以大到容纳所有的嵌套结构, 写代码时候, 函数的缩进层级不应该多于一层或者两层, 这样的函数更加的易读易懂.
短小, 我个人也有过一些思考. 首先我是一个记忆力并不怎么好的人, 一般吧! 所以对于大多数人来说, 小小的脑袋瓜子, 不可能一次性的记住软件中所有的逻辑关系, 不可能梳理好每个可能出现的bug, 即使是一个很简单的错误, 在逻辑关系复杂的系统中, 我们也很难发现, 除非重读代码或者测试. 但是, 一次考虑做好一件事情还是可以的. 这样, 每次写好一个完整的函数, 保证一个函数不出错, 一次写好两个或者及各类之间的关系, 每次写好复杂逻辑中的一小部分, 保证小范围的绝对准确, 这样当把所有小范围联系起来时候就是一个完整的复杂的程序. 其实我个人很陶醉这种创造. 要解决一个问题, 一层一层的, 写好最后一行代码, 编译,运行,成功! 很有成就感的时刻!!
2.2 只做一件事情
这个问题, 我想上文已经聊过了. 我们有限的记忆力和逻辑能力, 只允许我们每次做一件事情. 所以, 一次只做一件事情可以保证出错的概率. 所以函数应该一次只做一件事情.
2.3 每个函数一个抽象层级
要确保一个函数只做一件事情, 函数中的语句都要在同一个抽象层级上. 就是说, 不要在同一个函数中同时存在细节和抽象层级.
2.4 switch
switch这个东西, 我个人是拒绝的, 我遇到多分支我会用elif, 拒绝使用switch, 我觉得用switch回导致程序代码参差不齐, 导致代码混乱. 我拒绝!
2.5 给函数取一个好名字
这其实是上一章的内容. 千万别怕名字长, 长而有描述性的名字比短而费解的名称好.
别怕花时间取名字, 花时间是值得的. 命名方式必须保持一致, 在一个软件中, 同一个单词表达的意义必须是相同的, 要注意给相同的语境其完全相同的定义!!!
2.6 函数参数
最理想的函数参数是0个. 其次是1, 其次是2, 应该尽量避免三个参数!! 要有足够特殊的理由, 才能够使用3个参数!! 当一个函数参数过多的时候, 应该考虑拆分函数或者将参数封装成一个对象, 传递对象.
2.7 无副作用
副作用是一种谎言. 函数承诺只做一件事情, 但是还会做其它被藏起来的事情. 比如一个类方法, 承诺只是存储一个对象的数据到数据库中, 但是又承担了创建数据库访问对象的操作, 这就是被隐藏起来的事情, 稍有不慎就会导致时序性耦合以及顺序错误.
输出参数, 我觉得输出参数有时候是很明智的选择, 能够解决意想不到的问题. 比如有一个列表数据, 每条数据都有一个选中状态, 点击的时候修改每一条的选中状态即可, 最后统计时候, 遍历列表, 取出被选中的item即可. 个人还是比较喜欢用输出参数的, 并不是所有地方输出参数都能够被状态代替.
2.8 不要重复自己
重复是软件中一切邪恶的根源. 很多的原则和实践规则都是为了控制和消除重复而创建的.
2.9 结构化编程
每个函数每个代码块应该有一个入口. 就是说, 每个函数应该只有一个return语句, 循环中不能有break或者continue语句. 我赞成结构化编程的规则, 但是这些规则在小的函数中作用不太大.
2.10 如果写出一个好的函数
写代码和写别的东西一样, 不论写什么, 都要先想, 再琢磨, 初稿也许很丑陋, 但是仔细斟酌推敲后, 就可以达到你心中的样子.
刚开始写的代码可能有很多的缩进, 并且函数冗长, 函数名字不明确. 然后可以去打磨这些代码, 分解函数, 修改名称, 消除重复, 直至达到你心中的样子.
3. 第四章 注释
什么也不比良好的注释来的更有用. 什么也不比糟糕的注释更能捣乱一个模块.
程序猿应该负责将注释保持在可维护, 有关联, 精确的高度.
只有代码能够忠诚的告诉我们程序在做什么事情, 代码是最准准确的信息来源. 所以, 尽管有时候也需要注释, 但是我们也需要花心思尽量减少注释!
3.1 注释不能美化糟糕的代码
写注释的常见动机之一是: 糟糕代码的存在.带有少量注释的整洁而有表达力的代码, 要比带有大量注释的零碎而复杂的代码更好! 与其花时间编写复杂的注释, 不如花时间清洁糟糕的代码!
3.2 用好的代码来阐述
写代码过程中应该尽量避免使用注释, 但是一定要在必须的地方写注释! 有时候可以用代码去阐述操作的意义而不是注释!!
3.3 好注释
有的注释是必须写的, 也是有利的. 唯一真正好的注释, 是你想办法不去写的注释.
- 一般代码开头要写版权, 著作权等公司要求的法律文件等信息, 这是必须的.
- 提供信息的注释: 比如解释一个方法的用途; 解释一个for循环的作用; 阐述某些复杂的参数返回值等也是有意义的; 必要的警告信息也是有必要的; TODO注释; 放大某些看似不合理的代码并做解释.
3.4 坏注释
通常坏注释是糟糕代码的支撑或者接口. 或者对错误决策的修正.
- 喃喃自语不必要的注释不要写, 如果你决定写注释, 就必须花时间写出好的注释!
- 误导性注释. 写注释一定要准确, 不要提供误导信息.
- 循规式注释. 不要为了某些规定而去写注释, 至少不需要死板硬套的照搬规矩!
- 日志式注释.
- 废话注释. 如果注释不能比方法名字更能表现方法的功能, 那么就是废话注释!
- 能用函数或者变量表达清楚的地方, 就不要使用注释.
- 位置标记注释. 比如一行
////
来标记某个位置. 这个觉得不是必须要避免, 但是一定要慎重使用! 如果使用太频繁就会导致代码特别混乱, 也起不到标记的作用.
- 位置标记注释. 比如一行
- 注释掉的代码. 如果代码不用了, 请直接干掉, 别注释!!! 否则后人看到也不敢删, 然后没用的代码会一直留着.
- 无关的注释. 注释一定要写在与之相关代码最近的位置. 且不要包含太多无关的信息, 尽量少写注释, 注释尽量写的精简.
- 函数头. 短的函数尽量为函数起一个好的名字来代替注释. 长的,复杂的函数才会写上简介明确的注释.
网友评论