Loki bio photo

Loki

Android Developer,做有趣的事情,探寻有趣之物.

Email Github
  1. 第一部分 打好基础
  2. 第二部分 创建高质量代码
  3. 第三部分 变量
  4. 第四部分 语句
  5. 第五部分 代码改善
  6. 第六部分 系统考虑
  7. 第七部分 软件工艺

这一部分主要是讲如何创建高质量的代码,作者从软件设计,类,子程序,防御式变成,伪代码编码过程几个部分来进行讲解.

读书笔记

设计是一个险恶的问题,因为问题就是那种只有通过解决或部分解决才能被明确的问题.

设计是个了无章法的过程,犯错正是设计的关键所在–在设计阶段犯错并加以改正,其代价要比在编码后才发现同样的错误并彻底修改低得多.

设计什么时候才算完成呢? 最常见的回答是“到你没时间再做了为止”

设计就是确定取舍和调整顺序的过程,设计者工作的一个关键内容便是去衡量彼此冲突的各项设计特性,并尽力在其中寻求平衡.

设计受到诸多限制,是不确定的,是一个启发式过程,是自然而然形成的.

好的设计源于对一小批关键设计概念的理解.

软件的首要技术使命:管理复杂度.管理复杂度时软件开发中最为重要的技术话题.所有软件设计技术的目标都是把复杂问题分解成简单的部分.子系统间的相互依赖越少,就越容易在同一时间里关注问题的一小部分.

两类不同的问题导致软件开发变得困难–本质的问题和偶然的问题,本质的属性是一件事物必须具备,如果不具备就不再是该事物的属性,偶然的属性则是指一件事物碰巧具有的属性,有没有这些属性都并不影响这件事物本身,而软件开发中大部分的偶然性难题在很久以前就已得到解决了,本质上说,软件开发就是不断地去发掘错综复杂,相互连接的整套概念的所有细节.

当项目确由技术因素导致失败时,其原因通常就是失控的复杂度.

高代价低效率的设计源于下面三种根源:

用复杂的方法解决简单的问题;
用简单但错误的方法解决复杂的问题;
用不恰当的复杂方法解决复杂的问题.

可以用以下两种方法来管理复杂度:

把任何人在同一时间需要处理的本质复杂度的量减到最少;
不要让偶然性的复杂度无谓地快速增长.

理想的设计特征:

最小的复杂度:如果你的设计方案不能让你在专注于程序的一部分时安心地忽视其他部分的话,这一设计就没有什么作用了;
易于维护:在设计时为做维护工作的程序员着想;
松散耦合:让程序的各个组成部分之间关联最小,通过应用类接口中的合理抽象,封装性,及信息隐藏等原则;
可扩展性:增强系统的功能而无需破坏其底层结构;
可重用性:设计的系统的组成部分能在其他系统中重复使用;
高扇入:很好的利用在较低层次上的工具类;
低扇出:让一个类里少量或适中地使用其他类;
可移植性;
精简性;
层次性;
标准技术:尽量用标准化,常用的方法;

抽象是一种能让你在关注某一概念的同时可以放心地忽略其中一细节的能力—在不同层次处理不同的细节,抽象的主要好处就在于它能使你忽略无关的细节.

信息隐藏是减少重复工作的强大技术,它是软件的首要技术使命中格外重要的一种启发式方法,因为它强调的就是隐藏复杂度.

信息隐藏中所说的秘密主要分为两大类:

隐藏复杂度
隐藏变化源

信息隐藏的障碍:

信息过度分散
循环依赖
把类内数据误认为全局数据
可以察觉的性能损耗

信息隐藏的价值

运用了信息隐藏技术的大型项目与没有应用的相比,修改起来大约容易4倍
信息隐藏是结构化程序设计和面向对象设计的根基之一
能够激发出有效的设计方案
有助于设计类的公开接口

如果你能在给类的公开接口中增加函数或者数据而不牺牲该类的隐秘性,那么就做下去,否则停住.

优秀的设计师所共有的一项特质就是对变化的预期能力

好的程序设计所面临的最重要挑战之一就是适应变化,目标应该是把不稳定的区域隔离出来,从而把变化所带来的影响限制在一个子程序,类或者包的内部.应对变化的措施:

找出看起来容易变化的项目
把容易变化的项目分离出来
把看起来容易变化的项目隔离开来:类的接口应肩负起保护类的隐私的职责

容易发生变化的区域:

业务规则
对硬件的依赖性
输入和输出
非标准的语言特性
困难的涉及区域和构建区域
状态变量
数据量的限制

找出容易发生变化的区域的一个好办法是,首先找出程序中可能对用户有用的最小子集,这一子集构成了系统的核心,不容易发生变化.

类和子程序是用于降低复杂度的首选和最重要的智力工具

设计模式的益处:

设计模式通过提供现成的抽象来减少复杂度
设计模式通过把常见解决方案的细节予以制度化来减少出错
设计模式通过提供多种设计方案而带来启发性的价值
设计模式通过把涉及对话提升到一个更高的层次来简化交流

耦合度表示类与类或者子程序与子程序之间关系的紧密程度

内聚性是指类内的子程序或者子程序内的所有代码在支持一个中心目标上的紧密程度

人们在做其他事情时能记住的离散项目的个数是5-9个 –Miller 1956

子程序也是迄今为主发明出来的用以节约空间和提高性能的最重要手段

理论上认为的子程序最佳最大长度通常是一屏代码或者打印出来一到两页的代码,约50-150行代码

几乎每个宏都表明在编程语言,程序或者程序员身上存在问题 –Bjarne Stroustrup

防御式编程的主要思想是:子程序不应该传入错误数据而被破坏,哪怕是其他子程序产生的错误数据,其核心想法是要承认程序都会有问题,都需要被修改.其缺点是会引入额外的代码而增加软件的复杂度.

用错误处理代码来处理预期会发生的状况,用断言来处理绝不应该发生的状况.

后感

距离看完第一部分有一年多了,期间参与公司内部的创新项目,十个多月的996,无暇去看书学习,其实这部分时间对于自己来说是浪费的.

我们所看到的经典书籍往往都是相对落后的,我记得上家公司CTO说过一个例子,如何存储100w个数字,大部分人按照数据结构,C语言教程之类的,都会去使用链表,而100w个数字所占用的内存本身就没有多少,直接上数组就是了,出错概率极小.大部分时候我们都习惯性的把自己限制在内存几十K或者几M的年代,我是做移动端的,亲身经历了手机内存从128M到6G的时代,现在编程内存重要吗,也重要,处理图片的时候还是会去考虑内存,但是绝大多数情况,我们是可以少考虑内存以及CPU性能,来减小代码层面上的复杂度,而使得程序运行过程中的出错率大大降低.

架构重要吗?非常重要,但是现在成熟的架构框架太多,很多时候容易陷入过分设计当中,我始终觉得,一个好的架构最重要的一个标准就是简单,而现在看到太多的架构就是不停的添加层次去解决以为的问题,而使得复杂度极具增加.

返回到这本书的第二部分,里面的很多思想都有启发性,例如信息隐藏等,但是不可否认,一些思想在那个年代是很有代表性的,而对于现在追求性能越来越少(后台开发以扩容为主,性能优化出绩效),编程语言越来越自然语言化的年代,这些思想其实已经很自然的被融入到我们所使用的语言以及IDE里了.这个年代的我们是幸运的,因为我们可以站在巨人的肩膀上,这个年代的我们同样是不幸的,因为我们很多人不可避免的成为了API调用者,而不会去也没有这个机会去理解底层的那些优美的设计.