Ответ
Чистые функции (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 по определению имеет побочные эффекты. Ключ в изоляции "нечистых" операций и максимизации использования чистых функций для бизнес-логики.