Java开发经验——阿里巴巴编码规范实践解析10

article/2025/6/15 23:32:51

摘要

这篇文章主要介绍了阿里巴巴Java开发的编码规范实践解析,重点聚焦于系统设计规范。文中强调了存储方案和底层数据结构设计的重要性,指出其需要经过严格评审并形成文档。同时,详细阐述了设计与评审流程,包括设计方案初稿、建模设计文档等阶段,并明确了各阶段的责任人。此外,还列举了多个强制或推荐的系统设计规范,如使用用例图、状态图、时序图等来表达复杂需求和关系,以及在设计阶段遵循单一原则、依赖倒置原则等,旨在提高系统的可扩展性、可维护性和稳定性。

1. 【强制】存储方案和底层数据结构的设计获得评审一致通过,并沉淀成为文档。

说明:有缺陷的底层数据结构容易导致系统风险上升,可扩展性下降,重构成本也会因历史数据迁移和系统平滑过渡而陡然增加,所以,存储方案和数据结构需要认真地进行设计和评审,生产环境提交执行后,需要进行double check。

正例:评审内容包括存储介质选型、表结构设计能否满足技术方案、存取性能和存储空间能否满足业务发展、表或字段之间的辩证关系、字段名称、字段类型、索引等;数据结构变更(如在原有表中新增字段)也需要在评审通过后上线。

1.1. ✅ 为什么这条规范是“强制”

底层数据结构 = 系统地基,其一旦设计有缺陷,会造成:

  • 业务无法扩展(如字段类型限制、字段缺失)
  • 数据一致性问题(字段语义不明、冗余冲突)
  • 性能瓶颈(缺少索引、数据冗余、JOIN 复杂)
  • 重构成本高(历史数据迁移、接口兼容)
  • 影响稳定性(死锁、慢 SQL、磁盘爆)

1.2. ✅ 设计与评审流程(阿里风格)

阶段

说明

责任人

1️⃣ 设计方案初稿

说明存储目的、使用场景、性能要求

开发/架构师

2️⃣ 建模设计文档

绘制 ER 图、字段含义、约束说明

DBA/开发

3️⃣ 评审会议

从技术、业务、DBA 安全、数据治理角度评审

多方参与

4️⃣ 存储评审记录沉淀

存储方案、字段设计、表结构截图、SQL DDL

固化到 Confluence/语雀/Notion

5️⃣ 提交生产前二次确认

与 DBA double-check,避免漏审

开发 + DBA

1.3. ✅ 评审内容 Checklist(推荐模板)

项目

检查内容

说明

存储介质

MySQL、Redis、Mongo、ElasticSearch 等是否合适

选型必须合理

表结构设计

是否满足数据模型完整性,字段含义是否清晰

主键、唯一约束

字段类型选择

是否存在 varchar(255) 滥用、json 字段可解析性

禁用 magic 字段

字段命名规范

是否命名清晰、无拼音、无多义性

推荐采用驼峰/下划线统一规范

主键策略

是否使用雪花 ID、自增主键、联合主键是否合理

确保唯一性与查询效率

索引设计

查询字段是否有合适索引、是否避免冗余索引

联合索引顺序是否合理

表之间关系

是否存在重复字段、数据冗余,是否有依赖风险

冗余字段必须有合理理由

预估数据量

单表数据量是否超过 1千万,是否考虑分库分表

否则可能出现热点写入

可扩展性

新增字段、修改字段是否平滑、可兼容

老系统兼容性必须考虑

1.4. ✅ 变更操作的规范化流程

即便是新增字段、修改字段类型、增加索引,也必须:

  1. 提交 DDL 审批 → 通常通过 DBA 系统(如阿里内的 DMS)执行审批流程
  2. 压测验证性能变化 → 对比加索引前后 SQL 性能差异
  3. 灰度执行变更 → 小流量先试运行观察是否有风险
  4. 记录到系统字典或元数据平台 → 如阿里 DataMap、字节 DataLeap 等平台
  5. 文档沉淀 → 必须将变更记录同步到团队文档平台

1.5. ✅ 文档沉淀示例模板(可用语雀/Confluence)

1.5.1. 存储结构设计评审文档:用户支付流水表 pay_transaction

1.5.1.1. 背景说明

当前系统对支付记录存储性能不足,需重新建表支持百万级交易并发写入。

1.5.1.2. 表结构设计
  • 表名:pay_transaction
  • 主键:id(雪花算法)
  • 业务主键:transaction_id(唯一索引)
  • 字段列表:

字段名

类型

含义

索引

id

bigint

主键

主键

user_id

bigint

用户ID

amount

decimal(18,2)

支付金额

status

varchar(16)

支付状态

pay_time

datetime

支付时间

1.5.1.3. 索引设计
  • 唯一索引:transaction_id
  • 普通索引:user_id、pay_time
1.5.1.4. 预估数据量
  • 每日 500 万笔,月数据量约 1.5 亿,需归档策略
1.5.1.5. 变更风险评估
  • 数据写入高并发,需配合数据库写入限速、按用户 ID 分表
1.5.1.6. 评审通过人员
  • 业务负责人:xxx
  • DBA:xxx
  • 架构师:xxx

1.6. ✅ Double Check 操作建议

  • 所有 SQL 上生产前,必须由 DBA 二次确认是否安全、是否会锁表
  • 使用专门的 SQL 审批平台(如阿里 DMS)强制执行自动审核和人工确认
  • 操作前强制备份或启用闪回机制,保障可回滚

1.7. ✅ 总结:这条规范背后的核心思想

核心价值

具体体现

降低系统风险

杜绝隐性缺陷数据结构上线

提高可扩展性

提前考虑字段兼容和变更成本

强化团队协作

建立规范化评审流程与文档沉淀

加强运维安全

有审计、有追踪、有审批

2. 【强制】在需求分析阶段,如果与系统交互的User超过一类并且相关的 UseCase 超过 5 个,使用用例图来表达更加清晰的结构化需求。

3. 【强制】如果某个业务对象的状态超过 3 个,使用状态图来表达并且明确状态变化的各个触发条件。

说明:状态图的核心是对象状态,首先明确对象有多少种状态,然后明确两两状态之间是否存在直接转换关系,再明确触发状态转换的条件是什么。

正例:淘宝订单状态有已下单、待付款、已付款、待发货、已发货、已收货等。比如已下单与已收货这两种状态之间是不可能有直接转换关系的。

3.1. ✅ 为什么必须使用状态图?

  • 避免混乱:状态超过 3 个时,如果仅靠代码或文档描述,容易遗漏边界情况,或出现非法状态跳转。
  • 增强可维护性:未来开发者查看状态图能立刻理解业务流程,避免重复造轮子或误解状态定义。
  • 辅助编码/建模:状态图可以指导状态机实现,例如用 Spring Statemachine、Squirrel、状态枚举类等。

3.2. 🧩 状态图设计要素

  1. 状态集合(State):列出该对象的所有可能状态
  2. 事件/条件(Trigger/Event):触发状态变化的外部操作或系统事件
  3. 状态转移(Transition):从哪个状态可转到哪个状态,并标明触发条件
  4. 非法路径禁止跳转:列明哪些状态间禁止直接跳转

3.3. 📘 示例:贷款审批单状态图设计

3.3.1. 状态定义

状态编码

状态名称

说明

INIT

初始化

用户刚提交申请

AUDIT

审核中

系统或人工审核

APPROVED

审批通过

信审通过,进入放款准备

REJECTED

审批拒绝

信审未通过

LOANING

放款中

通知渠道放款

LOANED

已放款

成功打款到账

CLOSED

已关闭

终态,非正常关闭或完成关闭

3.3.2. 状态转移图(文字描述)

[INIT] --提交申请--> [AUDIT]
[AUDIT] --审核通过--> [APPROVED]
[AUDIT] --审核拒绝--> [REJECTED]
[APPROVED] --调用放款渠道--> [LOANING]
[LOANING] --放款成功--> [LOANED]
[任意状态] --用户取消/异常--> [CLOSED]

❌ 错误示例:INIT 不能直接跳转到 LOANED,即“未经审核放款”是不合法流程。

3.4. ✅ 应用建议(阿里/大厂最佳实践)

场景

是否建议使用状态图

建议工具

支付/订单/贷款流转

✅ 强制使用

ProcessOn

、PlantUML、draw.io

简单任务(2 状态以内)

❌ 可选

-

多人协同审批流

✅ 必须

BPMN+状态图

状态绑定数据库字段

✅ 推荐配合 enum 管理

Java Enum + 状态机框架

3.5. 🛠 补充:代码层的状态建模建议

public enum LoanStatus {INIT, AUDIT, APPROVED, REJECTED, LOANING, LOANED, CLOSED;public boolean canTransitionTo(LoanStatus next) {switch (this) {case INIT: return next == AUDIT;case AUDIT: return next == APPROVED || next == REJECTED;case APPROVED: return next == LOANING;case LOANING: return next == LOANED;default: return false;}}
}

4. 【强制】如果系统中某个功能的调用链路上的涉及对象超过3个,使用时序图来表达并且明确各调用环节的输入与输出。

说明:时序图反映了一系列对象间的交互与协作关系,清晰立体地反映系统的调用纵深链路。

5. 【强制】如果系统中模型类超过 5 个,且存在复杂的依赖关系,使用类图来表达并且明确类之间的关系。

说明:类图像建筑领域的施工图,如果搭平房,可能不需要,但如果建造蚂蚁 Z 空间大楼,肯定需要详细的施工图。

6. 【强制】如果系统中超过 2 个对象之间存在协作关系,并需要表示复杂的处理流程,使用活动图来表示。

说明:活动图是流程图的扩展,增加了能够体现协作关系的对象泳道,支持表示并发等。

7. 【强制】系统设计时要准确识别出弱依赖,并针对性地设计降级和应急预案,保证核心系统正常可用。

说明:系统依赖的第三方服务被降级或屏蔽后,依然不会影响主干流程继续进行,仅影响信息展示、或消息通知等非关键功能,那么这些服务称为弱依赖。

正例:当系统弱依赖于多个外部服务时,如果下游服务耗时过长,则会严重影响当前调用者,必须采取相应降级措施,比如,当调用链路中某个下游服务调用的平均响应时间或错误率超过阈值时,系统自动进行降级或熔断操作,屏蔽弱依赖负面影响,保护当前系统主干功能可用。

反例:某个疫情相关的二维码出错:“服务器开了点小差,请稍后重试”,不可用时长持续很久,引起社会高度关注,原因可能为调用的外部依赖服务 RT 过高而导致系统假死,而在显示端没有做降级预案,只能直接抛错给用户。

8. 【推荐】系统架构设计时明确以下目标:

  1. 确定系统边界。 确定系统在技术层面上的做与不做。
  2. 确定系统内模块之间的关系。确定模块之间的依赖关系及模块的宏观输入与输出。
  3. 确定指导后续设计与演化的原则。 使后续的子系统或模块设计在一个既定的框架内和技术方向上继续演化。
  4. 确定非功能性需求。非功能性需求是指安全性、可用性、可扩展性等。

9. 【推荐】需求分析与系统设计在考虑主干功能的同时,需要充分评估异常流程与业务边界。

10. 【推荐】类在设计与实现时要符合单一原则。

说明:单一原则最易理解却是最难实现的一条规则,随着系统演进,很多时候,忘记了类设计的初衷。

11. 【推荐】谨慎使用继承的方式来进行扩展,优先使用聚合/组合的方式来实现。

说明:不得已使用继承的话,必须符合里氏代换原则,此原则说父类能够出现的地方子类一定能够出现,比如,

钱交出来”,钱的子类美元、欧元、人民币等都可以出现。

继承(extends)意味着强耦合,子类会绑定父类结构,继承的是“实现”,不是“行为契约”。组合(Composition)/聚合(Aggregation)则更灵活,运行时替换,解耦能力更强。

11.1. 🎓 对比继承和组合

对比项

继承(extends)

组合(has-a)

耦合度

高耦合

低耦合

灵活性

编译时静态绑定

运行时动态替换

可扩展性

继承层级深易崩

容易插拔新功能

可维护性

改父类影响子类

独立模块互不干扰

设计模式支持

模板方法等

策略、桥接、装饰等

11.2. ✅ 正确使用继承的前提:满足里氏代换原则(LSP)

子类对象必须能完全替代父类对象运行

11.2.1. ✅ 正例(满足 LSP):

public class Money {public BigDecimal getAmount() { ... }
}public class Dollar extends Money {// 合理拓展,不破坏父类行为
}

11.2.2. ❌ 反例(不满足 LSP):

public class Bird {public void fly() { ... }
}public class Ostrich extends Bird {@Overridepublic void fly() {throw new UnsupportedOperationException("不会飞");}
}
  • Bird 本意代表会飞的鸟,Ostrich 不满足这一契约,破坏里氏代换原则

11.3. ✅ 推荐用组合重构的场景

11.3.1. ❌ 不推荐:

public class EmailOrderService extends OrderService {// 为了发邮件继承整个 OrderService,不合理
}

11.3.2. ✅ 推荐组合方式:

public class EmailOrderService {private final OrderService orderService;public void sendOrderWithEmail(Order order) {orderService.process(order);emailSender.send(order);}
}
  • EmailOrderService 拥有 OrderService,而不是继承它
  • 更清晰职责分离、可单测、可替换

11.4. 🏢 阿里/大厂的最佳实践

原则

做法

✅ 封装变化

用组合 + 策略/委托代替继承

✅ 保持职责单一

每个类组合具体职责组件

✅ 控制继承层级

不超过 2 层,超过就考虑组合

✅ 组合优先

实体类组合属性、服务类组合依赖,灵活解耦

11.5. 📌 总结:设计建议

建议

说明

🚫 不为“代码复用”而继承

复用实现应该通过组合或工具类完成

✅ 父类设计要抽象

继承应该是“is-a”关系,而非“use-a”

✅ 多用接口 + 实现类

接口聚合行为,避免具体实现污染继承体系

✅ 必须继承时,校验里氏代换原则

保证子类不会破坏父类行为语义

12. 【推荐】系统设计阶段,根据依赖倒置原则,尽量依赖抽象类与接口,有利于扩展与维护。

说明:低层次模块依赖于高层次模块的抽象,方便系统间的解耦。

13. 【推荐】系统设计阶段,注意对扩展开放,对修改闭合。

说明:极端情况下,交付的代码是不可修改的,同一业务域内的需求变化,通过模块或类的扩展来实现。

一个软件实体(类、模块、函数)应该对扩展开放,对修改关闭。

  • 对扩展开放:允许通过添加新代码(而非修改原代码)来增强系统功能。
  • 对修改关闭:已有的代码是“交付件”,应避免修改,以免引发未知问题。

13.1. 📌 为什么在“极端情况下”原代码不可修改?

  1. 原始代码已上线,改动风险大。
  2. 多团队协作,原模块由其他组维护。
  3. 代码已沉淀为框架/SDK,版本不可频繁迭代。
  4. 有审计和合规要求,不允许轻易更改。

13.2. ✅ 实现 OCP 的常见手段

手段

说明

示例

接口 + 实现类

抽象行为,通过实现类扩展

PaymentService接口 + 多种支付实现

策略模式

对行为进行抽象,每种策略独立实现

评分规则、风控策略

模板方法模式

抽象主流程 + 提供钩子扩展点

审批流中“审批通过”自定义逻辑

SPI 插件机制

服务发现方式动态加载实现类

Dubbo / Java SPI / Spring Factories

配置驱动

通过配置文件组合行为

新增字段类型 / 页面模块无需改代码

扩展点注册

自定义扩展注册机制

Map<String, Handler>实现动态路由

13.3. ✅ 示例:订单通知模块的开放封闭实现

❌ 反例:逻辑硬编码在类里

public class NotifyService {public void send(Order order) {if ("EMAIL".equals(order.getChannel())) {// 发送邮件} else if ("SMS".equals(order.getChannel())) {// 发送短信} else if ("PUSH".equals(order.getChannel())) {// 发送推送}}
}
  • 新增渠道就要改原类,违反 OCP。

✅ 正例:基于接口 + 策略模式实现

public interface NotifyHandler {boolean supports(String channel);void send(Order order);
}
@Component
public class EmailNotifyHandler implements NotifyHandler {public boolean supports(String channel) { return "EMAIL".equals(channel); }public void send(Order order) { ... }
}
@Service
public class NotifyService {@Autowiredprivate List<NotifyHandler> handlers;public void send(Order order) {handlers.stream().filter(h -> h.supports(order.getChannel())).findFirst().orElseThrow().send(order);}
}
  • 新增渠道只需实现新的 NotifyHandler,无需修改原有类,完全符合 OCP。

13.4. 🏗️ 在阿里等大厂项目中的 OCP 实践

领域

变化点隔离方式

风控系统

策略引擎 + 动态脚本 + SPI

支付系统

通道工厂 + 策略模式

工作流引擎

状态机 + 可插拔节点

规则系统

配置驱动 + Groovy 执行

营销系统

不同活动通过扩展类加载规则模块

中台架构

各业务线通过接口 + 插件组合复用基础模块

14. 【推荐】系统设计阶段,共性业务或公共行为抽取出来公共模块、公共配置、公共类、公共方法等,在

系统中不出现重复代码的情况,即RY原则(Don't Repeat Yourself)。

说明: 随着代码的重复次数不断增加, 维护成本指数级上升。 随意复制和粘贴代码, 必然会导致代码的重复, 在维护代码时,需要修改所有的副本,容易遗漏。必要时抽取共性方法,或者抽象公共类,甚至是组件化。

正例:一个类中有多个 public 方法,都需要进行数行相同的参数校验操作,这个时候请抽取:

private boolean checkParam(DTO dto) {...}

14.1. ✅ 为什么必须遵守 RY 原则?

  • 可维护性提升:只需修改一处即可完成所有修改,避免遗漏
  • 代码一致性增强:逻辑重复必然导致不一致,容易产生“伪 bug”
  • 代码体积变小:冗余逻辑抽象后,文件变短,易于阅读

14.2. 🔧 典型的共性代码抽取方式(实战)

类型

示例说明

抽取方式

参数校验

多个 Controller 方法都验证手机号格式

封装为 ParamValidatorUtil工具类

接口日志打印

多个 Service 方法都打 request/response 日志

使用 AOP 实现统一切面拦截

异常处理逻辑

try-catch 模板重复,处理 DB 异常

提炼为 ExceptionHandler模块

Bean 拷贝逻辑

DTO 与 Entity 频繁互转

使用 MapStruct 或 BeanCopyUtil

缓存设置逻辑

多个地方 Redis 缓存结构、key 组成逻辑重复

提取为 CacheKeyBuilder工具类

时间范围检查

多个方法中都校验开始时间小于结束时间

封装为 TimeRangeChecker.check(...)

14.3. 📘 重复参数校验抽取

14.3.1. ❌ 不推荐写法(重复)

public void createUser(UserDTO dto) {
if (dto.getPhone() == null || !dto.getPhone().matches("^1[3-9]\\d{9}$")) {throw new IllegalArgumentException("手机号格式错误");
}...
}
public void updateUser(UserDTO dto) {
if (dto.getPhone() == null || !dto.getPhone().matches("^1[3-9]\\d{9}$")) {throw new IllegalArgumentException("手机号格式错误");
}...
}

14.3.2. ✅ 推荐写法(抽取公共方法)

public void createUser(UserDTO dto) {ParamChecker.checkPhone(dto.getPhone());...
}
public void updateUser(UserDTO dto) {ParamChecker.checkPhone(dto.getPhone());...
}public class ParamChecker {public static void checkPhone(String phone) {if (phone == null || !phone.matches("^1[3-9]\\d{9}$")) {throw new IllegalArgumentException("手机号格式错误");}}
}

14.4. 📦 阿里推荐的公共模块分层结构(组件化建议)

common/├── common-util        // 通用工具类(校验、转换、加解密、UUID、Json)├── common-model       // 通用模型(DTO、VO、Enum)├── common-exception   // 通用异常体系(业务码、封装类)├── common-aop         // 通用切面(日志、权限、幂等等)├── common-config      // 通用配置(Spring Bean、拦截器、过滤器)└── common-constant    // 通用常量(字符串、正则表达式、header key 等)

✅ 推荐:将这些模块统一打包成 jar 供多个子项目依赖(如基于 Maven 构建 common-lib

14.5. 🧠 实战建议(如何发现重复)

方法

描述

代码审查(Code Review)

他人更容易发现你的重复逻辑

静态代码扫描(SonarQube)

可识别出逻辑重复、代码克隆等问题

抽象思维训练

自问:“这个逻辑未来会改几次?是否会被别人再写一次?”

模板提取(代码模板工具)

IntelliJ Live Template 可用于统一固定逻辑

14.6. ✅ RY 原则背后的思考路径

抽取复用 = 抽象 + 封装 + 解耦 + 模块边界控制

每当你看到:

  • 多个类中拷贝粘贴一样的逻辑
  • 同样的异常处理逻辑写了两遍
  • 相同的表达式或字段匹配出现多处
    就该提醒自己:“是不是违反了 RY 原则?” —— 并考虑是否值得提炼为公共组件或工具方法。

15. 【推荐】避免如下误解:敏捷开发=讲故事+编码+发布。

说明:敏捷开发是快速交付迭代可用的系统,省略多余的设计方案,摒弃传统的审批流程,但核心关键点上的必要设计和文档沉淀是需要的。

反例:某团队为了业务快速发展,敏捷成了产品经理催进度的借口,系统中均是勉强能运行但像面条一样的代码,可维护性和可扩展性极差,一年之后,不得不进行大规模重构,得不偿失。

16. 【参考】设计文档的作用是明确需求、理顺逻辑、后期维护, 次要目的用于指导编码。

说明:避免为了设计而设计,系统设计文档有助于后期的系统维护和重构,所以设计结果需要进行分类归档保存。

17. 【参考】可扩展性的本质是找到系统的变化点,并隔离变化点。

说明:世间众多设计模式其实就是一种设计模式即隔离变化点的模式。

正例:极致扩展性的标志,就是需求的新增,不会在原有代码交付物上进行任何形式的修改。

“可扩展性的本质是找到系统的变化点,并隔离变化点。”是架构设计中的核心原则,也是几乎所有设计模式、微服务、插件式架构、DDD、可插拔引擎等背后的思想根源。它帮助我们实现开放封闭原则(OCP):对扩展开放、对修改关闭。

17.1. ✅ 什么是“变化点”?

在系统中,变化点指的是:

类型

示例

业务逻辑经常变化

风控策略、营销活动、价格计算

接口协议经常变化

第三方支付、外部供应商 API

配置项经常变化

参数化控制、限额、开关等

调用链可能变动

多渠道、不同方式的分发逻辑

扩展类目

新增商品类型、新业务模块

实现可能差异化

不同银行、不同租户,不同国家逻辑

17.2. 📘 如何通过“隔离变化点”实现极致扩展?

17.2.1. 🎯 场景:订单处理流程的扩展设计

❌ 不推荐做法(紧耦合)

public class OrderService {public void processOrder(Order order) {if ("PHYSICAL".equals(order.getType())) {// 实体商品处理} else if ("DIGITAL".equals(order.getType())) {// 虚拟商品处理} else if ("COUPON".equals(order.getType())) {// 优惠券订单}}
}

新增一种订单类型,就必须改动原有代码

✅ 推荐做法(策略模式 + SPI 插件隔离)

public interface OrderHandler {boolean support(Order order);void handle(Order order);
}
@Component
public class PhysicalOrderHandler implements OrderHandler {public boolean support(Order order) {return "PHYSICAL".equals(order.getType());}public void handle(Order order) {// 处理实体商品}
}
@Service
public class OrderService {@Autowiredprivate List<OrderHandler> handlers;public void processOrder(Order order) {handlers.stream().filter(h -> h.support(order)).findFirst().orElseThrow(() -> new IllegalStateException("不支持的订单类型")).handle(order);}
}

➡️ 特点: 新增订单类型,只需实现一个新的 OrderHandler,无需修改原有代码。

17.3. 💡 变化点隔离的常用设计模式

设计模式

用途

场景举例

策略模式

行为切换点(多种方式实现)

支付方式、评分规则、风控策略

工厂模式

产品创建点(创建不同类型的类)

消息对象生成、渠道工厂

责任链模式

多步骤链式执行

请求处理链、过滤器链

模板方法

不变主流程 + 可变子流程

统一执行逻辑下的自定义点

观察者模式

变化后通知多个下游

事件分发、埋点系统

装饰器模式

功能增强点

日志增强、权限增强

状态模式

对象状态变化的隔离

审批流、订单状态管理

17.4. 🏗️ 阿里大厂项目中如何隔离变化点(工程实践)

模块

常用做法

规则引擎

使用 Groovy / SpEL / 脚本引擎加载外部规则

风控策略

每一类策略使用 SPI 扩展点,动态加载

多渠道推送

使用策略 + 工厂模式管理短信/邮件/站内信等

多租户

使用插件化结构(如 Filter/Handler 插件包)

产品配置

使用 JSON 配置动态驱动功能组合

工作流流程

状态机引擎(如 Spring StateMachine)

17.5. ✅ 极致扩展性的目标是什么?

新增需求无需改动原有类/方法,仅需新增“可插拔组件”。这背后就是在设计阶段准确识别“未来会变”的点,并通过模块化、接口化、组件化将这些点隔离出来

18. 【参考】设计的本质就是识别和表达系统难点。

说明:识别和表达完全是两回事,很多人错误地认为识别到系统难点在哪里,表达只是自然而然的事情,但是大家在设计评审中经常出现语焉不详,甚至是词不达意的情况。准确地表达系统难点需要具备如下能力:表达规则和表达工具的熟练性。抽象思维和总结能力的局限性。基础知识体系的完备性。深入浅出的生动表达力。

19. 【参考】代码即文档的观点是错误的,清晰的代码只是文档的某个片断,而不是全部。

说明:代码的深度调用,模块层面上的依赖关系网,业务场景逻辑,非功能性需求等问题要相应的文档来完整地呈现。

20. 【参考】在做无障碍产品设计时,需要考虑到:

  1. 所有可交互的控件元素必须能被 tab 键聚焦, 并且焦点顺序需符合自然操作逻辑。
  2. 用于登录校验和请求拦截的验证码均需提供图形验证以外的其它方式。
  3. 自定义的控件类型需明确交互方式。

正例:登录场景中,输入框的按钮都需要考虑 tab 键聚焦,符合自然逻辑的操作顺序如下,

"输入用户名,输入密码,输入验证码,点击登录",其中验证码实现语音验证方式。如有自定义标签实现的控件设置控件类型可使用 role 属性。

博文参考

《阿里巴巴java规范》


http://www.hkcw.cn/article/VIOPcrsetD.shtml

相关文章

AutoML详解:自动化机器学习的未来

AutoML详解&#xff1a;自动化机器学习的未来 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 AutoML详解&#xff1a;自动化机器学习的未来摘要引言技术架构对比1. 核心组件&#xff1a;从算法到工作流2. 算法实现…

(8)-Fiddler抓包-Fiddler如何设置捕获会话

1.简介 在前面我们介绍了Fiddler界面内容以及作用。那么我们接下来讲解和分享如何设置Fiddler后&#xff0c;我们就可以捕获会话&#xff0c;进行抓包了。 2.捕获会话的设备 常见的捕获会话的设备分为PC&#xff08;电脑&#xff09;端和手机&#xff08;Android和IOS苹果&am…

虚拟DOM和DOM是什么?有什么区别?虚拟DOM的优点是什么?

虚拟DOM与真实DOM的概念 虚拟DOM&#xff08;Virtual DOM&#xff09;是一种对真实DOM的抽象表示&#xff0c;其结构通常为一个JavaScript对象&#xff0c;保存了DOM节点的标签、属性、子节点等信息。真实DOM则是浏览器中的实际文档对象模型&#xff0c;由HTML代码解析生成&am…

电赛TIMSPM0G3507 CCS环境安装在D盘的方法

前言 安装TI的环境内存占用还是比较大的&#xff0c;但是大家默认安装到C盘&#xff0c;本篇就教大家从0到一安装到D盘 先把3个要下载的下载了 1.安装SDK 登录LP-MSPM0G3507 评估板 | TI.com.cn这个网站 选择Windows的下载 2.下载图形配置软件 登录SYSCONFIG IDE、配置、编译器…

电力高空作业安全检测(3)RT-DETR模型

背景与挑战 YOLO 系列模型长期以来在实时目标检测领域占据主导地位&#xff0c;因其在速度与精度之间取得了良好的平衡。然而&#xff0c;这些模型在处理多尺度特征时&#xff0c;往往依赖于非极大值抑制&#xff08;NMS&#xff09;后处理步骤&#xff0c;这不仅增加了计算…

项目架构初始化,底部导航页面切换

引言 在移动端应用开发中&#xff0c;底部导航栏是一种常见的用户界面元素&#xff0c;用于在不同的页面之间进行快速切换。本文将介绍如何初始化一个 Vue.js 项目&#xff0c;并实现底部导航栏页面切换的功能。 &#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &…

51c大模型~合集133

我自己的原文哦~ https://blog.51cto.com/whaosoft/13948969 #用Veo 3Suno做了个AI Rapper 吊打音乐节上的流量明星 太疯狂了&#xff01;AI生成的嘻哈歌手唱Rap以假乱真&#xff0c;网友直呼「看不出破绽」。 来来来&#xff0c;眼尖的朋友请告诉我&#xff0c;下面这个…

俄称控制定居点 乌称打击俄纵深目标 双方战事持续升级

俄罗斯国防部5月31日发布战报称,俄军控制了苏梅州沃多拉哈和顿涅茨克地区诺沃波利居民点。在过去24小时内,俄军在苏梅、哈尔科夫、顿涅茨克、扎波罗热、赫尔松等方向打退乌军多次进攻并发动多次攻势。乌克兰武装部队总司令瑟尔斯基同一天表示,乌军在5月使用远程精确武器打击…

机器学习知识图谱——K-means++聚类算法

目录 一、图解K-means++ 聚类算法知识图谱 二、K-means 是什么? 三、K-means++ 是什么? 四、K-means++ 算法流程 第一步:选择初始质心(核心改进) 第二步:执行 K-means 正式流程 五、算法图示 六、优点 vs 缺点 七、常用场景 八、Python 代码示例 (使用 sklear…

Java SE 2.数据类型与变量

Java是一门强类型语言&#xff0c;数据类型和变量是构建程序的基石。理解数据类型的选择和变量的定义方式&#xff0c;直接影响代码的性能和可读性。就一句话&#xff1a;数据类型和变量很重要&#xff01; 1. 字面常量 我们刚接触Java时&#xff0c;曾写过一个简单的程序&am…

数据结构-算法学习C++(入门)

目录 03二进制和位运算04 选择、冒泡、插入排序05 对数器06 二分搜索07 时间复杂度和空间复杂度08 算法和数据结构09 单双链表09.1单双链表及反转09.2合并链表09.2两数相加09.2分隔链表 013队列、栈、环形队列013.1队列013.2栈013.3循环队列 014栈-队列的相互转换014.1用栈实现…

【前端】SPA v.s. MPA

链接&#xff1a;页面结构 误区 页面结构管理有两种常见方式&#xff1a;路由形式 和 组件形式。路由形式 对应MPA &#xff0c;组件形式对应SPA ❌ 误区 1&#xff1a;路由形式 MPA❌ 路由是 SPA 和 MPA 共有的概念&#xff0c;区别在于路由映射的对象&#xff1a; MPA 的…

国米0-5创欧冠决赛最大分差 巴黎青春风暴横扫夺冠

在安联球场举行的欧冠决赛中,巴黎圣日耳曼以5比0横扫国际米兰,创造了欧冠决赛历史上的最大分差纪录。此前欧冠决赛的最大分差为四球,最近一次是1993-1994赛季AC米兰对巴萨的4比0。恩里克带领下的巴黎圣日耳曼首次赢得欧冠冠军,他们的表现令人震惊。比赛开始后不久,巴黎便迅…

樊振东加盟德甲 俱乐部披露幕后 签约过程震撼乒坛

FC萨尔布吕肯俱乐部宣布,奥运冠军樊振东将加盟球队。当樊振东在社交媒体上发布观看欧冠的照片时,另一条消息也震惊了乒乓球圈:他将在新赛季代表萨尔布吕肯出战德国乒乓球甲级联赛(TTBL)。俱乐部官方公告中提到,前世界排名第一的樊振东将在新赛季为萨尔布吕肯效力。这位28…

Yunxi期中

Misc 谍影重重plus&#xff08;misc&#xff09; 随波逐流修复伪加密 零宽字符解密&#xff0c;&#xff1f;&#xff1f;&#xff1f;需要爆破 import itertools import stringdef generate_symmetric_passwords():# 扩展字符集&#xff1a;大小写字母 数字 符号chars st…

2024年ESWA SCI1区TOP,自适应学习灰狼算法ALGWO+无线传感器网络覆盖优化,深度解析+性能实测

目录 1.端午快乐2.摘要3.灰狼算法GWO原理4.改进策略5.结果展示6.参考文献7.代码获取8.读者交流 1.端午快乐 今天端午节&#xff0c;祝各位朋友端午安康&#xff0c;阖家平安&#xff01; 2.摘要 无线传感器网络&#xff08;WSNs&#xff09;是一种被广泛应用的新兴技术&…

YOLOv8 移动端升级:借助 GhostNetv2 主干网络,实现高效特征提取

文章目录 引言GhostNetv2概述GhostNet回顾GhostNetv2创新 YOLOv8主干网络改进原YOLOv8主干分析GhostNetv2主干替换方案整体架构设计关键模块实现 完整主干网络实现YOLOv8集成与训练模型集成训练技巧 性能对比与分析计算复杂度对比优势分析 部署优化建议结论与展望 引言 目标检…

【Oracle】TCL语言

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. TCL概述1.1 什么是TCL&#xff1f;1.2 TCL的核心功能 2. 事务基础概念2.1 事务的ACID特性2.2 事务的生命周期 3. COMMIT语句详解3.1 COMMIT基础语法3.2 自动提交与手动提交3.3 提交性能优化 4. ROLLBACK语句…

设计模式——单例设计模式(创建型)

摘要 本文详细介绍了单例设计模式&#xff0c;包括其定义、结构、实现方法及适用场景。单例模式是一种创建型设计模式&#xff0c;确保一个类只有一个实例并提供全局访问点。其要点包括唯一性、私有构造函数、全局访问点和线程安全。文章还展示了单例设计模式的类图和时序图&a…

STM32F103C8T6,bxCAN收发配置实例,包含ID过滤

文章目录 引言bxCAN简介bxCAN主要特点代码示例引言 bxCAN简介 bxCAN是基本扩展CAN(Basic Extended CAN)的缩写,它支持CAN协议2.0A和2.0B。它的设计目标是,以最小的CPU负荷来高效处理大量收到的报文。它也支持报文发送的优先级要求(优先级特性可软件配置)。 对于安全紧要的应…