Процедуры и функции
Дизайн
Для чего и когда нужно использовать процедуры или функции? Значимыми причинами могут быть:
- Уменьшение сложности кода
- Улучшение читаемости кода
- Предотвращение дублирования кода
- Скрытие сложного кода
- Повышение производительности
- Повторное использование кода
Связность (cohesion) — характеристика внутренней взаимосвязи между частями одной процедуры. Хорошо спроектированная процедура хорошо выполняет одно конкретное действие – и не делает ничего другого. Следует стремиться создавать максимально связные процедуры (например, функция Cos() – идеально связная).
Виды связности (по убыванию), граница приемлемости проходит где-то на уровне временной связности:
- Функциональная связность – когда процедура выполняет одну и только одну операцию. Примеры: Sin(),GetCustomerName(),EraseFile(),CalculateLoanPayment(),AgeFromBirthday().
- Последовательнаясвязностьвозникает, когда процедура содержит операции, которые должны быть выполнены в определенном порядке, при этом выходные данные одной операции являются входными для следующей. Например, вычисление возраста работника и времени выхода на пенсию по дате рождения.
- Коммуникационная связность – когда операции в процедуре используют одни и те же данные (например, одну и ту же запись таблицы).
- Временная связность – операции объединены в процедуру, потому что они всегда выполняются в одно и то же время. Пример: StartUp(), CompleteNewEmployee() и Shutdown().
- Процедурная связность – операции в процедуре всегда выполняются в данной последовательности.
- Логическая связность – операции сгруппированы исходя из их логической общности, хотя и различны по природе. Например, ComputeAll(), или, скажем, обработка всех действий мыши.
Может быть приемлема, если процедура состоит исключительно из серии IF (CASE) и вызовов других процедур (переключатель). - Случайная связность- операции в процедуре объединены только тем, что они в ней объединены – худший возможный случай.
Процедура или функция? Используйте функцию, если:
- Цель кода – вернуть единственное значение, указанное именем функции.
- Необходимо использовать в выражении.
При этом:
- Проверьте все возможные пути возврата.
Следует иметь в виду, что внутри функции запрещены операторы пользовательского ввода.
Пример из практики: Функция вызывает внешнюю процедуру, в одной из ветвей которой выполняется оператор ввода. Такая ошибка не выявляется при компиляции и приводит к ошибке времени выполнения. Рекомендация – не вызывайте внешних процедур из функций. Вы не можете гарантировать, что процедура не была изменена.
Именование процедур и функций.
- Описывайте всё, что выполняет процедура
- Избегайте невыразительных и неоднозначных глаголов
- Не ограничивайте длину имени искусственными правилами
- Для именования функции используйте описание возвращаемого значения
- Для именования процедуры используйте выразительный глагол, дополняя его объектом
- Дисциплинированно используйте антонимы (add/remove, create/destroy, old/new, show/hide)
- Определяйте конвенции именования часто используемых операций
- Не используйте для дифференциации имён методов исключительно номера
Размер процедур и функций.
Желательно сохранять размер процедур небольшим. В то же время, устанавливать жесткое ограничение длины процедуры нецелесообразно. В принципе, размер процедуры определяется:
- Связностью
- Глубиной вложенности
- Числом переменных
- Числом точек принятия решений
- Другими соображениями, связанными со сложностью кода
Следует лишь соблюдать особую осторожность и тщательность, кодируя процедуру длиной, скажем, 200 строк кода.
Параметры
Замечания по использованию параметров процедур и функций:
- Располагайте INPUT, INPUT-OUTPUT и OUTPUT упорядоченно
- Если несколько процедур используют одни и те же параметры, располагайте их в одинаковом порядке
- Используйте все параметры
- Параметры, возвращающие статус или ошибку, располагайте в конце
- Не используйте параметры как рабочие переменные внутри процедуры
- Документируйте все допущения о параметрах
- Разумное ограничение на число параметров – около семи
- Рассмотрите соглашение для именования INPUT, INPUT-OUTPUT и OUTPUT параметров
- Передавайте необходимые процедуре переменные или объекты как параметры, для поддержки абстрактности интерфейса
- Убедитесь, что реальные параметры соответствуют формальным
Примечания:
- Буфер всегда передаётся как INPUT-OUTPUT.
- Область видимости TEMP-TABLE – внешняя процедура, нет смысла передавать её как параметр в пределах одной внешней процедуры.
Поиск
При вызове процедуры
RUN test_proc.
OpenEdge выполняет поиск процедуры в следующем порядке:
- Внутренняя процедура с именем test_proc в текущей процедуре и супер-процедурах
- Внешний компилированный файл test_proc.r в каталогах и библиотеках PROPATH
- Исходный файл test_proc.p в каталогах и библиотеках PROPATH
При вызове процедуры RUN test_proc.p. – выполняется поиск по PROPATH, сначала ищется test_proc.r, затем test_proc.p.
При вызове RUN test_proc.r – выполняется поиск по PROPATH только test_proc.r
SUPER процедуры
Для каждой внешней процедуры ABL а также для сессии в целом могут быть добавлены SUPER процедуры.
В этом случае процедуры и функции из SUPER процедур могут использоваться как библиотечные.
Использование SUPER-процедур будет подробно описано ниже.
Обработка ошибок
Следует иметь в виду, что ошибки в блоке функции и процедуры не передаются блоку, из которого вызвана процедура/функция, реакция на ошибку – UNDO, RETRY или UNDO, LEAVE, в зависимости от наличия операторов пользовательского ввода.
Обработка ошибок детально будет рассмотрена ниже.