← Назад к вопросам

Что такое процедурное программирование?

1.3 Junior🔥 201 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Процедурное программирование

Процедурное программирование — это парадигма, где программа состоит из последовательности процедур (функций), которые изменяют состояние данных. Это один из основных подходов в программировании, особенно популярный в старых языках.

Основные принципы

1. Программа как последовательность команд:

// Процедурное программирование - команда за командой
let balance = 1000;
let interest = 0.05;

function addInterest() {
  balance = balance + (balance * interest);
}

function withdraw(amount) {
  if (amount <= balance) {
    balance = balance - amount;
  }
}

function deposit(amount) {
  balance = balance + amount;
}

addInterest();
withdraw(100);
deposit(50);

2. Состояние изменяется явно:

// Переменные глобального состояния
let count = 0;
let messages = [];
let isLoading = false;

// Функции изменяют это состояние
function increment() {
  count = count + 1; // Явное изменение
}

function addMessage(msg) {
  messages.push(msg); // Изменение массива
}

function startLoading() {
  isLoading = true; // Изменение флага
}

3. Сосредоточенность на «как» делать:

// Процедурное: ШАГ ЗА ШАГОМ
function calculateTotal(prices) {
  let total = 0;
  
  for (let i = 0; i < prices.length; i++) {
    total = total + prices[i]; // Шаг 1: перебрать
  }                               // Шаг 2: суммировать
  
  return total;
}

// vs Функциональное (декларативное): ЧТО мы хотим
const calculateTotal = (prices) => prices.reduce((sum, price) => sum + price, 0);

Реальный пример: простой счётчик

// Процедурное программирование
let count = 0; // Глобальное состояние

function increment() {
  count = count + 1;
  updateDisplay();
}

function decrement() {
  count = count - 1;
  updateDisplay();
}

function reset() {
  count = 0; // Явно устанавливаем значение
  updateDisplay();
}

function updateDisplay() {
  document.getElementById('counter').textContent = count;
}

// Использование
increment(); // count = 1
increment(); // count = 2
decrement(); // count = 1
reset();     // count = 0

Минусы процедурного подхода

1. Глобальное состояние (Spaghetti Code):

// Плохо - состояние везде, сложно отследить
let user = null;
let isAuthenticated = false;
let token = null;
let cart = [];
let isLoading = false;

function login(email, password) {
  isLoading = true;
  fetchUser(email, password).then((data) => {
    user = data.user;                    // Изменяем глобальное состояние
    isAuthenticated = true;               // Глобальное состояние
    token = data.token;                   // Глобальное состояние
    isLoading = false;                    // Глобальное состояние
  });
}

function addToCart(item) {
  if (!isAuthenticated) {                 // Зависит от глобального состояния
    return;
  }
  cart.push(item);                        // Изменяем глобальное состояние
}

2. Сложно тестировать:

// Процедурное - нужно мокировать всё
let globalData = { count: 0 };

function increment() {
  globalData.count++; // Зависит от глобального состояния
}

// Тест - нужно сбрасывать состояние
beforeEach(() => {
  globalData = { count: 0 }; // Очистка
});

test('increment', () => {
  increment();
  expect(globalData.count).toBe(1);
});

3. Побочные эффекты везде:

// Процедурное - побочные эффекты
let results = [];

function process(items) {
  results = []; // Модифицирует внешнее состояние
  
  for (let item of items) {
    const processed = item * 2;
    results.push(processed); // Побочный эффект
    console.log(processed);  // Побочный эффект
  }
  
  return results; // Но также возвращает значение
}

Процедурное vs Объектное vs Функциональное

// === ПРОЦЕДУРНОЕ ===
let balance = 100;

function withdraw(amount) {
  balance -= amount; // Изменяет внешнее состояние
}

// === ОБЪЕКТНОЕ (ООП) ===
class Account {
  constructor(initialBalance) {
    this.balance = initialBalance; // Состояние в объекте
  }
  
  withdraw(amount) {
    this.balance -= amount; // Изменяет состояние объекта
  }
}

// === ФУНКЦИОНАЛЬНОЕ ===
function withdraw(account, amount) {
  return {
    ...account,
    balance: account.balance - amount // Создаёт новый объект
  };
}

// Использование
const newAccount = withdraw(account, 50); // Не изменяет оригинальный

Когда процедурное программирование ХОРОШО

// 1. Простые скрипты
function generateReport() {
  const data = loadData();
  const processed = processData(data);
  const sorted = sortData(processed);
  displayReport(sorted);
}

// 2. Пошаговые алгоритмы
function bubbleSort(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
      }
    }
  }
  return arr;
}

// 3. Скрипты для обработки данных
function processCSV(data) {
  const lines = data.split('\n');
  const result = [];
  
  for (let line of lines) {
    const values = line.split(',');
    result.push({ name: values[0], age: values[1] });
  }
  
  return result;
}

Процедурное программирование в контексте Frontend

// jQuery эпоха - процедурное программирование
$(document).ready(function() {
  let todos = [];
  
  $('#add-btn').click(function() {
    const text = $('#input').val();
    todos.push({ id: Date.now(), text: text, done: false });
    $('#input').val('');
    renderTodos(); // Пересчитываем весь список
  });
  
  function renderTodos() {
    $('#list').empty(); // Очищаем
    
    todos.forEach(function(todo) {
      const li = '<li>' + todo.text + '</li>';
      $('#list').append(li); // Добавляем
    });
  }
});

// vs Современный React (декларативный)
function TodoApp() {
  const [todos, setTodos] = useState([]);
  
  return (
    <div>
      <input
        onChange={(e) => {
          // Не вызываем функции, просто описываем как должно выглядеть
        }}
      />
      <ul>
        {todos.map((todo) => (
          <li key={todo.id}>{todo.text}</li>
        ))}
      </ul>
    </div>
  );
}

Проблемы в больших приложениях

// Процедурное программирование становится ужасным когда много кода
let globalState = {
  user: null,
  cart: [],
  notifications: [],
  isLoading: false,
  // ... ещё 20 переменных
};

function updateUser() { /* ... */ }
function addToCart() { /* ... */ }
function removeFromCart() { /* ... */ }
function checkout() { /* ... */ }
function login() { /* ... */ }
// ... ещё 30 функций, всё модифицирует globalState

// РЕЗУЛЬТАТ: Impossible to debug, hard to test, spaghetti code

Вывод

Процедурное программирование:

  • Программа = последовательность команд
  • Состояние хранится в переменных
  • Функции изменяют это состояние
  • Подходит для простых скриптов
  • Плохо масштабируется на больших приложениях

В Frontend:

  • jQuery эра — процедурное программирование
  • React/Vue era — функциональное/компонентное (лучше)
  • Всё же процедурный код работает везде (старые браузеры, простые скрипты)

Современный подход:

  • Избегай глобального состояния
  • Используй React/Vue для управления состоянием
  • Функции без побочных эффектов где возможно
  • Тестируй компоненты, не глобальные переменные