四、团队协作
4.1 如何提出一个好问题
# ❌ 坏问题
“这个怎么不工作?”
“有人知道这个报错怎么解决吗?”
# ✅ 好问题模板
## 标题:[问题类型] 简要描述
示例:[Bug] 用户登录后页面白屏
## 正文
### 环境信息
- 操作系统: macOS 14.0
- 浏览器: Chrome 120
- 项目版本: v1.2.0
### 问题描述
(用一两句话描述现象)
### 复现步骤
1. 访问 http://localhost:3000/login
2. 输入用户名 test@example.com
3. 输入密码 123456
4. 点击登录按钮
5. 看到页面变白,控制台报错
### 预期行为
登录成功后应该跳转到首页
### 实际行为
页面白屏
### 已尝试的解决方案
- 清除浏览器缓存 → 无效
- 重启服务 → 无效
- 检查网络请求,登录接口返回 200
### 相关代码
```javascript
// 相关代码片段
日志/报错信息
完整的错误堆栈
### 4.2 会议效率
```markdown
# 会前
- [ ] 是否有必要开会?(能否用文档/消息解决)
- [ ] 明确会议目标(要达成什么决定?)
- [ ] 准备议程(按时间分配议题)
- [ ] 邀请必要的人(不要拉无关的人)
# 会中
- [ ] 指定主持人(控制时间、节奏)
- [ ] 指定记录人(记录结论和待办)
- [ ] 一个议题结束再进入下一个
- [ ] 每个议题都要有结论
# 会后
- [ ] 24 小时内发出会议纪要
- [ ] 明确待办事项的责任人和截止时间
- [ ] 同步给未参会的人
# 会议纪要模板
## 会议信息
- 时间:2024-01-15 14:00-14:30
- 主题:API 设计评审
- 参会人:张三、李四、王五
## 讨论内容
1. 用户接口设计
- 结论:采用 RESTful 风格
2. 认证方案
- 结论:使用 JWT,有效期 7 天
## 待办事项
- [ ] 张三:更新 API 文档,截止 1/16
- [ ] 李四:实现 JWT 中间件,截止 1/18
## 下次会议
- 时间:1/22 14:00
- 主题:数据库设计评审
4.3 知识分享
# 知识分享的方式
## 1. 技术分享会(每周/双周)
- 30-45 分钟
- 一个主题,深入讲解
- 包含 Demo 演示
## 2. 午餐学习会(非正式)
- 15-20 分钟
- 一个技巧或小知识点
- 轻松氛围,鼓励提问
## 3. 文档沉淀
- 遇到坑 → 写问题记录
- 新学的技术 → 写学习笔记
- 好用的工具 → 写使用指南
## 4. Pair Programming
- 处理复杂任务时
- 新人 onboarding 时
- 知识传递效率最高
## 5. Code Review 评论
- 这是最日常的知识分享
- 每条评论都是一次教学
4.4 处理冲突
# 技术分歧的处理
## 场景:对技术方案有不同意见
### 步骤1:理解对方的方案
“你的方案我理解了,核心是 X,对吗?”
### 步骤2:阐述自己的理由
“我建议用 Y,因为考虑到性能(数据支撑)”
### 步骤3:寻找共同目标
“我们最终目标是一致的:代码稳定、可维护”
### 步骤4:比较方案优劣
列出 A 方案和 B 方案的优缺点
### 步骤5:做小实验
“要不我们先花 1 小时做个原型对比?”
### 步骤6:向上升级
如果还是无法达成一致,请 TL 或架构师决策
# 不要做的事
- 人身攻击:“你怎么这么想?”
- 固执己见:“我的方案就是最好的”
- 消极对抗:不反对也不执行
- 越级告状:跳过技术负责人找老板
五、工具链:自动化规范
5.1 Prettier:代码格式化
// .prettierrc
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100,
"bracketSpacing": true,
"arrowParens": "always",
"endOfLine": "lf"
}
// package.json 添加脚本
{
"scripts": {
"format": "prettier --write .",
"format:check": "prettier --check ."
}
}
// VS Code 配置:保存时自动格式化
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
5.2 ESLint:代码检查
// .eslintrc.js
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
jest: true
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended',
'prettier' // 关闭与 Prettier 冲突的规则
],
parser: '@typescript-eslint/parser',
plugins: ['react', '@typescript-eslint', 'react-hooks'],
rules: {
// 可能有问题
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// 代码质量
'no-unused-vars': 'error',
'no-undef': 'error',
'eqeqeq': ['error', 'always'], // 强制使用 ===
'curly': ['error', 'all'], // 要求所有 if 都加大括号
// React 相关
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
'react/prop-types': 'off', // 使用 TypeScript
}
};
// package.json
{
"scripts": {
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix"
}
}
5.3 Husky + lint-staged:Git 钩子
// package.json
{
"scripts": {
"prepare": "husky install"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"*.{json,md}": [
"prettier --write"
]
}
}
// .husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
// .husky/commit-msg
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx commitlint --edit $1
5.4 Commitlint:提交信息规范
// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore']
],
'subject-empty': [2, 'never'],
'subject-max-length': [2, 'always', 100]
}
};
5.5 GitHub Actions:CI 自动化
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
lint-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- name: 代码格式检查
run: npm run format:check
- name: 代码规范检查
run: npm run lint
- name: 类型检查
run: npm run type-check
- name: 运行测试
run: npm test
- name: 构建
run: npm run build