最近一段时间在反复思考需求、概要设计、详细设计应该到各自什么粒度以及各自的界线是什么。

根据业务功能的不同,有些功能的设计要求很高,有些功能的实现要求很高。前者设计思考的非常清楚之后,找任何开发几乎都能够完成,典型的比如说在高并发的架构设计点如计数器、日常的增删改查、甚至复杂的业务流程。后者,比如说分布式缓存的实现,性能分析与优化,多线程,数据库的设计与SQL代码的编写,比如说oracle是堆表,而mysqlIOT表,mysql没有索引跳跃扫描但是具有ICP

 

论计划的制定

事实上,对于经验不是很丰富的工程师而言,制定计划的难点在于他们并不清楚需求、概要设计、详细设计分别需要到什么程度,为什么需要做,各自的界线是什么。这一点清楚之后,我们相信所有的开发人员都会乐意去指定计划。

软件的需求分析、概要设计、详细设计、开发虽然可能在一开始我们并不知道需要多少时间完成,领导可能也是拍脑袋的。正是因为这个不知道需要多少时间完成,因此我们才需要根据自己的经验对上层领导的高层拍脑袋进行细化,得出我们拍脑袋的结论。绝大部分的项目计划通常是在需求分析开始之前需要给出的,虽然可能不靠谱,但仍然需要我们给出如果我们需要把系统设计成这样,我们需要多少时间的初步结论。对于底层人员来说,可能会认为这个计划并没有什么意义,自己的职责是开发,自己的目标是更多的学习技术,搞这个计划纯粹是浪费时间,但是工作不能等同于学习,有些时候公司目标和个人目标可能就是存在矛盾的。但是对于高层领导来说,这个计划的意义在于这件事是否值得做,需要多少成本。

通常在需求分析完成之后,我们会更加清楚的估计出概要设计、详细设计、编码需要花费多少时间。他们可能会偏差很大,也可能会偏差很小。此时,无论是偏差很大、很小都没有关系,只要我们客观的分析了需求,我们有理由相信自己,即使可能会被上级认为夸大或者误解,甚至此时有可能会被取消这个项目,并且最终可能会影响到我们的年终绩效(视领导的魄力而言),但事实上我们为公司避免了损失,由此我们应该得到嘉奖。如果ok,此时就进入概要设计阶段了。

其实,接下去的概要设计、详细设计、编码都一样,随着概要设计的完成,我们会得出技术难点在哪里、哪里需要进一步细化,进一步的详细设计需要多少时间就会更加清晰的显露出来。同时,随着详细设计的完成,编码需要多少时间就会进一步的清晰起来。

事实上,绝大部分项目的悲剧性延期、成本剧增导致团队解散、失控、巨额亏损,并不是因为这个流程有问题,也不是开发人员本身出现了问题,甚至并不是项目经理不负责任、团队不够和谐,而是组建这个团队的分管领导组建了注定会失败的团队本身或者团队的组织结构为失败埋下了伏笔。不是一个成员或者项目经理有责任心、老黄牛、任劳任怨,项目就会成功的,市场不相信眼泪,如果市场的分配按照任劳任怨的原则,那么世界上挖煤矿、建筑工人应该是收入最高的人群。言归正传,项目最终是否是失败通常在每个阶段都会出现征兆,但是随着时间的进展,这种征兆会越来越明显,当然这需要洞见。每个阶段需要产生什么交付物、多少交付物并不是关键,交付物的质量度量是关键。项目之所以会在最后失控被发现,通常是因为对需求分析、概要设计、详细设计这三个阶段应该产生什么样的交付物没有明确的度量指标,这导致了很多的项目虽然每个环节都花费了很多时间,但是到了真正的编码阶段,发现有大量的不确定性和待确定性,同时大量的技术决策都是待定、待验证状态,甚至大量的业务点都处于待确定状态,仔细的站在旁观者的角度去看,似乎前面的三个阶段并没有什么进展。这是其中的一个关键。

另外,有些项目比如说要求TPS上万,完全的高可用,对于这些系统,项目中是否有掌握关键技术的人员或者其满意度决定了系统的成败,也就是最上面所述的根据业务功能的不同,有些功能的设计要求很高,有些功能的实现要求很高。举个高端的例子,汽车发动机不是项目管理能力强就能研究出来的,其中核心技术人员受到的待遇决定了其成败。有些软件项目也是一样,不是项目经理管理能力强,项目就会成功,其专业能力同样可能是必要条件而非充分条件。

虽然如此,不管什么样的项目,为了尽可能的确保成功,项目计划是个关键环节,没有计划就没有达到目标的路径,所以,制定项目计划并定期去调整、完善它是必不可少的。

 

论需求、概要设计、详细设计以及开发的界限

需求的目标输出应该包括是:术语以及对术语的解释,业务的正常流程以及业务的异常流程,各种业务状态。对象的业务元素和组成。各种参与者以及参与的流程。业务功能的详细描述与组成或分解。系统的运行环境限制,包括服务器、客户端、网络。

概要设计阶段,模块一级的拆分,具体哪些功能点必须是很清楚的,完全描述清楚模块之间(以及与外部系统)的接口以及参数,数据字典,错误号,暂定的调用关系。功能的抽象,重复功能模块的抽取和归属分配。

概要设计阶段,此时它的输出需要包括需要调用哪些外部接口,需要提供哪些外部接口,参数清单(不仅仅是业务,还包括处于维护或其他考虑增加的额外元素),格式,成功失败的状态,参数的取值范围,数据字典,所有的业务的异常流程、技术上可能的异常流程比如网络超时、回滚都已经包含,真正的表结构。理论上概要设计阶段的输出用UML或者当前主流属于来表示的话,相当于UI/外部系统->LS(业务服务)->AS/Logic(微服务/外部服务),没有必要细化到DAO的具体实现或者缓存的具体实现,功能号、菜单号。

在软件系统的不同生命周期,需求和设计的细化程度通常也会不同。举个例子来说,对于新系统开发而言,通常这个时候可以认为一切都是从0开始,此时,在需求中可能会这么写,“客户持仓查询”,而此时,系统中甚至都还没有持仓表,因此在概要设计的计划中,就需要体现出客户持仓表的模型设计,如果本系统只是管理持仓,但是业务本身并不是该系统的职责,此时还需要体现出对外提供给其他子系统或者外部系统增加持仓的接口。而这个需求如果放在系统的维护阶段,此时模型等各方面都是已经现成和成熟的,需求可以说是比较直观的就反映了设计阶段的工作。

 

论软件系统的设计与开发_概念

 

架构阶段,在进行需求设计阶段的同时,应该已经在同步进行架构设计,因为概要设计阶段事实上已经会涉及到系统间的调用、关键接口的出入参数,所以如果架构和概要设计阶段同时进行的话,很有可能会导致概要设计阶段需要返工,因此架构方案必须提前锁定。架构设计需要产出如下输出物:

业务架构

网络架构

部署架构

开发架构

开发设计规范与约束、模板

开发支持工具以及相关脚本

非业务基础功能

关键性功能的技术方案

 

详细设计阶段,概要设计文档相当于机械设计中的装配图,而详细设计文档相当于机械设计中的零件图。

在详细设计阶段,设计者的工作对象是一个模块,根据概要设计赋予的局部任务和对外接口(同时需要确认外部接口),设计并表达出模块的关键算法说明(比如调用本地缓存/分布式缓存、同步/异步、并行/串行、轮询/被轮询)、流程、状态转换等内容。这里要注意,如果发现有结构调整(如分解出子模块等)的必要,必须返回到概要设计阶段,将调整反应到概要设计文档中,而 不 能就地解决,不打招呼。详细设计文档最重要的部分是模块的流程图、状态图及相应的文字说明等。理论上概要设计阶段的输出用UML或者当前主流属于来表示的话,相当于UI/外部系统->LS(业务服务)->AS/Logic(微服务/外部服务),必须细化到DAO的具体实现或者缓存的具体实现,内部的参数类(这个时候的参数其实直接用eclipse去实现就可以了,至于拷贝到word中,直接导出javadoc粘贴进去可能会是更好的选择),这个时候可以说是到伪代码级别了(查询的输出字段、表结构字段、在UI层翻译或者POJO层翻译或者DAO层翻译)。因此,判断详细设计是否完成的依据是编码时是否还有一些if/else需要待定,包括技术的、业务的。如果到了编码阶段,还有一些业务需要推敲或者技术决策需要判断,可以说详细设计就是不充分的,或者说失败的。

花若盛开,蝶自飞来,你若精彩,幸福开怀!2020年12月11日-18日