编程经验
能新增不修改功能。
一个表中关联其他表,尽量包含其他主要字段。比如用id关联了一个用户表,尽量把表里的用户名也关联了这样可以减少不必要的查询请求。
两个系统对接谁给谁出接口,谁对接,其实没有固定模式。如果一个出了接口文档,另一方就要重新写代码去对接,无形中增加了他的工作量。
表的设计有两种一个是有基础数据,其余有基础数据生成。还有一个简单的方法,一个功能一个表,表之间没有绝对的关系
生成库表,生成mvc的crud,编写特有的业务逻辑,然后ui的crud。或者sql一键生成所有代码。
提示中要描述参考的代码或图片,使用什么技术比如mybatisplus,restful api
不管是表还是接口还是ui命名都应该按照功能区分,sql的命名是 A_B.sql,java的命名是 AxxBxx.java,前端的命名是 AxxBxx.vue
让ai完成一个功能后在完成下一个功能,千万不要一次完成所有功能。简单的功能可以一次提交。
问的越多ai越聪明。
如果一个问题非常复杂就分解为小问题一个一个解决
如果有多个文件被修改,只要指定的修改,那么确定你想确定的,其余都拒绝修改即可
能在sql层面完成的东西就不再java中完成,这样后台代码业务逻辑清晰。
数据库必须有的字段,创建时间,更新时间,创建者,权限字段(比如 部门id,区域id)
好的,你已经总结了几条非常有价值的编程经验。这些经验体现了在软件开发中对可维护性、效率和协作的关注。让我们来完善和扩展这些经验,并加入更多业界认可的最佳实践。
核心原则与设计模式
-
开闭原则 (Open/Closed Principle - OCP) - 对扩展开放,对修改关闭
-
你的观点: "能新增不修改功能。"
-
完善: 这是SOLID原则中的"O"。核心思想是,当需要添加新功能时,应该通过增加新代码(如新的类、方法、模块)来实现,而不是修改经过测试的、稳定的现有代码。这降低了引入新错误的风险。
-
技术示例:
-
策略模式 (Strategy Pattern): 将不同的算法或行为封装在独立的策略类中。当需要新行为时,添加新的策略类,而不是修改使用策略的上下文类。
-
模板方法模式 (Template Method Pattern): 定义一个操作中的算法骨架,而将一些步骤延迟到子类中。子类可以重定义算法的某些特定步骤而不改变算法的结构。
-
插件化/模块化架构: 系统设计成允许加载外部模块或插件来扩展功能。
-
-
参考:
-
代码: 使用接口和实现类来演示策略模式。
-
图片: 可以用UML类图展示策略模式或模板方法模式的结构。
-
-
-
单一职责原则 (Single Responsibility Principle - SRP)
-
新增: 一个类或模块应该只有一个引起它变化的原因。换句话 P 化说,它应该只负责一项明确的职责。
-
重要性: 提高内聚性,降低耦合度,使代码更容易理解和维护。当需求变更时,只会影响到负责该职责的模块。
-
技术示例: 在 Spring Boot 应用中,通常分为 Controller (处理HTTP请求),Service (处理业务逻辑),Repository/DAO (处理数据访问),每个层级承担不同的职责。
-
参考:
-
代码: 展示一个职责清晰的 Service 类,它只处理特定的业务逻辑,而不涉及HTTP或数据库细节。
-
-
-
接口隔离原则 (Interface Segregation Principle - ISP)
-
新增: 客户端不应该被迫依赖它不使用的方法。应该使用多个专门的接口,而不是一个庞大的通用接口。
-
重要性: 避免接口臃肿,减少客户端不必要的依赖,提高灵活性。
-
技术示例: 设计API时,可以根据不同的使用场景提供不同的 RESTful API 端点或 GraphQL 查询,而不是一个包含所有可能字段的巨大端点。
-
参考:
-
代码: 展示两个独立的 Java 接口 (OrderReader, OrderWriter) 比一个包含所有读写方法的 OrderManager 接口更好。
-
-
-
依赖倒置原则 (Dependency Inversion Principle - DIP)
-
新增: 高层模块不应该依赖低层模块,两者都应该依赖抽象(例如接口)。抽象不应该依赖细节,细节应该依赖抽象。
-
重要性: 解耦,提高代码的可测试性和灵活性。使得替换底层实现(如数据库、第三方服务)变得容易。
-
技术示例: Spring Framework 的依赖注入 (DI) 就是DIP的典型应用。Service 层依赖 Repository 的接口,而不是具体的实现类。Spring 容器负责将具体的实现注入进来。
-
参考:
-
代码: 展示一个 Service 类通过构造函数注入一个 Repository 接口。
-
图片: UML 图展示高层模块、低层模块和抽象接口之间的依赖关系。
-
-
数据库设计与交互
-
适当的冗余与反范式设计 (Denormalization for Performance)
-
你的观点: "一个表中关联其他表,尽量包含其他主要字段...减少不必要的查询请求。"
-
完善: 这是一种常见的性能优化手段,称为“反范式设计”或“数据冗余”。通过在常用查询的表中直接存储关联表的常用字段(如用户名、订单状态名),可以避免频繁的 JOIN 操作,提高查询速度。
-
重要性: 显著提升读取性能,尤其是在高并发场景下。
-
权衡:
-
优点: 查询快,减少关联。
-
缺点: 数据冗余,存在数据不一致的风险(如果源数据更新,冗余数据可能未同步更新),增加了写入/更新操作的复杂性。需要有机制(如数据库触发器、定时任务、消息队列)来维护数据一致性。
-
-
技术示例:
-
MyBatisPlus: 可以在实体类中定义非数据库表字段(使用 @TableField(exist = false)),然后在 Mapper XML 或使用 @Select 注解编写包含 JOIN 的自定义 SQL 语句,一次性查出包括冗余字段在内的所有需要的数据。
-
数据库视图 (View): 可以在数据库层面创建一个视图来封装 JOIN 操作,应用层直接查询视图。
-
-
参考:
-
代码: MyBatisPlus 实体类和 Mapper XML 中包含 JOIN 查询的示例。
-
图片: ER 图展示范式化设计和反范式化设计的对比。
-
-
-
避免 N+1 查询问题 (Avoid N+1 Query Problem)
-
新增: 在查询列表数据,并且需要访问每个列表项关联的其他表数据时,要避免先查出N条主数据,然后对每条主数据再单独发起1次关联查询(总共1+N次查询)。
-
重要性: N+1 查询会造成大量的数据库交互,严重影响性能。
-
技术示例:
-
MyBatis/MyBatisPlus:
-
使用 JOIN 在一次查询中获取所有需要的数据。
-
使用 Mybatis 的 collection 或 association 标签进行嵌套结果映射(ResultMap),配合一次 JOIN 查询或两次查询(先查主表,再用主表 ID 列表一次性查关联表)。
-
MyBatisPlus: 提供 Eager Loading(急加载)配置,但需谨慎使用,最好还是通过显式 JOIN 或 ResultMap 控制。
-
-
JPA/Hibernate: 使用 JOIN FETCH 或 @EntityGraph 来指定需要急加载的关联属性。
-
-
参考:
-
代码: 展示使用 Mybatis ResultMap 的 collection 标签或 JPA JOIN FETCH 解决 N+1 问题的代码。
-
-
-
数据库设计理念权衡 (Normalization vs. Purpose-Built Tables)
-
你的观点: "表的设计有两种一个是有基础数据,其余有基础数据生成。还有一个简单的方法,一个功能一个表,表之间没有绝对的关系"
-
完善:
-
范式化设计 (Normalization): 遵循数据库范式(1NF, 2NF, 3NF 等),减少数据冗余,保证数据一致性。这是关系型数据库设计的标准方法,适用于大多数 OLTP(在线事务处理)系统。"基础数据+生成"可能指部分数据依赖于基础数据,可以通过计算或触发器生成,但核心是范式化。
-
面向功能/领域的设计 (Purpose-Built Tables): "一个功能一个表" 类似于领域驱动设计 (DDD) 中的聚合根或者微服务架构下的数据隔离思路。每个核心功能或服务可能有自己独立优化的数据表,可能存在数据冗余,表之间关系松散。
-
-
选择依据:
-
范式化: 适合需要强数据一致性、写入操作频繁、数据关系复杂的系统。
-
面向功能/领域: 适合微服务架构、需要独立扩展和部署的服务、读密集型应用(配合反范式)。需要更强的机制保证跨表/跨服务的数据最终一致性(如事件驱动、Saga 模式)。
-
-
参考:
-
图片: ER 图展示高度范式化的设计 vs. 微服务中按功能划分的几组表。
-
-
API 设计与系统集成
-
API 优先与契约驱动 (API-First & Contract-Driven)
-
你的观点: "两个系统对接谁给谁出接口...没有固定模式...增加了他的工作量。"
-
完善: 虽然谁先做没有绝对固定模式,但最佳实践是推行 API 优先 (API-First) 的设计理念。先定义好清晰、稳定、文档化的 API 契约(合同),双方基于这个契约进行开发。这能减少沟通成本和返工。
-
重要性: 促进并行开发,减少集成风险,提高协作效率。API 契约是双方沟通的基础。
-
技术示例:
-
使用 OpenAPI (Swagger) 规范来定义 RESTful API。先编写 .yaml 或 .json 格式的 API 定义文件,明确资源、路径、方法、参数、请求体、响应体、错误码等。
-
可以使用 Swagger UI 或 Redoc 等工具根据定义文件自动生成交互式 API 文档。
-
可以使用 OpenAPI Generator 等工具根据定义文件自动生成服务端代码骨架和客户端 SDK,减少重复劳动。
-
-
谁提供接口: 通常是拥有数据或提供核心功能的一方提供接口(Provider),需要数据或功能的一方调用接口(Consumer)。但在复杂系统中,也可能存在双向调用。关键是尽早明确接口定义。
-
参考:
-
代码: 一个简单的 OpenAPI (Swagger) .yaml 文件片段。
-
图片: 展示 API-First 开发流程图。
-
-
-
遵循 RESTful 或其他成熟的 API 风格
-
新增: 设计 API 时,遵循广泛接受的风格指南,如 RESTful。
-
RESTful 核心原则:
-
资源 (Resources): API 操作的对象,用名词表示(如 /users, /orders/{id})。
-
HTTP 方法 (Verbs): 使用标准的 HTTP 方法表达操作意图 (GET-查询, POST-创建, PUT-更新整个资源, PATCH-更新部分资源, DELETE-删除)。
-
状态码 (Status Codes): 使用标准的 HTTP 状态码表示请求结果 (200 OK, 201 Created, 400 Bad Request, 404 Not Found, 500 Internal Server Error 等)。
-
无状态 (Stateless): 服务器不保存客户端的会话状态,每次请求都应包含所有必要信息。
-
-
技术示例: 设计用户管理的 RESTful API:
-
GET /users - 获取用户列表
-
POST /users - 创建新用户
-
GET /users/{userId} - 获取特定用户信息
-
PUT /users/{userId} - 更新特定用户信息(整个替换)
-
DELETE /users/{userId} - 删除特定用户
-
-
参考:
-
文档: 链接到 RESTful API 设计指南或最佳实践文章。
-
-
开发流程与工具
-
代码生成与脚手架 (Code Generation & Scaffolding)
-
你的观点: "生成库表,mvc,然后ui。或者sql一键生成所有代码。"
-
完善: 代码生成工具可以显著提高开发效率,尤其是在项目初期或处理大量重复模式(如 CRUD 操作)时。
-
技术示例:
-
MyBatisPlus Code Generator: 可以根据数据库表结构自动生成 Entity, Mapper (Interface & XML), Service (Interface & Impl), Controller。高度可配置。
-
JHipster: 一个强大的应用生成器,可以快速创建基于 Spring Boot + (Angular/React/Vue) 的全栈应用,包含数据库设计、后端 API、前端 UI、安全、部署配置等。
-
Spring Initializr: 用于快速生成 Spring Boot 项目骨架,可以选择所需依赖。
-
数据库迁移工具 (Flyway, Liquibase): 通过 SQL 或 XML/YAML 文件管理数据库结构变更,实现版本控制和自动化部署。可以看作是 "SQL 生成库表" 的一种规范化实践。
-
-
权衡:
-
优点: 快速开发,减少重复劳动,保持结构一致性。
-
缺点: 生成的代码可能过于通用,需要定制;过度依赖可能降低对底层原理的理解;维护生成后的代码有时比手写更复杂。
-
-
参考:
-
图片: 展示 MyBatisPlus Code Generator 的配置界面或 JHipster 的生成选项。
-
代码: 由代码生成器产生的典型 Controller 或 Service 代码片段。
-
-
-
版本控制 (Version Control)
-
新增: 使用 Git 等版本控制系统管理所有代码和重要配置文件。遵循清晰的分支策略(如 Gitflow 或 GitHub Flow)。编写有意义的提交信息 (Commit Messages)。
-
重要性: 协作基础,代码历史追踪,方便回滚,支持并行开发。
-
技术示例: Git, SVN。常用的平台有 GitHub, GitLab, Bitbucket。
-
参考:
-
图片: Gitflow 分支模型图。
-
-
-
自动化测试 (Automated Testing)
-
新增: 编写单元测试 (Unit Tests)、集成测试 (Integration Tests) 和端到端测试 (E2E Tests)。确保代码质量,方便重构,快速反馈。
-
重要性: 保证代码正确性,减少手动测试负担,提高发布信心。
-
技术示例:
-
Java: JUnit, Mockito, Spring Boot Test
-
Frontend: Jest, Mocha, Cypress, Playwright
-
-
参考:
-
代码: 一个使用 JUnit 和 Mockito 的 Service 层单元测试示例。
-
-
-
持续集成/持续部署 (CI/CD)
-
新增: 建立自动化流程,在代码提交后自动进行构建、测试和部署。
-
重要性: 加快交付速度,减少手动操作错误,保证部署一致性。
-
技术示例: Jenkins, GitLab CI/CD, GitHub Actions, Travis CI。
-
参考:
-
图片: 一个简单的 CI/CD 流水线示意图 (Commit -> Build -> Test -> Deploy)。
-
-
命名与规范
-
一致且有意义的命名 (Consistent & Meaningful Naming)
-
你的观点: "不管是表还是接口还是ui命名都应该按照功能区分,sql的命名是 A_B.sql,java的命名是 AxxBxx.java,前端的命名是 AxxBxx.vue"
-
完善: 非常好的实践!命名是代码可读性的关键。
-
原则: 清晰、简洁、一致、有意义。名字应该能准确反映其功能或代表的数据。
-
Java:
-
类名: UpperCamelCase (e.g., UserService, OrderController)
-
方法名/变量名: lowerCamelCase (e.g., getUserById, orderList)
-
常量: ALL_CAPS_SNAKE_CASE (e.g., MAX_RETRY_COUNT)
-
包名: lowercase.dot.separated (e.g., com.example.myapp.service)
-
-
数据库:
-
表名/列名: snake_case (e.g., user_orders, order_id, creation_date) 是常见选择,保持一致性最重要。
-
SQL 脚本文件: V1__Create_user_table.sql (Flyway 命名规范),或者 模块_功能_描述.sql (e.g., order_management_init.sql)。
-
-
RESTful API URL:
-
路径: kebab-case 或 snake_case (e.g., /user-profiles/{userId}, /order_items),推荐 kebab-case,且用复数名词表示资源集合。
-
-
前端 (Vue/React/Angular):
-
组件文件名/选择器: UpperCamelCase 或 kebab-case (e.g., UserProfile.vue, user-profile.component.ts, <user-profile>)。团队内统一风格。
-
变量/函数: lowerCamelCase.
-
-
配置文件: .properties, .yaml, .json 等,通常使用 kebab-case 或 snake_case 作为键名 (key)。
-
-
参考:
-
文档: 链接到 Google Java Style Guide, Airbnb JavaScript Style Guide 等。
-
-
总结
你提到的几点都是非常有价值的实战经验。将它们与 SOLID 原则、API 设计最佳实践、自动化、测试以及一致的命名规范相结合,可以形成一套更全面、更强大的编程经验体系。记住,这些原则和实践不是孤立的,它们相互关联,共同服务于构建高质量、可维护、易于扩展的软件系统。在实际应用中,还需要根据具体项目、团队和技术栈进行权衡和调整。
以下是一些可以补充的编程经验,涵盖开发规范、架构设计、性能优化等方面:
---
### **1. 数据库设计经验**
- **冗余字段的权衡**:关联其他表时(如用户ID关联用户名),适当冗余高频查询字段可减少联表查询,但需注意数据一致性(可通过触发器或代码维护)。
- **索引优化**:为高频查询条件、外键、排序字段添加索引,但避免过度索引(影响写入性能)。
- **表分区**:大表按时间或ID范围分区,提升查询性能。
- **字段类型选择**:例如用`UNSIGNED INT`替代`VARCHAR`存储IP地址,空间和查询效率更高。
---
### **2. 接口设计规范**
- **RESTful API 设计**:
- 资源命名用复数(如`/users`),动作通过HTTP方法区分(GET/POST/PUT/DELETE)。
- 返回统一结构:`{code, data, message}`。
- **版本控制**:接口路径中嵌入版本号(如`/v1/users`),避免升级冲突。
- **谁对接谁**:若双方均有开发能力,约定接口规范后各自实现;若一方为服务提供方(如支付系统),由其主导接口设计。
---
### **3. 代码生成与架构**
- **代码生成工具**:
- MyBatis-Plus:用`AutoGenerator`生成Entity/Mapper/Service代码。
- 前端:`element-ui`或`ant-design`的代码生成器快速生成CRUD界面。
- **MVC分层**:
- Controller:参数校验 + 路由转发。
- Service:业务逻辑,避免直接操作数据库。
- DAO:仅负责数据读写,可通过MyBatis-Plus的`BaseMapper`减少SQL编写。
---
### **4. 命名与文件组织**
- **Java**:
- 类名:`UserController`、`OrderService`。
- 方法名:`getUserById()`(动词开头,驼峰式)。
- **SQL脚本**:按功能模块分目录,如`/sql/user/user_create.sql`。
- **前端Vue**:
- 组件:`UserList.vue`、`OrderDetailDialog.vue`。
- API请求:单独目录`/api/user.js`封装接口调用。
---
### **5. 性能优化技巧**
- **缓存策略**:
- 高频静态数据(如配置项)用Redis缓存。
- 数据库查询结果缓存(如MyBatis-Plus的`@CacheNamespace`)。
- **批量操作**:
- 数据库:`INSERT INTO ... VALUES (...), (...)`替代多次单条插入。
- 网络请求:合并多个API调用(如GraphQL)。
---
### **6. 联调与协作**
- **接口文档**:使用Swagger/YAPI自动生成,标注字段类型、示例值、必填项。
- **Mock数据**:前端开发时用Mock.js模拟接口返回,不阻塞进度。
- **日志规范**:统一记录请求参数、响应时间、错误堆栈(如Log4j2的JSON格式)。
---
### **7. 安全实践**
- **SQL注入**:禁止拼接SQL,用预编译(MyBatis的`#{}`)。
- **XSS防护**:前端转义用户输入(如`v-html`慎用),后端过滤敏感字符。
- **权限控制**:
- 接口层:`@PreAuthorize("hasRole('admin')")`。
- 数据层:MyBatis-Plus的`@DataScope`注解实现数据权限。
---
### **8. 测试与部署**
- **单元测试**:Service层用JUnit+Mockito,覆盖率不低于70%。
- **数据迁移**:旧系统迁移时,保留双写逻辑(新旧表同时更新),逐步切换。
- **SQL审核**:上线前用工具(如Archery)检查慢查询和潜在风险。
---
### **9. 其他经验**
- **枚举替代魔法值**:数据库状态字段用`ENUM('ACTIVE','INACTIVE')`,代码中定义枚举类。
- **工具类复用**:封装日期处理、加密解密等工具,避免重复代码。
- **技术债务管理**:代码注释中标记`// TODO @author 2024-12-31`,定期清理。
---
以上经验可根据具体技术栈(如Spring Cloud、Vue3等)调整实现细节,核心是保持一致性、可维护性和扩展性。
浙公网安备 33010602011771号