Привет всем, я Дмитрий Кислов, системный аналитик в ПСБ. Отвечаю за создание новых и доработку существующих продуктов для клиентов малого и среднего бизнеса.
Решение, которое описано в этой статье, мне кажется простым и очевидным. Но я написал эту статью для тех коллег, которые пока что не сталкивались с вопросом оптимизации API.
Думаю, описанное ниже может оказаться полезным. При том, что предлагаемый кейс действительно элементарный, решение понятно и хорошо работает.
Немного предыстории
Когда я пришёл в компанию, процессы были таковы: для создания нового документа из фронта использовались простые хранимые процедуры.
В такой процедуре передаётся набор параметров, необходимый для открытия документа. Выглядит это как-то так. В примере ниже – процедура для создания некого абстрактного документа:

По этим параметрам открывается соответствующий документ. Стандартная и простая схема.
Но жизнь не стоит на месте. И появляется необходимость добавлять новые параметры при создании новых продуктов, их особенностей и т. п. Что в этом случае происходит?
Добавляются новые параметры и количество переменных быстро растёт.
А что делать, если в параметре нужно передать массив данных? Можно использовать разделитель типа «;» (точка с запятой), различные виды экранирования, как в случае с кавычками, которые я поставил вокруг точки с запятой.
Забегая вперёд обозначу, что даже при использовании XML, JSON применяются подобные подходы в SOAP- и REST-запросах. Ну вот так исторически сложилось. Я и сконцентрируюсь именно на передаче параметров.
Способ хранения особенностей или свойств документа
У любого документа есть некий набор свойств. Эти наборы делятся на два основных вида.
Основные свойства: тип документа, номер документа и т. п.
Например, это документ в системе формирования заказов в ресторане. Тогда это будет Заказ с определённым номером, типом заказа (например, «паста»), названием, весом, датой и временем заказа. Набор этих свойств у всех заказов будет похожим.
И дополнительные свойства: например, количество сыра (одинарный, двойной или без сыра) в пасте, пожеланиях клиента (не добавлять бекон или зелень) и информация об аллергенах посетителя.
Дополнительные свойства, в свою очередь, делятся на:
Флаг (FLAG), объект который может принимать три значения (null, false, true);
Настройка с фиксированным набором параметров (LIST), набор значений такой настройки строго определён;
Нефиксированная настройка (SET), текстовое поле в котором может сохраняться произвольный текст.
Каждому из дополнительных свойств мы присвоим:
Наименование: Label;
Идентификатор: ID;
Значение: VALUE.
И для наглядности приведу пример свойств коктейля.
FLAG: Label «Срочность заказа», ID 123; возможные значения: null, false, true.
SET: Label «Пожелания клиента», ID 456; возможные значения: «Не добавлять зелень» – то есть, любое текстовое значение.
LIST: Label «Количество сыра», ID 789; возможные заранее заданные значения: 0, 1, 2, 3.
При этом любое из свойств может быть использовано в любом документе, например, количество сыра также применимо для пиццы.
Постановка задачи
Для отправки информации о заказе бармену (то есть, для создания документа) на приготовление коктейля, нужно передать (кроме названия коктейля) приведённые выше свойства – те самые «Срочность заказа», «Пожелания клиента» и «Количество оливок».
Нужно понимать, что набор свойств будет постоянно расширяться (добавятся новые ингридиенты, варианты подачи и так далее).
Как можно всё это реализовать?
Варианты решения
Решение 1
Как для хранимых процедур, так и для SOAP- и REST-запросов один из вариантов передачи новых свойств документа – это добавить новый параметр. Более того, за день до начала работы над этой статьёй я получил такое предложение от аналитика. По большому счёту, это допустимое решение. Тогда для нового свойства необходимо: добавить новый параметр, доработать фронт и бэк.
Решение 2
С другой стороны можно задать три новых параметра: вид свойства (FLAG, SET, LIST), в значении которых передавать ID и VALUE. Обработку этих параметров настроить на бэке.
Если решено оставаться на хранимых процедурах, то ID и VALUE можно передавать через разделители. Я бы сказал, что это слишком громоздкий вариант.
Мы решили сразу переходить на SOAP- или REST-запросы с использованием XML и JSON.
Таким образом, для всех будущих дополнительных свойств заказа добавили 3 новых параметра и 2 значения для каждого параметра.
Пример:
<FLAG>
<ID>123</ID> <!—Срочность заказа—>
<VALUE>1</VALUE>
</FLAG>
<SET>
<ID>456</ID> <!—Пожелания клиента—>
<VALUE>Взболтать, но не перемешивать</VALUE>
</SET>
<LIST>
<ID>789</ID> <!—Количество оливок—>
<VALUE>3</VALUE>
</LIST>
При этом бэк мы дорабатываем один раз для разбора дополнительных атрибутов, а фронт сможет их добавлять столько, сколько понадобится в будущем.
Выводы
Таким образом, понимая структуру хранения свойств документа, получилось оптимизировать:
саму интеграцию, перешли с хранимых процедур на SOAP и REST запросы;
объём (количество) передаваемых параметров.
Также устранили необходимость доработки на стороне бэка при передаче свойств документа и уменьшили разрастание табличных пространств.
Т. к. не нужно дорабатывать обработчик запроса на стороне бэка, выросла надёжность системы. Регрессионное тестирование можно обложить автотестами, чтобы также экономит ресурсы.
Этот кейс показывает, что понимание архитектуры бэкэнда позволяет значительно экономить на ресурсах при разработке и повышает отказоустойчивость.
Спасибо всем дочитавшим, делитесь своим опытом в комментариях!