第二章 注重实效的途径

1. 重复的危害

a) DRY-Don’t Repeat Yourself。系统中的每一项知识都必须具有单一、无歧义、权威的表示。

b) 重复是怎样发生的

Imposed Duplication强加的重复。开发者觉得他们无可选择-环境似乎要求重复。

Inadvertent Duplication无意的重复。开发者没有意识到自己在重复信息。

Impatient Duplication无耐心的重复。开发者偷懒,因为重复似乎更容易。

Interdeveloper dumplication开发者之间的重复。同一个团队的几个人重复了同样的信息。

下面是对这四类重复的详细解释

c) 强加的重复

1) 注释。糟糕的代码才需要许多注释。要把低级的知识放在代码中,把注释保留给其它高级的说明,否则过多的注释只是在重复知识,每次改变代码,注释也需要更改,最终注释会变得过时,不可信任的注释比完全没有注释更糟。可以考虑用合理的变量命名、逻辑清晰的代码逻辑来代替低级的注释,而描述函数运作原理的注释,以及约定函数的输入、输出等,这些应该算是高级注释。

2) 文档与代码。撰写文档,然后编写代码,文档和代码在重复同样的知识,文档需要与代码保持同步,但常常得不到及时的维护。这种情况估计执行力不到位的公司都会遇到。

d) 无意的重复。这常常来自不合理的设计。比如一条线段,设计了起点、终点两个属性后,如果再加上长度属性,便是多余的。

e) 无耐心的重复。这种重复最容易检测,为了走捷径而简单复制,常常是欲速而不达,一旦需要修改代码,这种简单地复制的行为就会受到应有的惩罚。

f) 开发者之间的重复。这类重复最难检测,项目在演进过程中,随着人员的变动,方案的调整,到最后往往很难看清项目的全貌,也许正在编写的函数已经实现过了却没人能想起来。对于这类重复,最好是通过清晰的设计、强有力的技术项目领导、明确的责任划分来规避。


2. 正交性

“正交性”本是本意是指几何中相互垂直的两条直线,正交时某个点沿着一条直线移动,它投影在另一条直线的位置不变。在软件领域中,正交性指某种不相依赖或解耦性。如果一个软件模块发生变化,不会影响其它模块,那它们就是正交的。要尽量设计内聚的组件(独立,具有单一、良好定义的目的)。

a) 软件模块正交的好处

1) 提高生产率

使改动局部化,降低开发测试时间

促进复用。如果组件具有明确而具体的、良好定义的职责,就可以用最初的开发者未曾想象过的方式,把它们与新组件组合起来。

充分发挥模块的功能,A组件M件事,B组件N件事,如果A B正交,可以组合成M*N种功能,这是最大化的。可能只一点只能体现在理论上吧。

2)降低风险

正交的设计可以隔离有问题代码区域,如果某个模块有问题,在正交系统中,不会蔓延到其它模块,要更换问题模块也很容易

让系统更健壮。对某个模块的改动,所导致的任何影响都被局限在该区域内。

更方便测试,因为设计测试、并针对其组件运行测试更容易,否则为了测试一个模块还要关联测试其它模块,这就像之前单元测试描述的,复杂度会快速膨胀。

3) 不会与某个特定的供应商、产品或平台绑在一起。但如果使用的是UI控件、ORM框架,要不绑在一起估计很困难。

b) 在工作中运用正交原则的几种方式

1) 项目团队。怎样把团队划分为责任互不重叠的小组,这个没有明确的答案,据项目而定,但可以从基础设施与应用分离开始。比如按照主要的基础设施组件(数据库、通信接口、中间件等)划分,并根据具体情况进行调整。对团队的正交性衡量有一个方法:查看在讨论每个所需改动时涉及的人数,人数越多正交性越差

2) 设计。采用分层的方法是设计正交系统的强大方式。每层都只使用在其下面的层次提供的抽象,在改动一个层的实现时,可以不影响其他层,拥有极大的灵活性。而且分层也降低了模块间依赖关系失控的风险,否则根本无法驾驭模块间的互相引用。衡量设计好坏,可以考虑这个问题:如果我显著地改变某个特定功能背后的需求,有多少模块会受影响?在最理想的正交系统中,答案应该是“一个”,现实中虽然很少能做到这样,但也应该是越少越好。而且要小心地作出假设,不要依赖你无法控制的事物,比如将电话号码作为顾客的识别码

3) 编码。要努力地让代码保持解耦。作者形象地比喻为:编写“羞涩”的代码。羞涩的代码不会没有必要地向其他代码模块暴露任何事情、也不依赖其他模块的实现。此外避免重复、应对变化是设计模式的拿手好戏,需要多学习领会

4) 测试。正交地设计和实现的系统更易于测试。建议每个模块都有自己的、内建在代码中的单元测试,并让这些测试作为常规构建过程的一部分自动运行。而且构建单元测试本身就是对正交性的有趣测试,如果为了构建某个单元测试,你需要把系统中其余部分拉进来,那么正交性就很差。


3. 可撤销性

a) 如果某个想法是你唯一的想法,再没有什么比这更危险的事情了。

b) 没有什么永远不变,而如果你严重依赖某一事实,你几乎可以确定它将会变化。要把决策视为写在沙滩上的,而不要把他们刻在石头上。大浪随时可能到来,把他们抹去。

c) 除了保持代码的灵活性,还需要考虑架构、部署及供应商等领域的灵活性。


4. 曳光弹

a) 在机枪射击中,常会把曳光弹与常规弹药交错装在弹药带上,发射时曳光弹会在枪与击中的地方留下烟火般的踪迹,而如果曳光弹击中目标,常规弹药也会击中目标。在软件开发中,如果有新的项目是你从未构建过,客户也没有用过类似系统以致需求模糊不清时,可以使用类似的曳光弹方法。

1) 曳光弹与真正的子弹在相同的环境和约束下工作,枪手能够得到即时的反馈。在软件开发中,使用曳光代码可以快速、直观可重复地从需求出发,满足最终系统的要求。

2) 曳光代码并非用过就扔的代码,它含有任何一段产品代码都拥有的完整的错误检查、结构、文档、自查,只是功能不全而已。曳光开发与项目永不会结束的理念是一致的:总有改动需要完成,总有功能需要增加,这是一个渐进的过程。

b) 曳光代码的优点

1) 用户能够及早看到能工作的东西,并帮你定位目标

2) 曳光代码相当于一个有待壮大的集成平台,一旦新的代码段通过了单元测试,就可以将它加入该环境中

3) 有了用于演示的东西

4) 将更能感觉到工作进展,相当于把一个大目标分成了许多小目标来完成

c) 但是曳光弹并非总能击中目标,曳光代码也不是总能满足需求,这正是曳光弹和曳光代码的价值所在。曳光代码可以帮助在客户的不断反馈中接近目标,而小段代码的惯性也小,改变起来容易、迅速

d) 曳光代码与原型的区别。原型制作的是用过就扔的代码,而曳光代码虽然简约,却是完整的,并且构成了最终系统的骨架的一部分。可以把原型制作视为在第一发曳光弹发射之前进行的侦查和情报搜集工作。


5. 调试

a) 调试的“心理学”

最容易欺骗的人是自己

不要恐慌

如果见到Bug的第一反应是“那不可能”, 就完全错了。不要浪费时间在以“那不可能”起头的思路上,因为那不仅可能,而且已经发生了。

在调试时小心近视,要抵制只修正你看到的症状的迫切愿望,要尽可能找到其它相关的地方,找出问题的根源,而不是问题的特定具体表现。

测试时尽可能覆盖全部边界条件。

b) 跟踪。如果需要观察程序或数据结构随时间的变化情况,就需要用到跟踪的方法。比如并发编程、实时系统、基于事件的应用中,将跟踪信息打印到屏幕或文件中就是有效的方法。

c) 审视自己的代码,看看是否有一些不严密的假定

欢迎关注我的个人公众号【菜鸟程序员成长记】

《程序员修炼之道》笔记(二)相关推荐

  1. css中怎么加入立体模型,CSS学习笔记二:css 画立体图形

    继上一次学了如何去运用css画平面图形,这一次学如何去画正方体,从2D向着3D学习,虽然有点满,但总是一个过程,一点一点积累,然后记录起来. Transfrom3D 在这一次中运用到了一下几种属性: ...

  2. qml学习笔记(二):可视化元素基类Item详解(上半场anchors等等)

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7851 ...

  3. oracle直查和call哪个更快,让oracle跑的更快1读书笔记二

    当前位置:我的异常网» 数据库 » <>读书笔记二 <>读书笔记二 www.myexceptions.net  网友分享于:2013-08-23  浏览:9次 <> ...

  4. 【Visual C++】游戏开发笔记二十七 Direct3D 11入门级知识介绍

    游戏开发笔记二十七 Direct3D 11入门级知识介绍 作者:毛星云    邮箱: happylifemxy@163.com    期待着与志同道合的朋友们相互交流 上一节里我们介绍了在迈入Dire ...

  5. [转载]dorado学习笔记(二)

    原文地址:dorado学习笔记(二)作者:傻掛 ·isFirst, isLast在什么情况下使用?在遍历dataset的时候会用到 ·dorado执行的顺序,首先由jsp发送请求,调用相关的ViewM ...

  6. PyTorch学习笔记(二)——回归

    PyTorch学习笔记(二)--回归 本文主要是用PyTorch来实现一个简单的回归任务. 编辑器:spyder 1.引入相应的包及生成伪数据 import torch import torch.nn ...

  7. tensorflow学习笔记二——建立一个简单的神经网络拟合二次函数

    tensorflow学习笔记二--建立一个简单的神经网络 2016-09-23 16:04 2973人阅读 评论(2) 收藏 举报  分类: tensorflow(4)  目录(?)[+] 本笔记目的 ...

  8. 趣谈网络协议笔记-二(第十九讲)

    趣谈网络协议笔记-二(第十九讲) HttpDNS:网络世界的地址簿也会指错路 自勉 勿谓言之不预也 -- 向为祖国牺牲的先烈致敬! 引用 dns缓存刷新时间是多久?dns本地缓存时间介绍 - 东大网管 ...

  9. 趣谈网络协议笔记-二(第十八讲)

    趣谈网络协议笔记-二(第十八讲) DNS协议:网络世界的地址簿 自勉 勿谓言之不预也 -- 向为祖国牺牲的先烈致敬! 正文 DNS用于域名解析,但也不仅仅是用于域名解析,不仅仅是将域名转换成IP. 在 ...

  10. 趣谈网络协议笔记-二(第十七讲)

    趣谈网络协议笔记-二(第十七讲) P2P协议:我下小电影,99%急死你 自勉 逃离舒适区! 正文 一. P2P协议 整个篇章讲的就是这两个协议之间的区别.P2P协议就是迅雷下载数据时所用的协议, 众所 ...

最新文章

  1. 06 回归算法 - 损失函数、过拟合欠拟合
  2. UI自动化测试工具White简介以及使用经验总结(一)
  3. .Net高级技术笔记
  4. spring中容器启动过程中初始化资源使用方法
  5. unity人物旋转移动代码_Unity实现人物旋转和移动效果
  6. Python 批量修改文件后缀
  7. 三菱Q系列PLC程序,该设备由24个伺服电机、1套焊接机、2套CCD、4套扫码枪、6套位移传感器组成
  8. Java项目源码下载SSM网上水果生鲜超市商城|电商购物系统
  9. 《C++ Primer Plus》学习笔记——共用体union
  10. html语言中%3cp%3e%3cbr%3e,求一段弹出窗口代码
  11. 华为云牛客网之学生华为云服务器体验之路_1云服务器的购买篇
  12. vsCode好用插件记录
  13. Unable to get offset lags for kafka. Reason: java.lang.NullPointerException at org.apache.storm.kafk
  14. BLE(7)—— 发起态数据包组成( Initiating Packets PDUs)
  15. 让人春分日 哈工科教110132.平面分割
  16. java闭锁_Java并发工具类(闭锁CountDownLatch)
  17. tkinter可视化天气查询
  18. JAVA 计算日期属于当月第几周(日期周计算)
  19. Windows下Kafka集群搭建
  20. [李开复]给中国学生的第三封信:成功、自信、快乐

热门文章

  1. Go Slice【Go语言圣经笔记】
  2. 《深入理解计算机系统》CSAPP第3版术语索引表
  3. 【QT项目——视频播放器——音频录制】6.1QAudioFormat音频播放
  4. u3d 总是背向相机_大疆口袋云台相机升级,DJI Pocket 2更大、画质更佳,角度更广,配件更足...
  5. matlab校正系统使相角裕度不小于45,4验算已校正系统的相角裕度.PPT
  6. Mybatis_plus的一些介绍
  7. 字符串转数组,并去除掉字符串的中英文引号
  8. html视频自动缩放,HTML5 视频(videos)缩放JavaScript插件
  9. 榕基软件公司笔试面试
  10. Berkeley DB 的内容