书籍推荐
技术圈的朋友经常让我推荐一些软件开发相关的技术书,我职业早年确实读过不少编程相关书籍,如果只能推荐两本的话,我认为真正值得推荐的是这两本,一本是《深入理解计算机系统》,另外一本是《代码大全》。
《深入理解计算机系统》,英文名是《Computer System: A Programmer’s Perspective》,它是美国卡耐基梅隆(CMU)大学的计算机系统课程教材,CMU是全美计算机科学(CS)排名前三的大学。这门课在CMU被誉为镇校神课,对应的课程编号是15-213,它正好是CMU大学的邮编,所以这门课也被戏称为"The course gives CMU its zip code"。《深入理解计算机系统》讲的是包括位运算,CPU指令结构,汇编,编译,存储管理,操作系统和网络等计算机底层技术,如果你想在软件研发行业内走得更远,那么《深入理解计算机系统》是必修课。我发现国内很多程序猿是喜欢钻细节的,但是真正让他们深入到计算机底层细节的时候,他们往往又深入不下去,对于这部分程序员,我建议你们花几个月时间认真研读这本《深入理解计算机系统》,包括亲自动手实现书籍配套提供的大部分Labs!!!(参考附录1),它可以帮你打下坚实的计算机系统编程基础,让你成为一个更有sense,也更有潜力成长为架构师的程序员。该书目前已经出第三版,算上前几个版本,目前在豆瓣上总计有超过五千人评价,综合评分为9.7。
《代码大全》是知名软件工程专家McConnell Steve撰写的软件技艺(Software craftmanship)书籍,内容偏向软件工程实践和编程技艺,是面向一线程序员的,它的主要内容是关于如何开发出高质量的对人友好(可维护)的软件。《代码大全》的英文全名是《Code Complete: A Practical Handbook of Software Construction》,代码大全这个中文名翻译其实是有误的,Code Complete应翻译成编码完成,它是软件开发中的一个阶段,表示程序员把代码写完,在把软件交付到测试和运维之前的这个阶段。《代码大全》我读过不下三遍,每次读都有新的体会,它对我的软件开发思维产生过重大影响。
如果说《深入理解计算机系统》是教你如何深入计算机系统的底层(钻细节),让你对程序运行时的底层细节有深入理解,并编写出对计算机硬件友好的(hardware friendly)程序,那么《代码大全》则是教你如何做好软件需求分析、架构设计和抽象,如何遵循工程流程,遵循编程惯例,确保开发出高质量的对人友好的(human friendly)和可维护的软件。两本书可谓一阴一阳(底层细节 vs 宏观抽象),相互补充。
《代码大全》是一本大部头的书,读起来还是比较费劲的,另外据说这本书在国内已经绝版了,为此,我把这本书的十个核心观点总结如下(主要参考附录2),方便大家快速掌握其核心:
1. 征服复杂性
Conquer Complexity
软件架构设计的首要目标是管理或征服复杂性,通过工程纪律(流程)、惯例和抽象等手段,来减轻我们大脑的认知负担,从而让我们更好的管理复杂性,开发更高质量和大规模的系统。
2. 选择合适的流程
Pick Your Process
质量不应该只是事后考量,从需求分析、架构设计、代码实现,测试,到最后部署+运维,在软件开发的每一个阶段都需要考虑质量,设置相应的质量关卡。即便是在敏捷和快速迭代流行的今天,强调前期的需求和架构设计仍然必要,你在前期的需求和架构设计投入的越多,那么你就越可能生产出高质量的软件。
3. 先写出对人友好的程序,然后才是对计算机友好
Write Programms for People First, Computers Second
代码的可读性,对于软件可维护性(包括可理解性,可评审性,错误率,可修复性,可修改性,还有后续的开发成本和质量)很重要,也就是要先写出对人友好的程序。在此基础上,再考虑代码对计算机硬件的友好性,这个是后续可以不断迭代优化的。
4. 深入一种语言编程
Program into Your Language, Not it it
不要被你的编程语言所提供的API所限制(只会用API),如果某编程语言不提供某种功能API,初级程序程序员往往只能干瞪眼,而中高级程序员会深入一种编程语言,如果所需的功能API没有提供,他们能够超越这种编程语言,自己去实现这种抽象(API)。
5. 通过惯例减轻认知负担
Focus Your Attention with the Help of Conventions
通过引入惯例结构可以帮助我们管理复杂性,从而让我们的最宝贵资源~我们的注意力可以得到更高效的使用。为啥要用有意义的变量名?为啥要写职责单一的类和函数(把类和函数都写得小小的),为啥要尽量减少全局变量的使用(让变量的声明和使用的距离尽可能靠近),为啥要尽量减少状态数据?为啥要尽量减少复杂的条件判断逻辑?为啥要放弃聪明但是难以理解的算法?这些做法的目标都是通过惯例减轻我们的认知负担,释放我们的大脑,帮我们把注意力投放到开发更高质量和更大规模的系统上,否则你的注意力很容易陷入复杂性的沼泽。
6. 像讲故事一样写程序
Program in Terms of the Problem Domain
尽可能在高层次抽象上进行工作,顶层代码应该看上去上像讲故事一样,例如订购商品OrderProduct -> 支付订单PayOrder -> 交付订单DeliverOrder, 而不是addItemToList -> callXXXBankAPI -> callXXXDeliveryAPI。产品和用户关心的是问题领域术语,不是操作系统和编程语言等底层细节。要做到像讲故事一样写程序,需要培养良好的抽象思维能力。
7. 认真对待每一个编译器警告
Watch for Falling Rocks
尽可能设置严格的编译器选项,对编译器提示的每一个警告都要追根溯源,不容马虎。
8. 没有完美,只有迭代
Iterate, Repeatedly, Again and Again
对需求、设计、估算、编码和调优都需要不断迭代。优质软件离不开一开始的架构设计,同时更是不断迭代演进的结果。
9. 避免盲信和狂热
Thou Shalt Render Software and Religion Asunder
保持好奇心和批判性思考,多动手实践,不要变成顽固不化的狂热分子(某某技术的死忠),这种狂热只会限制你的进步。保持灵活,避免陷入手中有锤子,满世界都是钉子的狭隘中。切记,技术世界里没有银弹,真正的复杂性在业务领域中。
10. 优秀程序员的性格
Personal Character of top programmer
成长性思维 ~ 技术能力非天生,只要不断努力学习实践,技术能力就会不断成长。谦虚,好奇,理性诚实,遵守工程纪律,富有创新和探索精神,动手实践而非坐而论道。优秀程序员和普通程序员之间的差异,不是一倍二倍,而是十倍(McConnell Steve),甚至五十倍(乔布斯)。
课程推荐
明天(11.26)正好是感恩节,我在极客时间上的《Spring Boot和K8s云原生微服务实践》课程有限时优惠,原价 ¥199,拼团+口令「yangbo666」立减 ¥30,到手 ¥99,欢迎感兴趣学员关注学习。
参考
-
《深入理解计算机系统》配套实验
http://csapp.cs.cmu.edu/3e/labs.html -
https://softwareengineering.stackexchange.com/questions/2777/what-are-the-key-points-of-code-complete