架构即代码:如何用系统化思维驯服AI
🧠 AI编程的终极困境:你是在"使用AI"还是"被AI使用"?
大多数人在AI编程中都陷入了一个悖论:本来是想让AI提高效率,结果却花大量时间在"纠正AI"和"修复AI生成的问题"上。
问题的根源在于:缺乏系统化架构思维。没有好的架构,AI就像一匹野马,有能力但不可控。
在希语低喃心绪笔记开发中,我总结出一套"架构即代码"的方法论,让AI从"不可控的天才"变成"听话的专家"。
🎯 核心认知:架构先于代码,规则先于功能
传统AI编程的误区
❌ 典型的错误流程:
- 有一个想法
- 直接让AI写代码
- AI生成复杂的解决方案
- 发现不对,让AI修改
- 问题越来越多,项目失控
问题在哪里?
- 没有明确的架构边界
- 没有预先定义的规则
- 没有系统化的约束机制
- AI在"自由发挥",偏离了真实需求
架构即代码的正确流程
✅ 系统化的正确流程:
- 定义架构原则和边界
- 创建规则约束和模板
- 让AI在框架内工作
- 通过架构控制输出质量
- 持续优化架构本身
🏗️ 第一层:项目级架构约束
1. 技术栈的强制约束
问题:AI为什么会推荐不合适的技术栈?
- AI倾向于推荐"最新最热"的技术
- 缺乏对项目真实需求的了解
- 过度考虑"未来可能的扩展需求"
解决方案:在Claude.md中强制锁定技术栈
## 技术栈强制约束(不可更改)
### 前端技术栈(锁死)
- 框架:Taro 4.1.7 + React 18(不得使用Vue、Next.js等)
- 语言:TypeScript 5.4.5(严格模式,不得使用any)
- 状态管理:React Context + useReducer(不得使用Redux、Zustand等)
- 样式:SCSS + CSS变量(不得使用Tailwind、Styled Components等)
- 图表:ECharts(不得使用Chart.js、D3等)
### 后端技术栈(锁死)
- 运行时:Node.js 18+(不得使用Python、Java等)
- 框架:Fastify(不得使用Express、Koa等)
- 数据库:PostgreSQL 14+(不得使用MySQL、MongoDB等)
- ORM:Prisma(不得使用TypeORM、Sequelize等)
- 认证:JWT(不得使用Session、OAuth等)
### 禁止使用的技术
- ❌ 任何形式的微服务架构
- ❌ 消息队列(Redis Queue、RabbitMQ等)
- ❌ 复杂的缓存策略
- ❌ 多数据库设计
效果:AI无法再推荐"炫技"方案,只能在给定框架内解决问题
2. 文件结构的强制规范
问题:AI为什么喜欢创建复杂的文件结构?
- 受到"最佳实践"文章影响
- 倾向于过度分层和抽象
- 不理解小项目的实际需求
解决方案:定义精确的文件结构模板
## 强制文件结构(不可违背)
project/
├── frontend/
│ └── tidepool/
│ ├── src/
│ │ ├── app.tsx # 应用入口,不超过100行
│ │ ├── context/ # 全局状态,每个文件不超过200行
│ │ │ └── AppContext.tsx
│ │ ├── pages/ # 页面组件,每个文件不超过300行
│ │ │ ├── index/
│ │ │ ├── record/
│ │ │ ├── chat/
│ │ │ ├── insights/
│ │ │ └── settings/
│ │ ├── components/ # 通用组件,每个文件不超过200行
│ │ │ ├── PageWrapper.tsx
│ │ │ ├── CustomTabBar.tsx
│ │ │ └── SketchIcon.tsx
│ │ ├── services/ # API服务,每个文件不超过300行
│ │ │ └── api.ts
│ │ └── types/ # 类型定义,每个文件不超过150行
│ │ └── index.ts
│ └── config/ # 配置文件,不可更改
│ └── apiConfig.js
└── backend/
└── src/
├── routes/ # API路由,每个文件不超过200行
│ ├── auth.routes.ts
│ ├── users.routes.ts
│ └── sessions.routes.ts
├── services/ # 业务逻辑,每个文件不超过400行
│ ├── auth.service.ts
│ ├── users.service.ts
│ └── llm.service.ts
├── repositories/ # 数据访问,每个文件不超过300行
│ ├── users.repository.ts
│ └── sessions.repository.ts
└── types/ # 类型定义,每个文件不超过150行
├── users.types.ts
└── sessions.types.ts
**关键约束:**
- 单文件不超过1500行(AI上下文窗口限制)
- 目录结构不可更改
- 文件命名必须遵循规范
- 禁止创建额外的utils、helpers等目录
3. 依赖管理的强制规则
问题:AI为什么喜欢添加不必要的依赖?
- 倾向于使用"专门的库"解决简单问题
- 受到GitHub stars数量影响
- 不理解依赖维护的成本
解决方案:制定严格的依赖管理规则
## 依赖管理强制规则
### 禁止添加的依赖类型
- ❌ 任何形式的工具库(lodash、date-fns、classnames等)
- ❌ 任何UI组件库(Ant Design、Material-UI等)
- ❌ 任何表单验证库(yup、zod、joi等)
- ❌ 任何HTTP客户端库(axios、got等,用原生fetch)
- ❌ 任何状态管理库(redux、mobx、zustand等)
### 必须使用原生实现的场景
```typescript
// ❌ 禁止使用lodash
import { map, filter, find } from 'lodash'
// ✅ 使用原生JavaScript
const filtered = users.filter(user => user.age > 18)
const found = users.find(user => user.id === targetId)
// ❌ 禁止使用date-fns
import { format, addDays } from 'date-fns'
format(new Date(), 'yyyy-MM-dd')
// ✅ 使用原生Date
const formatDate = (date: Date) => {
return date.toISOString().split('T')[0]
}
// ❌ 禁止使用axios
import axios from 'axios'
const response = await axios.get('/api/users')
// ✅ 使用原生fetch
const response = await fetch('/api/users')
const data = await response.json()
依赖决策树
需要功能F?
├── 是否可用JavaScript原生API实现?
│ ├── 是 → 使用原生实现
│ └── 否 → 检查是否为项目核心需求
│ ├── 是 → 考虑添加依赖(需要充分理由)
│ └── 否 → 重新设计需求,避免依赖
🧩 第二层:代码级架构约束
1. 函数设计的强制规范
问题:AI为什么写出复杂的函数?
- 倾向于展示"全面考虑"
- 过度处理边界情况
- 喜欢使用复杂的设计模式
解决方案:函数设计的三重约束
// ✅ 函数模板:强制简洁
export class TemplateService {
// 约束1:单个函数不超过50行
async create(data: CreateData): Promise<ReturnData> {
// 约束2:只有必要的错误处理
try {
const result = await repository.create(data)
logger.info(`Entity created: ${result.id}`)
return result
} catch (error) {
logger.exception('Create failed', error)
throw error
}
}
// 约束3:单一职责,不做多余的事情
private validate(data: CreateData): void {
if (!data.requiredField) {
throw new Error('Required field missing')
}
}
}
// ❌ AI可能会生成的复杂函数
export class ComplexService {
async createComplexEntity(data: ComplexInput): Promise<ComplexResult> {
// 过度输入验证(50行)
this.validateInputFormat(data)
this.validateBusinessRules(data)
this.validatePermissions(data)
this.validateDependencies(data)
// 复杂的重试逻辑(30行)
const result = await this.withRetry(async () => {
return await this.performComplexCreation(data)
}, { retries: 3, backoff: 'exponential' })
// 过度的日志记录(20行)
logger.debug('Starting creation process', { dataId: data.id })
logger.info('Validation passed', { validationResults: this.lastValidation })
logger.info('Creation completed', { resultId: result.id })
// 不必要的缓存处理(15行)
await this.updateCache(result)
await this.invalidateRelatedCache(result.relatedEntities)
return result
}
}
2. 错误处理的统一标准
问题:AI为什么设计复杂的错误处理?
- 倾向于"兼容所有情况"
- 喜欢创建复杂的错误分类体系
- 过度考虑用户体验
解决方案:Let it Crash + 统一错误格式
// ✅ 统一的错误处理模板
export class StandardService {
async operation(data: InputData): Promise<OutputData> {
try {
const result = await repository.operation(data)
return result
} catch (error) {
// 统一格式:记录 + 抛出
logger.exception('Operation failed', error)
throw new Error(`Operation failed: ${error.message}`)
}
}
}
// ❌ AI可能会生成的复杂错误处理
export class ComplexErrorService {
async operation(data: InputData): Promise<OutputData | null> {
try {
const result = await repository.operation(data)
return result
} catch (error) {
// 过度的错误分类
if (error instanceof ValidationError) {
return { error: 'VALIDATION_ERROR', details: error.details }
} else if (error instanceof PermissionError) {
return { error: 'PERMISSION_DENIED' }
} else if (error instanceof NetworkError) {
// 复杂的重试逻辑
return await this.retryWithBackoff(() => repository.operation(data))
} else {
// 返回null而不是抛出错误
return null
}
}
}
}
3. 类设计的简约原则
问题:AI为什么喜欢过度设计类结构?
- 受到设计模式书籍影响
- 倾向于"为未来扩展做准备"
- 喜欢使用继承和抽象
解决方案:禁止过度抽象,强制组合
// ✅ 简单的组合设计
export class UserService {
constructor(
private userRepository: UserRepository,
private logger: Logger
) {}
async create(userData: CreateUserInput): Promise<User> {
const user = await this.userRepository.create(userData)
this.logger.info(`User created: ${user.id}`)
return user
}
}
// ❌ AI可能会生成的复杂继承结构
abstract class BaseService<T, CreateInput, UpdateInput> {
protected abstract repository: Repository<T, CreateInput, UpdateInput>
protected abstract logger: Logger
protected abstract validator: Validator<T>
async create(data: CreateInput): Promise<T> {
await this.validator.validate(data)
const result = await this.repository.create(data)
this.logger.info(`${this.getEntityName()} created: ${result.id}`)
return result
}
protected abstract getEntityName(): string
}
class UserService extends BaseService<User, CreateUserInput, UpdateInput> {
// 复杂的模板方法模式
}
🔧 第三层:流程级架构约束
1. 开发流程的标准化
问题:为什么AI编程项目容易失控?
- 缺乏清晰的开发节奏
- 没有明确的完成标准
- 缺乏持续的质量控制
解决方案:标准化的开发流程
## 强制开发流程
### 阶段1:架构定义(不可跳过)
1. 创建/更新Claude.md文档
2. 定义明确的需求边界
3. 确定技术栈约束
4. 创建文件结构模板
### 阶段2:骨架搭建(必须先做)
1. 创建所有必要的目录结构
2. 定义TypeScript接口
3. 创建基础的CRUD操作
4. 设置基础的错误处理
### 阶段3:功能实现(严格按顺序)
1. 先实现数据层(repositories)
2. 再实现业务层(services)
3. 最后实现接口层(routes)
4. 每层完成后必须测试通过
### 阶段4:质量检查(必须执行)
1. 文件行数检查(不超过1500行)
2. 类型检查(noImplicitAny: true)
3. 代码风格检查(ESLint)
4. 单元测试覆盖率检查
### 每日质量门禁
- [ ] 所有文件不超过1500行
- [ ] 没有使用any类型
- [ ] 所有错误都正确抛出
- [ ] 依赖项符合约束规则
- [ ] 函数职责单一
2. 代码审查的强制要求
问题:如何确保AI生成的代码符合架构要求?
## 强制代码审查清单
### 架构一致性检查
- [ ] 文件结构是否符合规范
- [ ] 依赖关系是否正确
- [ ] 接口设计是否一致
- [ ] 错误处理是否统一
### 质量标准检查
- [ ] 函数长度不超过50行
- [ ] 类的职责是否单一
- [ ] 是否有不必要的复杂性
- [ ] 是否遵循KISS原则
### 约束规则检查
- [ ] 没有使用禁止的依赖
- [ ] 没有使用any类型
- [ ] 错误是否正确抛出
- [ ] 日志格式是否统一
### 性能和安全检查
- [ ] 没有不必要的数据库查询
- [ ] 输入验证是否充分
- [ ] 敏感信息是否正确处理
- [ ] API响应是否合理
3. 重构的自动化机制
解决方案:自动化架构守护
// scripts/archural-guard.ts
import fs from 'fs'
import path from 'path'
interface ArchitecturalRule {
name: string
check: (filePath: string, content: string) => boolean
message: string
}
const rules: ArchitecturalRule[] = [
{
name: 'file-size-limit',
check: (filePath, content) => {
const lines = content.split('\n').length
return lines <= 1500
},
message: 'File exceeds 1500 lines limit'
},
{
name: 'no-any-types',
check: (filePath, content) => {
return !content.includes(': any') && !content.includes('as any')
},
message: 'Found usage of any type'
},
{
name: 'required-imports',
check: (filePath, content) => {
if (filePath.endsWith('.ts')) {
return content.includes('import traceback')
}
return true
},
message: 'Missing import traceback statement'
},
{
name: 'error-handling',
check: (filePath, content) => {
if (filePath.includes('service')) {
return content.includes('logger.exception')
}
return true
},
message: 'Service files must use logger.exception for error handling'
}
]
function checkArchitecture() {
const srcDir = './src'
const files = getAllTypeScriptFiles(srcDir)
let hasViolations = false
files.forEach(file => {
const content = fs.readFileSync(file, 'utf8')
rules.forEach(rule => {
if (!rule.check(file, content)) {
console.error(`❌ [${rule.name}] ${file}: ${rule.message}`)
hasViolations = true
}
})
})
if (hasViolations) {
console.error('\n❌ Architecture check failed!')
process.exit(1)
} else {
console.log('✅ Architecture check passed!')
}
}
checkArchitecture()
🎯 实战案例:希语低喃心绪笔记的架构演进
案例1:消息系统的架构重构
初始状态(AI自由发挥的结果):
// AI生成的复杂消息系统
class MessageManager {
// 支持多种消息类型
async createTextMessage(data: TextMessageData): Promise<TextMessage>
async createImageMessage(data: ImageMessageData): Promise<ImageMessage>
async createVoiceMessage(data: VoiceMessageData): Promise<VoiceMessage>
async createVideoMessage(data: VideoMessageData): Promise<VideoMessage>
// 复杂的消息处理流程
async processMessage(message: Message): Promise<ProcessedMessage> {
await this.validateMessage(message)
await this.transformMessage(message)
await this.enrichMessage(message)
await this.routeMessage(message)
await this.indexMessage(message)
await this.cacheMessage(message)
return this.formatMessage(message)
}
// 过度的错误处理
async handleError(error: Error, context: ErrorContext): Promise<ErrorResult> {
// 50行复杂的错误分类和处理逻辑
}
}
应用架构约束后的简化:
// 约束后的消息系统
export class MessageService {
constructor(
private messageRepository: MessageRepository,
private logger: Logger
) {}
async create(data: CreateMessageData): Promise<Message> {
try {
const message = await this.messageRepository.create(data)
this.logger.info(`Message created: ${message.id}`)
return message
} catch (error) {
this.logger.exception('Failed to create message', error)
throw error
}
}
async findBySessionId(sessionId: string): Promise<Message[]> {
return await this.messageRepository.findBySessionId(sessionId)
}
}
架构约束带来的效果:
- 代码行数从800行减少到150行
- 维护成本降低70%
- AI生成的一致性提高90%
- 新功能开发速度提升50%
案例2:AI集成的标准化
AI自由发挥的复杂方案:
// AI倾向于过度设计LLM集成
class LLMOrchestrator {
constructor() {
this.promptManager = new ComplexPromptManager()
this.conversationManager = new ConversationStateManager()
this.responseParser = new MultiFormatResponseParser()
this.errorHandler = new RetryWithBackoffHandler()
this.cacheManager = new MultiLevelCacheManager()
}
async generateResponse(input: UserInput): Promise<AIResponse> {
// 复杂的多层处理逻辑
const context = await this.conversationManager.getContext(input)
const prompt = await this.promptManager.buildPrompt(context, input)
const rawResponse = await this.callLLMWithRetry(prompt)
const parsedResponse = await this.responseParser.parse(rawResponse)
const enrichedResponse = await this.enrichResponse(parsedResponse)
await this.cacheManager.store(input, enrichedResponse)
return enrichedResponse
}
}
架构约束后的标准化:
// 标准化的LLM集成
export class LLMService {
constructor(
private openaiClient: OpenAIClient,
private logger: Logger
) {}
async generateSuggestion(sessionData: SessionData): Promise<string> {
try {
const prompt = this.buildPrompt(sessionData)
const response = await this.openaiClient.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }],
temperature: 0.7,
max_tokens: 1000
})
return response.choices[0].message.content
} catch (error) {
this.logger.exception('Failed to generate suggestion', error)
throw error
}
}
private buildPrompt(sessionData: SessionData): string {
return `基于用户会话数据,提供情绪建议:${JSON.stringify(sessionData)}`
}
}
案例3:架构守护的自动化
实现的自动化检查:
// 每次提交前自动执行
{
"scripts": {
"pre-commit": "npm run type-check && npm run lint && npm run arch-check",
"arch-check": "ts-node scripts/architectural-guard.ts",
"type-check": "tsc --noEmit",
"lint": "eslint src --ext .ts"
}
}
// CI/CD管道中的架构检查
name: Architecture Check
on: [push, pull_request]
jobs:
check-architecture:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- run: npm install
- run: npm run arch-check
- run: npm run test
🌟 总结:架构即代码的核心原则
架构思维的三个层次
1. 项目级架构(顶层设计)
- 明确的技术栈约束
- 标准化的文件结构
- 严格的依赖管理规则
- 统一的开发流程
2. 代码级架构(中层控制)
- 函数设计的三重约束
- 错误处理的统一标准
- 类设计的简约原则
- 接口设计的一致性
3. 流程级架构(底层保障)
- 标准化的开发流程
- 强制的代码审查
- 自动化的架构守护
- 持续的质量控制
实施架构即代码的步骤
第一步:建立架构文档
- 创建详细的Claude.md
- 定义明确的约束规则
- 提供具体的代码模板
- 制定质量检查清单
第二步:实现自动化守护
- 创建架构检查脚本
- 集成到CI/CD流程
- 设置代码质量门禁
- 建立持续监控机制
第三步:持续优化架构
- 定期回顾架构效果
- 根据实际问题调整规则
- 优化自动化检查机制
- 分享架构实践经验
关键成功要素
1. 约束的明确性
- 每个规则都要具体可执行
- 提供正面和负面示例
- 定期检查规则的有效性
- 及时更新过时的约束
2. 工具的自动化
- 减少人工检查的依赖
- 集成到开发工作流
- 提供清晰的错误反馈
- 确保检查的快速执行
3. 文化的持续性
- 团队对架构约束的认同
- 持续的架构思维培训
- 定期的架构评审会议
- 开放的问题反馈机制
记住:AI编程的核心不是"让AI做什么",而是"让AI不做什么"。好的架构就是为AI划定清晰的边界,让它在可控的范围内发挥价值。
下一篇预告: 《提示工程即架构:如何让AI理解你的真实需求》
微信搜索"四哥还会聊AI",看这些架构原则如何在实际项目中创造价值