Как Яндекс Такси вынесло ценообразование из кода: архитектура и верификация
Когда вы открываете Яндекс Go и вводите адрес, приложение за доли секунды показывает цену поездки. Кажется, что это просто: взять расстояние и время, умножить на тариф. На самом деле за ценой стоит десятки факторов: скидки, спрос, геозоны, даже кот или лыжи пассажира. Инженеры Яндекс Такси решили вы

Когда вы открываете Яндекс Go и вводите адрес, приложение за доли секунды показывает цену поездки. Кажется, что это просто: взять расстояние и время, умножить на тариф. На самом деле за ценой стоит десятки факторов: скидки, спрос, геозоны, даже кот или лыжи пассажира. Инженеры Яндекс Такси решили вынести алгоритм ценообразования из кода сервиса в отдельный модуль. В статье на Хабре они рассказали, почему не стали использовать готовый скриптовый язык, что такое цепочка преобразований цены и зачем понадобился формальный верификатор.
Почему ценообразование вынесли из основного кода
Раньше логика расчёта цены была встроена непосредственно в код сервиса, написанного на C++. Это создавало серьёзные проблемы: любые изменения требовали релиза всего приложения, что занимало время и увеличивало риск ошибок. Кроме того, код был сложным для понимания и тестирования — в нём переплетались бизнес-правила и технические детали.
Инженеры решили выделить ценообразование в отдельный модуль, который можно обновлять независимо от основного сервиса. Это позволило ускорить внедрение новых тарифов и акций, а также снизить вероятность ошибок. Однако возник вопрос: на чём реализовать этот модуль? Рассматривались готовые скриптовые языки, такие как Lua или Python, но от них отказались из-за проблем с производительностью и безопасностью. В итоге в Яндексе разработали собственный предметно-ориентированный язык (DSL), специально заточенный под задачи ценообразования.
Как устроена цепочка преобразований цены
Центральное понятие новой системы — цепочка преобразований цены. Она представляет собой последовательность шагов, каждый из которых изменяет цену, применяя определённое правило. Например, сначала базовая стоимость по тарифу, затем применение скидки за срочность, потом учёт спроса и так далее. Каждый шаг описывается на DSL, что делает логику прозрачной и легко изменяемой.
Важно, что цепочка не просто линейна: она может содержать ветвления и условия, зависящие от входных данных. Например, если пассажир везёт кота, применяется дополнительный коэффициент. Такая гибкость позволяет учитывать множество сценариев без изменения основного кода.
Какие факторы влияют на итоговую цену поездки в Яндекс Такси?
На цену поездки влияет не только расстояние и время, но и множество других факторов. Среди них: спрос и предложение в конкретный момент, погодные условия, время суток, наличие специальных тарифов и акций, а также индивидуальные особенности пассажира, такие как перевозка животных или багажа. Каждый из этих факторов может быть учтён в цепочке преобразований цены, что делает расчёт максимально гибким и адаптивным к текущей ситуации.
Зачем нужен формальный верификатор
Разработка собственного языка потребовала создания инструментов для проверки корректности кода. Для этого в Яндексе разработали формальный верификатор, который автоматически проверяет, что цепочка преобразований цены удовлетворяет заданным свойствам. Например, что цена всегда положительна, что скидки применяются в правильном порядке, что нет конфликтов между правилами.
Формальная верификация — это математически строгий подход к проверке программ, который гарантирует отсутствие целого класса ошибок. В отличие от обычного тестирования, верификатор доказывает корректность для всех возможных входных данных, а не только для заранее подготовленных примеров. Это особенно важно для такой критической системы, как ценообразование, где даже небольшая ошибка может привести к финансовым потерям или недовольству пользователей.
Технические детали реализации
В статье на Хабре инженеры поделились некоторыми техническими подробностями. Язык DSL компилируется в C++ код, который затем встраивается в модуль. Это обеспечивает высокую производительность — расчёт цены занимает миллисекунды. Верификатор построен на основе SMT-решателя Z3, который используется для проверки логических условий.
Особое внимание уделено безопасности: код на DSL не имеет доступа к системным вызовам и работает в изолированной среде. Это предотвращает возможные атаки через вредоносные правила. Кроме того, для отладки предусмотрен режим визуализации цепочки преобразований, который позволяет разработчикам видеть, как меняется цена на каждом шаге.
Кого затронет это изменение
Новая архитектура в первую очередь важна для разработчиков Яндекс Такси, которые теперь могут быстрее вносить изменения в тарифы и акции. Для бизнеса это означает большую гибкость в ценообразовании: можно оперативно реагировать на изменения спроса и конкурентной среды. Пассажиры заметят улучшение точности прогноза цены и, возможно, более персонализированные предложения.
В более широком смысле, этот подход может быть интересен другим компаниям, которые сталкиваются с похожими проблемами: сложная бизнес-логика, встроенная в код, и необходимость частых изменений. Выделение такой логики в отдельный модуль с собственным DSL — это паттерн, который может быть применён в различных доменах, от финтеха до логистики.
Что будет дальше
Яндекс планирует развивать свой DSL и верификатор, расширяя их функциональность. Возможно, в будущем они поделятся инструментами с сообществом, как это уже было с другими технологиями. Пока же компания продолжает использовать новую систему в продакшене, постепенно перенося все сценарии ценообразования на неё.
Эксперты отмечают, что формальная верификация становится всё более востребованной в индустрии, особенно в системах, где ошибки дорого обходятся. Опыт Яндекса может стать примером того, как совместить гибкость скриптовых языков с надёжностью формальных методов.
Итог
Яндекс Такси сделало важный шаг, вынеся алгоритм ценообразования из кода в отдельный модуль на собственном DSL. Это повысило гибкость, ускорило внедрение изменений и повысило надёжность благодаря формальной верификации. История показывает, что иногда неочевидные решения — такие как разработка собственного языка — могут быть оправданы, если они решают ключевые проблемы проекта. Следить за развитием этой технологии стоит не только разработчикам такси, но и всем, кто проектирует сложные бизнес-системы.