读书之《程序员修炼之道》

读书分享《程序员修炼之道》

0.0几篇序

读书之前首先看到的内容,让大家知道这不是一本烂书,本书从项目管理,软件架构和设计、代码编写和测试,各方面都有精彩的阐述。序中的重点内容:

《领悟程序员的哲学》

  • 这不是一本只要读一遍的书
  • 给程序员做培训的首选材料

《再次阅读,感受颇多》

  • 公司新人的必备学习材料
  • 看似朴素的道理,实际是若干经验的总结
    • 看到了“破窗户”
    • 看到了DRYdont repeat yourself,dont repeat others
    • 曳光弹,开发prototype代码应该是抛弃型的
  • 知识资产的管理、沟通、交流。

《一切阅读都是误读》

  • 爱不释手
  • 作为书单的第一本
  • 嚼烂的东西也有新味道

《程序员升级必备》

  • 如果要成为一个好程序员,其实所需要的道理也多不了多少,只不过,当水平不够的时候,永远不能认识到那些朴素道理的重要性
  • 不逊于《代码大全》
  • 这是一本经得起时间沉淀的书
  • 注重实效的程序员应该不断学习

《程序员心底的小声音》

  • 高手的显著标志是能用正确的原则指导正确的行动本身
  • 实践、实践、不断实践

读书分享《程序员修炼之道》

0.0几篇序 1

第一章 注重实效的哲学 3

1我的源码让猫给吃了 3

2软件的熵 3

3石头汤与煮青蛙 4

4足够好的软件 4

5你的知识资产 5

6交流 6

第二章 注重实效的途径 6

7重复的危害 6

8正交性 7

9可撤销性 9

10曳光弹 9

11原型与便笺 10

12领域语言 11

13估算 11

第三章 基本工具 11

14纯文本的威力 11

15shell游戏 12

16强力编辑 12

17源码控制 12

18调试 13

19文本操纵 13

20代码生成器 13

第四章 注重实效的偏执 14

21按合约设计 14

22死程序不说谎 14

23断言式编程 14

24何时使用异常 14

25怎样配平资源 15

第五章 弯曲,或折断 17

26解耦与得墨忒耳法则 17

27元程序设计 18

28时间耦合 18

29它只是视图 18

30黑板 18

第六章 当你编码时 19

31靠巧合编程 19

32算法效率 20

33重构 20

34易于测试的代码 23

35邪恶的向导 23

第七章 在项目开始之前 26

36需求之坑 26

37解开不可能解开的谜题 26

38等你准备好 26

39规范陷阱 26

40圆圈与箭头 27

第八章 注重实效的项目 28

41注重实效的团队 28

42无处不在的自动化 28

43无情的测试 28

44全都是写 30

45极大的期望 30

46傲慢与偏见 30

 

第一章 注重实效的哲学

1我的源码让猫给吃了

责任是你主动担负的东西

Provide Options, Dont Make Lame Excuses

提供各种选择,而不是各种蹩脚的借口

不要说做不到:要说明能够做什么挽回局面。必须扔掉代码?可以讲讲重构的价值。要花时间建立原型,来确定最好的前进路线?还是要引入更好的测试或自动化,防止问题再度发生?又或许是其他的额外资源。

2软件的熵

当软件中的无序增长时,程序员们称之为“软件腐烂”(software rot)。有许多因素可以促生软件腐烂。其中最重要的一个似乎是开发项目时的心理(或文化)。引出“破窗户理论”。

Dont Live with Broken Windows

不要容忍破窗户

一扇破窗户——一段设计低劣的代码、团队必须在整个项目开发过程中加以忍受的一项糟糕的管理决策——就足以使项目开始衰败。如果你发现自己在有好些破窗户的项目里工作,会很容易产生这样的想法:“这些代码的其余部分也是垃圾,我只要照着做就行了。”项目在这之前是否一直很好,并没有什么关系。

3石头汤与煮青蛙

这是一种促成变化的策略,在有些情况下,你也许确切地知道需要做什么,以及怎样去做。整个系统就在你的眼前——你知道它是对的。设计出你可以合理要求的东西,好好开发它。一旦完成,就拿给大家看,人们知道,参与正在发生的成功要更容易,所以再增加其他功能就会容易的多,万事开头难的意思。

Be a Catalyst for Change

做变化的催化剂

另一方面,石头汤的故事也是关于温和而渐进的欺骗的故事。我们都看见过这样的症状。项目慢慢地、不可改变地完全失去控制。大多数软件灾难都是从微不足道的小事情开始的,大多数项目的拖延都是一天一天发生的。系统一个特性一个特性地偏离其规范,一个又一个的补丁被打到某段代码上,直到最初的代码一点没有留下。

Remember the Big Picture

记住大场景

在破窗户理论中,人们失去与熵战斗的意愿,是因为他们觉察到没有人会在意。而青蛙只是没有注意到变化。
不要像青蛙一样。留心大图景。要持续不断地观察周围发生的事情,而不只是你自己在做的事情。

4足够好的软件

Make Quality a Requirements Issue

使质量成为需求问题

今天的了不起的软件常常比明天的完美软件更可取。如果你给用户某样东西,让他们及早使用,他们的反馈常常会把你引向更好的最终解决方案。不要因为过度修饰和过于求精而毁损完好的程序。继续前进,让你的代码凭着自己的质量站立一会儿。它也许不完美,但不用担心:它不可能完美

5你的知识资产

在一切还未掌握之前,需要拥有广泛的知识和经验基础才能赢得这一切。学习是一个持续不断的过程,在本小节中讨论一些策略,让我们“开足马力”。

随着新技术、语言及环境的出现,你的知识会变得过时。不断变化的市场驱动力也许会使你的经验变得陈旧或无关紧要。

  随着你的知识的价值降低,对你的公司或客户来说,你的价值也在降低。我们想要阻止这样的事情,决不让它发生。

Invest Regularly in Your Knowledge Portfolio

定期为你的知识资产投资

1. 每年至少学习一种新语言

2.  每季度阅读一本技术书籍

3. 也要阅读非技术书籍

4. 上课

5. 参加本地用户组织

6. 试验不同的环境

7. 跟上潮流

8. 上网

持续投入十分重要,一旦你熟悉了某种新语言或新技术,继续前进,学习另外一种。设法把你学到的东西应用到你当前的项目中。即使你的项目没有使用该技术,你或许也能借鉴一些想法。

如果你自己找不到答案,就去找能找到答案的人。不要把问题搁在那里,与他人交谈可以帮助你建立人际网络,而因为在这个过程中找到了其他不相关问题的解决方案,你也许还会让自己大吃一惊。

所有阅读和研究都需要时间,而时间已经很短缺。所以你需要预先规划,让自己在空闲的片刻时间里总有东西可读。

批判的思考你读到的和听到的。你需要确保你的资产中的知识是准确的,并且没有受到供应商或媒体炒作的影响。

 

 

6交流

我们不是活在真空世界,需要花大量时间与人交流。只有当你是在传达信息时,你才是在交流。

有效交流的几种方法:知道你想要说什么,了解你的听众,选择时机,选择风格,让文档美观,让听众参与,做倾听者,回复他人。

Critically Analyze What You Read and Hear
批判地分析你读到的和听到的

Its Both What You Say and the Way You Say It
你说什么和你怎么说同样重要

第二章 注重实效的途径

7重复的危害

“重复的危害”提醒你,不要在系统各处对知识进行重复。作为程序员,我们收集、组织、维护和利用知识。我们在规范中记载知识、在运行的代码中使其活跃起来并将其用于提供测试过程中所需的检查。遗憾的是,知识并不稳定。所有这些不稳定都意味着我们要把很大一部分时间花在维护上,重新组织和表达我们的系统中的知识。程序员须持续不断地维护。我们的理解逐日变化,当我们设计或编码时,出现了新的需求。环境或许变了。不管原因是什么,维护都不是时有时无的活动,而是整个开发过程中的例行事务。可靠地开发软件、并让我们的开发更易于理解和维护的惟一途径,是遵循我们称之为DRY的原则:
系统中的每一项知识都必须具有单一、无歧义、权威的表示。

DRY – Dont Repeat Yourself
不要重复你自己

DRY原则是注重实效的程序员的工具箱里最重要的工具之一。我们所见到的大多数重复都可归入下列范畴:

1. 强加的重复(imposed duplication)。开发者觉得他们无可选择——不同的环境似乎要求重复。

2. 无意的重复(inadvertent duplication)。开发者没有意识到他们在重复信息。

3. 无耐性的重复(impatient duplication)。开发者偷懒,他们重复,因为那样似乎更容易。

4. 开发者之间的重复(interdeveloper duplication)。同一团队(或不同团队)的几个人重复了同样的信息
Make It Easy to Reuse
让复用变得容易

你所要做的是营造一种环境,在其中要找到并复用已有的东西,比自己编写更容易。如果不容易,大家就不会去复用。而如果不进行复用,你们就会有重复知识的风险。

8正交性

“正交性”提醒你,不要把任何一项知识分散在多个系统组件中。在计算技术中,该术语用于表示某种不相依赖性或是解耦性。如果两个或更多事物中的一个发生变化,不会影响其他事物,这些事物就是正交的。非正交的例子:直升机驾驶操作的各个控制器之间就是相互影响的,不是正交的。

正交的好处就是为了可以局部修正(local fix)。

Eliminate Effects Between Unrelated Things
消除无关事物之间的影响

如果你编写正交的系统,你得到两个主要好处:提高生产率与降低风险

提高生产率

1. 改动得以局部化,所以开发时间和测试时间得以降低。

2. 正交的途径还能够促进复用

3. 如果你对正交的组件进行组合,生产率会有相当微妙的提高。

降低风险

1. 有问题的代码区域被隔离开来。

2. 所得系统更健壮。

3. 正交系统很可能能得到更好的测试,因为设计测试、并针对其组件运行测试更容易。

4. 你不会与特定的供应商、产品、或是平台紧绑在一起

 

工作中应用正交原则的几种方式

项目团队:有些项目团队很有效率,每个人都知道要做什么,而另一些团队的成员却老是在争吵,而且好像无法避免互相妨碍

设计:如果我显著地改变某个特定功能背后的需求,只有1个模块会受影响;你的设计在多大程度上解除了与现实世界中的的变化的耦合?

工具箱与库

在你引入第三方工具箱和库时,要注意保持系统的正交性。要明智地选择技术。

编码

编写代码,都有降低应用正交性的风险。除非你不仅时刻监视你正在做的事情,也时刻监视应用的更大语境,否则,你就有可能无意中重复其他模块的功能,或是两次表示已有的知识。

怎样维持正交性

1. 让你的代码保持解耦。编写“羞怯”的代码——也就是不会没有必要地向其他模块暴露任何事情、也不依赖其他模块的实现的模块。

2. 避免使用全局数据。

3. 避免编写相似的函数。你常常会遇到看起来全都很像的一组函数——它们也许在开始和结束处共享公共的代码,中间的算法却各有不同。Ps:这个深有体会

4. 养成不断地批判对待自己的代码的习惯。寻找任何重新进行组织、以改善其结构和正交性的机会。这个过程叫做重构(refactoring)。

测试

正交地设计和实现的系统也更易于测试,因为系统的各组件间的交互是形式化的和有限的,更多的系统测试可以在单个的模块级进行。与集成测试(integration testing)相比,模块级(或单元)测试要更容易规定和进行得多。

认同正交性

如果你参加了一个项目,大家都在不顾一切地做出改动,而每一处改动似乎都会造成别的东西出错,回想一下直升机的噩梦。项目很可能没有进行正交的设计和编码。是重构的时候了。但如果你紧密结合DRY原则、运用正交性原则,你将会发现你开发的系统会变得更为灵活、更易于理解、并且更易于调试、测试和维护。

挑战
问题:考虑常在Windows系统上见到的面向GUI的大型工具和在shell提示下使用的短小、但却可以组合的命令行实用工具。哪一种更为正交,为什么?如果正好按其设计用途加以应用,哪一种更易于使用?哪一种更易于与其他工具组合、以满足新的要求?

思路:win上的GUI大型工具是多个功能综合在一起的一个系统,各个功能可能互相依赖,不满足正交,而shell上的命令行工具,功能单一,不需要依赖其他外界条件就可以单独执行,且不影响其他功能的正常使用,满足正交性。Win上的GUI更加易于使用,因为不需要人为的综合各个功能的处理结果进行处理,只需要让系统按照自己的工作流程得到最终结果即可。Shell命令行更容易与其他工具组合,满足新要求,正交的组合更为容易。

9可撤销性

There Are No Final Decisions
不存在最终决策

1. 不确定市场部门想怎样部署系统?预先考虑这个问题,你可以支持单机、客户-服务器、或n层模型——只需要改变配置文件。

2. 你可以把第三方产品隐藏在定义良好的抽象接口后面。

3. 无论你使用的是何种机制,让它可撤消。如果某样东西是自动添加的,它也可以被自动去掉。

10曳光弹

它适用于新的项目,特别是当你构建从未构建过的东西时。因为你的用户从未见过这样的系统,他们的需求可能会含糊不清。因为你在使用不熟悉的算法、技术、语言或库,你面对着大量未知的事物。同时,因为完成项目需要时间,在很大程度上你能够确知,你的工作环境将在你完成之前发生变化。

Use Tracer Bullets to Find the Target
用曳光弹找到目标

曳光代码并非用过就扔的代码:你编写它,是为了保留它。它含有任何一段产品代码都拥有的完整的错误检查、结构、文档、以及自查。它只不过功能不全而已。

曳光代码方法有许多优点:

1. 用户能够及早看到能工作的东西。

2. 开发者构建了一个他们能在其中工作的结构。

3. 你有了一个集成平台。

4. 你有了可用于演示的东西。

5. 你将更能够感觉到工作进展。

曳光代码 vs. 原型制作

使用原型,你是要探究最终系统的某些具体的方面。使用真正的原型,在对概念进行了试验之后,你会把你捆扎在一起的无论什么东西扔掉,并根据你学到的经验教训重新适当地进行编码。而曳光代码不是写完就扔的代码。

11原型与便笺

原型不一定要以代码为基础。要为像工作流和应用逻辑这样的动态事物制作原型,便笺(post-it note)就非常好。用户界面的原型则可以是白板上的图形、或是用绘图程序或界面构建器绘制的无功能的模型。(PS:上次实习,开发之前在A4纸上的画图工作)。

但如果你发现自己处在不能放弃细节的环境中,就需要问自己,是否真的在构建原型。或许曳光弹开发方式更适合这种情况。

可以构建原型的事物

1. 架构。

2. 已有系统中的新功能。

3. 外部数据的结构或内容。

4. 第三方工具或组件。

5. 性能问题。

6. 用户界面设计。

Prototype to Learn
为了学习而制作原型

制作架构原型

7. 主要组件的责任是否得到了良好定义?是否适当?

8. 主要组件间的协作是否得到了良好定义?

9. 耦合是否得以最小化?

10. 你能否确定重复的潜在来源?

11. 接口定义和各项约束是否可接受?

12. 每个模块在执行过程中是否能访问到其所需的数据?是否能在需要时进行访问?

在你着手制作任何基于代码的原型之前,先确定每个人都理解你正在编写用过就扔的代码。对于不知道那只是原型的人,原型可能会具有欺骗性的吸引力。你必须非常清楚地说明,这些代码是用过就扔的,它们不完整,也不可能完整。

12领域语言

计算机语言会影响你思考问题的方式,以及你看待交流的方式。面对不同的环境和问题时,可以开发一套专注于这个领域的编程技术,属于自己的小众语言。

Program Close to the Problem domain
靠近问题领域编程

13估算

Estimate to Avoid Surprises
估算,以避免发生意外

在被要求进行估算时,放慢估算速度,并花一点时间仔细检查各步骤,你几乎总能得到更好的结果。时间估算,表示单位很重要,给出125天和25周,六个月的估算,传达的精确度不一样。

Iterate the Schedule with the Code
通过代码对进度表进行迭代

第三章 基本工具

主旨:工欲善其事,必先利其器。

14纯文本的威力

持久地存储知识的最佳格式是纯文本。

使用纯文本的缺点

  • 与压缩二进制相比,存储纯文本所需空间多
  • 解释和处理纯文本,计算代价更多

纯文本优点:

  • 保证不过时
  • 纯文本数据,人能够阅读并理解
  • 杠杆作用
  • 源码管理系统到编译器环境,再到编辑器及独立的过滤器,都能在纯文本上操作
  • 易于测试
  • 纯文本创建测试合成数据,增删改查测试数据很简单
纯文本与非纯文本不熟悉或者不明确概念的可以看转载的这个文章:http://blog.csdn.net/recsysml/article/details/44195793

15shell游戏

利用命令shell的力量,提高效率。

16强力编辑

推荐使用Emacsvi等工具,好的编辑器特性:

  • 可配置
  • 字体、颜色、尺寸等
  • 可扩展 
  • 适应很多不同的语言环境
  • 可编程
  • 对编辑器编程,执行多步骤的任务
  • 语法高亮、自动补全、缩进、初始模板等。

做了一个对比:notepadvi的生产率,假如要将import的前几行语句按照字母顺序排列,notepad表示只能一个一个调,vi直接命令输入:.,+3!sort,搞定了

17源码控制

总是使用源码控制系统,追踪每一处变动,可撤销性,对于bug追踪、审计、性能及质量等目的,这种信息很宝贵。

 

18调试

要修正问题,而不是发出指责。也不要恐慌。

调试策略:

  • 数据可视化
    • 数据及其所有的相互关系可视化,例如DDD调试器有可视化能力,可以多种语言一起工作,包括CC++JavaPythonPerl(正交的设计)
  • 跟踪
    • 跟踪语句,沿着调用树下降时增加跟踪语句。
  • 橡皮鸭 
    • 一步步解释代码要做什么,常常能找到问题的所在。
  • 消除过程
    • Bug可能存在于OS,编译器,或者第三方产品中,但是有很大可能是bug存在正在开发的应用代码中。在提交bug报告之前,先消除自己代码中的bug

修正bug后,想一想:以前为什么没有发现这个bug?是不是可以改进单元测试来发现这个bug?如果查找这个bug花了很长时间,问问自己为什么,下一次是不是可以更快地修复类似的bug?

19文本操纵

基本工具不能完成的时候,需要文本操纵工具。Unix开发者喜欢shell的力量,并用像awksed这样的工具加以增强。偏爱结构化的工具的人喜欢Python面向对象的本质。使用它们可以快速构建实用程序,为你的想法构建原型——传统语言完成这些需要5倍甚至10倍的时间。

20代码生成器

类似于工匠面临一再重复制作同一样东西的任务时,它们会制造模板或建造工具。程序员也不例外。

编写能编写代码的代码。

  • 被动代码生成器
    • 创建新的源文件,使用模板
    • 编程语言之间进行转换。
  • 主动代码生成器
    • 让两种不同的环境一起工作,例如数据库应用,利用代码生成器,读取schema,生成结构的源码。Schema发生变化,代码也自动变化。再例如,从一种语言的源文件解析信息,生成第二种语言的代码,而不是重复这些信息。

第四章 注重实效的偏执

21按合约设计

简称DBC

  • 前条件:为了调用例程,但必须为真的条件;例程的需求
  • 后条件:例程保证会做的事情,例程完成时的状态
  • 类不变项:在例程退出、控制返回到调用者时,不变项为真

22死程序不说谎

早崩溃。发现问题,就要让它在问题的现场崩溃,不要跑到调用的栈顶再告诉你发生了什么。

23断言式编程

如果它不可能发生,就用assert。极端情况下1个月会少于28天,a=2;b=3;a+b!=5,三角形内角和不是180度,一分钟没有60秒,(a+1)<=a

24何时使用异常

将异常用于异常的问题。例如:文件读写,例程返回值,各种状态异常检测,服务器超时等异常情况,都需要使用异常,通常为异常分等级,可以抛出异常,或者将异常写入日志。

25怎样配平资源

分配资源的例程要负责释放它。以与资源分配的次序相反的次序解除资源的分配。因为先后2个资源可能会有依赖关系。相同的顺序分配同一组资源。降低死锁的机率。
要会用try{ } finally{ }
要学会Dispose()

总结

对“怎样配平资源”小节特别有感触,在读写文件的问题上,经常造成读写耦合,当时的解决思路和书上的差不多。将读写的打开和关闭文件操作总是维持在同一个地方。打开和关闭时相互对应的。


 

第五章 弯曲,或折断

26解耦与得墨忒耳法则

目标:使耦合减至最少
“得墨忒耳法则”也叫“迪米特法则”

我们从下面这几条基本规则开始:

得墨忒耳定律--对象 O  M 方法,可以访问/调用如下的:

1. 对象 O 本身

2. M 方法的传入参数

3. M 方法中创建或实例化的任意对象

4. 对象 O 直接的组件对象

5. M范围内,可被O访问的全局变量

一些比喻

我的理解是:常见的踢皮球现象和委托代理

最常见的比喻是:不要和陌生人说话(这是大的规则)

看看这个:假设我在便利店购物。付款时,我是应该将钱包交给收银员,让她打开并取出钱?还是我直接将钱递给她?

PS:再进一步->付款时,我将钱给收银员,但是自己也不清楚钱怎么拿出来的(隐藏属性),自己只负责要钱,要多少钱,实际操作是助理完成并传递给我的,然后在传递给收银员。再做一个比喻:人可以命令一条狗行走(walk),但是不应该直接指挥狗的腿行走,应该由狗去指挥控制它的腿如何行走。

遵循这个规则有什么好处?

  • 我们可以更改一个类,而无需因连锁反应再去改许多其他的(类)。
  • 我们可以改变调用的方法,而无需改变其他任何东西。
  • 遵从LOD,让测试更容易被构建。我们不必为了模拟而写很多的’when’和各种return
  • 提高了封装和抽象(下文将举例说明)。
  • 基本上,我们隐藏了“xx是如何工作的”。
  • 让代码更少的耦合。主叫方法只耦合一个对象,而并非所有的内部依赖。
  • 它通常会更好地模拟现实世界。想想钱包与付款的那个比喻。
  • 符合正交性和松耦合、可撤销性,降低耦合度,提高封装……

 

 

27元程序设计

高度可配置,不需要重新编译,用纯文本来表示配置元数据可能是一种好的选择。
改变了配置,最好别让用户重启系统。

28时间耦合

要提前考虑到程序的并发性。时间有两个方面对我们很重要:并发(事情在同一时间发生)和次序(事情在事件中的相对位置)。

29它只是视图

发布/订阅模式:模型与模型的视图分离
经典的MVC

  1. 模型:表示目标对象的抽象数据模型,模型对任何视图或控制器都没有直接的了解。
  2. 视图:解释模型的方式,它订阅模型中的变化和来自控制器的逻辑事件。
  3. 控制器:控制视图,并向模型提供新数据的途径,它既向模型,也向视图发布事件。

30黑板

黑板:数据到达的次序无关紧要;在收到某项事实时,它可以出发适当的规则,反馈也很容易处理;任何规则集的输出都可以张贴到黑板上,并出发更为适用的规则。
黑板模式是一种常用的架构模式,应用中的多种不同数据处理逻辑相互影响和协同来完成数据分析处理。就好像多位不同的专家在同一黑板上交流思想,每个专家都可以获得别的专家写在黑板上的信息,同时也可以用自己的分析去更新黑板上的信息,从而影响其它专家。黑板模式的应用场景是要解决的任务可以分为多个子任务。

 

第六章 当你编码时

传统智慧认为,项目一旦进入编码阶段,工作主要就是机械地把设计转换为可以执行的语句。我们认为,这种态度是导致程序丑陋、低效、结构糟糕、不可维护和完全错误的最大的一个原因。

编码需要对每一次决策进行仔细的思考和判断。不主动思考代码的开发者是靠巧合编程。提倡更积极地参与编码过程。

我们偶尔会开发出一些算法,会让处理器陷入困境。算法效率中,讨论评估代码的速度的方法。

注重实效的程序员批判的思考所有代码。不断思考是否可以有改进的余地,是否可以重构。

易于测试的代码能增加通过测试的可能性。

在邪恶的向导中,建议小心那些替你编写大量代码的工具,除非能理解它们在做什么。

31靠巧合编程

实现的偶然

是指在有限的“测试”下,编写的代码好像能工作,但是一开始就不知道代码为什么能工作。 这正是一种巧合,可能一段时间之后,代码就不能正常工作了。

  • 靠巧合编程的影响:
  • 也许只是看起来能工作
  • 依靠的边界条件只是偶然
  • 没有记入文档的行为可能会随着库的下一次发布而变化
  • 多余和不必要的调用会使代码运行缓慢
  • 多余的调用会增加引入新BUG的风险

语境的偶然

不要依靠什么没有保证的东西?

隐含的假定

假定很少被写入文档,不要假定,要测试证明。

怎样深思熟虑地编程

  • 总是意识到自己在做什么
  • 不要盲目的编程。试图构建不完全理解的应用,或者使用你不熟悉的技术。(PS:这个跟前面说的曳光弹是否冲突?个人理解:曳光弹是针对毫无头绪的情况,什么都没有可以用曳光弹,而这条是提示你要理解已经有的应用)
  • 按照计划行事,前面也提到过“按合约”编程
  • 依靠可靠的事物。不依靠巧合和假定。
  • 为假定建立文档。
  • 代码要测试,假定也要测试。
  • 为工作划分优先级。
  • 不做历史的奴隶。不要让已有的代码支配将来的代码。

 

总结:

软件开发者,每天就像工作在雷区,有成百的陷阱等着抓住我们。多余的或不必要的代码可能这次能够正常运行,但换个环境可能就会崩溃,另外会使代码变慢,或引入新的bug。总之,不要靠巧合编程。

尽可能在开发周期的早期抓住并修正错误,道理很简单,但在项目进度压力大的时候,把这句话忘在脑后。为编码工作划定优先级,把时间花在重要的上面,经常也是最难的部分。但如果基础设施不正确,再花哨的界面或装饰也没有什么用。

32算法效率

就是大O表示法,要注意的是,在进行所有的估算之后,唯一作数的计时是代码运行在实际环境中、处理真实数据的速率。所以要测试你的估算。

33重构

定义:重写、重做、重新架构代码

何时进行重构

  • 重复
  • 非正交设计
  • 过时的知识
  • 性能

要注意的的是:

  • 不要试图在重构的同时加入新功能。
  • 在开始重构前,确保你拥有良好的测试。
  • 采用短小、深思熟虑的步骤,每一步都执行一遍你的单元测试代码。

本节提倡的是:早重构,常重构。实际中呢?时间压力最大。

 

34易于测试的代码

  • 针对合约进行测试,编写单元测试会给别人(甚至是将来的自己)提供代码调用的例子,例于重构时的回归测试。
  • 要使用xUnit之类的测试工具。
  • 可以设置某种热键,让软件开发人员看到程序内部的错误日志。

35邪恶的向导

不要使用你不理解的向导代码。向导代码确实给你生成了一大堆代码,而且功能也很强大。但它们为你创建了代码,然后就走了。如果你不真正理解它们,将来就会给你带来麻烦。


实例:如果我们要执行一个命令,命令返回的信息,要保存下来继续查找或者判断,有两种比较实用的方法:

方法1:标准IO输入输出,执行cmdN多种方法,但是比较喜欢subprocess模块,因为功能比较全,for example

点击打开链接下面部分

实例2:给/etc/rc.local文件打注册码,一开始以为就是打开,然后写入,最后关闭,一个函数搞定就是分分钟的事。

点击打开链接

第七章 在项目开始之前

36需求之坑

项目开始之前,要确定各种需求。

1. 不要搜集需求,挖掘它们。

2. 一种能深入了解用户需求,却未得到足够利用的技术:成为用户。与用户一同工作,像用户一样思考。

3. 维护词汇表,把需求制作成web文档,更多的满足不同听众的需求。

37解开不可能解开的谜题

解开谜题的秘诀是真正的约束,有些约束是绝对的,有些是先入之见。

遇到不可能解决的问题时,退一步问问自己如下问题:
1)有更容易的方法吗?
2)你是在设法解决真正的问题,还是被外围的技术问题转移了注意力?
3)这件事情为什么是一个问题?
4)是什么使它如此难以解决?
5)它必须以这种方式完成吗?
6)它真的必须完成吗?

不要在盒子外面思考——要找到盒子。

38等你准备好

项目开始之前,到底是良好的判断还是拖延?解决之道,马上开始构建原型,然后进行某种“概念验证”,随着原型的进展,会在某个时刻得到启示。

39规范陷阱

对有些事情,“做”胜于“描述”,应该倾向于把需求搜集、设计、以及实现视为交付高质量系统的不同方面,而不是简单的作为各个孤立的步骤。

在没有任何支持实现,或没有构建原型,在规范之上构建另外一层规范要小心,因为规定无法构建的东西太容易了。在某个时刻,要进行编码,考虑构建原型,或是考虑曳光弹开发。

40圆圈与箭头

不要做形式化方法的奴隶。形式化开发知识一种工具,如果觉得有必要使用,就采用它,但要记住,自己才是主人。批判的看待方法学。


第八章 注重实效的项目

41注重实效的团队

针对团队,重述前面的章节

  • 不要留破窗户
  • 质量是一个团队的事情,质量源于全体团队学员都作出自己的贡献
  • 煮青蛙
  • 每个人主动的监视环境的变化
  • 交流
  • 团队的开发者互相交谈;与外界交流时,团队用一个声音说话,团队就是一个品牌
  • 不要重复你自己
  • 消除团队成员之间的重复工作
  • 正交性
  • 围绕功能,而不是工作职务进行组织,按照功能划分团队
  • 自动化
  • 确保准确和一致的一种很好的方式
  • 知道何时停止绘画

42无处不在的自动化

无论是构建和发布流程、代码复查、其他反复出现的任务,必须是自动的。人工流程不能保证一致性,自动化来确保项目的一致性和可重复性。

  1. 同一种IDE
  2. 自动化工具cron,无人看管的任务周期性运行。
  3. Makefilemake

43无情的测试

早测试,常测试,自动测试

要到通过全部测试,编码才算完成

测试什么

  • 单元测试
    • 对某个模块进行演练的代码
  • 集成测试
    • 整个子系统遵守其合约的情况,是系统bug来源最大的一个
  • 验证和校验
    • 是否满足用户的功能需求
  • 资源耗存、错误和恢复
    • 内存、磁盘、cpu
  • 性能测试
    • 用户数、连接数、每秒事物数
  • 可用性测试
    • 真实的用户、真实的环境下

怎样测试

  • 回归测试
    • 测试的值与已知的值作对比。
  • 确保bug的修正没有破坏之前可以工作的代码。
    • 对性能、合约、有效性等进行校验。
  • 测试数据
    • 现实的数据和合成数据
  • 演练GUI系统
  • 对测试进行测试
    • 故意引入bug,证实测试能抓到它
  • 彻底测试
    • 测试状态的覆盖,而不是代码的覆盖

何时进行测试

  • 代码一旦存在,就需要进行测试
  • 大多数测试自动完成
  • 尽可能频繁的进行测试

44全都是写

把代码和文档结合在一起,所有文档都是代码的反映。代码中的注释要规范,像javadocDOC++这样的工具,根据源码生成API级的文档。

45极大的期望

给用户的东西要比他们期望的多一点。

46傲慢与偏见

在你的作品上签名,作为质量的保证。

 

 

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值