Please enable JavaScript.
Coggle requires JavaScript to display documents.
201 principles (DESIGN PRINCIPLES (保持概念完整一致 (使用有限的设计形式,统一使用,…
201 principles
DESIGN PRINCIPLES
meta
包含:
定义满足需求的软件架构
明确架构中每个软件组件的算法
架构包含:
软件中所有组成模块
它们之间的接口
它们之间的组成结构
组件的生命周期
产出:设计说明
需求到设计的转变并不容易
设计到问题的跟踪(了解各个需求是被哪个组件满足的)
可维护一个二维表
多方案评估
所有工程中都有的一个关键原则:多种可选方案(描述高大上),权衡分析,最终采取一个
没有文档的设计不是设计
如同建筑设计师设计完但是没有图纸,作家完成了小说但尚未写出来
设计是落实在纸上或其他媒介上的对于合适架构和算法的选择和抽象
封装
信息隐藏,便于测试和维护
不要重造轮子
所谓“工程”,就是在设计新事物时,可以参考当前可用的类似事物(比如建筑师可以采用已有的门窗等)。
这在软件领域叫
“复用”
保持简洁
简单更容易维护(KISS, Keep it simple, stupid)
"There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies."
避免过多特殊情况
异常情况导致在算法中添加特殊 case,每一个特殊 case 都会让调试、修改、维护和提升变得更困难
如果发现太多 special cases,可能算法不合适,可重新思考并设计
最小化 intellectual distance(现实世界的问题同计算机解决方案间的距离)
软件结构应尽量模拟现实世界结构
现实世界的结构不唯一(不同的人理解可能不一样)
将设计保持在智力控制范围内(创造者和维护者可以完全理解)
层次化:抽象地一层一层地理解,每层都应站在外部视角描述,所以每层的每一个组件都是简单而优雅的
保持概念完整一致
使用有限的设计形式,统一使用
设计形式:组件如何通知调用者错误信息,软件如何通知用户错误,数据结构如何组织,组件通信机制,文档标准
设计完成,应看起来是一个人创建的
有时可以因为优雅、简洁、性能而加入新的形式,但不要只是因为个人喜好或满足感而屈服于诱惑
概念性错误比语法错误更严重(每一个阶段)
高内聚、低耦合
为变化而设计
模块化(独立,容易升级或替换,最小化对其他部分的影响)
可移植
可塑性,易延展
#69, #70, #71
为维护而设计
为错误而设计
尽量做到:
不引入错误;
引入的错误可以容易被检测到;
发布后仍存在的错误,要么不重要,要么没有造成灾难?
不要遗漏
case
;
预测尽可能多的“不可能”情况,并给出恢复方案;
为减少灾难,为可预测的不安全情况做故障树分析??
通用性
灵活性
比通用组件(#77)运行时高效?
比非灵活性的容易复用
使用高效算法
算法复杂度分析
模块规格提供所有用户需要的信息,无需更多
设计的关键部分:系统中每个组件的精确定义(组件的公开部分)
包含:目的,名字,使用方法,如何同环境通信
不包含:算法,内部数据结构
设计是多维的
包含关系:what is part of what?
依赖关系:who needs whom?
调用:who invokes whom?
进程/线程:划分,及创建、执行、停止、销毁的条件
伟大的设计来自伟大的设计者
简洁,简单,优雅,快速,可维护,易实现
需要灵感、洞察力,而不只努力工作或遵循一步一步的设计方法
熟悉应用,了解业务
复用
你们曾经写过做xx的组件吗?
"GARBAGE IN, GARBAGE OUT" is INCORRECT
输入无效数据,应输出无效原因信息
软件可靠性可通过冗余来解决
硬件方面可通过多台机器并行/备用方式提高可靠性,且设计成本提升很小
软件不同,因为同一个软件做了两个拷贝,一个失败,另一个也会失败,想提高可靠性,可以两个团队做两个版本,这样设计成本也会增加很多,所以高可靠性的成本非常昂贵
管理
好管理比好技术更重要
勿尽信书
理解用户优先级
倾听 teamer
信任 teamer,互相信任
Expect Excellence: 高期望
奖励,指导,鼓励(实在不行,介绍其他工作,不然留着可能让其他人以为可以接收较差质量)
沟通技能及其重要
团队协作与沟通
沟通,说服,倾听,妥协
Carry the Water
同甘共苦;即使技术上帮助不了,也可在其他地方提供帮助
每个人的需要不同,被激励的方式不同
安静?
人力和时间不可互换
软件工程师之间差别巨大
生产力(代码行数/人月)可能差 25 倍
质量(千行 bug 数)可能差 10 倍
优化你所想:侧重一点,则其他点会被忽视;关注所有,则一无所有;每次优先级应该不一样,并且需要同步给团队
trade-off
低调采集数据
不要让采集本身影响数据;尽量让开发者无感知
cost per line of code 没啥用
没有完美的评估生产力的方法
Source Lines Of Code 和 Function Points 每人月都不靠谱。
同样的功能质量,代码越少越好;
功能点一样,但质量要求可能不一样
调整评估成本的方法(根据人员和项目)
don't set unrealistic DEADLINES
不现实的排期不会被完成;
会导致士气下降,distrust,离职;质量下降
AVOID the IMPOSSIBLE
T > 2.15(PM ** 1/3) ??
KNOW before you COUNT
维护 vs 开发
采集生产力数据
成本评估模型精确性依赖于模型调整
数据的理解、采集、建模和解析非常重要
不要忘记
团队
生产力
个人生产力评估好定,但团队的不好定,团队成员可能各司其职
LOC/PM 语言无关
相信排期
排期既然定了就要相信,不相信就无法完成
要么 RD 参与定排期,要么参与 trade-off
精确成本估计并不够:管理者,假设,概率
Requirements engineer principles
meta
了解需要解决的问题;
指定可以解决问题的系统的外部行为(黑盒)
产出:需求说明出
需求搞不好,成本评估也不会好
需求频繁变更 -> 配置管理
需求缺失 -> 下一版本
同用户交流不够
需求说明不足
分析不够
写需求前先确定问题
从不同参与者角度看某现象,问题可能大相径庭(e.g. 电梯问题),而不同解决方案对不同参与者的影响也不同
尝试解决问题前,首先要确定谁真正有问题,这个问题是什么
解决问题时,不要为找到第一个解决方案的兴奋蒙蔽了双眼
尽早决定需求
不要寄希望于需求本身会自己神奇地生效
立即修复需求错误
否则留到后面,会面临指数级实践浪费
原型减少选择 UI 的风险
记录需求添加的原因
动机、背景,想法来源
方便后续 evolve 需求
当系统无法满足需求时可以快速响应
定义子集
可能有用的最小子集
可以变得更有用的最小增量子集
更好的理解业务
REVIEW
不要在需求中设计
需求阶段是要说明解决方案的
外部行为
的,需要
明确
到保证每个设计者看到这个需求都会得出同样的预期行为结论
不应考虑软件架构或算法,设计者应该在后续选择最优的架构或算法来实现需求
若有必要使用设计方案来说明外部行为,需要说明:这些设计只是辅助说明,设计者可以选择任意方案来实现这种外部行为
技术
使用合适的技术
没有一项技术适用于所有场景;复杂应用的需求可以使用多种技术,比如 ER 图,状态机图,决策表等
使用不同表达形式
比如,OO 分析现实中的实体及其之间的关系和属性,状态机描述 UI 行为,决策树描述复杂外部条件组合下的反应
organize requirements sensibly
优先级
简洁
唯一标识
减少歧义/不明确
不要用专业语言替换自然语言(可以两者都保留,一正面一反面)
把自然语言写在专业模型之前(否则前者可能沦为后者的描述)
可读性(面向各种参与者)
可靠性说明要明确
明确环境异常时的处理方案
SELF-DESTRUCT TBD's(To Be Determined)
如果一定要包含,需要附上负责人和截止日期
保存到数据库
General Principles
Poor reliability is worse than poor efficiency
尽早交付
开发者和客户间目标协调
排定需求优先级
一次性原型
区别于进化型原型
用于
快速
收集客户反馈(仅针对
理解不到位
的需求),完成后即可抛弃
快!不用管质量、设计、代码文档、可维护性,可以用任意工具或语言
Change during development is inevitable
在开发过程中,变化无处不在
准备好应对变化
If possible, buy instead of build
不重造轮子
初始想法可能很好,但是自造的结果很可能同现成的轮子一样有问题,且成本更高
用户手册越短,软件越好: self-evident
标准的接口、图标、命令、协议、用户场景…
记录假设
系统的实际应用环境是
无限
的,不可能被完全理解,我们总会做一些假设
记录假设,不管多么明显
Different languages for different phases
不同阶段应使用对应最佳的技术和语言
每个复杂的问题都有一个简单的解决方案?错!
技术先于工具
在使用工具自动化某项技术之前,首先应该确保这项技术是有效的并且经过自己的实践
只有工具而没有技术是危险的
使用工具,但要现实一些
工具可以提高效率,但不能代替所有,重要的还是人的
思考
Give software tools to good engineers
工具不会把差劲的工程师变好,正如文字处理器之于作家
CASE 工具昂贵但是也有其价值
"Know-When" is as important as know-how
选型
:学习了一项新技术没什么可说的,想着用到各种地方更是不可理喻;掌握许多不同的技术,并知道对于不同的项目或模块适合用哪个技术才是好的工程师
Stop when you achieve your goal
达到目标,即可停止,不要陷入太深
不过还要有一个全局视角,避免忽略的流程导致重大问题
对待 bug 的看法
犯错是人的本性;对于 bug 应持开放而非保守的态度(
thankful, not defensive; broadcast it, not hide it
)
尽信书则不如无书
每个人都在做的事不一定适合你,你需要细心评估你所在场景的应用性
学习新技术时,不要被宣传蒙蔽,要仔细阅读,认清代价和风险,需要试验
Don't ignore technology
虽说不要尽信新技术,但也不要忽视
软件工程技术发展迅速,一浪跟着一浪,每一浪都带着大量新技术,虽说每一浪仅可持续 5-7 年,但不会完全消失,后浪会基于前浪的最好的 features(最流行的)
文档
遵守文档标准
但不要过于拘泥,有必要加入的尽管去加
文档词汇表
词汇定义中应该尽量减少需要定义的其他词汇(需要
斜体标注
),尽量通俗易懂
索引
使用同一名称表示相同的概念(或句子结构)
否则会干扰用户,以为这种区别本身有什么技术含义
Research-then-transfer doesn't work(研究者 vs. 实践者)
研究者闭门造车后把成果交给实践者是行不通的
两者应该从一开始紧密合作,处于同一环境,产生想法并证明有效
责任
软工同其他工程一样,产品出了问题,工程师都有责任,不应找借口
total
每条原则都有其作用,但是也需要限定在其特定场景;
多条原则间可能有冲突,如同有冲突的格言一样;
所以关键还是要根据场景选择合适的原则
软件工程的原理同其他一些领域有很大不同,不像物理学一样精确与可预见,因为它是由
人
来管理和实现的
原理随学科成长(实践,经验)而进化
技术&语言&工具?