写在开头:本文旨在分析服务端工程师的核心开发流程
需求分析->抽象建模->系统设计->数据设计->非功能性设计
服务端核心开发流程
需求分析
深入交流与理解客户需求
1.一般PDO牵头与客户沟通,“5W1H”(即What、Why、Who、Where、When、How)
2.BA建立用户故事来捕捉需求,格式为“作为一个[角色],我想要[目标],以便于[获益]”。
3.BA创建原型图以及明确的需求文档
持续管理与调整
1.Refine Meeting上进行Effort评估和优先级确定
2.变更管理:
建立需求变更管理流程,任何需求变更都需要经过评估、审批和文档更新。
3.迭代反馈:
在开发过程中不断回顾和验证需求,必要时进行调整。
作为SK以及配置管理员在其中发挥的作用
1.组织Refine会议以及Review会议,促进沟通协作和确保流程遵循。
2.Sprint开始前检查所有用户故事的梳理以及完成情况。如果有未完成需求会积极寻找解决方案以及归因分析。
3.推动需求结构化管理:(重要)
敏捷骑士在需求分析中推动Epic、Feature、Story和Task的划分,帮助团队理解不同层级的需求如何相互关联,并通过细化需求来增加其可管理性。
配置管理员则通过配置管理工具跟踪这些不同层级需求的变更,保持需求的一致性和完整性,从技术层面支持需求管理的结构化方法。
抽象建模
深入业务需求
做好第一步需求分析,这是建模的基础。
什么是抽象建模
将业务需求抽象成领域模型、模块、服务和系统,面向对象开发时需抽象出类和对象,面向过程开发时抽象出方法和函数。
命名抽象+分层抽象
命名抽象
Creating good names is hard, but it should be hard, because a great name captures essential meaning in just one or two words.
分层抽象
经典三层架构(展现+业务+DAO(框架模式)
MVC(Model、View、Controller)(设计模式)
阿里四层架构(Manager层,专注代码复用)
抽象原则
在设计系统或解决问题时,将具体细节和复杂性隐藏起来,只暴露出必要的接口和功能。这样可以使系统更加模块化、易于理解和修改,同时提高代码的可维护性和可扩展性。
单一职责原则:
一个模块应该只做一件事,并把这件事做好
依赖倒置原则:
高层模块不应该依赖于低层模块的实现,两者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖与抽象
举例:
1.JDBC和Java 的日志接口 Slf4j
2.所有的协议和标准化都是 DIP 的一种实现。包括 TCP、HTTP 等网络协议、操作系统、JVM、Spring 框架的 IOC 等等。设计模式里有不少模式,也是典型的依赖倒置,例如状态模式、工厂模式、代理模式、策略模式等等
3.日常生活中也有很多依赖倒置的例子。比如电源插座,家庭的供电只需要提供符合国家标准的电源插座,我们购买电器产品时,就不用担心买回来无法接入电源。汽车和轮胎、铅笔和笔、USB/耳机接口等等,也都是同一思想的体现。
里氏替换原则:
子类必须能够替换成它们的基类
举例:
正方形和长方形
虽然几何上说,正方形是一个特殊的长方形,但把正方形作为长方形的子类,却未必合适,因为它已经不存在宽和高的概念了。如果一个抽象不能符合里氏替换原则,那我们就需要考虑下这个抽象是不是合适了。
接口隔离原则:
客户端不应该被迫依赖它们不使用的方法
举例:
例如下面的 Square 类如果继承了Shape 接口,该如何计算体积以实现volume方法?
迪米特法则:
模块不应该了解它所操作的对象的内部情况
下面是一段违反迪米特法则的典型代码。这样的代码把对象内部实现暴露了出来,应该考虑讲将功能直接暴露为接口,或者合理使用设计模式(例如Facade模式)
final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
系统设计(系统架构)
将抽象建模的成果映射到具体的技术实现
设计和划分功能域
对于复杂的业务,首先应设计和划分功能域,以降低复杂度。
- 设计功能域之间的协作
确定功能域之间的数据边界
以微服务架构为例,一个功能域可作为一个应用,不同功能域之间通过服务调用来协作,对于服务,通常用请求(服务调用方发起请求)和响应(服务提供方响应请求返回结果)的数据模型来描述边界。
- 功能域内部设计
如下图: 详细设计
绘制相关模型:如类图,实体关系图等
通过流程图、时序图来描述方案数据设计
领域概念模型设计和逻辑数据模型设计(非必需)
领域分析
业务流程梳理:深入分析业务流程,了解业务从开始到结束的整个流程。
业务实体识别:确定业务中的核心实体,如顾客、订单等。
业务规则提取:提取业务规则和逻辑,明确实体之间的交互方式。概念识别与定义
实体定义:定义系统中的核心对象,包括它们的属性、行为和关系。
关系映射:确立实体之间的关系,如一对一、一对多或多对多关系。
属性归纳:为每个实体归纳出关键属性,并定义其数据类型和约束。模型构建
类图绘制:利用UML(统一建模语言)绘制类图,展示实体及其关系。
概念层次划分:根据实体的层次结构,建立清晰的分类和分层。
关联模型构建:构建关联模型,展现实体间的动态交互和数据流动。模型验证
一致性检查:检查模型中的实体和关系是否逻辑一致,无矛盾。
完整性验证:确保模型覆盖了所有业务需求,没有遗漏重要元素。
可行性评估:评估模型的实际可行性,包括技术实现和业务逻辑的适应性。物理存储模型设计
数据库选型和存储方案设计
- 分析系统需求
数据类型:分析需存储的数据类型,如结构化数据、半结构化数据或非结构化数据。
数据量:预估数据量大小及增长趋势。
访问模式:识别数据的访问模式,如读多写少、读写混合等。
并发用户数:评估系统的用户并发访问量。
数据一致性与可用性要求:明确数据一致性和可用性的要求级别。 - 选择合适的数据库类型
关系型数据库:适用于结构化数据和复杂查询。
非关系型数据库:适用于非结构化或半结构化数据,高并发访问,大规模数据存储等场景。
分布式数据库:适合需水平扩展和高可用的场景。 - 评估性能与扩展性
性能测试:基于实际工作负载进行性能测试。
扩展策略:考虑数据库的扩展策略,包括垂直扩展和水平扩展。
分区和分片:根据数据访问模式和分布,设计合理的分区和分片策略。 - 设计存储方案
存储容量规划:根据数据量和增长趋势规划存储容量。
高可用配置:设计数据库的高可用方案,如主从复制、集群等。
备份与恢复:制定数据备份与恢复计划,保障数据安全。
容灾计划:考虑灾难恢复方案,确保在严重故障下的数据安全。 - 经济性考量
成本评估:考虑数据库的总拥有成本,包括许可费、硬件成本、维护费用等。
商业数据库与开源数据库:权衡商业数据库和开源数据库的成本与收益。
常见的数据库类型举例以及它们的特性和适用场景和业界常用产品:
数据库类型 特性 适用场景 业界常用产品 关系型数据库 基于表格,支持SQL语言;强一致性和事务支持 需要复杂查询的业务系统 MySQL, PostgreSQL, Oracle 键值存储数据库 简单的键值对存储;快速读写 缓存系统,计数器应用 Redis, DynamoDB 文档型数据库 存储JSON或BSON格式的文档;模式灵活 内容管理系统,博客平台 MongoDB, Couchbase 列式数据库 数据按列存储;适合大规模数据分析 数据仓库,大数据处理 Cassandra, HBase 图数据库 存储实体及其关系;高效图形查询 社交网络分析,推荐系统 Neo4j, Amazon Neptune 时序数据库 优化时间相关数据的存储;高效的时间序列数据检索 IoT设备监控,实时数据分析 InfluxDB, TimescaleDB 对象存储 存储非结构化数据对象;可扩展性好 云存储,多媒体文件存储 Amazon S3, OpenStack Swift 搜索引擎 专为文本搜索优化;支持全文搜索和实时索引 网站搜索功能,日志分析 Elasticsearch, Solr - 分析系统需求
非功能性设计
性能设计
性能需求分析:明确系统的性能指标,如响应时间、吞吐量等。
性能优化:采用高效的算法和数据结构,优化数据库查询,利用缓存减少I/O操作。
负载均衡:通过负载均衡技术分散请求,提高系统的处理能力。
安全性设计
认证与授权:实现健全的认证机制,如OAuth、JWT等,确保只有授权用户访问资源。
数据加密:对敏感数据进行加密存储和传输,使用HTTPS保护数据传输安全。
安全漏洞防范:定期进行安全漏洞扫描和代码审查,及时修复安全隐患。
可维护性设计
代码规范:遵循编码规范,编写清晰、可读的代码。
文档编写:提供详细的系统文档和API文档,方便后续维护。
日志记录:实现全面的日志记录策略,便于问题追踪和故障排查。
测试与监控设计
全面测试:进行单元测试、集成测试和压力测试,确保系统质量。
性能监控:实时监控系统性能,及时发现并解决性能瓶颈。
错误监控:监控错误和异常,快速响应故障。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。