Fourth Brother's AI Journey

Post-80s Breakthrough: From Programmer to AI's Fourth Dream

article-3-kiss-let-it-crash-golden-rules

KISS Principle + Let It Crash: The Golden Rules of AI Programming

๐ŸŽช The Biggest Trap in AI Programming: The Temptation of Complexity

AI has a natural flaw: it loves to show off. When you give it a simple requirement, it always tries to showcase its "talents" by making simple problems complex.

During the development of Tidepool Notes, I discovered that the KISS Principle and Let it Crash are the two most effective rules for constraining AI and keeping code simple.

Today, I'll teach you how to apply these two golden rules in AI programming.

๐ŸŽฏ KISS Principle: Simplicity is the Ultimate Complexity

What is KISS?

KISS = Keep It Simple, Stupid

  • Keep it simple, don't be clever
  • If you can solve it with 1 line of code, never use 10 lines
  • If you can use a simple solution, never use a complex one

Why AI Violates the KISS Principle?

1. Show-off Mentality
AI wants to prove it's smart, so it tends to use complex technical solutions.

2. Excessive Safety Considerations
AI anticipates various edge cases and future needs, leading to over-engineering.

3. Lack of Context
AI doesn't know your actual business scenario and user scale, so it can only provide "universal" complex solutions.

KISS Practice in Tidepool Notes

Principle 1: 1500-line limit per file

// โŒ Complex code that AI might generate
class AbstractFactoryProviderProxy {
  private decoratorChain: DecoratorPattern[]
  private middlewareStack: MiddlewareComposite[]
  private configurationManager: ConfigurationManager
  private dependencyInjector: DependencyInjector

  constructor() {
    // 200 lines of complex initialization logic
  }

  public createProvider<T>(type: ProviderType): Promise<T> {
    // Complex factory pattern implementation
    // Contains multiple layers of abstraction and indirect calls
  }
}

// โœ… Simple and direct implementation
function createUser(userData: UserData): Promise<User> {
  return prisma.user.create({ data: userData })
}

Principle 2: Single Responsibility Principle

// โŒ "All-purpose function" that AI might write
async function processUserAction(data: any) {
  // Validate user
  // Process data
  // Send notifications
  // Log activities
  // Update statistics
  // Clear cache
  // ... 100 lines of code
}

// โœ… Each function does only one thing
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)
}

Principle 3: Avoid Over-abstraction

// โŒ Over-abstracted configuration management
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 {
  // Complex implementation
}

class DatabaseConfigurationProvider implements ConfigurationProvider {
  // Complex implementation
}

// โœ… Simple configuration object
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 Errors Expose Early

What is Let It Crash?

Let it Crash = Let the program crash

  • When encountering unhandleable errors, crash directly
  • Don't try to mask errors or provide fallback solutions
  • Crashing is the best error message because it exposes the root cause

Misconceptions in Traditional Error Handling

โŒ Traditional "Defensive Programming":

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
  }
}

// Caller needs to handle null
const user = await getUser(userId)
if (user) {
  // Process user
} else {
  // Handle null, but don't know why it's null
}

Problems:

  • Caller doesn't know why null is returned
  • Errors are masked, making debugging difficult
  • Business logic becomes complex

โœ… Let it Crash approach:

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
}

// Caller uses directly, let it crash on error
const user = await getUser(userId) // If error occurs, program crashes, immediately exposing problem
// Process user, no need to check null

Applying Let it Crash in AI Programming

1. Input Validation: Reject Invalid Data

// โŒ "Lenient" validation that AI might write
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 // Default value, masks the problem

// โœ… Strict validation, crash if not valid
function parseAge(input: unknown): number {
  if (typeof input === 'number' && input >= 0 && input <= 150) {
    return input
  }
  throw new Error(`Invalid age: ${input}`)
}

2. Environment Configuration: Crash if Required Config is Missing

// โŒ Overly fault-tolerant
const dbUrl = process.env.DATABASE_URL || 'sqlite://default.db'
const jwtSecret = process.env.JWT_SECRET || 'default-secret'

// โœ… Crash if required config is missing
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 Calls: Fail if Failed, No Fallback

// โŒ Complex retry logic that AI might write
async function callAPI(url: string): Promise<any> {
  try {
    const response = await fetch(url)
    return await response.json()
  } catch (error) {
    // Retry once
    try {
      const response = await fetch(url)
      return await response.json()
    } catch (retryError) {
      // Return empty data
      return {}
    }
  }
}

// โœ… Simple and direct, crash if failed
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()
}

๐Ÿ›ก๏ธ Type Safety: The Most Effective Way to Prevent AI Errors

Although AI is powerful, it's prone to making mistakes in type inference. Using type-safe languages is an effective way to constrain AI.

TypeScript Application in Tidepool Notes

1. Clear Data Type Definitions

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 Response Type Constraints

type ApiResponse<T> = {
  success: boolean
  data?: T
  error?: {
    code: string
    message: string
  }
}

// Usage example
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. Avoid any Type

// โŒ AI might use any
function processUserData(data: any): any {
  // Unsafe processing
}

// โœ… Clear type definitions
interface UserData {
  name: string
  email: string
  age: number
}

function processUserData(data: UserData): ProcessedData {
  // Type-safe processing
}

๐Ÿ“‹ Claude.md: The Soul Document of the Project

Why is Claude.md so Important?

Claude.md is the most important file in AI programming projects. It defines your core requirements and development principles.

Core Content of Tidepool Notes Claude.md:

  1. Project Overview: Positioning as an intelligent emotional companion application
  2. Three-Layer Playbook Architecture: L1 Core Portrait, L2 Recent Battle Report, L3 Current Briefing
  3. Technology Stack Selection: Taro + React + Fastify + PostgreSQL
  4. Development Principles: KISS Principle, Let it Crash, Type Safety
  5. API Modes: Mock/Real/Local three modes
  6. Error Handling Standards: logger.exception, structured error responses

Claude.md Best Practices

1. Keep it Simple and Highlight Key Points

# Project Overview
Tidepool Notes: Providing AI emotional companionship for young people having late-night emotional moments

# Core Principles
- KISS Principle: Simplicity first, single file not exceeding 1500 lines
- Let it Crash: Expose errors directly, don't mask them
- Type Safety: Strict TypeScript usage, avoid any

# Technology Stack
- Frontend: Taro + React + TypeScript
- Backend: Fastify + TypeScript + Prisma
- Database: PostgreSQL
- AI: OpenAI API

2. Include Specific Code Examples and Best Practices

# Error Handling Examples
// โŒ Don't do this
try {
  // some code
} catch (error) {
  return null // Mask errors
}

// โœ… Should do this
try {
  // some code
} catch (error) {
  logger.exception('Error details', error)
  throw error // Let errors expose
}

3. Update Regularly to Reflect New Project Requirements

  • New feature requirements
  • Technology stack adjustments
  • Development principle updates
  • Lessons learned summaries

๐ŸŽฏ Practical Application: Specific Cases in Tidepool Notes

Case 1: Simplification of Message Storage System

AI Initial Solution:

  • Support multiple message formats (text, images, voice, video)
  • Implement message version control
  • Add message search functionality
  • Support message recall and editing
  • Implement message sync and conflict resolution

Simplification after Applying KISS Principle:

  • Only support text messages
  • Simple CRUD operations
  • Display by time order
  • Basic message status (sent, read)

Case 2: User Authentication System Refactoring

Traditional Complex Solution:

  • Multiple login methods (phone, email, WeChat, QQ)
  • Complex permission management system
  • Operation audit logs
  • Password strength validation and reset flow

Simplification after Applying Let it Crash:

  • Only support WeChat login
  • Simple user authentication
  • Login failure crashes directly, no fallback provided
  • Startup fails if necessary configuration is missing

Case 3: Standardization of Error Handling

Complex Error Handling Recommended by AI:

  • Custom error type system
  • Error code mapping table
  • Multi-layer error capture and handling
  • Error recovery and retry mechanisms

Applying Type Safety and Let it Crash:

  • Use strict TypeScript type checking
  • Throw errors directly, log with logger.exception
  • No error compatibility solutions provided
  • Direct crash in development, unified error page in production

๐ŸŒŸ Summary: Golden Rules of AI Programming

KISS Principle Key Points

  1. 1500-line limit per file: Force keeping things simple
  2. Single Responsibility Principle: Each function does only one thing
  3. Avoid Over-abstraction: Don't add complexity for "future needs"
  4. Reject Show-off: Working code is good code

Let it Crash Key Points

  1. Expose Errors Directly: Don't try to mask or make compatible
  2. Crash if Required Configuration Missing: Don't use default values
  3. Throw Exception if Validation Fails: Don't return special values
  4. Crash if API Call Fails: Don't use complex retry logic

Type Safety Key Points

  1. Strict TypeScript Usage: Avoid any types
  2. Clear Interface Definitions: Make AI-generated code more controllable
  3. Runtime Type Validation: Don't trust input data
  4. Compile-time Error Checking: Eliminate problems at the bud stage

Claude.md Key Points

  1. Clearly Define Project Principles: Constrain AI's behavior boundaries
  2. Include Specific Examples: Give AI clear reference templates
  3. Regular Updates and Maintenance: Reflect project's latest requirements
  4. Keep Simple and Clear: Highlight the most important constraints

Remember: AI programming is not about letting AI do what it wants, but letting AI do what you need. The KISS principle and Let it Crash are the best tools to constrain AI.


Next Article Preview: Token Economics in Practice: How to Save 90% of AI Programming Costs


Search "ๅ››ๅ“ฅ่ฟ˜ไผš่ŠAI" on WeChat to see how these principles are applied in actual projects

Search "ๆฑๅฑฟ็ฌ”่ฎฐ" on WeChat to see how these architectural principles are applied in real projects

โ† Back to Home