需求前提:
- 需求目标是什么
- 需求研发性价比;工期是否合适
- 产品业务逻辑是否:自洽(自身的逻辑推演是否正确,或者是能否形成完成闭环)
- 需求功能拆分细粒度,并且是否保证每个功能点都可以实现
- 功能实现的技术选型
如果以上5点还没有完全确定说明我们对于需求的前期准备工作还不够完善;强烈建议不要进入下一步流程。
整体的流程如下流程图所示:
image.png
正文
项目整体设计/系统架构设计
首先需要阐述项目整体设计和系统架构设计不一定等同;它是系统架构的重要一环。如果是新项目开发;它一般包括以下部分:
-
硬件和资源申请:需要业务方提前规划未来1-2年需求未来是否要支持高并发方案,以及TPS/QPS范围。以此为基础制定高并发的方案以及是否要考虑容灾,高可用设计。(为什么需要业务方来规划:如果业务上不存在这些要求,那么花很大的精力去实现这些就会出现:输入高于产出,简单而言就是性价比不高)
-
业务难点分析:将业务难点分析转化成技术难点实现。如千人千面的UI和查询,灵活的业务配置等。我们需要在模块设计做额外的处理或者引入一些未用过的中间层来解决,这些都是未知的风险。在整体设计以及风险评估时都需要考虑进去。
-
数据持久化解决方案:需要考虑业务数据的特征来选择;如短期内数据量会很大,但是并不属于热点数据,那么我们可以考虑数据归档的方式。不管时技术还是资源成本都较低;如果数据量很大又是热点数据,那么则可以考虑分布式数据库如ddm如果热点数据不涉及update那么也可以引入ES来做query等。(需要注意的是,引入未知中间层不管服务提供商说得如何天花乱坠我们都需要加入到风险评估因素中)
-
技术选型:根据业务复杂度以及模块功能划分,选择合理的软件架构模式(条条大路通罗马,不一定需要最好的一定要最合适的)如业务流程较多变或者较长,可以用事件驱动模型实现,简单一点的用状态机,复杂一点的则可以使用工作流。开发语言选型:一般推荐生态较成熟以及人力成本较低的,方便日后的维护以及扩展。(如JAVA+spring框架)
-
整体设计文档输出:在以上四步完成之后,项目的前期轮廓基本出来了,这时需要项目owner进行设计文档输出,推荐采用物理部署图与业务流程图相结合的方式进行技术文档留底。同时也可以在团队成员以头脑风暴的方式进行讨论最终进行定型。
领域模型与DB设计
领域模型概念:业务对象模型(也叫领域模型 domain model)是描述业务用例实现的对象模型。它是对业务角色和业务实体之间应该如何联系和协作以执行业务的一种抽象。业务对象模型从业务角色内部的观点定义了业务用例。该模型为产生预期效果确定了业务人员以及他们处理和使用的对象(“业务类和对象”)之间应该具有的静态和动态关系。它注重业务中承担的角色及其当前职责。这些模型类的对象组合在一起可以执行所有的业务用例。(简单来说就是:业务的抽象)
为什么需要将领域模型和DB设计结合一起阐述;在领域模型中抽象概念和数据的关系以及约束;如是一对一还是一对多,多对多的关系是非常重要的一环。数据库结合领域模型做映射转化(ORMapping)需要重点关注:
-
数据库中表字段,相同的概念在项目中应该统一
-
不可避免数据库为了减少过多的查询会进行一些必要字段的冗余,但是不能过度冗余需要进行平衡
-
数据库的职责应该保持单一性,只进行数据的持久化。不应该把业务逻辑加入到数据库中;不利于后期维护以及对于功能点的增加导致扩展性较低,并且容易导致因为业务不熟悉产生不必要的bug
-
数据的删除应该只做逻辑删除,不做物理删除。方便数据的追溯还原
-
数据库索引设计合理性分析
-
以上5步完成基本上存储方案以及底层的数据结构就成型了。这时需要通过double check或集中评审方式进行推敲;最终沉淀为领域模型设计文档。
API接口设计
一个好的api接口设计是在业务需求中抽象出独立的功能点并在业务需求与系统实现的平衡中找到一个最佳的点;既要考虑后续业务的扩展性也要对系统的安全性,可用性,扩展性做保障。除开主干正向流程外,也需要对逆向流程以及异常流程进行考量。
api接口的三种使用场景:
-
提供给前端页面使用
-
系统内部模块之间的调用
-
提供给外部使用也就是openAPI
api接口使用注意点:
-
非对外公开的api接口需要对接口进行权限隔离以及验证
-
对外公开的api接口。如提供给外部查询的则要考虑网络攻击(网关层处理,这里不进行赘述)。一般对外公开的接口不直接对映射到DB,可以通过缓存或者中间层的方式来提高系统的并发能力。
-
基于数据交互纬度进行api接口设计
-
数据的推拉模式
-
同步还是异步
-
是否需要削峰(MQ)
-
数据是否需要保证强一致性
-
api定义完成基本项目研发的前中期工作就算完成了。对于核心功能api设计需要整理详细的需求背景对应的功能点拆分的映射,研发设计文档以及详细的流程图进行设计评审并进行文档留底。
代码实现设计
Code基本上是对前面定义的api接口进行灵活实现。
主要有以下几大原则:
-
单一原则(一个类或者一个方法只负责一项职责,尽量做到类的只有一个行为原因引起变化
-
里氏替换原则:子类可以扩展父类的功能,但不能改变原有父类的功能;(本质其实就是java的多态)(目的:增强程序的健壮性)实际项目中,每个子类对应不同的业务含义,使父类作为参数,传递不同的子类完成不同的业务逻辑。
-
依赖倒置原则 面向接口编程;(通过接口作为参数实现应用场景)抽象就是接口或者抽象类,细节就是实现类含义:上层模块不应该依赖下层模块,两者应依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象;通俗点就是说变量或者传参数,尽量使用抽象类,或者接口;接口负责定义public属性和方法,并且申明与其他对象依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑
-
接口隔离 建立单一接口;(扩展为类也是一种接口,一切皆接口)定义:a.客户端不应该依赖它不需要的接口;b.类之间依赖关系应该建立在最小的接口上;简单理解:复杂的接口,根据业务拆分成多个简单接口;(对于有些业务的拆分多看看适配器的应用)接口的设计粒度越小,系统越灵活,但是灵活的同时结构复杂性提高,开发难度也会变大,维护性降低
-
迪米特原则 最少知道原则,尽量降低类与类之间的耦合;一个对象应该对其他对象有最少的了解
-
开闭原则 用抽象构建架构,用实现扩展原则;
设计模式本身也是根据这6大设计原则衍生而来,所以只要对设计原则理解清楚了,我们运用各种设计模式时才能体会其真正的价值以及含义
总结
上述讲述的这么多步骤核心含义是:
-
需求含义:需求诉说时,对需求进行剖析明白其后面的真正含义(痛点是什么)
-
需求拆分:对一个大的需求进行功能点拆分。是否都可以正确实现(功能是什么)
-
api接口设计:从业务纬度对接口进行抽象,在满足业务的同时保证系统的可用性,扩展性,安全性(实现是什么)
-
文档的沉淀:编写的在好的代码也经历不住时间的摧残,技术在进步也许当时编写的时候是用的最新的技术,也许过一段时间最新技术就变了。阅读文档永远比直接阅读代码来的效率高。
网友评论