Ответ
Чистые функции (pure functions) — это функции, которые обладают двумя ключевыми свойствами:
- Детерминированность — для одинаковых входных данных всегда возвращают одинаковый результат
- Отсутствие побочных эффектов — не изменяют внешнее состояние (глобальные переменные, файлы, БД) и не зависят от него
Пример чистой функции в PHP:
// Чистая функция
function calculateDiscount(float $price, float $discountPercent): float {
return $price * (1 - $discountPercent / 100);
}
// Использование
$finalPrice = calculateDiscount(1000, 15); // Всегда 850
$finalPrice2 = calculateDiscount(1000, 15); // Снова 850 - детерминировано
Пример НЕчистой функции:
// Нечистая функция - зависит от внешнего состояния
$taxRate = 20;
function calculatePriceWithTax(float $price): float {
global $taxRate; // Зависимость от глобальной переменной
$taxRate += 1; // Побочный эффект - изменение внешнего состояния
return $price * (1 + $taxRate / 100);
}
// Результат зависит от порядка вызовов
$price1 = calculatePriceWithTax(1000); // 1210 (если taxRate был 20)
$price2 = calculatePriceWithTax(1000); // 1221 - разный результат!
Преимущества чистых функций:
1. Предсказуемость и надежность:
// Легко рассуждать о поведении
$result = calculateDiscount(1000, 10);
// Гарантированно вернет 900, независимо от контекста
2. Простота тестирования:
// Не нужны моки и сложная настройка окружения
public function testCalculateDiscount(): void
{
$this->assertEquals(850, calculateDiscount(1000, 15));
$this->assertEquals(0, calculateDiscount(0, 50));
$this->assertEquals(1000, calculateDiscount(1000, 0));
}
3. Возможность кэширования (мемоизация):
// Реализация простого кэша для чистой функции
function memoizedCalculateDiscount(float $price, float $discountPercent): float {
static $cache = [];
$key = $price . '|' . $discountPercent;
if (!isset($cache[$key])) {
$cache[$key] = $price * (1 - $discountPercent / 100);
}
return $cache[$key];
}
4. Параллельное выполнение:
// Чистые функции можно безопасно выполнять параллельно
$prices = [100, 200, 300, 400];
$discountedPrices = array_map(
fn($price) => calculateDiscount($price, 20),
$prices
);
// Можно распараллелить без риска гонок данных
5. Референциальная прозрачность:
// Вызов функции можно заменить ее результатом
$total = calculateDiscount(1000, 10) + calculateDiscount(500, 10);
// Эквивалентно:
$total = 900 + 450; // 1350
Практическое применение в PHP:
- Функции-хелперы для работы с данными (форматирование, валидация)
- Бизнес-логика в Domain слое (DDD)
- Функциональные преобразования в коллекциях
- Сервисные классы без состояния
Ограничения: Не все можно сделать чистыми функциями — работа с БД, файлами, внешними API по определению имеет побочные эффекты. Ключ в изоляции "нечистых" операций и максимизации использования чистых функций для бизнес-логики.
Ответ 18+ 🔞
Слушай, давай разберёмся с этими чистыми функциями, а то народ иногда нихуя не понимает, зачем это нужно. Представь себе, что ты пишешь код, который должен работать как часы, а не как пьяный слесарь в пятницу вечером.
Чистые функции (pure functions) — это, по сути, такие функции-отличницы, которые всегда ведут себя прилично. У них две главные фишки:
- Детерминированность — скорми им одно и то же, они всегда отплюются одинаковым результатом. Никаких сюрпризов.
- Никаких побочных эффектов — они не шастают по глобальным переменным, не портят файлы и вообще ведут себя скромно, как будто их мама рядом стоит.
Вот тебе пример чистой функции на PHP, чтобы было понятно:
// Чистая функция — святая корова
function calculateDiscount(float $price, float $discountPercent): float {
return $price * (1 - $discountPercent / 100);
}
// Использование
$finalPrice = calculateDiscount(1000, 15); // Всегда 850, ёпта
$finalPrice2 = calculateDiscount(1000, 15); // Опять 850, хоть сто раз вызывай
А вот пример функции, которая ведёт себя как последняя мразота:
// Нечистая функция — настоящий распиздяй
$taxRate = 20;
function calculatePriceWithTax(float $price): float {
global $taxRate; // Лезет в глобальную переменную, как в чужой холодильник
$taxRate += 1; // Побочный эффект — меняет что-то снаружи, ядрёна вошь!
return $price * (1 + $taxRate / 100);
}
// Результат теперь зависит от того, в каком порядке ты её дёргаешь
$price1 = calculatePriceWithTax(1000); // Допустим, 1210
$price2 = calculatePriceWithTax(1000); // А тут уже 1221 — волнение ебать! Где логика?
Так зачем, спрашивается, этот цирк с чистыми функциями? А вот зачем, чувак:
1. Предсказуемость и надёжность — доверия ебать ноль к тем, кто их не использует.
// Не надо гадать на кофейной гуще
$result = calculateDiscount(1000, 10);
// Гарантированно вернёт 900, даже если у тебя сервер горит. Как швейцарские часы.
2. Простота тестирования — не надо городить огород из моков и заглушек.
// Тест пишется за две секунды
public function testCalculateDiscount(): void
{
$this->assertEquals(850, calculateDiscount(1000, 15));
$this->assertEquals(0, calculateDiscount(0, 50));
$this->assertEquals(1000, calculateDiscount(1000, 0));
}
// Никаких подвохов, всё прозрачно, как слёза ребёнка.
3. Возможность кэширования (мемоизация) — чтобы не вычислять одно и то же сто раз.
// Простой кэш — и производительность взлетает
function memoizedCalculateDiscount(float $price, float $discountPercent): float {
static $cache = [];
$key = $price . '|' . $discountPercent;
if (!isset($cache[$key])) {
$cache[$key] = $price * (1 - $discountPercent / 100);
}
return $cache[$key];
}
// Первый раз посчитал, запомнил, дальше просто отдаёт из кэша. Умно, блядь.
4. Параллельное выполнение — можно кидать задачи в разные потоки без страха, что они друг другу нахуй наступят.
$prices = [100, 200, 300, 400];
$discountedPrices = array_map(
fn($price) => calculateDiscount($price, 20),
$prices
);
// Запускай хоть в десяти потоках — гонки данных не будет, потому что функции не лезут в общее состояние.
5. Референциальная прозрачность — это когда вызов функции можно мысленно заменить её результатом, и ничего не сломается.
$total = calculateDiscount(1000, 10) + calculateDiscount(500, 10);
// По сути, то же самое, что:
$total = 900 + 450; // 1350
// Мозг не взрывается, когда пытаешься понять логику.
Где это применить в реальной жизни на PHP?
- Различные хелперы для форматирования данных или валидации.
- Ядро бизнес-логики в Domain слое (это если ты по DDD шаришь).
- Преобразования коллекций в стиле функционального программирования.
- Любые сервисы, которые не тащат за собой состояние, как хвост.
Но есть и ограничения, куда без них. Нельзя же всё сделать чистым — работа с базой данных, файлами или внешними API по своей природе грешна и имеет побочные эффекты. Весь фокус в том, чтобы изолировать эту "грязь" и максимально использовать чистые функции для всей логики, которая может без этого обойтись. Тогда код будет жить долго и счастливо, а не разваливаться при первом чихе.