《程序员修炼之道》-pdf,txt,mobi,kindle,epub电子版书免费下载

由于链接总是被和谐,需要本书电子版的朋友关注公众号:【奥丁读书小站】(njdy668),首页回复书名或者数字3922, 自动弹出下载地址.

分类榜单第1,畅销20多年的一本书

今日重点推荐《程序员修炼之道》

屹立20多年影响力大作。

作者: Andrew Hunt / David Thomas

这本书讲了什么?

1.先声明下,这不是一本专业的编程书籍,也不会告诉你如何学编程,更没有复杂的编程公式及应用。别看到书名,就吓跑了。

这本书只是简单、明了地讲了什么是务实的程序员?

编程是一门技艺,是一项艰难的工作。想帮助你的人有很多,如工具供应商,方法论大师等等,他们都说自己的编程语言是最完美的,事实上漏洞百出。

哪有什么简单的答案。没有最好的解决方案,无论是工具、语言还是操作系统;只在特定的环境下才有所谓更合适的系统。

对于一个想要成为程序员的准新人,容易对这些东西不知所措,编程本身不复杂,复杂的是如何才能培养自己的编程思维。仅仅知道如何编程,并不会让你成为一名更好的程序员,在这个过程中必须经历有意识和深思熟虑的实践。

这就让务实主义有了用武之地。

2.是什么造就了务实的程序员?

务实的程序员有一些共同的特性

好奇心,这个是功能如何实现的?用了什么符号链接?可以用多少年?多久会被迭代?

批判性思维,但凡还没有结果,就得怀疑到底会出现什么漏洞?

现实主义,必须对时间有一个良好的感知,因为项目是在规定时间内完成的。

多面手,熟悉各种计算机语言只是基础,但凡要开发一个行业软件,就会对这个行业全面了解,基本会变成这个行业的专家。

想象力,做的每一件事,都是为子孙后代建设未来,这是职责所在,必须想到未来20年甚至更长时间可能出现的事情。

3.程序员有一股巨大的力量。伴随着这种力量而来的,是一种非同寻常的责任。

做任何一个程序,程序员必须问自己两个问题。

1.我已经保护好用户了吗?

2.我自己会用它吗?

婴儿监视器会不会对孩子造成伤害,汽车控制软件会不会出现故障,出现故障如何控制?个人信息是否加密?家用电器的恒温器会不会失效?

从发电厂到汽车再到医疗设备。即使是简单的中央供暖控制系统或家用电器,如果设计或实施不当,也会致人死亡。当你为这些设备做开发时,所承担的责任是难以预估的。

程序员创造的东西可以改变世界,我们希望是美好的改变。

务实的程序员一定要守住道德底线,不要因为钱去参与擦边球项目,因为一旦参与,到底会带来多大的伤害犹未可知。

4.在作品上签名

在网络环境中,很多人可以肆无惮忌的说辱骂别人的话,说不负责任的话,站在道德高点谴责别人……这一切都因为是匿名。

同样的,一个保持匿名的程序员,会滋生粗心、错误、懒惰和糟糕的代码,特别是在大型项目中——很容易把自己看成只是大齿轮上的一个小齿,在无休止的工作汇报中制造蹩脚的借口,而不是写出好的代码。

“这是我写的,我与我的作品同在”。你的签名应该被认为是质量的标志。人们应该在一段代码上看到你的名字,并对它是可靠的、编写良好的、经过测试的、文档化的充满期许。这是一件非常专业的工作,出自专业人士之手。

过去的工匠很自豪地为他们的作品签名,务实的程序员也应该这样。

欲知更多,敬请阅读原书

试读

宁弯不折

生活不会裹足不前,我们写的代码也不会。为了跟上当今近乎疯狂的变化速度,我们需要尽一切努力编写尽可能宽松、灵活的代码。否则,就可能会发现,我们的代码很快便会过时,或是因太脆弱而无法在出错后修复,最终都可能在疯狂冲向未来的过程中被抛在后面。

在前面的可逆性中,我们谈到了不可逆转的决定的危险。在本章中,我们将告诉你如何做出可逆的决策,这样代码在面对不确定的世界时可以保持灵活性和适应性。

首先我们来看看耦合——代码之间的依赖关系。解耦展示了如何将不同的概念分开,以减少耦合。

接下来,我们将介绍在现实世界中抛球杂耍时可以使用的不同技术。我们将研究四种不同的策略,它们可以用来帮助管理和响应事件,而这是现代软件应用程序的一个关键方面。

传统的过程式和面向对象的代码可能过于紧密耦合,与你的目标不一致。在变换式编程中,我们将利用函数管道,获得一个更灵活、清晰的风格,即使你用的语言不直接支持也没关系。

常见的面向对象风格可能会让你陷入另一个陷阱。不要上当,否则最终你要支付高额的继承税。我们将探索更好的替代方法来保持代码的灵活性,让其更易变更。

当然,有一个保持灵活性的好方法,那就是编写更少的代码。修改代码可能会引入新的 Bug。配置将解释如何将细节完全移出代码,以便实现更安全、更容易的变更。

所有这些技术,都将帮助你编写出只弯曲却不会折断的代码。

28 解耦

当我们试着单独挑出一个事物的时候,总会发现它与宇宙中其他一切都有关联。

——约翰·缪尔《夏日走过山间》

在第28页的话题8:优秀设计的精髓中,我们宣称使用良好的设计原则会让你的代码易于变更。耦合是修改之敌,因为它将事情连接在一起,要改就得一起改。这使得修改变得更加困难:要么需要花上不少时间,弄清楚所有需要修改的地方到底有哪些,要么又会因为“仅仅只修改一处”而没有跟着改与之相耦合的地方,把时间花在想明白为什么会出问题上。

当你设计一些想确保刚性的东西,比如一座桥或一座塔时,就需要把组件耦合在一起:

这种连接方式让结构获得了刚性。

与下面这样的连接方式比较一下:

这里结构上的刚性没有了:连接的个体可以变动,而其他部分总能适应它。

当设计桥梁的时候,你想让其保持自己的形状,需要它们具备刚性。但当设计未来会变化的软件时,想要的恰恰相反:你希望它是灵活的。为了更灵活,单个组件应该与尽可能少的其他组件耦合。

更糟糕的是,耦合有传递性:如果 A与B、C耦合,B与M、N耦合,C与X、Y耦合,那么A实际上与B、C、M、N、X及Y耦合。

这意味着你应该遵循一个简单的原则:

提示44 解耦代码让改变更容易

既然我们通常并不使用钢梁和铆钉来编码,那么对代码进行“解耦”到底是指什么呢?在本部分中,我们将讨论:

· 铁道事故——一连串的方法调用

· 全局化——静态事物的风险

· 继承——为什么子类很危险

在某种程度上,这个列表有些刻意为之:任何时候,只要两段代码共享点什么东西,都可能发生耦合,因此在阅读下面的内容时,请注意更深层次的模式,以便将其应用到你的代码中。再就是注意留心一些耦合的“症状”:

· 不相关的模块或库之间古怪的依赖关系

· 对一个模块进行的“简单”修改,会传播到系统中不相关的模块里,或是破坏了系统中的其他部分

· 开发人员害怕修改代码,因为他们不确定会造成什么影响

· 会议要求每个人都必须参加,因为没有人能确定谁会受到变化的影响

铁道事故

我们都见过(可能也写过)这样的代码:

我们从 customer对象获取到一组订单的引用,从中查找出特定的订单,然后获取订单的总金额。基于这些总金额对象,我们从订单总金额中减去折扣金额,并且更新了折扣值。

这段代码跨越了从客户到总金额的五个抽象层次。最终,我们的顶层代码必须知道,客户对象暴露了订单,而订单有一个 find方法,这个方法可以接收一个订单 id并返回一个订单对象;然后还需要知道,订单对象有一个 total对象,该对象具备读取器和设置器,可以用来计算总金额和折扣——这里有如此之多的隐含知识。但更糟糕的是,将来有很多事情是不能改变的,否则代码无法继续工作下去。火车的所有车厢都是耦合在一起的,所有的方法和属性就像铁道事故中的那些列车车厢一样,紧紧连在一起。

让我们假设一下,公司如果决定订单的折扣不能超过 40%,我们应该把执行这条规则的代码放在哪里?

你可能会说,那正是我们刚写的 applyDiscount函数的责任。这当然是答案的一部分。但是在现在的代码组织方式下,你并不知道这是否就是全部的答案。在每个地方的随便一个代码块中,都可能设置 totals对象的字段,如果代码的维护者不守规矩,代码就无法按照新的折扣策略一一修正。

似乎可以从责任的角度看待这个问题——totals对象当然要承担管理汇总的责任。然而这里并非如此:它实际上只是一个容器,容纳了一堆任何人都可以查询和更新的字段。

解决这个问题的方法如下:

提示45 只管命令不要询问

这个原则说的是,不应该根据对象的内部状态做出决策,然后更新该对象。这样做完全破坏了封装的优势,并且在这样做时,也会把实现相关的知识扩散到整个代码中。因此,处理这个铁道事故,首先要做的就是,把计算折扣的工作委托给total对象:

对于客户对象和对象的订单两者来说,这里也存在TDA(tell-don’t-ask,只管命令不要询问)的问题,我们不应该取出订单列表再从中搜索,而应该直接向客户要我们想要的订单:

订单对象和订单的总金额之间也有相同的问题。订单的实现使用了一个分离的对象totals来保存总金额,外部世界为什么必须知道有这么一个对象呢?

我们可能应该在这里停下来。

此时,你可能会认为,如果要想遵循TDA,就应该在客户对象内添加一个applyDiscountToOrder(order_id)方法。而且如果机械地进行下去,理应如此。

但TDA不是一个自然法则,它只是帮助我们识别问题的一种模式。在本例中,我们可以轻松地暴露这样一个事实:客户有订单,并且通过向客户对象发出请求,可以找到其中一个订单。这是一个务实的决定。

在每个应用程序中,都有一些通用的顶层概念。在这样的应用程序中,顶层概念包括客户和订单。将订单完全隐藏在客户对象中是没有意义的:它们有自己的存在价值。因此,我们完全可以创建出暴露订单对象的API。

得墨忒耳法则

在关于耦合的讨论中,人们经常提及得墨忒耳法则,或简称LoD。LoD是由伊恩·霍兰德在20世纪80年代末提出的一组参考指南[1]。创建这组指南是为了帮助得墨忒耳项目的开发人员保持函数简洁和解耦。

LoD 说的是,定义在C 类中的函数只应该调用:

· C类其他实例的方法

· 它的参数

· 它所创建出来的对象的方法,包括在栈上和堆上的对象

· 全局变量

在这本书的第一版中,我们花了一些时间来描述LoD。在这二十年间,这朵玫瑰的花苞已经凋谢了。我们现在不喜欢“全局变量”这一条款(原因将在下一部分讨论)。我们还发现在实践中很难使用它:感觉有点像每次调用方法时都必须解析一遍法律文件一样。

不过,这个原则仍然是合理的。我们只是推荐一种更简单的表达方式: