一、软件特征维度

可测试性

质量属性 级别定义 示例/说明
方便单元测试 好:无需打桩,环境准备即可对任一接口进行单元测试;达到80%覆盖率的单元测试工作量与模块开发工作量的比率在1:4以下。 Q:为什么设计时要关注“方便单元测试”?A:经验表明,单元测试是一种非常有效的质量保证方法,具有测试全面,测试过程无需人工干预,测试效率高,错误前移,可回归等优点。
单元测试难度和效果,很大程度上依赖于设计上是否能做到接口明确稳定、低耦合。耦合高的模块打桩难,准备工作多,案例编写困难。接口不够明确稳定的模块案例编写难,案例持续维护的工作量大。
Q:怎么做更方便单元测试?A:一般采用分层设计方法即可,把对系统其它部分有依赖的逻辑、数据结构剥离,降低业务逻辑和算法(一般来说是复杂性最高的两个部分)对其它模块的依赖。对后台服务来说,一般可分为四层:
1)表现层/UI层,一般用于处理用户或其它模块的请求,一般用于对外提供服务;
2)业务层,与业务密切相关的逻辑处理,容易随需求变化而变化;
3)机制/引擎层,相对通用,与业务无关,随需求变化比较小的的数据结构和算法;
4)IO层,调用其它模块提供的功能、驱动其它模块完成某个任务;
层与层之间一般用独立数据结构作为交互媒介。比如:
a) UI层,一般逻辑是接受一个请求消息,进行业务处理,然后回复一个消息告知处理结果。要测试这个逻辑,可以把数据收发逻辑和业务处理逻辑分离。数据收发逻辑(假设叫on_dosomething)负责接收消息和发送回复,数据序列化和反序列化,调用业务处理逻辑。业务逻辑剥离为独立函数(假设叫dosomething)。可以定义两个数据结构,一个存所有参数(假设叫request),一个用于接受所有结果(假设叫result),业务处理函数原型为int dosomething(request req, result res);这个函数不再依赖收发消息的细节,做单元测试就非常简单了。
b) 完成业务过程(假设叫do_something)中,可能需要与其它模块通讯来获取一些信息。可以把这部分逻辑独立为某个函数(比如do_getinfo),只要对do_getinfo进行打桩,即可完成对do_something的单元测试。或者定义一个中介的数据结构,由独立逻辑调用do_getinfo将依赖信息读取到这个数据结构,do_something仅仅依赖这个数据结构,不依赖do_getinfo,自然也可以非常方便的对do_something做单元测试。
中:简单打桩,或者简单的环境准备(如准备数据库),达到80%覆盖率的单元测试工作量与模块开发工作量的比率在1:4以上,2:5以下
差:需要大量打桩,或者复杂的准备(比如功能完备的关联模块)才能进行单元测试,达到80%覆盖率的单元测试工作量与模块开发工作量的比率在2:5以上,或者打桩代码+案例准备代码占总单元测试代码量的30%以上。
方便联调测试 好:无需其它模块配合即可独立测试; Q:为什么设计时要关注“方便联调测试”?A:如果设计时模块间隔离做得不好,模块间依赖性过强,接口过多,会导致联调时,错误难以定位,联调工作难以并行(甚至经常被阻塞),进度很难准确评估控制。
中:对其它模块的依赖较少,接口满足基本保证即可测试。模块内部缺陷不会造成测试阻塞;其它模块的错误对模块的功能影响较小或者能在接口处准确报告;
差:对其它模块的依赖较多,其它模块的错误不能在接口处及时发现,错误很难定位。

可调试性

质量属性 级别定义 示例/说明
错误发现能力; 好:运行时错误能在出错点自动发现,并报告。即:调试人员对系统有基本了解,无需熟悉代码,即可定位错误位置。模块相关人员(比如测试人员)即可定位错误位置。 Q:为什么设计时要关注“可调试性”?A:大家都应该有体会,写代码其实速度是很快的,1天上千行并不是神话。但为什么我们的平均开发效率仅仅能做到30行/人天左右,时间都去哪了?答案就是“都花在解决错误上了”。
所谓磨刀不误砍柴工,设计时多想想哪些地方容易出错,出什么样的错,遇到错误该怎么办,然后提前做点准备工作,绝对是高投资回报的一件事情。

Q:什么叫“错误边界”,分哪几种,怎么选择边界?A:所谓错误边界,就是在发生错误时能防止错误扩展到其它模块/其它逻辑的一些防护机制。比如内存隔离,数据检查清洗。
常见错误边界有:主机边界, 进程边界, 内部边界,无边界。
选择边界主要看打破边界的难度和代价,既希望错误不会轻易突破边界的防护,又希望正常业务需求能方便的、低代价的打破边界的隔离。即:边界能放通正常业务访问,隔离错误造成的影响。
对于防范错误而言,主机边界 > 进程边界 > 内部边界 > 无边界。正常信息通过边界的代价正好相反。考虑到运行效率和开发效率的影响,我们需要在防范错误和提高开发、运行效率取得一个平衡。这和具体业务需求有关,比如到底是效率更重要还是可维护性更重要。

Q:为什么在错误防护方面,主机边界好于进程边界,进程边界又好于内部边界?A:总结起来就六个字:“途经少、易监控”。因为主机之间的相互影响只有一个途径,即远程消息;进程之间的相互影响除了消息,还有些进程间通讯机制(如文件,内核对象等);内部边界相互影响除了这些,还可以通过直接内存操作完成(比如溢出);无边界即几个模块在同一块数据区上工作(包括多进程共享内存),任何一个模块的失误即直接影响到其它任一模块。主机间的通讯比进程间的通讯更容易监控到,进程间的通讯比进程内部的相互操作又更容易监控。

Q:什么叫“错误会造成无直接业务关联性的模块受到影响”?A:比如:FTP解析插件和HTTP解析插件是没有直接关系的,但因为它们运行在同一个进程环境里,而且内存管理机制设计不佳,导致FTP插件出错时极易写坏HTTP插件管理的内存块,从而导致HTTP解析插件莫名其妙就出问题。 | | | 中:绝大部分错误通过分析日志能够发现并诊断。即:调试人员需要对系统比较了解,熟悉代码,通过分析可以定位错误位置。 | | | | 差:大量错误需要临时修改代码增加调试日志或手段来定位。即:调试人员需要对系统非常了解,熟悉代码,并且需要根据错误现象加入临时性的调试代码才能定位错误。 | | | 错误上下文保存能力; | 好:所有发现的错误有完整的上下文输出,绝大部分错误通过分析报告中的上下文信息可进行定位 | | | | 中:所有报告的错误有较为完整的上下文输出,辅以单步跟踪等调试器手段能够容易定位; | | | | 差:报告出来的较多错误无法定位引入点,需要临时加入诊断代码定位; | | | 交互调试能力; | 好:能够在运行时通过指令来调试模块,能通过调试指令简单观察程序内所有全局性数据。调试时不会对系统正常运行造成业务中断等影响; | | | | 中:有交互调试手段,但功能不全,或者对系统正常运行影响较大; | | | | 差:无交互调试能力 | | | 错误边界防护 | 好:错误发生时不会扩散到其它子模块,能通过故障现象或监控工具迅速判断发生错误的子模块。 | | | | 中:错误发生对内部其它子模块有影响,会扩散,但不会扩散到其它模块; | | | | 差:错误发生时很难判断具体是哪个模块造成,错误会造成无直接业务关联性的模块受到影响; | |

可维护性

质量属性 级别定义 示例/说明
错误发现能力; 好:运行时错误能在出错点自动发现,并报告; Q:什么是“错误恢复能力”?A:比如网络故障能自动重连,配置损坏能使用默认/备份配置工作,等等。比较典型的反例是早期的windows系统注册表,windows的重要数据都保存在这,有点小小的错误,普通用户唯一的处理方法就是重装系统。

Q:什么是“灾难防护能力”?A:就是整个系统遭到破坏的情况下,是否有一个能坚守底线的大后方?比如,烧在固件里的备用系统。bypass系统等。

Q:为什么“灾难防护能力”对可维护性来说很重要?A:有了这个保证,普通用户就敢于随意试验新功能,新特性,不用担心系统损坏,或造成其它什么不良后果。举例说明,有些手机可以随意刷机,即使刷坏了,也能启用备用系统刷回原厂的包。这样就大大降低普通用户操作系统的难度,不懂没关系,可以随便试,大不了重新刷回原厂系统就可以了。再比如,在电梯系统中,有一项设计可以保证系统突然断电时,电梯不会直接掉地,而是保持原地不动。这样维护人员就不用担心修电梯把自己小命修掉了。 | | | 中:绝大部分错误通过分析日志能够发现并诊断; | | | | 差:大量错误需要临时修改代码增加调试日志或手段来定位; | | | 错误报告能力; | 好:所有故障具有完备的信息输出,客户/技术支持人员能根据错误信息进行排障; | | | | 中:所有故障有信息输出,但信息不全,或不能指导技术支持人员排障; | | | | 差:故障输出不全,需开发人员才能诊断定位错误; | | | 错误恢复能力; | 好:所有内部性的错误能自动发现,自动恢复。至少保证业务基本可用性; | | | | 中:错误能自动恢复,但对客户业务存在一定影响; | | | | 差:错误不能自动恢复,需要人工干预; | | | 灾难防护能力,应急备用系统; | 好:具有基本应急机制,在出现灾难情况下能快速恢复系统运行,或保证基本业务运行。 | | | | 中:有灾难应急机制,但机制不佳,或者不能快速恢复系统运行,或者应急系统本身容易失效。 | | | | 差:缺少应急机制,出现灾难时,设备需返厂 | |

可扩展性

质量属性 级别定义 示例/说明
增加全新功能对现有代码的影响; 好:对于比较高概率扩展的需求,有良好的扩展设计,能保证扩展功能完全不影响现有代码及现有功能; Q:有哪些不修改现有代码对软件进行扩展的设计手法?A:常见扩展方式有:
1) unix/linux shell - 积木式扩展;
linux/unix提供了非常多的有用的命令,这些命令能够巧妙的结合完成复杂的业务处理,shell就是把这些命令结合起来构成复杂系统的“胶水”。很多程序库常采用此类设计方法。此类扩展的关键是,怎么设计积木。必须关注职责单一性、完备性、正交性等等;
2) eclipse - 插件式扩展;
eclipse中的插件设计非常特别,最特别是,eclipse中无处不插件,即使是eclipse的核心功能,也是以插件的方式提供。eclipse中,少有所谓的“未公开API”,原生插件(如JDT)和扩展插件(如CDT)基本站在同一起跑线上,可以使用的底层支持完全一样。
3) emacs - 内部语言式扩展;
AC new_actrace模块采用的是这种设计方式,其内部语言是一门现成语言:LUA.
内部语言常用两大类,一类是采用现有的某种动态语言或其变种,如emacs中用的common lisp,及上述的new_actrace。一种是采用专门为某类业务设计的DSL语言,如LEX/YACC中用的BNF.
4) m4 - 预处理器/后处理器式扩展;
C语言编译器通过外挂预处理器的方式扩展C语言功能;knuth的排版系统Tex也采用了这种方式;
5) netfilter - 流水线式扩展;
在流水线上,每一台生产机器都满足一样的输入输出接口标准,以致于可以方便的增加生产工序,调整生产流程。

Q:什么叫做“为新功能提供底层机制支撑”;A:比如:有完善的内存管理机制,增加新功能完全不用担心内存泄露。再比如,为HTTP协议解析模块提供字符串库,支持新的字段解析时可以用很少的代码完成字符串处理。

Q:什么叫“概念设计/业务模型”?A:LEX/YACC就是个典型例子,LEX中的核心概念叫正则表达式,YACC中的核心概念是:BNF+LALR(1)+属性文法。WOC的业务模型可以总结为链路层优化+数据消减+应用层优化;

| | | 中:对于比较高概率扩展的需求,有扩展机制,但扩展机制需要对现有代码进行修改,或者新功能对原有功能存在影响,导致原有功能需重新测试。 | | | | 差:完全没有考虑如何扩展需求,增加功能必须在现有代码基础上做大量修改。 | | | 增加全新功能的代价,是否提供了足够的底层机制支撑; | 好:对高概率的需求,有足够的底层支撑,增加新功能仅需关注核心业务的实现,无需其它内容,开发难度低; | | | | 中:对高概率的需求,有扩展支撑,但增加新功能需要完成的代码量大,或者有较高的开发难度; | | | | 差:完全没有支持,代码无法复用原有设计逻辑; | | | 是否有良好的API接口; | 好:扩展功能时能利用已经明确定义的API进行,且API设计简单完整无冗余; | | | | 中:API设计复杂、冗余、或不充分,或需大量垫片代码; | | | | 差:无相关API接口。 | | | 是否有良好/完备的概念设计或业务模型; | 好:有完整清晰简单的概念设计,业务模型,通过简单文档即可理解原有逻辑和扩展功能之间的交互方式和细节; | | | | 中:业务模型比较复杂,或者概念散乱,理解原有设计和新增功能之间的交互较为困难; | | | | 差:无抽象程度高的业务模型/概念设计,理解原有设计逻辑必须依赖代码分析 | | | 技术支持 | 是否能更好地得到技术支持,当前出现当前已有人员无法解决的问题时是否能寻求到帮助? | | | 是否开源 |
- 如果开源,开源协议是什么?是否有法律风险?是否允许商用?
- 如果收费,什么计费方式
- 使用后是否软件是否强制开源?
| | | 流行度/成熟度 |
- 在市场上是否容易招到开发者,是否为通用技术,可替代的开发人员是否够多
- 是否成熟,是否稳定等,网上的好评度如何,是否被大家广泛使用,还是只是一些偏门技术
- 是否有大厂支持,持续更新了多久,是否还在持续迭代与维护
| |

可复用性

质量属性 级别定义 示例/说明
内聚性 好:所有功能围绕一个“概念/需求”设计,基本功能完备,无冗余; Q:讲到可复用性时,常说一句话“多不如少”,这是为什么?A:罗列过多东西,即意味着使用者可能要面对很多根本用不上的功能,它们之间可能相互干扰,即使不相互干扰,也会消耗使用者的精力去学习。增加使用难度。
中:功能围绕一个“概念/需求”设计,但有些无关紧要的,或不是密切相关的功能;
差:概念松散,罗列多个不是密切相关的“概念/需求”;
依赖性 好:无需任何其它模块辅助即可工作,在公司现有设备/系统环境下都可运行,无需特殊硬件/环境的支持。 Q:什么叫做不必要的依赖性?A:举例说明,比如某模块依赖mysql数据库,dbase数据库等多个数据库的驱动,缺少任何一个都无法启动,但实际上某些数据库只在某些硬件环境上使用。另外由于存储数据简单,用配置文件即可替代,不用数据库更方便。
依赖性过强,即意味着移植难度加大。
中:核心功能需要移植其它模块作为辅助,或者需要某些特殊硬件/环境的支持;
差:依赖某些模块/硬件/环境。但是依赖其实是不必要的。有的根本用不上,或者不重要(缺失只影响不重要的小功能),或者有简单替代方案(换一种方案也可以达到类似效果,替换起来还很简单)。
环境适应能力; 好:在公司现有平台/环境下都可正常运行,无需修改; Q:什么叫“环境适应能力”?A:比如可在windows上运行,也可在linux上运行。即可配合mysql进行工作,也可配合dbase进行工作。
比如在网桥环境可以工作,在路由环境下也可以工作。比如可以在640480分辨率下工作,也可在1024768下工作,即可适应横屏,也可适应竖屏。
中:在预定义的平台/环境下可正常运行,无需修改或仅需做简单修改和验证;
差:除了原生环境,其它环境需要修改和验证,修改验证的工作量比较大;
可配置能力; 好:核心策略可通过配置方式调整(通过调用参数传递也可以)或自动调整; Q:什么是“可配置能力”?A:比如通过配置内存池大小,可适用于不同档次的设备,或者适用不同应用(如性能敏感应用,内存敏感应用)。
中:策略的调整需要修改模块代码,但仅需通过参数调整或设置预编译选项重编代码达成;
差:任何策略的调整都需要修改模块策略相关代码;
接口易用性 好:接口可充分使用到模块的所有功能,概念清晰,一致性强,使用简单,接口无冗余。无需学习(或简单浏览文档)即可使用; Q:一个可复用模块设计最关键的一点是什么?A:接口!接口设计最关键的一点又是什么?KISS - keep it so simple!
简单才是王道。

看看从CORBA到web service的发展历程,应该可以很好的说明这一点。 | | | 中:接口概念不统一、不清晰,或者接口过多,调用接口时需要做的准备工作复杂。有较多注意事项,需要专人指导,但短时间可掌握; | | | | 差:调用接口时需要满足的约束条件过多,容易出错,使用难度很高,无专人指导+长时间训练无法掌握。 | |

可靠性

质量属性 级别定义 示例/说明
健壮性 好:对于用户合法的输入,总是能正确回应。对于用户不合法的输入,能明确加以拒绝,不会导致不可预期的错误,如程序崩溃,内存溢出等问题。 Q:何谓“健壮性”?A:面对任意输入,都能获得可预期的输出。不因不合法的输入造成破坏性后果。

Q:怎么提高健壮性?A:主要是对输入做严格检查;具有一定的容错机制。 | | | 中:对于合法输入,能正确回应。对于不合法输入,能报告错误。出现错误的场景很少而且很罕见,对用户的正常使用几乎没有影响。 | | | | 差:不能保证合法输入的执行结果。影响到用户的正常使用,但还在用户可以接受的范围内。 | | | | 不可接受:常用功能有较高几率出现故障,用户很难正常使用。 | | | 输入接受能力 | 好:几乎能接受一切输入,对格式的要求不高,对每种输入都有用户可预期的结果。对几乎所有输入都能良好处理,得到用户期望结果。 | 广谱杀虫剂,广谱除草剂
广谱输入:允许输入的范围更大,对输入、环境不敏感,不挑食,依赖条件少。
比如,有些语言对代码格式的要求非常宽松,能忽略空格换行等语义无关的格式信息。而有的程序对输入要求很高,几乎只接受专门软件生成的专有数据文件。 | | | 中:对输入的检查比较严格,对格式的要求比较高,构造机器可理解、可接受输入有一定难度。 | | | | 差:比较娇气,对输入要求很严格,构造机器可理解的输入比较困难,可以接受的输入范围小。 | 比如有的语音识别,要求非常安静的环境,要求发音很洪亮,很标准 … …
比如:早期流缓存的优化效果就很依赖环境(依赖应用类型倒也罢了,它甚至依赖数据传输顺序,并发连接特点等),即使我们明确会有效果的应用,也有可能出现优化效果不佳的情况。给定环境下,优化效果的波动范围比较大,很难准确预测效果。 | | 用户友好程度 | 好:能猜测用户真实意图,给出正确的预期结果,或者给出可选的指引,解决方案。当存在二义性时,能帮助用户快速纠正输入。 | Q:何为“用户友好程度”,和输入接受能力的区别是?A:用户友好程度,就是当明确用户的输入是有错误的情况下,能尝试理解用户的真实意图,帮助用户更好的完成期望的操作,允许用户犯错。
比如,对于输入法来说,如果用户混淆了卷舌和平舌音,系统能自动纠正,如果存在多个可选输入,也能全部列出来,按可能性由大到小排序,供用户快速确认。
“用户友好程度”和“输入接受能力”的区别是,“输入接受能力”指正常输入的范围广,容易构造,“用户友好程度”指已经明确用户的输入是有错误的情况下,仍能给出比较好的回应。以代码编辑器为例,允许语句块以任意空格进行缩进是“输入接受能力”,因为这是语法明确规定允许的。如果中间不小心多出了一个逗号,编辑器能自动发现,并提示用户,甚至尝试自动纠正,这就是“用户友好程度”。 | | | 中:对于异常输入,有准确详细的错误说明,帮助用户定位问题,纠正错误。 | | | | 差:对于异常输入,给出的错误信息不明确,不能指引用户快速定位解决问题。 | | | 环境适应能力 | 好:对环境的基本要求比较低,很容易满足程序正常运行所需要的环境和条件。 | 比如:linux,openbsd等系统对环境的依赖就比较低,还能运行在很多古董硬件上。
与eclipse等相比,vi/notepad++对环境的依赖也比较低。 | | | 中:对环境的依赖相对较高,但是一旦满足声称的必要条件,就能够正常运行,不会出现不可预料的错误。 | 比如:相比linux而言,windows对环境的依赖更高,但是只要达到手册要求的最低安装条件(磁盘,内存等),还是能够正常使用的。所以可以认为windows的硬件环境适应能力为中等 | | | 差:对环境的依赖很高,构建程序正常运行需要的环境非常困难。或者即使达成了必要的环境保证,也有一定几率出现异常、失败情况。或者需要在专有的硬件上才能正常运行。 | 比如:某些游戏只能在装有某种最高端的显卡的计算机上运行。
某些软件只能在局域网内运行。

| | 容错能力、行为可预见性 | 好:对用户的请求总是能够成功执行,不会因为中间过程的问题导致错误; | Q:怎么做到这一点?A:
1)提前申请必要的资源,避免中间因资源不足导致的失败;
2)当中间过程出现异常,启用备用措施,降效措施,重试等方法,确保完成用户请求; | | | 中:如果无法达成用户请求,则立即给用户足够反馈。只要操作正式开始,就可以得出有效结果,不会因为中间环节的错误而导致失败。 | Q:做到这一点有什么好处?A:对于一些耗时操作来说,如果进行到一半才报告失败,会让用户不可接受;
对于一些危险操作来说,进行到一半失败,会导致数据有破坏丢失的可能性;如果涉及到资金一类的操作,甚至可能发生不可挽回的损失。
Q:怎么做到这一点?A:在正式操作之前,对所有依赖条件进行检查,如果不满足条件,给用户足够提示,帮助其排除问题。一旦开始就不再发生因为依赖条件不足导致的失败。
或者类似数据库的做法,对每个操作记录日志,中间任意过程失败就进行回滚,保证操作是原子的。 | | | 差:耗时操作过程中可能发生依赖条件不足导致的失败,导致时间、资源(比如计算资源、存储资源等)上的浪费。 | | | | 不可接受:失败以后无法恢复到操作前的状态,出现数据丢失,信息泄露等无法挽回的损失。 | | | 稳定性 | 好:品质如一,运行多久都能保持刚开始时的功能和性能,压力、容量变化不会引起功能和性能的异变。(无故障运行时间为6个9以上)。即:可信任级别。 | Q:何谓“稳定性”?A:指程序的功能和性能不会随着时间、压力、容量、强度等条件的变化而发生异变。在长时间运行时能始终保持功能及额定性能,在额定的条件下,能始终保证额定的功能性能,不随容量,强度,压力等变化而发生异变;

Q:怎么提高稳定性?A:在这几方面下功夫:
1) 资源分配;
2) 数据结构设计;
3) 压力测试; | | | 中:在常见场景下,程序稳定运行,但在接近设计极限的条件或者少数场景下,会有性能方面的问题。换句话说地下可能埋了有雷,但我们清楚哪些地方是安全区域。(或出错概率很低,无故障运行时间为4个9以上)。即:可预测级别。 | | | | 差:程序运行过程较高概率发生程序故障或性能问题,完全无法保证不出问题。即:走在任意地方都有可能触雷,完全没有安全保证。即:不可预测级别。 | | | 安全性 | 好:能应对用户的蓄意攻击,任何情况下不出现信息泄露,服务不可用,数据丢失或被篡改等问题。 | Q:怎么提高安全性?
A:标准的参考SDL流程,仔细学习与知行,核心关注是否有新增暴露面,尤其是对接接口、交互等 | | | 中:极端情况下,不出现权限提升,数据丢失、被篡改等问题,但可能出现服务临时不可用,非关键信息泄露等问题。 | | | | 差:比较容易破坏系统的正常运行,可能出现提权类问题,数据丢失篡改类问题。 | |

二、软件开发维度

人力资源

工作量

  1. 人力耗时
  2. 开发速度
  3. 开发周期,现有多少人力资源,是否赶得上预期的发布时间? — 技术对现实的妥协

技术复杂度

  1. 技术方案自身是否要求一些特殊技能?或者是一些需要很有深度的技能?
  2. 技术方案自身的流程、步骤是否繁多?比如一个方案要10个步骤,另一个方案只要3个步骤
  3. 不要过重,杀鸡不用牛刀


技术匹配度(学习成本)

  1. 所使用技术、方案,当前人员是否已经熟练掌握?有多少人掌握这个技术、用过这个技术
  2. 这些技术方案之前是否有使用过,是否有成熟的开发案例
  3. 如果全新学习需要多久,难度多大

程序资源

内存/CPU/磁盘/IP/端口等 资源消耗

  1. 常规的资源消耗需求与规划计划,使用预期
  2. 需要重点关注是否可能有线性增长的数据产生
  3. 比如设备维护的连接跟踪数可能与用户数成正比,那么当用户数直线上升,内存消耗也会直线上升,如果没有考虑好对程序资源的保护,而用户数的上升又是不可控的,那么当实际用户数超过预期时肯定会导致异常

新增独立硬件

  1. 是否需要新增独立硬件运行?
  2. 一些涉及高性能、大带宽处理的服务一般要求独立硬件运行
  3. 新增独立硬件就要考虑单点硬件的故障等,以及对于运维、高可用等的挑战

开发环境

  1. 是否对特定的开发环境、编译环境有依赖
  2. 比如windows开发则需要专门的微软签名服务器等

性能

带宽吞吐

  1. 在资源约束下,处理流量的设备可以处理多大的吞吐?
  2. 需要考虑各种不同的背景流量,大包、小包、真实场景等等

并发连接数/并发用户数/QPS

  1. 涉及接口、服务等常规的性能指标

需求满足

价值效果

  • 对需求、价值实现的准确性
  • 是否满足主要需求、所有需求?是否在方案选型上会导致某些需求无法实现
  • 是否有需求遗漏?

用户体验

  • 用户的使用复杂度
  • 使用方式是否易于理解,步骤是否繁重,是否小白也用得来?
  • 区别于上面的“可靠性”中的“用户友好程度”,更侧重用户使用的流程过程是否友好,上面的是交互上的容错程度是否友好