Контракт функции начинается с вопроса о данных
Функция должна иметь понятное назначение: что принимает и что возвращает при корректном выполнении. Число, строка с цифрами и отсутствие значения являются разными ситуациями. Автоматическое преобразование типов не отменяет необходимости понимать правила языка и условия задачи. Например, ноль может быть допустимым результатом, а отсутствующее значение обозначать, что расчёт не выполнен. Если смешать эти случаи, дальнейший код получит неоднозначность. Полезно записать ограничения словами до реализации и проверить, одинаково ли их понимает вызывающая сторона.
Проверка и вычисление решают разные задачи
Проверка устанавливает, соответствует ли вход ожидаемым условиям. Вычисление работает с уже понятными данными. Такое разделение помогает локализовать проблему: неверный формат не нужно объяснять как арифметическую ошибку. При этом проверять следует именно необходимые свойства, а не любые случайные признаки. Строка, которая визуально похожа на число, может содержать лишние символы или неоднозначный формат. Обработка внешнего ввода требует отдельного внимания. Общая учебная функция не должна молча принимать данные, смысл которых ей неизвестен.
Ошибка должна иметь понятный путь
Исключения в PHP позволяют сообщить о ситуации, которая не укладывается в обычный путь выполнения. Обработка должна происходить там, где есть осмысленное решение: объяснить проблему, изменить действие или корректно завершить операцию. Пустой обработчик, скрывающий все ошибки, не делает систему надёжнее. Пользовательский ответ и технический журнал выполняют разные роли. В публичное сообщение не следует выводить секреты, внутренние пути или полные чувствительные данные. Журнал тоже должен содержать только необходимое для диагностики и соблюдать ограничения доступа.
Проверяйте границы и независимость результата
Один обычный пример не охватывает все варианты. Нужны случаи с минимальным допустимым значением, отсутствующим входом и неподходящим типом, если они относятся к контракту. Ожидаемый ответ полезно определить заранее. Для чистого вычисления результат не должен зависеть от случайного вывода на экран или состояния внешнего сервиса. Разделение расчёта и представления облегчает повторное использование. При обновлении версии языка поведение незнакомых конструкций сверяют с актуальной документацией, а не только с давним фрагментом из обсуждения.
Попробуйте на практике
Спроектируйте контракт учебной функции расчёта стоимости без написания и запуска программы.
- Опишите вход: количество как неотрицательное целое число и стоимость единицы как неотрицательное числовое значение. Укажите, что пример не предназначен для реального денежного учёта.
- Запишите обычный результат как произведение двух значений и отдельно определите поведение при отсутствии одного входа.
- Составьте четыре теста: обычные данные, нулевое количество, отрицательное количество и текст вместо числа.
- Для каждого подпишите ожидаемый результат или понятную ошибку. Не используйте один и тот же ноль для обозначения корректного расчёта и любого сбоя.
Как проверить результат. Контракт различает допустимый вход, обычный результат и ошибку. Все четыре теста имеют заранее определённый смысл, независимый от оформления ответа.
Частые вопросы
Нужно ли перехватывать любое исключение в каждой функции?
Нет универсальной необходимости. Обработка полезна там, где можно осмысленно отреагировать. Скрытие ошибки без действия затрудняет диагностику.
Вывод на экран равен возвращаемому значению функции?
Нет. Вывод относится к представлению, а возвращаемое значение передаёт результат другому коду. Их разделение делает вычисление понятнее и удобнее для проверки.
Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.