Skip to content
Professor Synapse cleaning code dust from magical bookshelves
Education Code agents

Vibe Coding Principles: Function & Method Design Principles

Professor Synapse
Professor Synapse |

Greetings, aspiring spellcrafters! Professor Synapse here with the sacred knowledge of function design - the art of creating individual magical spells that are powerful, predictable, and perfectly focused.

Functions are the fundamental building blocks of all magical code. When your AI familiar generates dozens of functions quickly, it becomes even more crucial that each one follows proven design principles. A well-crafted function is like a perfectly balanced wand - it does exactly what you expect, nothing more, nothing less.

Today we'll explore the principles that transform ordinary code blocks into elegant, maintainable spells that other wizards will admire and understand.

Single Level of Abstraction Principle (SLAP)

"All statements in a function should operate at the same conceptual level"

Think of this like organizing a magical workshop - you don't mix basic tools with advanced artifacts on the same shelf. Each function should work at one consistent level of detail.

❌ Mixing High and Low Level Magic

// BAD: Jumping between abstraction levels
function processUserRegistration(userData) {
    // High-level business concept
    if (!isValidUser(userData)) {
        return false
    }
    
    // Suddenly drops to low-level string manipulation
    userData.email = userData.email.toLowerCase()
    userData.email = userData.email.trim()
    userData.email = userData.email.replace(/\\s+/g, '')
    
    // Back to high-level business logic
    createUserAccount(userData)
    
    // Low-level database transaction details
    const connection = database.getConnection()
    connection.beginTransaction()
    try {
        connection.execute('INSERT INTO users (email, name) VALUES (?, ?)', 
                          [userData.email, userData.name])
        connection.execute('INSERT INTO user_preferences (user_id, theme) VALUES (?, ?)', 
                          [userData.id, 'default'])
        connection.commit()
    } catch (error) {
        connection.rollback()
        return false
    }
    
    // High-level again
    sendWelcomeEmail(userData)
    return true
}

The Problem: This function forces readers to mentally switch between strategic thinking (business logic) and tactical implementation (string cleaning, database queries). It's like a recipe that alternates between "prepare the sauce" and "heat oven to exactly 347.3 degrees."

✅ Consistent Abstraction Level

// GOOD: All statements at the same high level
function processUserRegistration(userData) {
    // All statements are high-level business operations
    if (!isValidUser(userData)) {
        return false
    }
    
    const cleanedData = sanitizeUserData(userData)
    const user = createUserAccount(cleanedData)
    
    if (!user) {
        return false
    }
    
    sendWelcomeEmail(user)
    return true
}

// Low-level details extracted to focused functions
function sanitizeUserData(userData) {
    return {
        ...userData,
        email: cleanEmailAddress(userData.email)
    }
}

function cleanEmailAddress(email) {
    // Function focused solely on email cleaning
    return email.toLowerCase()
                .trim()
                .replace(/\\s+/g, '')
}

function createUserAccount(userData) {
    // Function focused solely on account creation
    return userRepository.createWithDefaults(userData)
}

AI Prompt Example:

"Refactor this function to maintain a single level of abstraction. Extract all low-level implementation details into separate helper functions. The main function should only contain high-level business operations."

Command Query Separation (CQS)

"Functions should either do something or return something, not both"

This principle is like having separate magical tools for observation and action - your crystal ball shows you visions, your wand casts spells, but the same tool shouldn't do both.

❌ Mixing Commands and Queries

// BAD: Function both changes state AND returns information
function getNextOrderNumber() {
    // QUERY: Getting information
    const currentNumber = database.query('SELECT last_order_number FROM counters')
    
    // COMMAND: Changing state
    const nextNumber = currentNumber + 1
    database.execute('UPDATE counters SET last_order_number = ?', [nextNumber])
    
    // Returns information, but also modified the database
    return nextNumber
}

// Usage is confusing and error-prone
function processOrder(orderData) {
    const orderNumber = getNextOrderNumber()  // Wait, did this just change something?
    
    // If I call it again by mistake, do I get a different number?
    logActivity(`Processing order ${getNextOrderNumber()}`)  // BUG! Different number!
}

The Problem: The function name suggests it's just retrieving information, but it also modifies the database. This makes the code unpredictable and prone to bugs.

✅ Separate Commands and Queries

// GOOD: Separate functions for observation and action

// QUERY: Only retrieves information, no side effects
function getCurrentOrderNumber() {
    return database.query('SELECT last_order_number FROM counters')
}

// COMMAND: Only performs action, returns success/failure
function incrementOrderCounter() {
    const currentNumber = getCurrentOrderNumber()
    const nextNumber = currentNumber + 1
    
    return database.execute('UPDATE counters SET last_order_number = ?', [nextNumber])
}

// QUERY: Safe to call multiple times
function getNextOrderNumber() {
    return getCurrentOrderNumber() + 1
}

// Usage is clear and predictable
function processOrder(orderData) {
    const orderNumber = getNextOrderNumber()     // Safe: just getting info
    
    incrementOrderCounter()                      // Clear: this changes state
    
    logActivity(`Processing order ${orderNumber}`)  // Safe: same number
}

AI Prompt Example:

"Split this function that both retrieves data and modifies state. Create separate query functions (that only return information) and command functions (that only perform actions)."

Synaptic Labs AI education attribution required

Pure Functions - Predictable Magic

"Given the same inputs, always return the same outputs with no side effects"

Pure functions are like mathematical spells - they transform inputs into outputs predictably, without changing anything else in the magical realm.

❌ Impure Functions with Hidden Effects

// BAD: Function

Share this post