Привет! Меня зовут Михаил Журавлёв, я работаю в компании SM Lab, занимаюсь разработкой и ревью кода. Сегодня хочу рассказать вам о допускаемых ошибках в запросах 1С и создании чек-листа для их предотвращения
Зачем нужен чек-лист в разработке
Чек-лист. Что это? Это список. Мы идем в магазин и берем с собой список, чтобы не забыть что-то купить. С этим списком мы в магазине сверяемся: всё купили – всё хорошо. То же самое и в разработке: у нас есть чек-лист, мы выписываем, что нам нужно сделать, что нужно проверить. Посмотрели, сравнили – отлично.
«Всё должно быть безобразно единообразно» (или наоборот, уже точно не помню) – это про унификацию кода в компании. У нас достаточно много разработчиков 1С – целый центр компетенции. Даже в нашей маленькой команде (4 с половиной разработчика) получается, что часто каждый сам себе художник, «он так видит». Для того, чтобы избежать беспорядка, был введен принцип стандартизации.
Небольшое лирическое отступление.
Наша компания заботится о сотрудниках и часто проводит вебинары с психологами. Мне запомнился следующий момент.
Выступающий психолог сказал, что очень часто его спрашивают о каких-то сакральных знаниях; как сделать так, чтобы получилось. А он в ответ: «Вы делаете вот это? (ну, это же понятно – естественно, не делаем). Если вы не делаете очевидные вещи, вам остальное просто не поможет». Так вот, чек-лист – это такая простая штука, которая помогает делать очевидные вещи и двигаться с помощью этого вперед. Да, никто не идеален. Можно сделать неправильно, потому что сроки поджимают. Но в голове хотя бы откладывается своеобразная напоминалка: «Окей, сейчас я делаю неправильно, но я делаю неправильно сознательно – я помню про это».
История появления чек-листа для разработчиков
В 2021 году y нас была небольшая команда – три разработчика, которую постоянно ревьюил куратор.
Я был, наверное, самым большим генератором повторяющихся ошибок. В личном разговоре с куратором договорились, что я больше не буду так делать и выпишу все повторяющиеся ошибки. У меня руки не дошли, а вот куратор сделал большой чек-лист, в основном по объектной модели. Все команды, работающие в 1С, стараются его придерживаться. Часть списка, чтобы было понятно, это какие-то очевидные вещи: дублирование кода, запросы в цикле, нулевое тестирование и его передача на проверку. Примерно так он выглядит в Confluence:
Весной я тоже ревьюил и стал замечать, что одни и те же ошибки в запросах повторяются. Поэтому родилась следующая идея: на базе большого чек-листа сделать свой подраздел в рамках дополнения. У нашей команды есть своя страничка на портале Confluence и там продублирован большой чек-лист по объектной модели, а под ним уже наш чек-лист по языку запросов.
Первые 4-5 пунктов появились в мае и за пару месяцев выросли до 10. Ошибки выписывались в порядке выявления и долгое время оставались неструктурированными.
Сейчас чек-лист переработан и выглядит более упорядочено с разбивкой по категориям.
А теперь, собственно, перейдем к примерам ошибок, разделенным на следующие блоки:
-
оформление (чистота кода);
-
ошибки в логике;
-
элементы оптимизации;
-
неоднозначность интерпретации.
Оформление
При выборке из полей и таблиц бывают случаи, когда в конструкторе двойным кликом скинули сразу весь состав полей в выборку. Потом про это забыли, частично что-то убрали, что-то оставили, не проверили до конца и, как итог, остались неиспользуемые поля.
Да, это некритичная ошибка. Она по большей части просто засоряет код, делает его более сложным для восприятия. Но, если говорить об оптимизации, при одном или нескольких забытых полях на очень большую таблицу разница, думаю, будет.
Следующий пример ошибки – это неиспользование такой функции в языке запросов, как ПРЕДСТАВЛЕНИЕ (или ПРЕДСТАВЛЕНИЕССЫЛКИ). Часто нужно просто взять из финальной выборки поля и вывести, например, сообщение пользователю. Нам для этого необязательно тащить ссылку, мы можем сразу в запросе получить представление ссылки и использовать его в объектной модели.
Таблицы без выборки полей. Тут нужно быть внимательнее с условиями. Понятно, что когда у нас идет соединение и не выбираются поля, соединение может быть внутренним, оно тем самым налагает условия и меняет выборку. А когда левое соединение остается, поля не выбираются, интерпретатор игнорирует соединение (в последних релизах платформы – нет), это больше к вопросу о чистоте кода. Но бывают ситуации, когда можно описать внизу условия, например, сравнить поле основной таблицы с полем левой таблицы, и тут уже нужно быть аккуратнее, поскольку в данном случае такое соединение накладывает ограничение на выборку (на картинке выше как раз такой случай).
Разыменование. На картинках ниже один из примеров, отловленных Сонаром. Подразумевается, что мы везде используем левое соединение. Здесь в ЕСТЬNULL обёрнуто поле из основной таблицы. Сбивает с толку потому, что таблица основная, значение в NULL быть не должно. Но! Такое значение у нас появляется, когда мы делаем разыменование (вторая картинка) и следуем общему правилу: когда больше одной точки, нужно обернуть ЕСТЬNULL, указать значение подмены – и всё будет хорошо. Ну и не забывать, что разыменование – это, по сути, неявное соединение.
Ещё один интересный случай: добавление одинакового поля в две таблицы. Оно заполняется одинаковым значением для того, чтобы потом сделать соединение, но по факту это так называемое декартово произведение.
Ещё один пример декартового произведения. На картинке внизу правильный вариант – одна таблица перемножается на другую, наверху полное соединение по условию ИСТИНА.
Ошибки логики
Основная ошибка – когда в ЕСТЬNULL оборачивается какое-то выражение, составные части которого могут сами по себе принимать значение NULL.
Внизу правильный вариант. Мы каждое такое значение выцепляем, а затем собираем в общее выражение. Это может быть произведение, может быть сумма, может быть оператор ВЫБОР и т.д.
Протягивание поля через половину запроса. Это пример, когда по-хорошему нужно было в параметры виртуальной таблицы поместить условие, а оно вместо этого протаскивается через весь запрос. В пакете 9 запросов между первым и последним. И только в самом конце делается отбор, хотя это можно было бы сделать в самом начале. Однако Артем Кузнецов (из Финтеха который), чей доклад в том числе меня вдохновил (ссылка будет ниже), говорит про то, что не нужно получать по ссылке значения и тащить их через весь запрос – лучше сделать это в конце, т.е. через запрос мы пробрасываем ссылку, а значения по этой ссылке мы получаем уже в результирующей выборке.
Лишние временные таблицы, или «размазывание тонким слоем по тарелочке». Плавно переносимся в то время, когда разработчикам платили за количество строк кода. Можно сделать сразу два левых соединения, но сделаны две временные таблицы вместо одной. Вендор говорит, что 6-7 левых соединений нормально, если больше – уже да, надо разбивать (ссылка, кстати, на стандарты вендора тоже будет в конце).
Элементы оптимизации
Дублирование кода. Это словосочетание больше привычно для кода в объектной модели, где у нас в разных методах одно и то же, дополненное чем-то ещё, и понятно, что надо вынести в отдельный метод, чтобы убрать эти одинаковые совпадающие куски кода.
Здесь не так очевидно бросается в глаза, что они одинаковы почти до степени смешения. Кстати, я не говорю про скобки, которые появились из-за того, что перепутан порядок полей в условиях; не говорю про то, что сначала надо получить ключи аналитики, отобраться и потом по ним уже соединяться, а не вкрячивать разыменование в условиях. Здесь общий смысл в том, что правильнее из регистра сведений, из достаточно большой таблицы, сделать выборку, и потом уже с этой выборкой отдельно поработать, отдельно взять текущую коллекцию, отдельно взять предыдущую коллекцию. На следующей картинке плюс-минус как должно быть.
Собрали в таблицу ключи аналитики, соединились с временной таблицей регистра СрезПоследних. При этом, как вендор нам рекомендует и завещает, сделали отбор в параметрах виртуальной таблицы. И дальше работаем с этой таблицей ВТ_ЦеныИзПрайсЛиста. Возвращаясь к предыдущей картинке, можем отдельно взять коллекции, которые у нас в составе спецификации, отдельно коллекции из таблицы прошлых коллекций.
По поводу дублирования кода у нас есть договоренность в команде. За дублирование – прилюдный выговор и порицание (как говорится, «…и постигнет меня кара моих товарищей»).
Неочевидный случай из той же серии. Общее, что сложилось из подобных ситуаций, это то, что если мы видим, что более-менее совпадают строки в разных частях выборки, это всегда повод обратить внимание и более пристально посмотреть на запрос. Здесь вместо того, чтобы сделать сначала объединение, а потом это объединение соединить с виртуальной таблицей регистра, 2 раза соединяется со срезом последних; опять же, параметров отбора нет.
Неоднозначность интерпретации
Поля из других таблиц в условии соединения. Два соединения, в первом всё хорошо. Второе соединение со справочником, в первом условии все нормально. Второе условие приехало из таблицы ВТРеквизитыДокумента. Получается, что у нас третья таблица соединяется через поле из второй. Мы у себя договорились так не делать. Очень много было копий сломано и в команде ERP, и в нашей, и между командами в компании. К единому выводу не пришли, всё остаётся на уровне договоренности.
Конструктор, кстати, скобки ставит неспроста – показывает, что что-то не так. По факту здесь вложенное соединение.
1С настоятельно не рекомендует нам делать вложенное соединение, т.к. оно превращается в подзапросы. Мы рекомендацию приняли, и она стала одной из общих, сквозных договоренностей для всех команд в компании (смоделировать картинку для примера не удалось).
И один рабочий пример из выступления Дмитрия Дудина на InfoStart 2019 (скрин с
YouTube). Здесь у нас два левых соединения, соединение в третьей таблице как раз через вторую (условие с полем из второй), но здесь поле само по себе. И ещё, на что я сразу обратил внимание,
табчасть Товары из заказа клиента фактически соединяется с одной и той же таблицей. Да, наверное, здесь это обоснованно допустимо. Мою картину мира, во всяком случае, подобный пример не нарушает. Ну и, повторюсь, всё это на уровне договоренностей внутри команды.
Итак, из разобранных выше случаев вытекает вполне очевидная вещь: чек-лист – это полезный и нужный инструмент базового характера, который при грамотном составлении и регулярном использовании принесет много пользы в разных аспектах.
Спасибо за внимание! Буду рад вашим комментариям!
Познавательный бонус
Ссылки на использованные доклады:
-
Дмитрий Дудин SQL для 1С: пишем правильно, красиво, сложно – IE 2019
www.youtube.com/watch?v=e-NyKYgP0xo
-
Артём Кузнецов Быстрый фронт в базе размером 6.8 терабайт – наши стандарты при разработке и рефакторинге запросов – IE 2021 Moscow Premiere
www.youtube.com/watch?v=oGEu44LolFA
Наиболее часто используемый в работе стандарт: Ограничения на соединения с вложенными запросами и виртуальными таблицами
ссылка на оригинал статьи https://habr.com/ru/articles/872718/
Добавить комментарий