Не всякий код является решающим правилом. Это руководство начинается с того, как выбрать, что выносить в правило, а затем показывает написание и тестирование двух примеров, одобрения возврата и ставки скидки. Все правила здесь остаются внутри проверяемого подмножества, с которым работает Lispex Vouch, поэтому один и тот же вход всегда даёт один и тот же ответ.
Что выносить в правило
Кандидатов отбирают три вопроса.
- Попросят ли вас позже объяснить это решение? Отказы в возврате, ставки скидок и лимиты одобрения притягивают обращения в поддержку и аудиты, поэтому они хорошие кандидаты.
- Можно ли перечислить все входные данные правила? Если решение сводится к нескольким значениям, например дням с момента доставки и признаку вскрытия, оно годится в правило. Значения, которые правилу пришлось бы запрашивать самому, например текущее время или остатки на складе, хост должен прочитать заранее и передать аргументами.
- Даёт ли оно ответ, не трогая экран и хранилище? Правило только судит. Что делать с этим суждением, решает хост-приложение.
Три «да» дают хорошего кандидата. Если хотя бы одно «нет», оставьте эту часть в приложении и вырежьте суждение поменьше.
Форма функции правила
Правило состоит из одной функции, которая получает входные данные аргументами и возвращает ответ. Несколько привычек делают правила читаемыми.
- Правилу с ответом «да или нет» дайте имя с вопросительным знаком на конце, как
refund-auto-approved?. - Правило, возвращающее значение, назовите по ответу, как
discount-rate. - Все входные данные принимайте аргументами. Ничего не читайте снаружи правила и ничего не меняйте внутри.
Пример 1. Одобрение возврата
Возврат одобряется автоматически в течение четырнадцати дней с доставки, если заказ не вскрыт.
(define (refund-auto-approved? days-since-delivery opened?)
(and (<= days-since-delivery 14)
(not opened?)))
(refund-auto-approved? 9 #f) ; ⇒ #t
(refund-auto-approved? 14 #f) ; ⇒ #t граничный день ещё одобряется
(refund-auto-approved? 15 #f) ; ⇒ #f на день позже
(refund-auto-approved? 3 #t) ; ⇒ #f вскрытый заказ
Держите тестовые вызовы прямо под правилом, и его границы станут документацией. Одобряется ли четырнадцатый день? Код отвечает сразу.
Пример 2. Ставка скидки
Для решений с несколькими ветками подходит cond. Пусть ставка скидки зависит от уровня участника и суммы корзины. Уровни записаны числами, 2 для золотого, 1 для серебряного, 0 для обычного.
(define (discount-rate member-level cart-total)
(cond ((and (= member-level 2) (>= cart-total 100000)) 15)
((= member-level 2) 10)
((>= cart-total 100000) 5)
(else 0)))
(discount-rate 2 120000) ; ⇒ 15 золотой уровень и крупная корзина
(discount-rate 2 50000) ; ⇒ 10
(discount-rate 0 120000) ; ⇒ 5
(discount-rate 0 30000) ; ⇒ 0
cond проверяет ветки сверху вниз и отвечает первой, которая выполнилась. Порядок и есть приоритет, поэтому самое конкретное условие ставьте первым.
Как тестировать правило
Способов два, и оба вычисляет один и тот же эталонный интерпретатор.
Вставьте правило и тестовые вызовы в Песочницу, и результаты появятся сразу. Ставить ничего не нужно, что удобно на этапе поиска формы.
Чтобы держать правила в файлах, сохраните их, например, в rules.lspx и запустите CLI.
npm install -g lispex
lispex run rules.lspxЕсли рядом с каждым тестовым вызовом записать ожидаемое значение комментарием, позже будет видно, что именно сдвинуло изменение правила.
Как остаться в проверяемом подмножестве
Примеры выше используют только define, and, cond и операторы сравнения, а этого уже достаточно, чтобы быть внутри подмножества. Когда правило растёт, держат его там две вещи.
- Никаких макросов и расширений ридера. В проверяемом подмножестве они дают немедленную ошибку. Полный список допустимых форм есть в разделе «Синтаксис».
- Используйте только аргументы, которые передал хост. Правило, которое само тянет время, случайные числа или внешние данные, ломает обещание «один вход, один ответ».
Дальше квитанции
Правила из этого руководства и есть материал для Lispex Vouch. Если правило влияет на реальное решение, сгенерируйте квитанцию нативным бинарником и храните её вместе с записью о решении. Квитанция показывает, какое правило было применено к каким данным и с каким результатом. Она не устанавливает, кто действовал на основании результата, когда это произошло и совпадает ли развёрнутое правило с проверенным. Эти вопросы требуют контроля за пределами Lispex. Команды lispex verify и lispex replay описаны на странице Lispex Vouch.