团队协作开发规范
团队协作开发规范的重要性
多人协作开发项目时,统一的规范能显著提高代码质量、降低维护成本。规范化的开发流程让团队成员更容易理解彼此的代码,减少沟通成本,提升整体效率。缺乏规范的项目往往会出现风格混乱、功能冲突等问题。
代码风格规范
命名约定
- 变量和函数使用小驼峰命名法:
userName
,getUserInfo()
- 类名使用大驼峰命名法:
UserModel
- 常量使用全大写加下划线:
MAX_COUNT
- 私有成员以下划线开头:
_privateMethod()
// 好的命名示例
const MAX_RETRY_TIMES = 3;
let currentPage = 1;
function fetchUserData() {
// ...
}
class UserController {
constructor() {
this._token = null;
}
}
代码格式化
统一使用Prettier或ESLint等工具自动格式化代码,配置应提交到项目仓库中:
// .prettierrc
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5"
}
Git工作流规范
分支管理策略
采用Git Flow分支模型:
master
:生产环境代码develop
:开发主分支feature/*
:功能开发分支hotfix/*
:紧急修复分支release/*
:预发布分支
# 创建功能分支示例
git checkout -b feature/user-authentication develop
提交信息规范
使用Angular提交规范:
- feat:新功能
- fix:bug修复
- docs:文档变更
- style:代码格式调整
- refactor:代码重构
- test:测试相关
- chore:构建过程或辅助工具变更
示例:
feat(user): add login API endpoint
- Implement JWT authentication
- Add login route handler
- Write unit tests for new feature
前端项目结构规范
目录结构
推荐按功能模块组织代码:
src/
├── assets/ # 静态资源
├── components/ # 通用组件
├── pages/ # 页面组件
├── store/ # 状态管理
├── utils/ # 工具函数
├── styles/ # 全局样式
├── api/ # API接口
└── router/ # 路由配置
组件开发规范
- 一个组件一个目录
- 组件文件命名使用PascalCase
- 包含测试文件
components/
└── UserProfile/
├── UserProfile.vue
├── UserProfile.spec.js
└── UserProfile.module.css
代码审查标准
审查要点
- 功能实现是否符合需求
- 是否有潜在的性能问题
- 代码是否遵循项目规范
- 测试覆盖率是否足够
- 是否有安全漏洞
审查流程
- 开发者在本地运行所有测试
- 创建Pull Request并添加详细描述
- 至少需要1名核心成员批准
- 解决所有审查意见后才能合并
文档编写要求
项目文档
- README.md:项目概述、环境配置、启动命令
- API.md:接口文档
- CHANGELOG.md:版本变更记录
代码注释
复杂逻辑必须添加注释:
/**
* 计算折扣后价格
* @param {number} originalPrice - 原始价格
* @param {number} discountRate - 折扣率(0-1)
* @returns {number} 折扣后价格
*/
function calculateDiscountedPrice(originalPrice, discountRate) {
if (discountRate < 0 || discountRate > 1) {
throw new Error('折扣率必须在0到1之间');
}
return originalPrice * (1 - discountRate);
}
测试规范
单元测试
使用Jest或Mocha等测试框架,覆盖率要求:
- 语句覆盖率 ≥ 80%
- 分支覆盖率 ≥ 70%
// UserService.spec.js
describe('UserService', () => {
it('should return user data when login success', async () => {
const mockUser = { id: 1, name: 'test' };
UserRepository.getById = jest.fn().mockResolvedValue(mockUser);
const result = await UserService.login('test', '123456');
expect(result).toEqual(mockUser);
expect(UserRepository.getById).toHaveBeenCalledTimes(1);
});
});
E2E测试
使用Cypress或Puppeteer进行端到端测试:
// login.spec.js
describe('Login Page', () => {
it('should login successfully with valid credentials', () => {
cy.visit('/login');
cy.get('#username').type('admin');
cy.get('#password').type('123456');
cy.get('button[type=submit]').click();
cy.url().should('include', '/dashboard');
});
});
持续集成/持续部署
CI/CD流程
- 代码推送触发构建
- 运行lint检查和单元测试
- 构建静态资源
- 部署到测试环境
- 人工确认后部署生产环境
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npm run lint
- run: npm test
依赖管理
包版本控制
- 精确版本号:
"lodash": "4.17.21"
- 定期更新依赖:
npm outdated
- 使用
package-lock.json
锁定版本
# 安全更新依赖
npm audit fix
异常处理规范
错误处理
统一错误处理中间件:
// errorMiddleware.js
function errorHandler(err, req, res, next) {
if (err instanceof CustomError) {
return res.status(err.statusCode).json({
error: {
code: err.code,
message: err.message
}
});
}
// 未知错误
console.error(err.stack);
res.status(500).json({ error: 'Internal Server Error' });
}
日志记录
使用Winston等日志库:
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
// 使用示例
logger.info('User login', { userId: 123 });
性能优化指南
前端优化
- 代码分割
- 图片懒加载
- 缓存策略
// 动态导入实现代码分割
const UserProfile = React.lazy(() => import('./UserProfile'));
后端优化
- 数据库查询优化
- 接口缓存
- 批量处理请求
// 批量查询示例
async function getUsersByIds(userIds) {
return User.findAll({
where: {
id: {
[Op.in]: userIds
}
}
});
}
安全最佳实践
前端安全
- 防范XSS攻击
- CSP策略
- 敏感数据保护
// 防范XSS示例
function sanitizeInput(input) {
return input.replace(/</g, '<').replace(/>/g, '>');
}
后端安全
- 输入验证
- SQL注入防护
- 权限控制
// 参数验证中间件
function validateLogin(req, res, next) {
const { username, password } = req.body;
if (!username || !password) {
throw new ValidationError('用户名和密码不能为空');
}
next();
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn