《软件设计的哲学》读书笔记

深模块/浅模块

作者使用深模块和浅模块的概念来形容模块封装的不同程度。

  • 深模块:即暴露给用户极少的必要接口,其它的实现细节尽量封装在模块内部/接口背后,这样便于用户使用和模块对外接口的稳定性。典型的深模块有linux i/o接口,java垃圾回收等。

  • 浅模块:即暴露大量的接口给用户,让用户自己选择如何组合使用,这样设计接口的好处是增加了用户使用的灵活度,但是,大多数时候往往增加了用户选择的负担。例如链表的接口设计就是属于浅模块,另外java的FileInputStream和BufferInputStream大多数时候要同时使用的设计就属于浅模块的一个例子,其实可以将是否使用缓冲区的选择封装在通用接口后,因为大部分情况都是要使用缓存的,对于少部分不使用的情况,可以通过另一个接口或者通过增加参数来提供特例使用。
    因此作者推荐设计成深模块从而减轻用户使用的负担。作者认为应该设计更少的通用接口,而不是带有很多细节的专用接口。关于接口的通用性,qsort是一个不错的例子。

异常处理

用户面对异常时,很多情况下会不知如何处理。毫无节制地将异常抛给上层用户是不负责任的表现,异常应该尽可能少。几种处理异常的方法:

  • 屏蔽异常:一些无关紧要,不影响用户感受的异常应该在API内部屏蔽处理,而不应该抛给用户。
  • 汇聚异常:很多琐碎的同类异常,应该在内部汇聚后抛到上层一处处理。
  • 系统崩溃:一些致命的异常,例如内存耗尽而导致的内存申请失败,最好让系统直接崩溃,而不是抛出异常。

总之异常处理是要仔细斟酌的,仔细分辨哪些是不需要抛出内部可以消化的,尽量多地在内部消化异常,同时识别必须抛出的异常,坚决抛出。

多次设计

以设计接口为例,同一个功能多设计几个接口有助于你的思考,从而提炼出更好的接口,虽然有时候你一次就能设计出比较好的接口,但是,建议你还是要坚持这么做,因为习惯一旦养成,力量不容小觑。

命名

  • 糟糕的命名不仅是影响可读性,有时候还会是引入bug的隐患。例如作者的例子,因为没有在变量命名上区分fileblock和diskblock,导致错用变量内存被覆盖的隐晦的bug,用了半年之久才定位出来。
  • 一个变量的定义和使用之间的距离越远,它的命名应该相对越长。模块之间变量的定义,应该加上模块前缀,而一些简单的循环变量只要使用i,j就可以了。
  • 一个好的命名需要花些心思和时间,但这是一项值得的投资,因为它对代码后期的可维护性带来很大收益,并且随着这项技能越来越熟练,它将会花的时间越来越少,那时它带来的好处将是免费的。

注释

关于注释这个颇具争议的话题,作者倾向于先写注释,并且也提倡只写必要的注释。注释其实是一种抽象工具,在你开始写代码实现之前,将框架代码写出来,并且加好注释,这其实是对思路的一次整理,同时,由于当前还没有实现细节的干扰,注释更多是在抽象层面描述,它将更加能够体现设计思路,也更加稳定。一个难点在于修改代码的同时要及时修改注释,作者的建议是通过一些纪律和规则来解决,注释应该离它所解释的代码尽可能近,这样修改代码的时候就容易看到这些注释同时修改它们。

重构

重构是一个永恒的话题,需要把重构看成一种投资。如果在增加一个需求/解决一个bug时,可以在2小时简单修补完成,也可能发现一个架构调整点可以更好地实现,同时具备更好地扩展性,但需要2周才能完成,这种情况下,项目很难抵住快速实现的诱惑,或者说时间上根本不允许2周才完成。但是一旦有了重构的意识,就会去想有没有2天能够完成相同重构效果的方案,如果确实没有,可以使用快速实现方案,同时记录下这个重构点,在下个迭代周期要坚决预留时间进行相关重构。这是保持架构持续演进的必要工作,也是会产生持续收益的战略投资。

敏捷软件开发

关于敏捷软件开发,作者将其一系列实践归纳为战术设计范畴,很多人忽略了整体的战略设计,这点也批判了在敏捷软件实践的一个误区,那就是完全不要设计。其实真实的敏捷践行是需要有战略设计,即软件架构设计的。这点从Martin Fowler对DDD的赞誉中可见一斑。

性能优化

关于性能优化,作者的观点是不需要时刻关注性能,而是对一些性能耗时的操作要了解,对这些有限的点有所关注就行。例如,对于内核网络报文转发效率不高要有所了解,那么在需要高速转发的场景下,你需要专门的硬件来处理报文转发,一开始的这个方向性的决策很重要。但是,你不需要对每一行for语句的性能过分关注,这些细节可能会由编译器进行优化,程序员自己的优化未必有效果,甚至会起到反作用。最后,性能优化一定要通过工具进行测量后,找到关键路径进行优化,这样是效果最好的,也是最高效的。

简洁的代码往往是性能高效的,除非有非常明显的性能提升,否则不要以代码复杂为代价来提升性能。

你可能感兴趣的:(《软件设计的哲学》读书笔记)