前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何做好需求分析和设计?

如何做好需求分析和设计?

作者头像
技术从心
发布2019-08-06 10:57:00
1.4K0
发布2019-08-06 10:57:00
举报
文章被收录于专栏:技术从心技术从心

分析需求

  做一个需求第一步就是分析需求了,这一步也是开发流程中最重要的一步。记住,这里说的分析需求不是产品经理分析的需求,而是我们开发拿到“产品需求”之后做的二次分析,也叫需求把控。

开发为什么要分析需求

  先定基调:产品经理和用户一样不可靠,技术一定要再做一次需求分析。这里不是对产品经理能力的否认,而是对技术人员的一种自我保护。原因如下:

第一个方面,在一个复杂的业务系统中,我们往往会发现,开发和测试(尤其是测试)比产品经理更了解这个系统,产品有时需要开发的帮助。

第二个方面,产品经理也是人,很少有人能思维极其缜密的考虑问题,人的记忆总是会有遗漏,思维总会有疏忽。

第三个方面,在业务部门里,开发人员对于产品的发展也有很大责任,一个糟糕的需求下来,最终遭殃的一定是开发人员。(血的教训就不一一列举了)

  以上列出的方方面面,从软件开发的角度,归根到底,就是在需求阶段认清楚需求风险,避免后面的需求变更。

  读到这里你可能有很多疑问,为什么需求变更要开发来买单呢?为什么不用敏捷开发来应对需求风险呢?这些可能和我们部门长期的开发方式有关:看似有章法,实际无章法。结果导向、业务导向的后果就是业务方先定下来发布时间,这个时间之前把这件事情搞定。在这种模式下,没有人会给你时间搞小周期迭代,更没有人会帮你挡住需求变更。大家会把赌注都压在项目一气呵成的假设上。也可以说,开发需要有能力识别出项目的全部风险。

举个例子,需求范围评估不全,导致开发后期发现需求影响到了某个原有功能,但是影响的结果却未定义(产品经理也没考虑到),这种事情领导最不愿意看到,而又总是将责任推给开发人员。尽管这种事情我认为也算是一种需求变更,但是从来不会有人给你延期帮你讲情(结果导向)。

  长期演变过来的结果,就是要求开发要有很高的业务理解能力,其实主要就是需求分析能力,甚至这种能力成为了你晋升最重要的因素之一。因为按照上面的开发模式,最理想的办法,就是在需求分析阶段指出需求缺陷,发现项目风险,使得后面的开发过程一马平川的走过来。当然这就需要我们的开发具备这项能力了。

开发如何分析需求

这个需求解决了什么现实问题?  此时一定要着重考虑现实问题,从现实问题入手和理解,一连串为什么要问到底,抓到问题的本质。这个需求真的能解决这个问题吗?

  对问题有了理解之后,就要对当前的需求方案进行评估,看一下这个需求是否能真的解决这个问题,对于边界情况和特殊情况是否也会生效。如果这个需求只是个临时方案,那还要去考虑最终方案是什么样的,临时方案是否值得去做。

  另一方面,还要考虑需求会不会留下新的问题,不能出现“捡了芝麻丢了西瓜”的需求。需求描述是否足够清晰?

  和传统的软件开发不同,我们缺乏严谨的需求规格说明书,因此产品提交的需求文档很可能有疏漏。我们需要检查它的一致性(是否存在自相矛盾),二义性(是否存在语义不明的表述)。每个用例的前置条件是什么,不同状态下的输出是什么(需要考虑系统的大量状态,很可能是笛卡尔乘积),边界情况下的输出是什么。  现实情况是,需求文档会有大量不清晰的表述,也是俗称的“一句话需求”,例如:查询结果可导出。(导出哪些字段,是否需要分页,导出的文件格式和模板是什么,非功能性需求有哪些) 这个问题是不是只能通过这个需求来解决,有没有更好的办法?

  一个需求提过来的可能是很具象的,比如在哪里哪里加一个按钮,在哪里新增一个输入框,这种需求提过来很有可能会对开发造成误导,低下头来直接去做了。开发此时要考虑的是,这个需求侵入到这个领域模型里是否合理,用户的操作归属在这个页面上是否合理,相似的需求已经有过类似的实现能否复用等。

  如果到了这一步开发有不同的见解,就要做好讨(si)论(bi)的准备了。职场上如何说服一个人,还是有很深的方法和套路的。可以寻求上级的支持,也可以用一些技术上的借口来旁敲侧击- -。需求的范围是否有遗漏?

  需求的范围决定了项目的范围,项目的范围影响着项目的时间和质量。因此需求范围的改变对项目的影响是巨大的,可惜的是我们在需求阶段总是会遗漏一些范围,为项目后期埋下隐患。

  评估一个需求的范围,可以从系统角度来看待,每个模块的改造都需要考虑到直接依赖它的模块是否需要改造,包括接口的变动,接口实现的变动,数据的变动。如果需要,还要一层一层的分析下去,因此每个模块的改造的影响范围可能是一连串的模块。(由此可见模块的解耦多么重要) 历史数据是否兼容,如何做数据迁移?

  当存在关系模型变动时(例如一对多变成了一对一),尤其要考虑历史数据如何处理,如何兼容的问题。同样还有新增了一些关键的属性,但是历史数据都没有这些属性时,是否需要初始化和特殊处理。码农的注意事项

  千万不要因为自己想搞技术而忽略需求分析,程序员的意义在于对现实问题抽象建模,用计算机的手段来解决现实问题,也就是充当着现实和计算机之前的桥梁,因此桥梁的两边都要顾及和熟悉。尤其是身处业务部门时,业务能力要远比技术能力重要,此时不去积极参与需求讨论和分析,就是舍本逐末。

技术设计

  业务开发做技术设计的核心,在于模型、接口和数据库表结构设计,在于业务逻辑的抽象能力。少数情况下可能涉及到技术选型的问题,这一点就不在此做概括了。得益于公司大中台小前台的组织结构,前台业务并不需要关心技术问题的具体实现,包括但不限于数据的读写性能、网站的并发能力、搜索引擎的数据同步、异地多活等等技术问题,使得业务开发完全投入到业(ban)务(zhuan)中。

  设计像是一门艺术,他不一定有对与错,但是良好的设计确实可以对软件开发带来极大的积极作用,也是一个工程师综合能力的体现。

模型/接口设计

  模型是我们为了解决业务问题进行的系统建模,代表了一个模块的职责。

系统模型与业务模型

  系统模型(也可以说是领域模型)就是业务服务层暴露出的模型。系统模型的设计离不开业务模型,应该在业务模型的设计基础上推导分析得出。而业务模型应该在需求分析阶段输出。因此,需求分析阶段的业务模型极其重要,在一个业务系统架构上,很多模块之间的耦合关系不是技术设计得出的,而是产品设计时就诞生了。当业务模型设计出来之后,我们同样可以用软件工程的角度来评估这个模型和模块的合理性,例如职责是否明确(可以表现在这个页面内的动作职责是否内聚,每个用例与业务模型的关系是否合理)、业务模块之间的依赖能否减少。尤其是业务模块之间的依赖关系,我们希望的能减少就减少,能单向依赖就不要双向依赖。模型设计追求简单

  因此在技术设计时,我们可能需要反思模型的合理性,当一个设计变得越来越复杂时,一定要停下来反思,业务模型是否合理,系统模型是否合理,是否有更简单有效的做法。一个优秀的开发工程师,应该将复杂问题抽象化和简单化,而不是将简单问题复杂化。我见过一些简单问题复杂化的例子,甚至我也做过这样的事情,工程师总是喜欢面向未来去做一些设计,做一些框架,但结果总是有好有坏。我认为如果一个复杂设计解决的问题是已知的、普遍的,那就可以放手去做;如果一个复杂设计解决的问题是不确定的、面向未来的,那么存在过度设计的风险,我倾向于用简单的方案。职责明确、单一

  模型设计的核心就是明确职责,如果一个模型能够保持一份明确的职责,那么在软件迭代开发中,维护和设计会变得更清晰可靠。职责这个词说起来容易,具体分析时却很困难,很难说有一个明确的划分方式,通常来说,逻辑和数据越内聚的地方,职责就越明确。关于接口设计

  接口设计我一直在考虑一个问题,接口的粒度应该尽量细化,还是创建一个大而全的粗粒度接口呢。按照设计原则,接口(方法)应该细化,这样一来职责明确,参数也明确。但是实践中,我们的服务化接口很多是大而全的接口,修改接口都是整个模型扔进去都可以改,这样的好处在于逻辑收敛,接口太细就会有太多接口和方法,维护起来相当困难。总的来说,每个应用越往上层(展示层),接口就要越细化,职责就要越单一;越往下层(业务逻辑层),接口的粒度越粗,通用性也越强。最终应该呈现出一个倒三角形的接口层级。通用性

  对于一些业务相关度不高的模块,设计的时候要考虑通用性。例如:打标、快照等模型,设计的时候尽量不要和当前业务有太多的耦合,直接通过outid+outtype去关联外部业务模型即可。这样设计出的模块更容易复用,更容易诞生出平台化的解决方案。

  除了上述,开发人员对于技术模型的设计也是有很大空间的,例如,一个业务模型是否需要拆分成多个系统模型,系统模型的设计是否具有可复用性和扩展性,模型是否清晰易懂?这样看来,模型的设计也是很讲究经验和感觉的,只有不断的尝试和总结,才能摸索出自己的方式。

存储模型设计

  系统模型设计完成之后,才可以进行存储模型的设计。相比于存储模型,系统模型才是设计的核心,因此千万不要有先设计数据库再设计领域模型的想法。对于存储模型我们指的都是关系型数据库的表结构,因为事实证明,电商的大多数情况下离不开事务,也离不开关系型数据库。

  这里要提一下现在常见的分布式数据库,现在的OLTP数据库为了实现分布式,很多采用的都是分库分表的方式。分库分表的方式缩减了数据库的查询和关联能力,从某种程度上来说变成一种弱关系型数据库。因此在进行表结构设计时,可能需要作出一些反范式的设计。

  存储模型大多由系统模型推导出,也可以认为是系统模型的持久化层实现方案。但是存储模型的设计不代表不重要,不同的存储设计带来的维护成本可能差别很大。

范式与反范式

范式与反范式也可以理解为减少冗余和提高性能之间的权衡。

范式可以减少冗余,这对于维护数据的一致性来讲是一个大好消息,毕竟冗余总是有可能带来数据不一致,从而影响系统功能的。这种可能性通常来自于代码缺陷,但是这种缺陷又是很难避免的:因为如果要在代码里维护各个表之间的冗余存储,很容易就把存储逻辑与业务逻辑紧密的耦合在了一起,这种代码会变得复杂+难以维护+容易出错。

反范式可以提高查询性能,减少表关联和查询次数。如果完全按照范式设计我们需要多建很多表结构,这些表结构的维护和查询成本也对程序有很大影响。现实中我们会看到很多反范式的表结构,这些可能是为了克服分库分表带来的查询成本,也可能是为了存储模型简化、减少表关联等。

存储设计也没有绝对的对错,但是我倾向于用范式设计来减少冗余,用搜索引擎来提高查询能力,用反范式来做模型简化。冗余我认为在大多数情况下都要尽量避免的,至少我遇到冗余带来的痛苦比带来的好处要多很多;相对应的查询能力的削弱,可以用搜索引擎来解决,我相信每个业务都会有接入搜索引擎的经历;最后一点“用反范式来做模型简化”我解释一下,范式设计会带来很多表,例如N:M的实体关系通常会建立一张关系表。但是如果拆分出的表可以用其他简单的方式代替,例如原表加字段,甚至存json格式的文本,那么这种方案也可以列入考虑范围。严格的关系模型设计的确会带来复杂度,在一些简单且不需要考虑扩展性的场景下,还是需要用一些方式来简化我们的表结构的。

可扩展性

  不要以为存储模型的设计会简单一些,存储模型的设计依然需要带着业务的思考来看待。具体表现就是存储模型需要有优良的可扩展性,迎合业务发展方向。毕竟模型变更只需要改代码,存储结构变更就可能要做数据迁移了。例如两个实体的关系,究竟是1:1还是1:N甚至是N:M呢,这一点上很有可能在业务上发生变化,而每次这种变动对于底层数据来说都是一项大工程。类似的,哪些系统模型需要拆成多个表结构,哪些系统模型可以合并在一张表里,这些决定很可能不是因为上面讲的范式设计,而是开发者对未来发展方向的考量。不过我还是保持上面的观点,除非已经了解到了未来的业务规划和业务需求,面向未来的事情做起来还是谨慎为好,难以确定的时候尽量选择简单的方案。

其他

代码结构

  模型定下来之后,其他的设计内容通常不会有太大的困难和变数。当然,对于一些复杂的业务模块,代码结构的设计也很重要。这里不需要给出详细设计文档一样的东西,其实想清楚大概要用的设计模式和大体的结构即可。毕竟我相信好的代码结构是不断重构出来的。

配置化

  业务逻辑复杂起来以后,配置化是一个值得考虑的方向:例如利用流程引擎去解决复杂的流程分支,或者利用元数据驱动去提高相似产品的开发效率。代码毕竟还是属于比较具体、接近于机器的逻辑表述,如果上述两种方式能够提高代码的可维护性,你又有能力设计出一套适合当前业务场景的框架,那么就大胆的尝试吧。

结语

  软件开发的流程很长,但是关键的节点往往都是在前期的需求和设计阶段,毕竟这些都是在项目初期决定着项目未来方向的重要事项。工程师的价值不仅仅在于编码实现,更应该在于设计和分析。想清楚再做,往往可以避免很多无用的体力开发工作量。

每天

进步一点点

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 技术从心 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 分析需求
  • 开发为什么要分析需求
  • 开发如何分析需求
  • 技术设计
  • 模型/接口设计
  • 系统模型与业务模型
  • 存储模型设计
  • 范式与反范式
  • 可扩展性
  • 其他
  • 结语
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档