# 代码文件拆分规范

> 跨框架通用的代码文件行数控制与拆分策略
> 版本: v1.0.0 | 更新: 2026-03-31

---

## 🎯 核心原则

1. **职责单一** — 每个文件承载一个主要概念
2. **行数可控** — 超过阈值必须拆分
3. **去重优先** — 拆分前先搜索项目中是否已有同类实现

---

## 📏 行数阈值

| 级别 | 行数 | 行动 |
|------|------|------|
| ✅ 正常 | < 300 行 | 无需处理 |
| ⚠️ 关注 | 300–500 行 | 考虑是否可拆分 |
| 🔶 警告 | 500–800 行 | 应当拆分 |
| 🔴 强制 | > 800 行 | 必须拆分 |

---

## ⚡ Flutter / Dart 拆分策略

### 策略 A: `part / part of`（私有类）

**适用场景**: 拆分出去的类需要访问主文件的私有成员（`_privateVar`）。

```dart
// exchange_home_page.dart（主文件）
part 'exchange_home_widgets.dart';
part 'exchange_tuition_tab.dart';

class ExchangeHomePage extends GetView<ExchangeController> {
  @override
  Widget build(BuildContext context) => ...;
}
```

```dart
// exchange_home_widgets.dart（part 文件）
part of 'exchange_home_page.dart';

class _CurrencySelector extends StatelessWidget {
  // 可以访问主文件的私有成员
}
```

**优点**: 保持私有作用域、无需额外 import
**缺点**: part 文件不能有自己的 import

### 策略 B: Barrel Export（公有类）

**适用场景**: 拆分出的组件是独立公有类，不需要访问私有成员。

```dart
// auth_page_widgets.dart（barrel 导出文件）
export 'auth_backgrounds.dart';
export 'auth_inputs.dart';
export 'auth_buttons.dart';
export 'auth_dialogs.dart';
```

```dart
// auth_backgrounds.dart（独立文件）
import 'package:flutter/material.dart';

class AuthBackground extends StatelessWidget {
  const AuthBackground({super.key});
  // 独立实现，公有类
}
```

**优点**: 独立 import、可单独测试、清晰的依赖关系
**缺点**: 需要通过构造函数传递数据

### 选择指南

| 条件 | 推荐策略 |
|------|---------|
| 拆分出的类使用 `_private` 成员 | `part / part of` |
| 拆分出的类完全独立 | Barrel Export |
| 拆分出的类可能被其他页面复用 | Barrel Export |
| 页面内部的私有 Widget | `part / part of` |

---

## ⚡ Vue 拆分策略

### 策略 A: 子组件提取

```vue
<!-- 拆分前：OrderPage.vue（800行） -->
<!-- 拆分后 -->
<script setup>
import OrderTable from './components/OrderTable.vue'
import OrderFilter from './components/OrderFilter.vue'
import OrderStats from './components/OrderStats.vue'
</script>

<template>
  <OrderFilter @change="handleFilter" />
  <OrderStats :data="stats" />
  <OrderTable :data="orders" />
</template>
```

### 策略 B: Composable 提取

```typescript
// 拆分前：逻辑全在组件中
// 拆分后：useOrderLogic.ts
export function useOrderLogic() {
  const orders = ref<Order[]>([])
  const loading = ref(false)

  async function fetchOrders(params: FilterParams) { ... }
  async function deleteOrder(id: string) { ... }

  return { orders, loading, fetchOrders, deleteOrder }
}
```

---

## 🔍 去重检查（拆分前必做）

**创建新组件/文件前，必须先搜索：**

### Flutter
```bash
# 搜索已有组件
grep -rn "class.*Widget\|class.*Page\|class.*View" lib/core/widgets/ lib/**/presentation/widgets/

# 搜索类名关键词
grep -rn "Card\|Button\|Dialog\|Input\|Selector" lib/core/widgets/
```

### Vue
```bash
# 搜索已有组件
find src/components -name "*.vue" | head -30
grep -rn "defineComponent\|<script setup" src/components/
```

**如果找到同类组件：**
1. 评估是否可以复用或扩展现有组件
2. 如果确实不同，命名必须体现区别（如 `AppCard` vs `TransactionCard`）

---

## 📊 真实案例

> 来自 my_flutter 项目 P0-P1 优化

### 案例 1: auth_page_widgets.dart — Barrel Export

| 指标 | 拆分前 | 拆分后 |
|------|--------|--------|
| 行数 | 1396 行（单文件） | 4 个文件 + 1 个 barrel |
| 类数量 | 8 个公有类 | 每个文件 1-3 个类 |
| 策略 | — | Barrel Export（公有类） |

### 案例 2: exchange_home_page.dart — Part/Part Of

| 指标 | 拆分前 | 拆分后 |
|------|--------|--------|
| 行数 | 1142 行（单文件） | 212 行主文件 + 2 个 part 文件 |
| 私有 Widget | 5 个 `_Widget` | 用 `part` 保持私有访问 |
| 策略 | — | `part / part of`（私有类） |

### 案例 3: 重复组件 AppCard

项目 `core/widgets/` 和 `presentation/widgets/` 各有一个 `AppCard`，功能重叠。
**教训**: 创建组件前不搜索 → 维护两套代码 → 最终需要删除一个并迁移引用。

---

## ✅ 检查清单

- [ ] 文件行数 < 500（或有拆分计划）
- [ ] 拆分前做了项目搜索去重
- [ ] 选择了合适的拆分策略（part vs barrel vs composable）
- [ ] 拆分后仍能通过编译
- [ ] barrel 文件 / part 声明完整
