Skip to main content

[技术/领域] 最佳实践

适用对象:初级/中级/高级开发者
更新日期:2025-01-20
维护人:[团队名称]


文档目的

本文档总结了 [技术/领域] 的最佳实践,帮助团队:

  • 统一编码规范
  • 避免常见陷阱
  • 提升代码质量
  • 提高开发效率

一、编码规范

1.1 命名规范

命名规范对比
类型规范示例说明
变量camelCaseuserName, isActive使用驼峰命名
常量UPPER_SNAKE_CASEMAX_SIZE, API_URL全大写下划线
类名PascalCaseUserService, DataModel首字母大写驼峰
函数camelCasegetUserData, handleClick动词开头,驼峰命名
私有成员_camelCase_privateMethod下划线前缀
文件名kebab-caseuser-service.js小写短横线分隔

示例

javascript
1// 推荐
2const MAX_RETRY_COUNT = 3;
3const userName = 'John';
4class UserService {}
5function getUserById(id) {}
6
7// 不推荐
8const max_retry_count = 3; // 常量应全大写
9const UserName = 'John'; // 变量不应大写开头
10class userService {} // 类名应大写开头
11function get_user_by_id() {} // 函数应驼峰命名

1.2 注释规范

函数注释

javascript
1/**
2 * 根据用户ID获取用户信息
3 *
4 * @param {number} userId - 用户ID
5 * @param {Object} options - 可选配置项
6 * @param {boolean} options.includeDetails - 是否包含详细信息
7 * @returns {Promise<User>} 用户对象
8 * @throws {NotFoundError} 当用户不存在时
9 *
10 * @example
11 * const user = await getUserById(123, { includeDetails: true });
12 */
13async function getUserById(userId, options = {}) {
14 // 实现代码
15}

复杂逻辑注释

javascript
1// 推荐:解释"为什么"而不是"是什么"
2// 使用二分查找提升大数组的查找性能
3const index = binarySearch(arr, target);
4
5// 不推荐:陈述代码本身
6// 调用binarySearch函数
7const index = binarySearch(arr, target);

1.3 代码格式

javascript
1// 推荐:清晰的代码结构
2function processUserData(users) {
3 if (!users || !Array.isArray(users)) {
4 throw new Error('Invalid users array');
5 }
6
7 return users
8 .filter(user => user.isActive)
9 .map(user => ({
10 id: user.id,
11 name: user.name,
12 email: user.email
13 }))
14 .sort((a, b) => a.name.localeCompare(b.name));
15}
16
17// 不推荐:混乱的代码格式
18function processUserData(users){
19if(!users||!Array.isArray(users))throw new Error('Invalid users array');
20return users.filter(user=>user.isActive).map(user=>({id:user.id,name:user.name,email:user.email})).sort((a,b)=>a.name.localeCompare(b.name));}

二、设计原则

2.1 SOLID原则

原则说明示例
S - 单一职责一个类只负责一件事UserService只处理用户相关逻辑
O - 开放封闭对扩展开放,对修改封闭使用策略模式扩展功能
L - 里氏替换子类可以替换父类子类不改变父类行为
I - 接口隔离接口应该小而专一拆分大接口为多个小接口
D - 依赖倒置依赖抽象而非具体实现依赖接口而非具体类

单一职责示例

javascript
1// 不推荐:职责混乱
2class User {
3 constructor(name, email) {
4 this.name = name;
5 this.email = email;
6 }
7
8 save() {
9 // 保存到数据库
10 }
11
12 sendEmail(message) {
13 // 发送邮件
14 }
15
16 generateReport() {
17 // 生成报表
18 }
19}
20
21// 推荐:职责分离
22class User {
23 constructor(name, email) {
24 this.name = name;
25 this.email = email;
26 }
27}
28
29class UserRepository {
30 save(user) {
31 // 保存到数据库
32 }
33}
34
35class EmailService {
36 send(user, message) {
37 // 发送邮件
38 }
39}
40
41class ReportService {
42 generateUserReport(user) {
43 // 生成报表
44 }
45}

2.2 DRY原则(Don't Repeat Yourself)

javascript
1// 不推荐:重复代码
2function validateEmail(email) {
3 const regex = /^\S+@\S+\.\S+$/;
4 return regex.test(email);
5}
6
7function validateUsername(username) {
8 const regex = /^[a-zA-Z0-9_]{3,20}$/;
9 return regex.test(username);
10}
11
12// 推荐:提取公共逻辑
13function validateWithRegex(value, regex) {
14 return regex.test(value);
15}
16
17const EMAIL_REGEX = /^\S+@\S+\.\S+$/;
18const USERNAME_REGEX = /^[a-zA-Z0-9_]{3,20}$/;
19
20const validateEmail = (email) => validateWithRegex(email, EMAIL_REGEX);
21const validateUsername = (username) => validateWithRegex(username, USERNAME_REGEX);

三、性能优化

3.1 前端性能优化

前端性能优化技巧
优化项技术方案提升效果优先级
资源加载懒加载、预加载50%+
代码分割Code Splitting40%+
图片优化WebP、压缩60%+
缓存策略Service Worker80%+
虚拟滚动大列表优化90%+
防抖节流减少函数调用30%+

懒加载示例

javascript
1// 推荐:路由懒加载
2const UserDashboard = () => import('./components/UserDashboard');
3
4const routes = [
5 {
6 path: '/dashboard',
7 component: UserDashboard // 仅在访问时加载
8 }
9];
10
11// 推荐:图片懒加载
12<img
13 src="placeholder.jpg"
14 data-src="actual-image.jpg"
15 loading="lazy"
16 alt="Image"
17/>

3.2 后端性能优化

数据库优化

sql
1-- 不推荐:未使用索引
2SELECT * FROM users WHERE email = 'test@example.com';
3
4-- 推荐:添加索引
5CREATE INDEX idx_users_email ON users(email);
6SELECT id, name, email FROM users WHERE email = 'test@example.com';

缓存策略

javascript
1// 推荐:多级缓存
2class UserService {
3 constructor() {
4 this.cache = new Map(); // 内存缓存
5 this.redis = new Redis(); // Redis缓存
6 }
7
8 async getUser(id) {
9 // 1. 检查内存缓存
10 if (this.cache.has(id)) {
11 return this.cache.get(id);
12 }
13
14 // 2. 检查Redis缓存
15 const cached = await this.redis.get(`user:${id}`);
16 if (cached) {
17 const user = JSON.parse(cached);
18 this.cache.set(id, user);
19 return user;
20 }
21
22 // 3. 查询数据库
23 const user = await this.db.findById(id);
24
25 // 4. 更新缓存
26 await this.redis.setex(`user:${id}`, 3600, JSON.stringify(user));
27 this.cache.set(id, user);
28
29 return user;
30 }
31}

四、安全最佳实践

4.1 输入验证

javascript
1// 危险:不安全的做法:未验证输入
2app.post('/api/users', (req, res) => {
3 const user = req.body;
4 db.insert(user); // 可能导致SQL注入
5});
6
7// 安全:推荐做法:严格验证
8const Joi = require('joi');
9
10const userSchema = Joi.object({
11 username: Joi.string().alphanum().min(3).max(30).required(),
12 email: Joi.string().email().required(),
13 password: Joi.string().min(8).required()
14});
15
16app.post('/api/users', async (req, res) => {
17 try {
18 const value = await userSchema.validateAsync(req.body);
19 // 处理已验证的数据
20 } catch (error) {
21 res.status(400).json({ error: error.message });
22 }
23});

4.2 密码处理

javascript
1// 危险:不安全的做法:明文存储密码
2const user = {
3 username: 'john',
4 password: '123456' // 明文密码
5};
6
7// 安全:推荐做法:加密存储
8const bcrypt = require('bcrypt');
9
10async function hashPassword(password) {
11 const salt = await bcrypt.genSalt(10);
12 return await bcrypt.hash(password, salt);
13}
14
15const user = {
16 username: 'john',
17 password: await hashPassword('123456')
18};

4.3 XSS防护

javascript
1// 危险:不安全的做法:直接插入HTML
2element.innerHTML = userInput;
3
4// 安全:推荐做法:转义HTML
5function escapeHtml(text) {
6 const map = {
7 '&': '&amp;',
8 '<': '&lt;',
9 '>': '&gt;',
10 '"': '&quot;',
11 "'": '&#039;'
12 };
13 return text.replace(/[&<>"']/g, m => map[m]);
14}
15
16element.textContent = escapeHtml(userInput);

五、错误处理

5.1 统一错误处理

javascript
1// 推荐:统一错误类
2class ApplicationError extends Error {
3 constructor(message, statusCode = 500, data = {}) {
4 super(message);
5 this.name = this.constructor.name;
6 this.statusCode = statusCode;
7 this.data = data;
8 Error.captureStackTrace(this, this.constructor);
9 }
10}
11
12class ValidationError extends ApplicationError {
13 constructor(message, data) {
14 super(message, 400, data);
15 }
16}
17
18class NotFoundError extends ApplicationError {
19 constructor(message) {
20 super(message, 404);
21 }
22}
23
24// 使用
25throw new ValidationError('Invalid email format', { field: 'email' });

5.2 错误边界

javascript
1// React错误边界
2class ErrorBoundary extends React.Component {
3 constructor(props) {
4 super(props);
5 this.state = { hasError: false, error: null };
6 }
7
8 static getDerivedStateFromError(error) {
9 return { hasError: true, error };
10 }
11
12 componentDidCatch(error, errorInfo) {
13 // 记录错误到日志服务
14 logErrorToService(error, errorInfo);
15 }
16
17 render() {
18 if (this.state.hasError) {
19 return <ErrorFallback error={this.state.error} />;
20 }
21
22 return this.props.children;
23 }
24}

六、测试最佳实践

6.1 单元测试

javascript
1// 推荐:清晰的测试结构
2describe('UserService', () => {
3 describe('getUserById', () => {
4 it('should return user when user exists', async () => {
5 // Arrange
6 const userId = 123;
7 const expectedUser = { id: 123, name: 'John' };
8 mockDB.findById.mockResolvedValue(expectedUser);
9
10 // Act
11 const result = await userService.getUserById(userId);
12
13 // Assert
14 expect(result).toEqual(expectedUser);
15 expect(mockDB.findById).toHaveBeenCalledWith(userId);
16 });
17
18 it('should throw NotFoundError when user does not exist', async () => {
19 // Arrange
20 mockDB.findById.mockResolvedValue(null);
21
22 // Act & Assert
23 await expect(userService.getUserById(999))
24 .rejects
25 .toThrow(NotFoundError);
26 });
27 });
28});

6.2 测试覆盖率目标

测试覆盖率建议
代码类型覆盖率目标说明
核心业务逻辑90%+必须有充分测试
工具函数95%+应该有完整测试
UI组件70%+重点测试交互逻辑
配置代码60%+基本测试即可

七、代码审查清单

7.1 提交前检查

  • 代码符合团队规范
  • 添加了必要的注释
  • 更新了相关文档
  • 编写了单元测试
  • 测试用例全部通过
  • 没有console.log等调试代码
  • 处理了所有TODO
  • 检查了安全隐患

7.2 Code Review要点

功能性

  • 代码是否实现了预期功能?
  • 边界条件是否处理?
  • 错误处理是否完善?

可读性

  • 命名是否清晰?
  • 逻辑是否易懂?
  • 是否需要注释?

性能

  • 是否有性能问题?
  • 是否有不必要的计算?
  • 是否可以优化?

八、Git最佳实践

8.1 提交信息规范

bash
1# 推荐:清晰的提交信息
2feat: 添加用户导出功能
3fix: 修复登录页面样式问题
4docs: 更新API文档
5refactor: 重构用户服务代码
6test: 添加用户服务单元测试
7chore: 更新依赖版本
8
9# 不推荐:模糊的提交信息
10update code
11fix bug
12changes

8.2 分支策略


九、文档最佳实践

9.1 README模板

markdown
1# 项目名称
2
3简短描述项目功能
4
5## 功能特性
6
7- 功能1
8- 功能2
9- 功能3
10
11## 快速开始
12
13### 安装
14\`\`\`bash
15npm install
16\`\`\`
17
18### 运行
19\`\`\`bash
20npm start
21\`\`\`
22
23## 文档
24
25详细文档请查看 [文档站点](https://docs.example.com)
26
27## 贡献指南
28
29请查看 [CONTRIBUTING.md](./CONTRIBUTING.md)
30
31## 许可证
32
33MIT

十、常见反模式

10.1 避免的做法

反模式对比
反模式问题正确做法
上帝类一个类承担太多职责拆分为多个小类
意大利面代码逻辑混乱,难以维护使用清晰的结构
魔法数字硬编码的数字定义为常量
过早优化在需要前就优化先保证正确性
重复代码相同逻辑多处出现提取为公共函数
过度设计添加不需要的抽象保持简单

总结

核心原则
  1. 简单优于复杂:保持代码简洁明了
  2. 可读性第一:代码是写给人看的
  3. 持续改进:不断学习和优化
  4. 团队协作:遵循团队规范
  5. 质量保证:测试和代码审查

相关资源

参与讨论