开发指南#
开发环境设置#
必需工具#
- Node.js 18+
- Java 17 LTS
- PostgreSQL 16
- Docker & Docker Compose
- Git
IDE 推荐#
前端开发:
- VS Code + 扩展:
- ESLint
- Prettier
- Tailwind CSS IntelliSense
- React Developer Tools
后端开发:
- IntelliJ IDEA Ultimate / Community
- Eclipse + Spring Tools
项目结构#
waterball-interview/
├── frontend/ # Next.js 前端
│ ├── src/
│ │ ├── app/ # App Router 页面
│ │ ├── components/ # React 组件
│ │ ├── store/ # Zustand 状态管理
│ │ ├── types/ # TypeScript 类型
│ │ └── lib/ # 工具函数
│ ├── public/ # 静态资源
│ └── package.json
├── backend/ # Spring Boot 后端
│ ├── src/main/java/
│ │ └── tw/waterball/
│ │ ├── controller/ # REST 控制器
│ │ ├── service/ # 业务逻辑
│ │ ├── repository/ # 数据访问
│ │ ├── entity/ # JPA 实体
│ │ ├── dto/ # 数据传输对象
│ │ ├── security/ # 安全配置
│ │ └── config/ # 配置类
│ └── build.gradle
├── doc/ # 项目文档
├── docker-compose.yml # 开发环境
├── docker-compose.prod.yml # 生产环境
└── CLAUDE.md # AI 协作指南开发工作流#
1. 创建新功能分支#
git checkout -b feature/your-feature-name2. 前端开发#
cd frontend
# 安装依赖
npm install
# 启动开发服务器
npm run dev
# 代码检查
npm run lint
# 类型检查
npm run type-check添加新页面#
// src/app/your-page/page.tsx
'use client';
import { useState } from 'react';
export default function YourPage() {
return (
<div>
<h1>Your Page</h1>
</div>
);
}创建新组件#
// src/components/your-component/YourComponent.tsx
interface YourComponentProps {
title: string;
}
export function YourComponent({ title }: YourComponentProps) {
return <div>{title}</div>;
}使用 Zustand Store#
// src/store/useYourStore.ts
import { create } from 'zustand';
interface YourStore {
count: number;
increment: () => void;
}
export const useYourStore = create<YourStore>((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}));3. 后端开发#
cd backend
# 运行应用(Windows)
gradlew.bat bootRun
# 运行应用(Mac/Linux)
./gradlew bootRun
# 运行测试
./gradlew test
# 构建 JAR
./gradlew bootJar添加新实体#
@Entity
@Table(name = "your_entity")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class YourEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}创建 Repository#
public interface YourEntityRepository extends JpaRepository<YourEntity, Long> {
List<YourEntity> findByName(String name);
}创建 Service#
@Service
@RequiredArgsConstructor
public class YourEntityService {
private final YourEntityRepository repository;
public YourEntity create(YourEntity entity) {
return repository.save(entity);
}
}创建 Controller#
@RestController
@RequestMapping("/api/your-entities")
@RequiredArgsConstructor
public class YourEntityController {
private final YourEntityService service;
@PostMapping
public ResponseEntity<YourEntity> create(@RequestBody YourEntity entity) {
return ResponseEntity.ok(service.create(entity));
}
}代码规范#
前端代码规范#
命名规范:
- 组件: PascalCase (
UserProfile.tsx) - 函数: camelCase (
getUserData()) - 常量: UPPER_SNAKE_CASE (
API_URL) - CSS 类: kebab-case (
user-profile)
组件规范:
// ✅ 推荐
export function UserProfile({ userId }: { userId: string }) {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
fetchUser(userId);
}, [userId]);
return <div>{user?.name}</div>;
}
// ❌ 避免
export default ({ userId }) => {
// 缺少类型定义
const [user, setUser] = useState(null);
return <div>{user?.name}</div>;
}后端代码规范#
命名规范:
- 类: PascalCase (
UserService) - 方法: camelCase (
getUserById()) - 常量: UPPER_SNAKE_CASE (
MAX_PAGE_SIZE) - 包名: lowercase (
tw.waterball.service)
代码组织:
// ✅ 推荐
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
public User createUser(UserCreateDto dto) {
validateEmail(dto.getEmail());
String encodedPassword = passwordEncoder.encode(dto.getPassword());
// ...
}
private void validateEmail(String email) {
// 验证逻辑
}
}
// ❌ 避免:所有逻辑都在 Controller
@RestController
public class UserController {
@PostMapping("/users")
public User create(@RequestBody UserCreateDto dto) {
// 直接在 Controller 中处理业务逻辑
}
}测试#
前端测试#
# E2E 测试(Playwright)
npx playwright test
# 交互式模式
npx playwright test --ui
# 调试模式
npx playwright test --debug后端测试#
# 运行所有测试
./gradlew test
# 运行特定测试类
./gradlew test --tests UserServiceTest
# 测试覆盖率
./gradlew test jacocoTestReport数据库迁移#
手动 SQL 迁移#
-- migrations/V1__initial_schema.sql
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(100) NOT NULL
);使用 JPA 自动生成#
开发环境 application.properties:
spring.jpa.hibernate.ddl-auto=update调试技巧#
前端调试#
React DevTools:
- 安装浏览器扩展
- 查看组件树和 state
网络请求:
// 添加请求日志
fetch(`${API_URL}/api/users`)
.then(res => {
console.log('Response:', res);
return res.json();
})
.catch(err => console.error('Error:', err));后端调试#
日志输出:
@Slf4j
@Service
public class UserService {
public User getUser(Long id) {
log.info("Getting user with id: {}", id);
User user = userRepository.findById(id)
.orElseThrow(() -> new NotFoundException("User not found"));
log.debug("Found user: {}", user);
return user;
}
}IDEA 断点调试:
- 设置断点
- Debug 模式启动 (
Shift + F9) - 发送请求触发断点
常见问题#
前端 Hot Reload 不工作#
# 清除 Next.js 缓存
rm -rf .next
npm run dev后端修改后不生效#
确保启用了 Spring DevTools:
dependencies {
developmentOnly 'org.springframework.boot:spring-boot-devtools'
}数据库连接失败#
检查 application.properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/waterball_academy
spring.datasource.username=postgres
spring.datasource.password=postgresGit 提交规范#
# 格式
<type>(<scope>): <subject>
# 示例
feat(auth): add Google OAuth login
fix(api): resolve CORS issue
docs(readme): update deployment instructions
refactor(user): simplify user service logicType 类型:
feat: 新功能fix: Bug 修复docs: 文档更新style: 代码格式调整refactor: 重构test: 测试相关chore: 构建/工具配置