1

201个软件工程原则

 2 years ago
source link: https://www.jianshu.com/p/d91075319ba9
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
2021.11.19 06:02:53字数 3,768阅读 10

201个软件工程原则

一、基本原则

1.质量第一。
2.不同的人对软件质量的定义不同。对于开发者来说,质量意味着优雅的设计和编码;对于高压环境下的用户来说,质量意味着响应时间和容量;对某些客户来说,质量意味着满足所有已知的和未知的需求…一个项目的质量取决于它需要优先考虑的事以及各参与方。
3.产量和质量不可兼得。产量越高,则质量越低。贝尔实验室发现,要想实现每千行代码只有1~2个bug,那么每人月只能产出150~300行代码。
4.高质量的软件是可以实现的。大型的软件系统是能以很高的质量构建的,但必须以很高的价格:每行代码$1000。作为开发者,要知道那些能够提高软件质量的技术:多与用户沟通,构建原型,保持设计简单,检查,雇佣最优秀的人…
5.不要试图改造软件质量。就好比不要试图把一个测试原型(throwaway prototype)转化成产品一样。
6.可靠性差比效率低更可怕。
7.尽早交付产品。可以尽快构建一个原型,让用户体验,一方面能早日收集到反馈,一方面可以验证需求,便于后续开发出令用户满意的产品。
8.与客户/用户沟通。人和环境都可能发生变化,跟进变化的唯一方法就是交流。
9.为开发者和客户制定激励措施
10.计划扔掉一个
11.建立正确的原型
12.将正确的功能构建到原型中
13.快速构建一次性原型
14.逐步增加系统
15.看到越多,要的越多
16.开发过程中的变化是不可避免的
17.如果可能,购买而不是自建
18.构建软件,使其需要简短的用户手册
19.每个复杂的问题都有解决方案
20.记录你的假设
21.不同阶段使用不同的语言
22.使用工具前的技巧
23.使用工具但要切合实际
24.将软件工具交给优秀工程师
25.CASE工具价格昂贵
26.何时知道与知道为什么一样重要
27.实现目标就停止
28.了解正规方法
29.使声誉与组织保持一致
30.小心跟随旅鼠(Lemmings)
31.不要忽视技术
32.使用文件标准
33.每个文件都需要一个词汇表
34.每个软件文档都需要索引
35.对相同的概念使用相同的名称
36.研究后转移不一定有效
37.承担责任

二、需求分析

38.需求不佳导致成本估算不佳
39.在编写需求之前确定问题
40.立即确定需求
41.立即修复需求规范错误
42.原型可降低选择用户界面的风险
43.记录为什么包括需求
44.识别子集
45.检视需求
46.避免在需求设计
47.使用正确的技术
48.使用需求的多个视图
49.合理地组织需求
50.优先考虑需求
51.简明扼要
52.单独给每个要求编号
53.减少需求中的歧义
54.增强,永不替代,自然语言
55.在更为正式的模型之前用自然语言写
56.保持需求规范可读
57.具体指定可靠性
58.指定什么环境下可以违背可接受的行为
59.自我解构未定义
60.将需求存储在数据库中

三、软件设计

61.把需求文档转变成设计文档并不是一件容易的事儿
62.跟踪每一个需求,记录每一个需求的设计及实现情况(可以用表格来记录)
63.评估每一种方案,从中选出最好的
64.没有文档的设计不算真正的设计
65.封装,便于维护以及隔离错误
66.不要重复造轮子
67.KISS(Keep It Simple, Stupid)原则,即 保持简洁和单纯
68.避免过多的特殊情况:如果需要考虑的特殊情况太多,说明设计或算法有问题
69.最小化计算机世界与现实世界的距离,即 在选择模型和方法时尽可能地模拟现实世界
70.保持设计的智能可控性,本质上是倡导分层设计,并提供多种视角 (->80)
71.保持概念完整性,包括数据结构的组织、模块间的通信方式、错误警告等等的一致性。即使是由多个人开发的系统,看起来也像一个人开发的一样。
72.概念错误比语法错误更重要、更难以排查。
73.松耦合,高内聚
74.为改变而设计,即 所作的设计必须能够适应变化的需求:模块化、可移植、可扩展、贴近现实(69)、智能可控(70)、概念完整(71)
75.设计需要考虑后期维护。就可维护性而言,架构的选择比算法和代码更重要。
76.设计需要考虑错误情况。尽量做到:

    1. 不引入错误
    1. 引入的错误很容易检测到
    1. 部署后依然存在的错误要么不重要,要么能够避免执行过程中出现灾难性问题

有些具体方法可以帮助提高设计的鲁棒性:

    1. 不要遗漏任何一种状态,例如一个变量有4种取值,不要只检查其中的3种
    1. 预测尽可能多的“impossible”的情况,并给出恢复策略
    1. 为了排除引发灾难的情况,使用故障树(fault tree)分析预测不安全的情形

77.构建通用性软件。通用性强的软件/组件一般运行会稍微慢一些。
78.构建灵活性软件。灵活性强的组件一般比通用性强的组件运行更高效。
79.使用高效的算法。要求设计者了解各种算法并能够进行算法复杂度分析。
80.模块规格说明应该包含用户需要的所有信息,不要加入用户不需要的任何信息。即模块化。
81.设计是多维度的,包括 打包(packaging, what is part of what), 分层(hierarchy, who needs whom), 调用(invocation, who invokes whom), 流程(processes)…
82.伟大的设计来自于伟大的设计者
83.了解你的应用程序,例如压力环境下的预期行为、输入频率、响应时间、天气的影响…等等
84.可以复用一些模块或组件,因为复用的成本小且效率高。
85.对于软件来说”garbage in, garbage out”是不正确的。对于无效的输入,软件应该给出智能的回应,指出为什么无效;并且不应该进行处理,而是返回错误码,避免错误向后扩散。
86.可以通过冗余来实现软件可靠性:

  • 并行策略,例如mr任务,每个分片的job都会起多个相同的、互不影响的task,如果其中一个跑完了,就可以kill掉其他的了
  • 冷备,当主控机器出现硬件故障时,可以启动备用机器继续提供服务
    软件的高可靠性需要很高的代价,有时针对一套需求可能需要提供两套设计方案。

四、编码原则

87.避免花招(avoid tricks)
88.避免全局变量
89.自上而下写代码
90.避免副作用(avoid side-effect)
91.使用有意义的名字
92.首先为人编写程序
93.使用最佳数据结构
94.做更快之前先做对它
95.在完成代码之前先做好注释
96.开始编码之前写好文档
97.手工执行每个组件
98.检查代码
99.您可以使用非结构化语言
100.结构化代码不一定是好的代码
101.不要嵌套太深
102.使用适当的语言
103.编程语言不是借口
104.语言知识不是那么重要
105.格式化程序
106.不要过早编码

五、测试原则

107.将测试跟踪到需求
108.在需要测试之前就计划测试
109.不要测试您自己的软件
110.不要编写自己的测试计划
111.测试暴露缺陷
112.尽管大量错误可确认无价值,但零错误不表示软件有价值
113.成功的测试发现错误
114.在15%的模块中发现一半的错误
115.使用黑盒和白盒测试
116.测试用例包括预期结果
117.测试无效的输入
118.总是做压力测试
119.大爆炸理论不适用
120.使用McCabe复杂性度量
121.使用有效的测试完成措施
122.达到有效的测试覆盖率
123.在单元测试之前不要集成
124.将你的软件仪器化
125.分析错误原因
126.不要亲自犯错误

六、管理原则

管理包含软件开发周期中的一系列活动,包括规划、控制、监督、汇报等。

  1. 好的管理比好的技术更重要

  2. 采用合适的解决方法:技术问题需要技术方案,政治问题需要政治解决,管理问题需要合适的管理方法。

  3. 不要对你读到的所有内容都深信不疑

  4. 理解客户的优先级

  5. 人才是成功的关键

  6. 少量有技术的人比大量没有技术经验的人要好

  7. 倾听你的队员:如果你和团队成员之间没有信任,那么你们的项目必将失败。信任的第一原则就是倾听。

  8. 相信你的队员

  9. 期望优秀和卓越

  10. 沟通技巧很重要:招聘过程中不能低估沟通和协作的重要性

  11. 给不同的员工以不同的激励

  12. 保持办公环境的安静

  13. 人力和时间是不能互换的

布鲁克斯法则(Brook's Law)指出,投入更多的人来开发一个紧急的项目只会让进度更慢,更多并不意味着更好。投入新的人力时,要考虑训练和沟通成本。

  1. 不同软件工程师之间的差别是很大的

  2. 可以优化任何方面

  3. 自动收集工程师数据

  4. 考虑每行代码的成本是没有意义的

  5. 没有完美的衡量开发效率的方法

    SLOC(source lines of code)代码行估算法:大家普遍认为代码产出越多越好,但有时候却并非如此。实现相同的功能,代码量肯定越少越好。

    FP(function points)功能点估算法:大家可能认为功能点越多表示产出越多、效率越高,但所要解决的问题的复杂程度或难度不同也是会影响产出率的。

    没有哪一种方法是完美的,也不要单独依赖一种方法进行考量。

  6. 调整成本估算方法

  7. 不要设定不切实际的交付时间

  8. 避免不可能

  9. 使用之前必须了解

  10. 收集生产数据

  11. 不要忘记团队生产力

  12. 代码行数取决于编程语言

  13. 相信设定的时间表

  14. 精心计算的成本估计也不是万无一失的

  15. 定期评估时间表

  16. 轻微的低估并非总是坏事

  17. 合理分配资源

  18. 详细地计划项目

  19. 及时更新你的计划

  20. 了解十大风险

  • 不切实际的时间表

  • 不理解需求

  • 构建了一个糟糕的用户界面

  • 试图增加用户不想要的feature

  • 没有把握需求变化

  • 缺少可重用的接口或组件

  • 缺少可外部执行的任务

  • 响应时间太差

  • 试图超过当前的计算机技术

  1. 预先了解风险

  2. 选择合适的开发模型

  3. 方法并不能拯救你

  4. 没有奇迹般地提高生产力的秘诀

  5. 理解进度的含义

  • BCWP(Budgeted cost of work performed),衡量目前已经完成的工作的预算
  • ACWP(Actual cost of work performed),衡量目前的实际开销
  • BCWE(Budgeted cost of work expected),衡量你预期的开销
  • (BCWP-BCWE)/BCWE, 技术状态,大于0表示进度提前,小于0表示进度delay
  • (BCWP-ACWP)/BCWP, 预算状态,大于0表示低于预算,小于0表示高于预算
  1. 通过偏差进行管理
  2. 不要过度紧张你的硬件
  3. 乐观看待硬件的发展
  4. 悲观看待软件的发展
  5. 认为灾难是不可能的想法往往导致灾难
  6. 要进行项目的事后分析

七、产品保证

173.产品保证不是奢侈
174.尽早建立SCM程序
175.使SCM适应软件过程
176.组织供应链管理独立于项目管理
177.通过产品保证轮换人员
178.给每个中间产品起一个名称和版本
179.控制基准
180.保存一切
181.跟踪所有更改
182.不要绕过变更控制
183.等级和时间表变更请求
184.使用验证和确认(V&V)事态发展

八、产品演化

185.软件将继续变化
186.软件的熵增加
187.如果没有破,请不要修复
188.解决问题,而不是症状
189.变更要求优先
190.释放前的错误产生释放后的错误
191.程序越旧,维护起来就越困难
192.语言影响可维护性
193.有时最好重新开始
194.翻新最烂的部分
195.维护导致的错误多于开发
196.每次更改后的回归测试
197.相信更改容易会导致错误地进行更改
198.构建非结构化代码并不一定对其进行改进
199.在优化之前使用Profiler
200.保持熟悉度---Manny Lehman软件演进法则
201.系统存在促进进化

作者:西东(来自豆瓣)
来源:https://www.douban.com/note/740934598/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK