Programming Fundamentals for Vibe Coding

Understanding programming fundamentals will significantly improve your ability to work with AI coding tools. Even a basic grasp of these concepts will help you communicate more effectively with AI and understand the code it generates.

While we covered some essential programming concepts earlier, this section will dive deeper into the fundamentals you need to understand to effectively communicate with AI coding tools and work with the code they generate. This knowledge will help you bridge the gap between your ideas and functional applications.

Programming Paradigms

Understanding different programming paradigms helps you choose the right approach for your projects:

Procedural Programming

Procedural programming organizes code as a sequence of steps or procedures:

// Procedural approach to calculating total price
let subtotal = 0;
for (let i = 0; i < items.length; i++) {
  subtotal += items[i].price;
}
let tax = subtotal * 0.08;
let total = subtotal + tax;

When to use: Simple scripts, straightforward algorithms, and when you're just getting started.

Object-Oriented Programming (OOP)

OOP organizes code around objects that contain both data and behavior:

// Object-oriented approach to a shopping cart
class ShoppingCart {
  constructor() {
    this.items = [];
  }

  addItem(item) {
    this.items.push(item);
  }

  calculateTotal() {
    let subtotal = this.items.reduce((sum, item) => sum + item.price, 0);
    let tax = subtotal * 0.08;
    return subtotal + tax;
  }
}

// Usage
const cart = new ShoppingCart();
cart.addItem({ name: "Laptop", price: 999 });
cart.calculateTotal();

When to use: Complex applications, when modeling real-world entities, and for code organization in larger projects.

Functional Programming

Functional programming treats computation as the evaluation of mathematical functions and avoids changing state:

// Functional approach to calculating total price
const calculateSubtotal = items => items.reduce((sum, item) => sum + item.price, 0);
const calculateTax = subtotal => subtotal * 0.08;
const calculateTotal = items => {
  const subtotal = calculateSubtotal(items);
  return subtotal + calculateTax(subtotal);
};

// Usage
const total = calculateTotal(items);

When to use: Data processing, complex calculations, and when you want to avoid side effects and mutable state.

Data Structures and Their Uses

Understanding common data structures helps you organize and manipulate data effectively:

Arrays/Lists

Arrays store ordered collections of items:

// Creating and using arrays
const fruits = ["apple", "banana", "cherry"];
fruits.push("date");  // Add to end
fruits.pop();  // Remove from end
fruits.unshift("apricot");  // Add to beginning
fruits.shift();  // Remove from beginning

When to use: When you need an ordered collection of items, like a list of tasks, products, or user information.

Objects/Dictionaries

Objects store key-value pairs:

// Creating and using objects
const user = {
  name: "John",
  email: "john@example.com",
  age: 30
};

// Accessing properties
console.log(user.name);  // Using dot notation
console.log(user["email"]);  // Using bracket notation

// Adding/modifying properties
user.location = "New York";
user.age = 31;

When to use: When you need to store properties of an entity, like user profiles, product details, or application settings.

Sets

Sets store unique values:

// Creating and using sets
const uniqueTags = new Set();
uniqueTags.add("javascript");
uniqueTags.add("webdev");
uniqueTags.add("javascript");  // Duplicate, won't be added

// Checking if a value exists
uniqueTags.has("javascript");  // true

When to use: When you need to ensure uniqueness, like tracking unique visitors, tags, or categories.

Maps

Maps store key-value pairs with any type of key:

// Creating and using maps
const userRoles = new Map();
userRoles.set(user1, "admin");
userRoles.set(user2, "editor");

// Getting values
userRoles.get(user1);  // "admin"

When to use: When you need to associate data with objects, or when keys aren't simple strings.

Web Development Fundamentals

The DOM (Document Object Model)

The DOM is a programming interface for web documents, representing the page as a tree of objects:

// Selecting elements
const header = document.getElementById("header");
const paragraphs = document.querySelectorAll("p");

// Modifying elements
header.textContent = "New Heading";
header.style.color = "blue";

// Creating elements
const newButton = document.createElement("button");
newButton.textContent = "Click Me";
document.body.appendChild(newButton);

// Handling events
newButton.addEventListener("click", function() {
  alert("Button clicked!");
});

When to use with AI: When describing how to interact with web page elements, create dynamic content, or respond to user actions.

HTTP and APIs

Understanding HTTP requests and APIs is crucial for web applications:

// Fetching data from an API
fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .then(data => {
    console.log(data);
    // Do something with the data
  })
  .catch(error => {
    console.error('There was a problem with the fetch operation:', error);
  });

Modern approach using async/await:

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    console.log(data);
    // Do something with the data
  } catch (error) {
    console.error('There was a problem with the fetch operation:', error);
  }
}

fetchData();

When to use with AI: When building applications that need to retrieve or send data to servers, integrate with external services, or store data in the cloud.

Responsive Design

Responsive design ensures your application works well on all devices:

/* Basic responsive design with CSS */
.container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
}

/* Media queries for different screen sizes */
@media (max-width: 768px) {
  .container {
    padding: 0 20px;
  }

  .column {
    width: 100%;
  }
}

When to use with AI: When describing how your application should adapt to different screen sizes and devices.

Common Programming Patterns

Understanding common patterns helps you communicate more effectively with AI tools:

Event-Driven Programming

Event-driven programming responds to user actions or system events:

// Event-driven programming example
document.getElementById("saveButton").addEventListener("click", function() {
  saveData();
});

window.addEventListener("resize", function() {
  adjustLayout();
});

function saveData() {
  // Code to save data
}

function adjustLayout() {
  // Code to adjust layout based on window size
}

When to use with AI: When building interactive applications that respond to user actions.

CRUD Operations

CRUD (Create, Read, Update, Delete) is a common pattern for data management:

// CRUD operations example
const taskManager = {
  // Create
  createTask(title, description) {
    const task = { id: Date.now(), title, description, completed: false };
    tasks.push(task);
    return task;
  },

  // Read
  getAllTasks() {
    return tasks;
  },

  getTaskById(id) {
    return tasks.find(task => task.id === id);
  },

  // Update
  updateTask(id, updates) {
    const taskIndex = tasks.findIndex(task => task.id === id);
    if (taskIndex !== -1) {
      tasks[taskIndex] = { ...tasks[taskIndex], ...updates };
      return tasks[taskIndex];
    }
    return null;
  },

  // Delete
  deleteTask(id) {
    const taskIndex = tasks.findIndex(task => task.id === id);
    if (taskIndex !== -1) {
      const deletedTask = tasks[taskIndex];
      tasks.splice(taskIndex, 1);
      return deletedTask;
    }
    return null;
  }
};

When to use with AI: When building applications that manage data, like task managers, contact lists, or inventory systems.

MVC Pattern

MVC (Model-View-Controller) separates application concerns:

  • Model: Data and business logic
  • View: User interface
  • Controller: Handles user input and updates model/view
// Simplified MVC example
// Model
class TaskModel {
  constructor() {
    this.tasks = [];
  }

  addTask(task) {
    this.tasks.push(task);
  }

  getTasks() {
    return this.tasks;
  }
}

// View
class TaskView {
  displayTasks(tasks) {
    const taskList = document.getElementById("taskList");
    taskList.innerHTML = "";

    tasks.forEach(task => {
      const li = document.createElement("li");
      li.textContent = task;
      taskList.appendChild(li);
    });
  }
}

// Controller
class TaskController {
  constructor(model, view) {
    this.model = model;
    this.view = view;

    // Initial render
    this.updateView();
  }

  addTask(task) {
    this.model.addTask(task);
    this.updateView();
  }

  updateView() {
    this.view.displayTasks(this.model.getTasks());
  }
}

// Usage
const app = new TaskController(new TaskModel(), new TaskView());
document.getElementById("addButton").addEventListener("click", function() {
  const taskInput = document.getElementById("taskInput");
  app.addTask(taskInput.value);
  taskInput.value = "";
});

When to use with AI: When building larger applications that benefit from clear separation of concerns.

Understanding Code Structure and Syntax

Variables and Scope

Understanding variable scope is crucial for avoiding bugs:

// Global scope
const globalVar = "I'm global";

function exampleFunction() {
  // Function scope
  const functionVar = "I'm function-scoped";

  if (true) {
    // Block scope (let/const)
    let blockVar = "I'm block-scoped";
    var functionScopedVar = "I'm function-scoped despite being in a block";
  }

  console.log(functionVar);  // Works
  console.log(functionScopedVar);  // Works
  console.log(blockVar);  // Error: blockVar is not defined
}

console.log(globalVar);  // Works
console.log(functionVar);  // Error: functionVar is not defined

When to use with AI: When discussing variable accessibility and lifetime in your application.

Asynchronous Programming

Understanding asynchronous code is essential for modern web development:

// Callbacks
function fetchDataWithCallback(callback) {
  setTimeout(() => {
    const data = { name: "John", age: 30 };
    callback(data);
  }, 1000);
}

fetchDataWithCallback(function(data) {
  console.log(data);
});

// Promises
function fetchDataWithPromise() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = { name: "John", age: 30 };
      resolve(data);
    }, 1000);
  });
}

fetchDataWithPromise()
  .then(data => console.log(data))
  .catch(error => console.error(error));

// Async/await
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error(error);
  }
}

fetchData();

When to use with AI: When building applications that involve network requests, timers, or other operations that don't complete immediately.

Error Handling

Proper error handling improves application reliability:

// Try/catch for synchronous code
function divide(a, b) {
  try {
    if (b === 0) {
      throw new Error("Cannot divide by zero");
    }
    return a / b;
  } catch (error) {
    console.error("An error occurred:", error.message);
    return null;
  }
}

// Error handling in asynchronous code
async function fetchUserData(userId) {
  try {
    const response = await fetch(`https://api.example.com/users/${userId}`);

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error("Could not fetch user data:", error.message);
    // Handle specific errors
    if (error.message.includes("404")) {
      alert("User not found");
    } else {
      alert("An error occurred while fetching user data");
    }
    return null;
  }
}

When to use with AI: When building robust applications that need to handle unexpected situations gracefully.

Common Programming Patterns in Different Languages

Understanding how patterns translate across languages helps you adapt AI-generated code:

JavaScript vs. Python Example

JavaScript:

// Array manipulation in JavaScript
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);
const sum = numbers.reduce((total, num) => total + num, 0);
const evens = numbers.filter(num => num % 2 === 0);

Python:

# Array manipulation in Python
numbers = [1, 2, 3, 4, 5]
doubled = [num * 2 for num in numbers]
sum_value = sum(numbers)
evens = [num for num in numbers if num % 2 == 0]

When to use with AI: When you need to adapt code from one language to another, or when you're more comfortable with a specific language.

Practical Application: Reading and Understanding Code

Being able to read and understand code is crucial for vibe coding. Here's a step-by-step approach:

1. Identify the Overall Purpose

Look at file names, comments, and function names to understand what the code is supposed to do.

2. Break Down the Structure

Identify major components:

  • Functions and their purposes
  • Data structures and what they store
  • Control flow (conditionals, loops)

3. Follow the Data Flow

Trace how data moves through the application:

  • Where does data come from? (user input, API, etc.)
  • How is it processed?
  • Where does it end up? (display, storage, etc.)

4. Understand the Control Flow

Follow the execution path:

  • What happens when the application starts?
  • What triggers different functions?
  • How do different parts interact?

5. Look for Patterns

Recognize common programming patterns:

  • Event handling
  • Data manipulation
  • API interactions