KISS原则+Let it Crash,AI编程的黄金法则
🎪 AI编程最大的陷阱:复杂化诱惑
AI有一个天生的毛病:喜欢炫技。当你给它一个简单需求时,它总会想方设法展示自己的"才华",把简单问题复杂化。
在汐屿笔记开发中,我发现KISS原则和Let it Crash是约束AI、保持代码简洁的两个最有效法则。
今天我就告诉你如何在AI编程中应用这两个黄金法则。
🎯 KISS原则:简单是终极的复杂
KISS是什么?
KISS = Keep It Simple, Stupid
- 保持简单,别耍小聪明
- 能用1行代码解决的,绝不用10行
- 能用简单方案的,绝不用复杂方案
AI为什么违反KISS原则?
1. 展示欲作祟
AI想证明自己很聪明,所以倾向于使用复杂的技术方案。
2. 过度安全考虑
AI会预想各种边界情况和未来需求,导致过度设计。
3. 缺乏上下文
AI不知道你的真实业务场景和用户规模,只能给出"通用"的复杂方案。
汐屿笔记的KISS实践
原则1:单文件1500行限制
// ❌ AI可能生成的复杂代码
class AbstractFactoryProviderProxy {
private decoratorChain: DecoratorPattern[]
private middlewareStack: MiddlewareComposite[]
private configurationManager: ConfigurationManager
private dependencyInjector: DependencyInjector
constructor() {
// 200行复杂的初始化逻辑
}
public createProvider<T>(type: ProviderType): Promise<T> {
// 复杂的工厂模式实现
// 包含多层抽象和间接调用
}
}
// ✅ 简单直接的实现
function createUser(userData: UserData): Promise<User> {
return prisma.user.create({ data: userData })
}
原则2:单一职责原则
// ❌ AI可能会写的"万能函数"
async function processUserAction(data: any) {
// 验证用户
// 处理数据
// 发送通知
// 记录日志
// 更新统计
// 清理缓存
// ... 100行代码
}
// ✅ 每个函数只做一件事
async function validateUser(data: UserData): Promise<User> {
return await userValidator.validate(data)
}
async function saveUserData(data: UserData): Promise<User> {
return await userRepository.save(data)
}
async function sendNotification(user: User): Promise<void> {
return await notificationService.send(user)
}
原则3:避免过度抽象
// ❌ 过度抽象的配置管理
interface ConfigurationProvider {
getValue<T>(key: string): T
setValue<T>(key: string, value: T): void
hasKey(key: string): boolean
clear(): void
reload(): Promise<void>
}
class EnvironmentConfigurationProvider implements ConfigurationProvider {
// 复杂的实现
}
class DatabaseConfigurationProvider implements ConfigurationProvider {
// 复杂的实现
}
// ✅ 简单的配置对象
const config = {
apiUrl: process.env.API_URL || 'http://localhost:3001',
databaseUrl: process.env.DATABASE_URL,
jwtSecret: process.env.JWT_SECRET,
}
export function getConfig(key: keyof typeof config) {
return config[key]
}
💥 Let it Crash:让错误尽早暴露
Let it Crash是什么?
Let it Crash = 让程序崩溃吧
- 遇到无法处理的错误,直接崩溃
- 不要试图掩盖错误或提供降级方案
- 崩溃是最好的错误提示,因为它能暴露问题的根源
传统错误处理的误区
❌ 传统的"防御式编程":
async function getUser(id: string): Promise<User | null> {
try {
const user = await prisma.user.findUnique({ where: { id } })
if (!user) {
logger.warn(`User not found: ${id}`)
return null
}
return user
} catch (error) {
logger.error(`Error fetching user: ${error.message}`)
return null
}
}
// 调用方需要处理null
const user = await getUser(userId)
if (user) {
// 处理用户
} else {
// 处理null,但不知道为什么是null
}
问题:
- 调用方不知道为什么返回null
- 错误被掩盖,难以调试
- 业务逻辑变得复杂
✅ Let it Crash的写法:
async function getUser(id: string): Promise<User> {
const user = await prisma.user.findUnique({ where: { id } })
if (!user) {
throw new Error(`User not found: ${id}`)
}
return user
}
// 调用方直接使用,出错就让程序崩溃
const user = await getUser(userId) // 如果出错,程序崩溃,立即暴露问题
// 处理用户,无需检查null
Let it Crash在AI编程中的应用
1. 输入验证:拒绝无效数据
// ❌ AI可能会写的"宽容"验证
function parseAge(input: any): number {
if (typeof input === 'number') return input
if (typeof input === 'string') {
const parsed = parseInt(input)
if (!isNaN(parsed)) return parsed
}
return 0 // 默认值,掩盖了问题
// ✅ 严格验证,不行就崩溃
function parseAge(input: unknown): number {
if (typeof input === 'number' && input >= 0 && input <= 150) {
return input
}
throw new Error(`Invalid age: ${input}`)
}
2. 环境配置:缺少必需配置就崩溃
// ❌ 过度容错
const dbUrl = process.env.DATABASE_URL || 'sqlite://default.db'
const jwtSecret = process.env.JWT_SECRET || 'default-secret'
// ✅ 缺少必需配置就崩溃
if (!process.env.DATABASE_URL) {
throw new Error('DATABASE_URL is required')
}
if (!process.env.JWT_SECRET) {
throw new Error('JWT_SECRET is required')
}
3. API调用:失败就失败,不要降级
// ❌ AI可能会写的复杂重试逻辑
async function callAPI(url: string): Promise<any> {
try {
const response = await fetch(url)
return await response.json()
} catch (error) {
// 重试1次
try {
const response = await fetch(url)
return await response.json()
} catch (retryError) {
// 返回空数据
return {}
}
}
}
// ✅ 简单直接,失败就崩溃
async function callAPI(url: string): Promise<any> {
const response = await fetch(url)
if (!response.ok) {
throw new Error(`API call failed: ${response.status}`)
}
return await response.json()
}
🛡️ 类型安全:避免AI错误的最有效方法
虽然AI很强大,但它在类型推断上容易犯错。使用类型安全语言是约束AI的有效方法。
TypeScript在汐屿笔记中的应用
1. 清晰的数据类型定义
interface UserSession {
id: string
userId: string
status: 'active' | 'completed' | 'paused'
createdAt: Date
updatedAt: Date
}
interface CreateSessionData {
userId: string
initialMood?: 'happy' | 'sad' | 'neutral'
notes?: string
}
2. API响应类型约束
type ApiResponse<T> = {
success: boolean
data?: T
error?: {
code: string
message: string
}
}
// 使用示例
async function createSession(data: CreateSessionData): Promise<ApiResponse<UserSession>> {
try {
const session = await sessionRepository.create(data)
return { success: true, data: session }
} catch (error) {
return {
success: false,
error: {
code: 'SESSION_CREATE_FAILED',
message: error.message
}
}
}
}
3. 避免any类型
// ❌ AI可能会用any
function processUserData(data: any): any {
// 不安全的处理
}
// ✅ 明确类型定义
interface UserData {
name: string
email: string
age: number
}
function processUserData(data: UserData): ProcessedData {
// 类型安全的处理
}
📋 Claude.md:项目的灵魂文档
为什么Claude.md如此重要?
Claude.md是AI编程项目中最重要的文件,它定义了你的核心需求和开发原则。
汐屿笔记Claude.md的核心内容:
- 项目概述:智能情绪陪伴应用的定位
- 三层Playbook架构:L1核心画像、L2近期战报、L3本次简报
- 技术栈选择:Taro + React + Fastify + PostgreSQL
- 开发原则:KISS原则、Let it Crash、类型安全
- API模式:Mock/Real/Local三种模式
- 错误处理标准:logger.exception、结构化错误响应
Claude.md的最佳实践
1. 保持简洁明了,突出重点
# 项目概述
汐屿笔记:为深夜emo的年轻人提供AI情绪陪伴
# 核心原则
- KISS原则:简单至上,单文件不超过1500行
- Let it Crash:错误直接暴露,不要掩盖
- 类型安全:严格使用TypeScript,避免any
# 技术栈
- 前端:Taro + React + TypeScript
- 后端:Fastify + TypeScript + Prisma
- 数据库:PostgreSQL
- AI:OpenAI API
2. 包含具体的代码示例和最佳实践
# 错误处理示例
// ❌ 不要这样做
try {
// some code
} catch (error) {
return null // 掩盖错误
}
// ✅ 应该这样做
try {
// some code
} catch (error) {
logger.exception('Error details', error)
throw error // 让错误暴露
}
3. 定期更新,反映项目的新要求
- 新功能需求
- 技术栈调整
- 开发原则更新
- 经验教训总结
🎯 实战应用:在汐屿笔记中的具体案例
案例1:消息存储系统的简化
AI初始方案:
- 支持多种消息格式(文本、图片、语音、视频)
- 实现消息版本控制
- 添加消息搜索功能
- 支持消息撤回和编辑
- 实现消息同步和冲突解决
应用KISS原则后的简化:
- 只支持文本消息
- 简单的增删改查
- 按时间排序显示
- 基本的消息状态(已发送、已读)
案例2:用户认证系统的重构
传统复杂方案:
- 多种登录方式(手机、邮箱、微信、QQ)
- 复杂的权限管理系统
- 操作审计日志
- 密码强度验证和重置流程
应用Let it Crash后的简化:
- 只支持微信登录
- 简单的用户身份验证
- 登录失败直接崩溃,不提供降级方案
- 缺少必要配置直接启动失败
案例3:错误处理的标准化
AI推荐的复杂错误处理:
- 自定义错误类型体系
- 错误码映射表
- 多层错误捕获和处理
- 错误恢复和重试机制
应用类型安全和Let it Crash:
- 使用TypeScript严格类型检查
- 错误直接抛出,用logger.exception记录
- 不提供错误兼容方案
- 开发环境直接崩溃,生产环境统一错误页面
🌟 总结:AI编程的黄金法则
KISS原则要点
- 单文件1500行限制:强迫保持简单
- 单一职责原则:每个函数只做一件事
- 避免过度抽象:不要为了"未来需求"增加复杂度
- 拒绝炫技:能工作的代码就是好代码
Let it Crash要点
- 错误直接暴露:不要试图掩盖或兼容
- 缺少必需配置直接崩溃:不要使用默认值
- 验证失败直接抛异常:不要返回特殊值
- API调用失败直接崩溃:不要复杂的重试逻辑
类型安全要点
- 严格使用TypeScript:避免any类型
- 清晰的接口定义:让AI生成的代码更可控
- 运行时类型验证:不要相信输入数据
- 编译时错误检查:把问题消灭在萌芽阶段
Claude.md要点
- 明确定义项目原则:约束AI的行为边界
- 包含具体示例:给AI明确的参考模板
- 定期更新维护:反映项目的最新要求
- 保持简洁明了:突出最重要的约束条件
记住:AI编程不是让AI做它想做的,而是让AI做你需要的。KISS原则和Let it Crash就是约束AI的最佳工具。
下一篇预告: 《Token经济学实战:AI编程如何省下90%成本》
微信搜索"四哥还会聊AI",看这些原则如何在实际项目中应用