最近在读《软件开发的201个原则》,书内容不多,但是每一页都看的很仔细,好像往往这种言简意赅的书更让人有静下心来仔细阅读的欲望。在我看来,读书的作用本来就不是解答所有的困惑,而是激发人更加深入地学习的动力。
如果看这本书的时候,你会主动搜索文献或者资料,去了解更多的信息,那说明这本书就已经帮助了你。话不多说,抛砖引玉,今天和大家分享下我的“读后感”。
-
质量第一:编程一定要把质量放在首位,没有可商量的余地。当你被要求要为质量做妥协时,要直接说不。质量必须可量化。
-
做好质量与开发效率之间的权衡:对质量要求越高,开发效率就越低。越是强调提高开发效率,最终的质量就越低,bug的密度就会增加。
-
如何提高软件质量:让客户参与、在全面开发之前验证需求、保持设计简单、code review、雇佣最优秀的人。
-
尽早把产品交给客户:在需求阶段,无论你多努力了解客户需求,都不如给他们一个产品,让他们使用后确定自己的真实需求。可以在开发过程的早期构建一个快速且粗糙的原型,交给用户,收集反馈,然后可确定真正的需求。最终产品也就更有可能让客户满意。
-
与客户/用户沟通:永远不要忽视开发软件的原因:满足真正的需求,解决真正的问题。解决真正需求的唯一方法就是去跟有真正需求的人沟通,让他们参与进来。
-
开发者要与客户的目标一致:从客户的角度出发,按优先级对需求排序,确保不要delay。
-
开发正确的原型:有两种原型,一次性原型和演进式原型。一次性原型用快速粗糙的方式构建,交给客户来获得反馈,得到反馈后废弃,然后获取正规的需求后再开发。演进式原型用高质量的方式构建,交给客户获取反馈,然后进行整改。如果你对大多数功能都不了解,应该首先构建一个一次性原型,然后从零开始构建一个演进式原型。
-
注意:开发一次性原型要快,不用担心质量,可以使用任何工具任何语言,只需要开发那些没有充分理解的特性。
-
注意:开发演进式模型时,从小的可用系统开始,只实现少数功能,然后逐步扩展,覆盖更多的功能子集,这样可降低风险。
-
-
为变化做好准备:开发过程中的变化是不可避免的,可能体现在新的代码、新的测试计划、新的需求或需求变更等,不要抱怨,积极应对,做好准备。
-
让软件只需简短的用户手册:即简短的文档,文档内容越少,软件质量越高,这里不是说要少写文档,而是要做高质量的软件,让用户尽量少看文档就能使用明白。
-
“知道何时”比“知道如何”同样重要:一个工程师要了解更多的技术,要知道什么时候使用什么技术,要知道什么项目使用什么项目。
-
跟风要小心:当学习新技术时,不要轻易接受与之相关的不可避免的炒作。
-
不要忽视技术:不要固步自封,紧跟技术潮流,每年努力参加1-2个关键会议。与参会者的交流,很可能比会议报告更重要。
-
使用文档标准:如果你的项目、组织或客户要求遵循一套文档标准,那就要遵循它,理智的执行。
-
要承担责任:软件有任何问题时,不要找任何借口,要承担责任,要么做好,要么就不做。
-
先确定问题,再写需求:先明白要解决的是什么问题,再提出相关的需求。
-
立即修复需求规格说明中的错误:
-
如果错误保持到系统设计阶段,定位和修复要多花5倍的代价
-
如果保持到编码阶段,要多花10倍的代价
-
如果保持到单元测试阶段,要多花20倍的代价
-
如果保持到交付阶段,要多花200倍的代价
-
-
记录需求为什么被引入:记录每个需求的动机。
-
给需求排列优先级:并非所有需求都是同等重要的,要明确需求的优先级,先做哪个需求,后做哪个需求,或者在关键阶段哪个需求可以暂时舍弃掉。
-
明确环境超出预期时的系统行为:当环境超出为其定义的任何约束时,在软件需求规格说明中应明确声明预期的系统响应。用我们开发者的话说就是,做好边界处理。
-
评估备选方案:设计架构或者某个解决方案时,最好详细列出多种方法,明确优缺点,在这些方法之间权衡分析,最终选择一种。
-
做好封装:面向对象的一种思想,对某一需求做好抽象,做好封装,做好信息隐藏。
-
不要重复造轮子:程序员经常一次又一次的重新发明组件,却很少修补已有的组件。
-
保持简单:构建软件设计有两种办法,一种办法是使它简单到明显没有缺陷,另一种办法是使它复杂到没有明显的缺陷。
-
保持概念一致:这是高质量设计的一个特点,方式一定要统一,包括模块如何向调用方通知错误,软件如何向用户通知错误,如何组织数据结构,模块通信机制,文档标准等等。
-
使用耦合和内聚:尽量做到高内聚低耦合。高耦合意味着,当修改一个组件时,很可能需要修改其他组件。低内聚意味着,难以分离出错误原因或者难以判断为满足新需求而要修改的位置。
-
为变化而设计:需要选择合适的架构、组件和技术来适应不断的变化,设计需要做到:
-
模块化:产品由独立部分组成,每一部分都可以单独升级和替换,对其他部分造成最小的影响。
-
可移植性:产品应该很容易修改以适应新的硬件和操作系统。
-
可塑性:产品可以灵活适应预期外的新需求。
-
-
软件最好做到通用,灵活:通用性体现在,在不同的场景下不做任何修改就能执行预期功能。灵活性体现在,它很容易被修改,以在不同的场景下执行其功能。
-
使用高效的算法:了解算法复杂度是成为优秀软件工程师的必要前提。高效的算法和低效的算法可能会相差几个数量级。
-
编码时避免使用特殊技巧:很多程序员喜欢编写比较trick的代码,然而这种程序让别人很难理解,也很难维护,这种特殊技巧被频繁使用的理由有很多:
-
程序员都非常聪明,他们想展示这种聪明
-
维护人员在最终搞清这些特殊技巧如何生效时,不仅会认识到原来的程序员有多聪明,也会意识到自己有多么聪明。
-
职业安全感。
-
-
避免使用全局变量:全局变量写代码很方便,但是如果此全局变量访问出现问题,很难确定问题具体出现在哪个模块,所以,可以将重要数据封装在对应模块中,做好封装。
-
编写可自上而下阅读的程序:有助于读者理解。
-
使用有意义的别名:确保每个变量,每个函数的命名都有意义,尽量做到代码即文档,代码即注释。
-
程序首先是写给人看的:程序的功能以及效率固然重要,但程序也是写给人看的,要提升程序的可读性,以免在这个过程中对相关人员造成负面影响。
-
先确保正确,再提升性能:不要担心优化问题,每个项目都有很大的进度压力,在这种情况下,任何时候一个组件要是能够按时完成并且可靠运行,都值得庆祝,先保证完整功能,然后再去考虑做性能优化。
-
先写文档后写代码:也可以理解为,不要上来就埋头写代码,要先想清楚代码应该怎么写,然后再动手。
-
代码审查:即code review,一定要做code review,code review大约会消耗15%的研发资源,可以将总成本减少25%~30%。
-
不要嵌套太深:即圈复杂度不要太高,不过过多的if-else,switch-case之类的嵌套,考虑做优化。
-
编程语言不是接口:如果你是一个好的程序员,对任何一种编程语言来说你都应该是一个好程序员。
-
编程语言的知识没那么重要:一个真正优秀的程序员很好的理解和赞赏高质量编程的概念,而不只是了解某些编程语言的语法和语义特性。为一个项目选择语言的首要驱动力应该是什么语言更适合,而不是说我们只知道C语言。
-
格式化代码:使用标准的format规则,可大大提高程序的可读性。选择遵循哪种规则不重要,但一旦选择了,就要保持一致。
-
不要太早编码:即在编码之前,要确认需求和设计都是正确且合适的,即想清楚再编码。
-
为你的代码做单元测试:老生常谈了,自己写的代码自己都不测试就去提测,那得多坑啊。
-
好的管理比好的技术更重要:好的管理可以激励人们做到最好,糟糕的管理会打击人们的积极性。
-
人是成功的关键:具备合适经验能力的人,是在预算内按时完成满足用户需求软件的关键。
-
几个好手要强过很多生手:对于关键任务,最好只安排少数有足够经验的工程师,而不是安排许多没有经验的工程师。
-
不要设定不切实际的deadline:要设定合理的deadline,然后严格踩住。
-
知晓风险:在开始项目时,要熟悉经常导致软件灾难的情况,并制定降低风险的计划:
-
人员短缺
-
不切实际的排期
-
不理解需求
-
开发糟糕的用户界面
-
没有控制需求变化
-
缺乏可重用或接口化的组件
-
糟糕的响应时间
-
试图超越当前计算机技术的能力
-
-
预先了解风险:在项目计划的早期阶段,要梳理与你的项目相关的最大风险列表。
-
有时重新开始会更好,有时候从头开始设计和编码可能是更好的选择。
-
每次改动后都要进行回归测试:这个相信大多数程序员都会遵循的一个原则,代码改动后需要验证它是否能够正确的运行。
-
在优化前先进行性能分析:先做性能分析,拿到性能数据进行性能分析后再考虑做优化,80-20原则,80%的CPU周期将被20%的代码消耗,我们应该找到那20%的代码,然后对它们做优化。