作者:borisyang,腾讯WXG应用开发工程师作为一名程序员,刚开始学习写代码,往往接到需求就开始写代码。有时候发现写完代码后,需求变了。更多时候,觉得写业务代码很枯燥,没有技术含量。另一方面,事实是项目的研发人员数量增加了,但是项目的质量却变低了,多人的开发只是个人努力的结合。1研发环境日趋成熟。经过PC互联网的持续深入发展和移动互联网的蓬勃发展,互联网进入了成熟繁荣期,研发环境也发生了翻天覆地的变化;它已经成为一个更加规范的研发体系和更多人的共同努力。研发流程持续加速为了尽可能的提高需求交付速度,紧跟市场变化,我们不断提高软件交付速度,尽可能从需求流程、编码实现、测试,发布。使用CICD,加速迭代。多人协作无处不在。现在的软件开发团队,再小也有2-3个人一起开发,测试、运维、运营、产品人员就更不用说了。一方面,软件产品竞争越来越激烈,需求越来越复杂,人力堆积在所难免;另一方面是有专业要求,行业精细化自然需要精细化的职业分工。2困境研发进程的速度提高了,团队人数也增加了。但是,需求的变化还是让广大研发同学感到痛苦,项目质量依然在一天天恶化。需求变更之痛需求变更之痛,让广大R&D同学都犯了难。只是为了优化性能,采用了kv存储,但是需求改成支持模糊查询;这是典型的不合理的架构设计,导致业务需求。实施是有限的。更痛苦的是,产品需求变化多端。今天简单实现一下,上线看看效果。明天,用户很生气,提出要求,又上线了一个功能,产品功能变成补丁加补丁。一方面,研发同学渴望一个完整、严谨的需求,进入研发阶段后不允许更改;另一方面,产品同学面临着各方面的压力,只希望先解决主要问题,再谈细节。工程质量下降。项目质量变差,部分原因是补丁代码的生成。由于时间紧迫,打了第一个补丁,不过是开破窗的先行者。下一次,下一个同学会更大胆的加上补丁码。临时的ifelse一个一个的堆起来,最终导致了整个项目的coderot。曾经维护过一段代码,20多个ifelse,中间还有一些过时的错误注释,维护起来很痛苦。项目代码腐烂的另一个原因是多人协作。团队里的人越多,代码似乎就越烂。为什么多人协作不能提高代码质量?一方面,多人协作其实只是分摊需求实现而已。相反,在大多数需求的分发中,应该尽可能地减少协作,以避免阻碍实现。另一方面,不同人的代码模块有着完全不同的设计意图和代码风格。维护前人的代码,如果没有全局的视野,不了解设计意图,只能往里面加补丁代码。烂项目代码很容易给程序员带来错觉。第一,业务代码什么都没有,还不如搞基础设施建设;第二,业务需求不可能完整严谨,最终会发生变化。他们中的大多数将被提供给那些要求它的人。3做什么在编写代码之前进行设计和建模。与历史不长的IT行业相比,很多行业和建筑行业的精准都离不开早期的设计。分析完设计,根据图纸规划施工,写代码应该是一样的。设计建模的有效性源于,第一,回归业务的跑道,与业务保持一致;第二,设计建模可以使协作真实有效;为什么研发实施要求与业务保持一致很重要?研发与业务需求的摩擦,本质是研发实现与实际需求不一致。无论是研发跑偏、需求没有被理解,还是需求本身不能满足利益相关者的利益,最终上线的功能都需要重新构建,这对项目组成员来说是一种折磨。对于商业项目来说,需求是非常重要的,是整个项目质量的源泉。如果源头的问题处理不好,就会不断发散、扩大,问题就会传递到最后,甚至到了产品上线的时候,整体损失就越大。从设计语言的角度来看,设计的层次是不同的,不仅是代码细节的设计,还有业务的高层设计。高层设计用业务术语表达,最贴近业务实际情况。可以帮助研发同学发现业务中的不合理点。为什么设计建模使协作真实有效?我之前经历的协作过程无非就是各司其职,尽量减少彼此协作的内容,避免太多的阻隔。研发端的协作,由于缺乏设计,不容易分工。另一方面,多人写同一个模块也会造成冲突,所以更多的协作放在codereview上。但是,代码审查的范围也是有限的。一方面,审查成本高,逐行阅读代码明确设计,对代码质量要求高。另一方面,review时间节点经常出现较晚,临近发布时,也需要对设计进行调整。不太可能。设计建模可以使协作更有效。一方面,设计建模前期是沟通和信息对接,协作内容超前。另一方面,通过使用适当的图形工具,审查成本相对较低。4如何设计和建模设计和建模分为几个部分业务建模,关注业务,不关注具体实现系统建模,关注构建系统的边界,识别系统在业务中的职责和约束并进行设计,定位核心领域,找到实际的类,明确类的职责和类之间的关系,通过设计使代码抽象和复用业务建模一般来说,业务建模主要侧重于利益相关者的利益分析和明确业务流程。工具方面,主要是用例图和流程图;从内容上来说,主要是找人(利益相关者、系统执行者)和业务主体(其他系统、相关重要对象)。干系人利益分析在分析干系人利益之前,需要找到干系人,一般要经过以下几个步骤:找到软件产品的愿景,表达软件产品带来的核心意义找到与利益相关的干系人及其利益demands形式是一种很好的表达方式。我负责的某商户从第三方商城采购人脸识别设备,通过仓配系统配送设备的业务可以表述为:愿景:以低成本、精准的方式向商户销售更多更快的设备.利益相关方利益诉求物资组老板在准确无误的情况下,更快、更低成本地把设备卖给商家。设备渠道商准确快速地将设备配送给商家。一般来说,利益相关者的利益是否得到满足,直接决定了一个软件产品的成功与否。分析stakeholderinterests需要做详细的research,R&D同学可以根据productresearch看到对应的stakeholder和他们的interests。业务用例图了解利益相关者的利益后,需要对业务流程进行分析,改进现有流程。在软件产品诞生之前,业务是如何处理的,找到原来的业务处理方式就可以梳理出业务用例。笔者负责的其中一项业务是为购买设备的商家运送设备。对于业务团队的实际业务来说,用户购买设备是有业务价值的。向右。值得注意的是,业务用例应该体现价值。虽然在实际业务流程中,商家同时做很多事情,比如签收设备,但是设备的签收并不能体现商业价值,所以购买设备只有一个用例。业务流程分析在了解了利益相关者的利益并绘制了用例之后,需要对业务流程进行分析,找到我们的软件系统可以改进的流程片段;完整的业务流程流程图可能是庞大的,需要关注的是最有可能影响到利益相关者感兴趣的流程片段,如下是配电设备在采购业务流程中的流程片段设备,不符合利益相关者的利益;配电设备的业务流程可见一斑。在原有的业务流程中,配电设备流程在所有业务流程中的流程片段较多,人员工作量大,不符合利益相关者的利益;商城订单信息采集不及时,导致配送不及时,影响利益相关方的利益相关方作为节点参与流程,成本高,耗时长。这不符合利益相关者的利益。所以很明显,我们的系统需要改进流程并取代人类的部分工作。新流程有效满足了利益相关者“将更多更快的设备准确、低成本地卖给商家”的利益。.在业务时序图中,每个箭头代表一个职责。在业务序列图中,需要考虑职责层次。将太小的职责放入流程图会导致信息过载,而忽略最有价值的职责。上图中,查看设备的分布信息是运维的一个很重要的职责,在原来的需求中是比较薄弱的。R&D同学可以通过对业务流程的分析,分析需求中不合理的部分,改进需求,避免后面出现问题。变化,前期越完善,后期损失成本越低。业务流程分析是一件非常复杂的事情。R&D同学可以利用需求中的信息,同时加上自己日常与干系人的沟通和研究,掌握干系人的核心利益、业务用例和业务流程,进而解决大问题。理解需求偏差的部分问题。系统建模系统建模着重于系统与外部的边界以及系统自身的职责。系统建模需要完成绘制系统用例编写用例规范系统用例图系统用例图是业务流程、系统执行者和系统发生有价值的交互。系统执行者可以是人,也可以是外部系统,甚至是时间。系统用例应该反映系统的价值。系统会做很多事情来实现商业价值,我们应该关注商业价值。有些是没有系统特定值的低级职责。例如订单中的设备发货出现“获取商城订单信息”,需要注意“发货设备”。下面是仓储配送系统的系统用例图:系统用例规范有业务流程图和系统用例图,需要进一步细化系统边界的约束,保证系统的稳定性系统。系统执行者与系统的交互细化了细化的约束条件,可以提高系统的稳定性。如果没有仔细列出约束条件,一些边界条件可能会被忽略,从而导致系统故障;第三方商城订单发货装备数量限制,将导致因第三方商城出错造成资产损失。系统约束来源于系统用例,根据业务规则详细描述业务流程中的基本路径、扩展路径和约束。配送设备:系统每小时检查一次要配送到第三方商城的订单。系统验证订单是否已交付。系统验证要发货的SKU是否合法,验证订单发货的设备数量是否超过最大限制1000件。系统向物流系统请求订单由于2、3、4步,有用户分配顺序中设备的其他可能路径,称为扩展路径。订单已交付。系统忽略该命令。这里的约束不是告诉研发同学如何实现功能。这里的约束就是业务规则,它明确了系统执行者和系统之间的边界,以及对边界的约束。在设计评审时,可以关注关键路径上的安全规则是否到位,这对提高系统的安全性和稳定性有很大帮助。类分析与设计这可能是大部分R&D同学都比较熟悉的领域,经典的设计模式,类之间的关系,泛化,组合等等。但是类是从哪里来的呢?是不是从需求中凭空产生的?或者突然间有了一个基本的类?在设计和分析类之前,需要做的是找出谁经历过识别类的业务流程,系统建模,我们最终来到了系统中寻找类。我们熟悉的类分为三类,边界类、控制类和实体类。边界类是外部系统在系统内部的映射,系统通过边界类与外部系统进行交互。因此,一些接口的请求、输入和输出就属于边界类的职责。在仓配系统中,商城是一个边界类,将外部系统转为内部系统,屏蔽了接口请求相关的细节。控制类通常反映用例过程。一般来说,一个用例就是一个控制类。实体类是系统的核心,良好的实体类设计可以提高系统的复用性,降低系统的复杂度。寻找实体名词知道有这三个类还不足以让我们识别具体的类。识别具体的类,我们需要去到业务流程、系统流程、系统规范中经常出现的名词。在上面的流程图中,order、mall、equipment、logistics、user是重复出现的名字,说明这几个类必须存在。找到这些业务实体是找到类的第一步。查找属性类的属性并不是凭空产生的。它需要对业务有价值。用户不一定有名字。在物流的背景下,用户的唯一属性是ID和送货地址。找到那些对系统实现必不可少的属性,并将它们放在正确的类中。比如仓配系统中的订单,包括订单号、产品、用户。用户有一个送货地址。在仓配系统中,用户只有一个地址,而在商城系统中,用户有多个地址,充分说明类的属性在不同的上下文中是不固定的。找到职责从业务规则和约束中,可以找到一些实体应该有的职责,比如订单,有责任验证合法性。有的时候,有些对象看似信息丰富,但是没有职责,说明他是一个值对象,像上图中的用户和收件人地址,我们不关心他的id,只关心收件人地址,收件人地址代表用户。状态机找到类和相应的职责。对于一些主要的实体类,需要设计其状态机。清晰的状态机可以有效地厘清系统中的一些事件和状态,增强系统的整体健壮性。仓配中的订单,从用户购买待发货的状态,到通知物流发货,再到实际发货,物流签有一系列的状态演变。5小结在多人协作项目中,项目质量的持续提升不仅需要依赖代码以外的工程方法,更需要依赖设计建模。从具体实践来看,在不同环境下设计建模,调整具体流程,聚焦具体节点,同样可以做到快速高效,不会出现繁琐低效的现象。写代码前应该做的几件事:识别干系人的利益(项目越新,越能分析,如果是小功能的迭代,可以从产品需求文档中找);绘制原始业务流程图,改进后的业务流程图(业务流程图对业务理解有很大帮助,大多数场景下不应该省略);分析系统的职责边界,画出系统用例(对系统中添加的小功能可以考虑不画出来,心里有数就行);写具体的用例路径和约束条件(越是注重系统的安全性和稳定性,越应该写具体的路径和约束条件);识别主要的类、属性和职责,画出重要实体的状态机(简单的功能可以直接用代码表达)。
