《程序员修炼之道——从小工到专家》读后记录
简述
本来是要写读书笔记的,但是这本书我主要是从地铁上读完的,因此现在我就写一个读书记录,大体把自己从这本书所学做个记录吧。
要是简单地说的话,这本书从需求、测试、文档记录、合约等几个方面来给每个开发人员讲述如何提高自己的工作技艺。
但是如果说具体点的话,我觉得书中的那81条小提示完完全全把这本书概括出来了。
面向群众
首先说下这本书的阅读群体应该是以下几种人:
1. 计算机专业在读或者毕业生;
2. 从事软件开发的新手;
3. 转行做开发一段时间发现无法提高的小伙伴;
4. 在小公司工作几年的人却总是很苦恼的人(当然这本书可能不会给你解决问题,只是告诉你问题出在哪儿了)。
今天看到这篇文章前来提醒下自己,自己已经工作三年,但是自己觉得自己技术很渣。7年的Java后端最终免不了被淘汰,一路北漂辛酸史
精髓小提示
下面这一段算是作者从这本书中提炼出来的,我就借花献佛反正跟这儿了。
1、 关心你的技艺
Care About Your Craft
如果你不在乎能否开发漂亮地开发出软件,你又为何要耗费生命去开发软件呢?
这是个态度问题。
2、思考!你的工作
Think! About Your Work
关掉自动驾驶仪,接管操作。不断的批评和评估你的工作。
3、提供各种选择,不要找蹩脚的借口
Provide Options, Don't Make Lame Excuses
要提供各种选择,而不是找借口。不哟按说事情做不到;说明能够做什么。
4、不要容忍破窗户
Don't Live With Broken Windows
当你看到糟糕的设计、错误的决策和糟糕的代码时,修正他们。
5、做变化的催化剂
Be a Catalyst for Change
你不能强迫人们改变。相反,要向他们展示未来可能会怎样,并帮助他们参与对未来的创造。
6、记住大图景
Remember the Big Picture
不要太过于专注于细节,以致忘了查看你周围正在发生什么。
7、使质量成为需求问题
Make Quality a Requirements Issue
让你的用户参与确定项目真正的质量需求。
8、定期为你的知识资产投资
Invest Regularly in Your Knowledge Portfolio
让学习成为习惯
9、批判地分析你读到和听到的
Critically Analyze What You Read and Hear
不要被供应商、炒作媒体或教条左右。要依照你自己的看法和你的项目的情况去对信息进行分析。
10、你说什么和你怎么说同样重要
It's Both What You Say and the Way You Say It
吐过你不能有效地向他人传达你的了不起的想法,这些想法就毫无用处。
11、不要重复你自己
DRY —— Don't Repeat Yourself
系统中的每一项知识都必须具有单一、无歧义、权威的表示。
这一点很重要啊
12、让复用变得容易
Make It Easy to Reuse
如果服用很容易,人们就会去复用。创造一个支持复用的环境。
13、消除无关事物之间的影响
Eliminate Effects Between Unrelated Things
设计自足、独立并且具有单一、良好定义的目的的组件。
14、不存在最终决策
There are No Final Decision.
没有决策是浇铸在石头上的。相反,要把没想决策都是为是写在沙滩上的,并未变化做好计划。
代码中固定的部分应该是真正固定的,而不是会产生变化的,不会随时间的变化而变化。
15、用曳光弹找到目标
Use Tracer Bullets to Find the Target
曳光弹能通过实验各种事物并检查他们离目标有多远让你追踪目标。
曳光弹就是一种功能不全面的可以同行的代码,每个项目起始都是通过一些最小化功能项目开始实现的,然后慢慢壮大,最后变成巨无霸。你的模块也可以这么成长起来的。
16、为了学习而制作原型
Prottype to Learn
原型制作是一种学习经验。其价值不在于所产生的代码,而在于所学到的经验教训。
原型模式可以让用户和技术人员很快挖掘出准确的需求,而不是说比较笼统的概念。
17、靠近问题领域编程
program Close to the Problem domain
用你的用户的语言进行设计和编码。
18、估算,以免发生意外
Estimate to Avoid Surprises
在着手之前先进行估算。你将提前发现潜在的问题。
19、通过代码对进度表进行迭代
Interate the Schedule with the Code
用你在进行实现时获得的经验提炼项目的时间标度。
20、用纯文本保存知识
Keep Knowledge in Plain Text
纯文本不会过时。它能帮助你有效利用你的工作,并简化测试和调试。
21、利用命令Shell的力量
Use the Power of Command Shells
当图形界面无能为力时使用Shell。
22、用好一种编辑器
Use a SIngle Editor Well
编辑器应该是你手的延伸;确保你的编辑器是可配置、可扩展、可编辑的。
尝试编辑编辑器的插件
23、总是使用源码控制
Always Use Source Code Control
源码控制是你工作的时间机器——你能够回到过去。
Github、SourceTree命令要熟练,我目前还生疏
24、要修正问题,而不是发出指责
Fix the problem, Not the Blame
bug是你的过错还是别人的过错,并不是真的很有关系——它仍然是你的问题,它仍然需要修正。
态度问题很重要,前提是你的技术要过关,否则就是把别人的bug变成你自己的bug了
25、不要恐慌
Don't Panic When Debuging
做一次深呼吸,思考什么可能是bug的原因。
是的,要思考,而不是焦虑,不是懵逼。
26、"Select"没有问题
"Select" Isn't Broken
在操作系统、编译器甚至是第三方库中很少发现bug。bug很可能出现在你的应用中。
当应用出现问题时候的第一反应是自己的系统的问题,而不是先去找外在的问题。
27、不要假定,要证明
Don't Assume It —— Prove It
在实际环境中——使用真实的数据和边界条件——证明你的假设。
当出现问题的时候,一定要考虑最一般的情况甚至是你的系统允许的错误情况,而不是假定那些情况不会发生。除非你能够证明这些情况确实不存在,即使别人说的不存在也不要轻信。
28、学习一种文本操纵语言
Learn a Text Manipulation Language
你用每天的很大的一部时间处理文本,为什么不让计算机替你完成部分工作呢?
过段时间把我的python学学,写写爬虫,不要老是手动处理麻烦的事。
29、编写能编写代码的代码
Write Code That Writes Code
代码生成器能够提高你的生产率,并有效避免重复。
现在还没写过代码生成器,写代码生成器可以了解更好的解构代码,让代码更灵活
30、你不可能写出完美的软件
You Can't Write Prefect Software
软件不可能完美。保护你的代码和用户,使它(他)们免于能够预见的错误。
代码不可能完美,你不要过于自责,但是要对他们负责。
31、通过合约进行设计
Design with Contracts
使用合约建立文档,并检验代码所做的事情正好是它声明要做的。
32、早崩溃
Crash Early
死程序造成的危害通常比有问题的程序要小得多。
代码出错要好过运行中错误,比如手动修改单据的事情尽量不要发生
33、用断言避免不可能发生的事情
Use Assertions to Prevent the Impossible
断言验证你的各种假定。在一个不确定的世界里,用断言保护你的代码。
我必须得学会使用断言。使用断言起码能解决了空指针或者不规范性错误,起码代码会说实话,但是生产环境一定要把断言关闭。
34、将异常用于异常的问题
Use Exception for Exceptional Problems
异常可能会遭受经典的意大利面条式代码的所有可读性和可维护性问题的折磨。将异常保留給异常的事物。
处理异常所需的代码例如try{}catch(){}语句有时能将人看蒙圈。坚决不要用异常来处理代码逻辑,用异常处理出现问题的收尾工作或者重启工作。
35、要有始有终
Finish What You Start
只要有可能,分配某资源的例程或者对象也应该负责解除其分配。
开始调用的资源的地方释放资源,不要传递释放(调用的方法中释放)。释放资源顺序和锁定顺序一致避免死锁。
死锁产生的原因:1、各个进程抢占系统中的公共的不可抢占的资源,如打印机等;2、各个进程中的资源调度顺序不同,导致对进程之间的消耗资源(如发送的消息)调度顺序不同;3、系统中进程调度推进顺序不对,就是说各个进程需要先调用其他进程未释放的资源,在释放自身调用资源的情况。
36、使模块之间的耦合减少至最少
Minimize Coupling Between Modules
通过编写”羞怯的“代码并应用得墨忒尔法则来避免耦合
1、多用接口,少用继承;2、使模块功能单一化;3、一个定义只在应用中出现一次;4、少用全局变量;5、尽可能降低类和方法的访问权限;6、多采用一些设计模式;7、减少”硬编码“处理问题(减少直接使用SQL处理数据库);8、降低模块之间的调用(如果模块间必须耦合尽量保持只用参数传递信息,而不是存在控制信息)
37、要配置,不要集成
Configure,Don't Integrate
要将应用的各种技术选择实现为配置选项,而不是通过集成或者工程方法实现。
并非固定不变的信息要用配置文件,而不是直接写在代码里面。例如:公司名、部门名、数据库配置信息等等
38、将抽象放进代码,将细节放进元数据
Put Abstractions in Code, Details in Meatdata
为一般情况编程,将细节放在被编译的代码库之外。
将代码编写最一般化的任务,每个特殊任务的具体细节应该是可配置项,而不是死代码或者说是if/else的情况。
这里引用书里的原话:没有元数据,你的代码不肯能获得它应有的适应性和灵活性。 不要让你的项目(或者你的职业生涯)走上渡渡鸟的道路。 引以为惕。
39、分析工作流,以改善并发量
Analyze Workflow to Improve Concurrency
利用你的用户的工组流中的并发量。
考虑实际业务中的可行性,降低流程对时间的依赖,减少时间耦合度,尽可能进行并发,减少线性代码量。
40、用服务进行设计
Design Using Services
根据服务——独立的、在良好定义、一致的接口之后的并发对象——进行设计。
我的理解是:我们要把自己的组件组成服务化,每一个模块都是相互独立的服务。
41、总是为并发进行设计
Always Design for Concurrency
容许并发,你将会设计出更整洁、具有更少假定的接口。
并发编程一方面使得你的流程更优化,另一方面使得你的程序的隔离性更好。
42、使视图和模块分离
Separate Views With Models
要根据模型和视图设计你的应用,从而以低廉的代码获取灵活性。
MVC/MVVM等模式可以避免修改代码的耦合度,降低修改代码的负责度。
43、用黑板协调工作流
Use Blackboards to Coordinate Workflow
用黑板协调完成完全不同的事实和因素,同时又使各参与方保持独立和隔离。
44、不要靠巧合编程
Don't Program By Coincidence
只依靠可靠的事物。注意偶发的复杂性,不要把幸运的巧合和有目的的计划混为一谈。
怎么好了?我也不知道啊。好好追踪下源码啊。
45、估算你的算法的阶
Estimate the Order of Your Algorithms
在你开始编码之前,先估算下事情大致需要多长时间。
46、测试你的估算
Test Your Estimate
对算法的数学分析并不会告诉你每一件事情。在你的代码的目标环境中测试它的速度。
如果你自己不去测试你的性能,那么只能是你的客户实际应用中给你测试你的系统了。
47、早重构,常重构
Refactor Early, Refactor Often
就和你毁在花园里除草并重新布置一样,在需要时对代码进行重写、重做和重新架构。要铲除问题的根源。
重构能够迭代开发,虽然会降低开发速度,但是能够保证代码质量。
48、为测试而设计
Design to Test
在你还没有开始编码之前就思考测试的问题
如果你的代码不能很好的进行自动化测试,那说明你的代码的隔离机制做得很差。
49、测试你的软件,否则你的用户就得测试
Test Your Software, Or Your use Will
为什么用户会发现那么多问题啊?当然是你没进行足够的测试了。
50、不要使用你不理解的向导代码
Don't Use Wizard Code You Don't Understand
向导可以生成大量代码。在你把它们合并进你的项目之前,请确保你已经完全理解他们。
如果加入了你不能理解的代码,那么你可以找到bug吗?
51、不要搜集需求——挖掘它们
Don't GatherRequirements - Dig for Them
需求很少存在于表面上。它们深深地埋藏在层层假定、误解和政治手段之下。
需求真的不只是项目经理说的那些,说不定给你的需求还是自相矛盾的呢。你看到需求以后得自个琢磨一下,然后还得问问,必须问(这是重点,要不然你做出来的可能是南辕北辙的)。
52、与用户一起工作,以像用户一样思考
Work with a User to Think Like a User
要了解系统实际上将如何被使用,这是最好的办法。
这个方法对系统实际环境、实际操作、会遇到的问题都会深入的了解。
53、抽象比细节活得更长久
Abstractions Live Longer than Details
"投资"于抽象,而不是实现。抽象能在来自不同的实现和新技术的变化的"攻击"之下存活下来。
用抽象来表达关系、框架、结构,用实现来表示具体每个事物。这样才能对"开闭原则"、“里氏代换原则”、"依赖倒转原则"进行很好的把握。
54、使用项目词汇表
Use a Project Glossary
创建并维护项目中使用的专用术语和词汇的单一信息源。
项目词汇表必须要单一准确,否则就会出现歧义,最后没人知道到底表达的是什么意思。因为项目开发过程中经常使用隐喻来描述的。
55、不要再盒子外面思考——要找到盒子
Don't Thikn Outside the Box —— Find the Box
在遇到不可能解决的问题时,要确定真实的约束。问问你自己:“它必须以这种方式完成吗?它真的必须完成吗?”
首先确定你要做的东西是不是真的要这么做,是不是真的应该这样做,如果你这样做是不是正确。作为初中级开发人员,其实你的工作不能完成大部分情况下不是你不会做什么,而是你做的东西没有给你描述准确。一般情况下你可能被需求的错误性描述给整蒙圈了,你必须了解真实业务才行。因此你必须要去问项目经理。
56、等你准备好再开始
Start When You're Ready
你的一生都在积累经验。不要忽视反复出现的疑虑。
当你与某些疑虑的时候,第一步首先找到解决问题的方法(如果没找到那么恭喜你可能找到一个真的需要你解决的问题,就解决了这个问题可能你就出名了。)第二步把这个问题的解决方案保存在你的工具箱、博客或者其他你能随时找到他的身影的地方,否则你就会一次又一次重复之前做过的东西。就像是一年的工作经验做了好几年一样。
57、对有些事情“做”生于“描述”
Some Things Are Better Done than Described
不要掉进规范的螺旋——在某个时刻,你需要开始编码。
不要完全被规范绑住自己,要使用规范。
58、不要做形式方法的奴隶
Don't Be a Slave to Formal Methods
如果你没有把某项技术放进你的开发实践和能力的语境中,不要盲目地使用它。
不要在生产项目中使用你还在学习的技术。当你完全学会了某项技术才能使用在你的生产项目中,否则你连哪儿出bug了都不知道。
59、昂贵的工具不一定制作出更好的工具
Expensive Tools Don't Produce Better Designs
小心供应商的炒作、行业教条、价格标签的诱惑。要根据工具的价值判定它们。
Just like Windows and CentOS.并且不要过于高估自己的软件,要根据他的能力定价啊。
60、围绕功能组织团队
Organize Teams Around Functionality
不要把设计师和编码员分开,也不要把测试员和数据建模员分开,按照你构建代码的方式构建团队。
如果你不能根据你的功能组织团队,那么你可能会陷入大家理解差异的怪圈中,而且互相恶心。
*61、不要使用手动流程
Don't Use Manual Procedures
Shell脚本或批文件会一次次地以同一顺序执行同样的指令。
我还是要多用用Shell、批处理脚本了。
62、早测试,常测试,自动测试
Test Early. Test Often. Test Automatically.
与呆在书架上的测试计划相比,每次构建时运行的测试要有效得多。
一次性去改70个bug和每次改一个bug, 你觉得哪个更安全呢?
63、要通过全部测试,编码才算成功
Coding Are Not Done Util All The Tests Run
就是这样。
如果你测试不到的地方,那么客户就会帮你测试到的。
64、通过“蓄意破坏”测试你的测试
Use Saboteurs to Test Your Testing
在单独的软件副本中故意引入bug,以检测测试能够抓住他们。
否则你怎么知道你的测试不是按照你的代码设计好的呢?你怎么知道你的测试是不是好的测试呢?
65、测试状态覆盖,而不是代码覆盖
Test State Coverage, Not Code Coverage
确定并测试重要的程序状态,只是测试代码行是不够的。
66、一个bug只抓一次
Find Bugs Once
一旦测试员找到一个bug,这应该是测试员最后一次找到它。此后自动测试应该对其进行检查。
67、英语就是一种编程语言
English is Just a Programming Language
像你编写代码一样编写文档:遵守DRY原则,使用元数据、MVC\自动生成等等。
68、把文档建在里面,不要栓在外面
Build Documentation In. Don't Bolt It On.
与代码分离的文档不太可能被修正和执行。
69、温和地超出用户的期望
Gently Exceed Your Users' Exceptions
要理解你的用户的期望,然后给他们的东西要多那么一点。
70、在你的作品上签名
Sign Your Work
过去时代的艺人为能在他们的作品上签名而自豪。你也应该如此。
检查清单###
71、要学习的语言
厌倦了C、C++和Java?试试CLOS、Dylan、Eiiffel、Object C、Prolog、 Smalltalk或者TOM。
它们每一种都有不同的能力和不同的“风味”。用其中一种或者多种在家里开发一个小项目。
主语言是Java,但是我也比较喜欢Go和Python。以后得多试试这两门语言的
72、WISDOM离合诗
| What do you want them to learn? | 你想让他们学到什么? |
| What is their interest in what you 've got to say? | 他们对你讲的什么感兴趣? |
| How sophisticated are they? | 他们有多富有经验? |
| Whom do you want to own the information? | 你想要让谁拥有这些信息? |
| How can you motivate them to listen to you? | 你如何促使他们听你说话? |
73、怎样维持正交性
- 设计独立、良好定义的组件。
- 使你的代码保持解耦。
- 避免使用全局数据。
- 重构相似的函数。
74、应制作原型的事物
- 架构
- 已有系统中的新功能
- 外部数据的结构或功能
- 第三方工具或组件
- 性能问题
- 用户界面设计
75、架构问题
- 责任是否得到了良好定义?
- 协作是否得到了良好定义?
- 耦合是否得以最小化?
- 你能否确定潜在的重复?
- 接口定义和各项约束是否可接受?
- 模块能否在需要时访问所需数据?
76、调试检查清单
- 正在报告的问题是底层bug的直接结果,还是只是症状?
- bug真的在编辑器里?在OS里?或者在你的代码里?
- 如果你向同事详细解释这个问题,你会说什么?
- 如果可以代码通过了单元测试,测试是否足够完整?如果你用该数据运行单元测试,会出现什么结果?
- 造成这个问题的bug是否存在于系统的其他地方?
77、函数的得墨忒尔法则
某个对象的方法应该只调用属于以下情景的方法:
- 它自身
- 传入的任何参数
- 它创建的对象
- 组建对象
78、怎样深思熟虑地编程
- 总是意识到你在做什么。
- 不要盲目地编程。
- 按照计划行事
- 依靠可靠的事物。
- 为你的假定建立文档。
- 不要只是测试你的代码,还要测试你的假定。
- 为你的工作划分优先级。
- 不要做历史的奴隶。
79、何时进行重构
- 你发现了对DRY原则的违反。
- 你发现事物可以更为正交。
- 你的知识扩展了。
- 需求演变了。
- 你需要改善性能。
80、劈开戈尔迪死结
在解决不可能解决的问题时,问问你自己:
- 有更容易的方法吗?
- 我是在解决正确的问题吗?
- 这件事情为什么是一个问题?
- 是什么使它如此难以解决?
- 它必须以这种方式完成吗?
- 它真的必须完成吗?
81、测试的各个方面
- 单元测试
- 集成测试
- 验证和校验
- 资源耗尽、错误及恢复
- 性能测试
- 可用性测试
- 对测试自身进行测试
总结
这本书不愧是开发必备书籍,以后要再多读几遍,好了打完收功。

浙公网安备 33010602011771号