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

Является ли функция time() "Чистой" в PHP?

2.0 Middle🔥 71 комментариев
#PHP Core#Архитектура и паттерны

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

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

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

Что такое "чистая" функция?

В контексте программирования чистая функция (pure function) — это функция, которая:

  1. Всегда возвращает одинаковый результат для одних и тех же входных аргументов (детерминированность).
  2. Не имеет побочных эффектов — не изменяет внешнее состояние (глобальные переменные, файлы, базу данных и т.д.).

Анализ функции time() в PHP

Нет, функция time() в PHP не является "чистой" функцией.

Почему time() нарушает первое правило чистых функций?

time() возвращает текущую метку времени Unix (количество секунд, прошедших с 1 января 1970 года). Даже при одинаковых аргументах (функция не принимает параметров) ее результат всегда разный при каждом вызове, так как зависит от внешнего состояния — системного времени.

// Пример, демонстрирующий недетерминированность time()
$firstCall = time();
sleep(1);
$secondCall = time();

var_dump($firstCall === $secondCall); // bool(false) - результаты разные

Почему time() нарушает второе правило?

Хотя сама функция time() не изменяет явно глобальные переменные или файлы, она зависит от внешнего состояния системы (системные часы). В некоторых контекстах это может считаться "чтением" внешнего состояния, что также противоречит строгому определению чистоты.

Практические последствия для тестирования

Непредсказуемость time() создает сложности при модульном тестировании:

// Проблемный код для тестирования
function isEventExpired(int $eventTimestamp): bool {
    return time() > $eventTimestamp;
}

// Тест будет неустойчивым, так как зависит от момента запуска
public function testIsEventExpired(): void {
    $expiredTimestamp = time() - 3600; // событие истекло час назад
    $this->assertTrue(isEventExpired($expiredTimestamp)); // Пройдет СЕЙЧАС
    
    // Но если бы мы запустили тест ДО создания события, он бы не прошел
}

Как сделать код с временными зависимостями "чистым" и тестируемым?

1. Внедрение зависимости времени

// "Чистая" версия функции
function isEventExpired(int $eventTimestamp, ?int $currentTime = null): bool {
    $currentTime = $currentTime ?? time();
    return $currentTime > $eventTimestamp;
}

// Теперь функция детерминирована и тестируема
public function testIsEventExpired(): void {
    $eventTimestamp = 1000;
    $this->assertTrue(isEventExpired($eventTimestamp, 2000)); // Всегда true
    $this->assertFalse(isEventExpired($eventTimestamp, 500)); // Всегда false
}

2. Использование паттерна "Clock" или "Time Provider"

interface Clock {
    public function now(): int;
}

class SystemClock implements Clock {
    public function now(): int {
        return time();
    }
}

class FixedClock implements Clock {
    private int $fixedTime;
    
    public function __construct(int $fixedTime) {
        $this->fixedTime = $fixedTime;
    }
    
    public function now(): int {
        return $this->fixedTime;
    }
}

// В производственном коде
$service = new EventService(new SystemClock());

// В тестах
$service = new EventService(new FixedClock(1234567890));

3. Функциональные подходы в современных PHP-фреймворках

Многие современные фреймворки предоставляют утилиты для работы со временем:

  • Laravel: фасад now() с возможностью "заморозки" времени в тестах
  • Symfony: компонент Clock с заменяемыми реализациями

Вывод

time() — классический пример нечистой функции, что делает код, ее использующий, трудным для тестирования и подверженным скрытым зависимостям. В production-коде рекомендуется применять подходы с инъекцией времени или абстракцией часов, которые:

  • Делают код детерминированным и предсказуемым
  • Упрощают написание стабильных тестов
  • Позволяют легко менять источник времени при необходимости
  • Способствуют соблюдению принципа единственной ответственности

Осознание "чистоты" функций важно не только для теоретического понимания функционального программирования, но и для написания надежного, поддерживаемого кода в реальных PHP-приложениях.