Оглавление
Качество кода
Коллеги, задумывались ли Вы о том, что код 1С может «пахнуть»? И по «запаху кода» можно определить его качество?
Впервые термин code smell был введен Кентом Беком — известным американским разработчиком программного обеспечения и автором множества книг и методик разработки. Впоследствии термин «код с душком» был популяризован Мартином Фаулером в его книге «Рефакторинг. Улучшение существующего кода».
В большинстве случаев, «плохо пахнущий» код не сказывается на функциональности и пользователи не замечают, что сталкиваются с проблемными участками кода. От некачественного кода в большей степени страдают сами разработчики, что замедляет процесс разработки или поддержки работоспособности системы.
Некачественный код является своего рода индикатором слабого места системы, в котором затруднена читаемость кода или возникают разного рода проблемы, связанные с пониманием архитектуры и организации кода.
В качестве примеров «кода с душком» можно привести следующие виды проявлений некачественного кода:
Дублирование кода.
Когда один и тот же код используется в разных местах. Поддержка такого кода потребует внесения изменений во все встретившиеся фрагменты и плохо отразится на затратах, связанных с поддержкой системы.
Неиспользуемый код.
Остатки-атавизмы процедур и функций, или код, оставленный «на будущее».
Длинный код.
Чрезмерно громоздкие процедуры и функции.
Сложные выражения.
Условные выражения с большим количеством ветвлений.
Возможно ли избавиться от неприятного запаха в коде и какой ценой?
Конечно, да. Можно посадить команду разработчиков, которые будут заниматься рефакторингом уже существующего кода, а также контролировать новый, выполняя код-ревью помещенного в хранилище кода. При этом параллельно необходимо организовать обучение разработчиков, направленное на улучшение качества кода. Ну и не забывать посвящать новых разработчиков в «Клуб ценителей чистого кода».
Если все так сложно на человеческом уровне, может стоит задействовать искусственный интеллект, который проверит и «причешет» код? Давайте проведем эксперимент, дадим задание ИИ и человеку-разработчику на создания отчета «Остатки запасов в упаковках», а затем «понюхаем» код и выясним, чьи в лесу шишки.
Эксперимент: чей код чище — ИИ или человека?
Начнем с постановки задачи (у всех задействованных агентов и человека-разработчика постановка одинаковая):
Необходимо разработать отчет «УНПП_ОстаткиЗапасовВУпаковках» (Остатки запасов в упаковках) для использования в конфигурации УНФ.
Отчет должен использовать типовой механизм вывода результатов отчета с отображением данных на общей форме отчета (посмотреть по аналогии с другими отчетами УОП_ и УНПП_).
Включить использование и просмотр отчета в роль «УНПП_ПолныеПрава», а также создать отдельную роль «УНПП_ПросмотрОстаткиЗапасовВУпаковках» для просмотра отчета. Добавить отчет в подсистему «УНПП_ОбъектыВсе».
Отчет строится по данным Регистра накопления «УНПП_ЗапасыВУпаковках» и частично по документу «УННП_УпаковкаЗапасов» (для получения записей по недоупакованным запасам).
Возможные быстрые отборы в отчете (необязательные):
Организация, Склад, Контрагент, Заказ, флажок «С учетом недоупакованных».
Недоупакованными запасами считаются запасы, отраженные в непроведенном документе «УНПП_УпаковкаЗапасов» с операцией «Упаковка» и статусом «Сформирован частично». Такие документы не формируют записи Регистра накопления «УНПП_ЗапасыВУпаковках».
В качестве ИИ-инструментов, привлеченных для выполнения задачи, были использованы:
![]() |
1С:Напарник |
Cursor
Claude Code
А сейчас вернемся к нашим баранам агентам-инструментам ИИ и рассмотрим ход взаимодействия с ними при решении задачи.
1C:Напарник (версия 2026.07.16)
1С:Напарнику был дан исходный промпт, плюс некоторые дополнительные инструкции. Далее напарник приступил к работе по навыку с исследованием кодовой базы и уточняющими вопросами.
По завершении работы «1С:Напарник» составил инструкцию по списку объектов, которые необходимо добавить вручную:
Создать макет СКД. В EDT: правой кнопкой по отчёту → Добавить → Макет → Схема компоновки данных → имя ОсновнаяСхемаКомпоновкиДанных. После создания .dcs-файл доступен агенту для правки.
В EDT создать варианты отчёта внутри СКД (Основной, ПлоскийСписок) — если агенту не удастся корректно сгенерировать структуру вариантов через .dcs. Это ручная операция в визуальном редакторе СКД.
Создать роль УНПП_ПросмотрОстатковЗапасовВУпаковках в EDT: правой кнопкой на «Роли» → Добавить. После создания агент дописывает Rights.rights.
Включить отчёт и роль в подсистему УНПП_ВсеОбъекты вручную (правой кнопкой по подсистеме → «Добавить в подсистему»). Альтернатива — отредактировать .mdo подсистемы, добавив <content> строки (агент может это сделать сам).
Прописать права в Rights.rights для УНПП_ПолныеПрава — отредактировать файл в EDT или попросить агента вставить блок (агент может выполнить через Edit).
Мы не смогли синхронизировать созданный 1С:Напарником макет СКД с приложением. Было принято решение удалить макет и попросить 1С:Напарника составить список изменений, которые разработчик может вручную внести в чистый макет СКД. После внесения всех изменений в чистый макет потребовался ряд уточняющих вопросов, связанных с отображением отчета в интерфейсе пользователя.
Пробный запуск отчета показал, что отчет формируется без падений, но и не отображает никаких данных. После наводящих вопросов «1С:Напарник» нашел ошибку, связанную с неверным получением значений отборов из настроек СКД и исправил её.
Получили вот такой промежуточный вариант отчета:
Полученный вариант отображает данные не так, как описано в постановке: в качестве группировки верхнего уровня используется идентификатор строки, а в детальных записях выведен штрихкод упаковки из верхнего уровня дерева упаковок. При детальном рассмотрении схемы СКД было выявлено, что в схеме отсутствует организация иерархии данных, вместо этого используется конструкция «ИЕРАРХИЯ» языка запросов.
Продолжаем обучать 1С:Напарника и даем подсказку, что построение иерархии можно «подсмотреть» в отчете «УОП_ОтчетПоСебестоимостиБлюд». В итоге получили построение иерархии по аналогии с исходным отчетом.
Выполняем отчет и обнаруживаем, что снова отсутствуют данные в отчете. Просим 1С:Напарника проверить и найти ошибку. Ошибка была найдена: при копировании отчета один в один не было задано условие начального выражения иерархии. После исправления ошибки был получен вариант отчета, приближенный к необходимому отображению.
Перейдем к исходному коду. Код написан с соблюдением правил оформления модулей. Размещены необходимые директивы выполнения, выделены области. Процедуры и функции имеют описание. Модуль менеджера и модуль объекта поддерживают интеграцию со стандартной подсистемой Варианты отчетов.
Для построения отчета используется принцип программного вывода результирующего отчета через процессор вывода компоновки данных. Вывод осуществляется в процедуре ПриКомпоновкеРезультата() модуля объекта. Для получения исходных данных используется процедуры и функции модуля менеджера.
Cursor
Передадим эстафету Курсору и посмотрим, как он справится с задачей. Принцип построения отчета Курсором почти такой же, как и у Напарника. Только вместо вызова процессора компоновки прямо в модуле объекта, Курсор нашел процедуру ПриКомпоновкеРезультата() общего модуля ОтчетыУНФ.
Claude Code
По оформлению кода, к Claude Code вопросов нет. Так же как и у предыдущих ИИ-агентов код написан с соблюдением всех правил оформления.
Вывод отчета осуществляется программно, как и у всех ИИ-агентов.
Человек-разработчик
При проверке кода за человеком мы переживали, что оформление будет проигрывать коду ИИ‑агентов, но всё в порядке. Директивы, описания — всё есть. Возможно, это результат заимствования кода из других отчетов, но тем не менее придраться не к чему.
Подход к построению отчета строится также на программном выводе отчета, но вся работа с исходными данными и подготовка таблицы для компоновщика выполняется прямо в теле процедуры ПриКомпоновкеРезультата().
Анализ кода ИИ-агентов и разработчика-человека в SonarQube
Вот мы и подошли к моменту, когда требуется определить, чей код «пахнет» сильнее, а чей код может и вовсе не источает «ароматов». Запустим проверку кода и загрузим результаты в проекты SonarQube.
Код присутствует только в двух модулях объекта, поэтому мы не будем выгружать конфигурацию целиком в файлы, а сохраним тексты модулей вручную (для каждого агента в отдельном каталоге).
Создадим и настроим проекты в SonarQube. Обязательно укажем профиль качества BSL Language Server rules и ключ проекта, а также сгенерируем токены доступа для каждого проекта.
Для загрузки исходного кода в SonarQube мы воспользуемся инструментом SonarScanner, который проверит наши файлы в соответствии с правилами чистого кода и передаст собранные данные на сервер SonarQube. Запустим клиентскую утилиту из командной строки. Передадим каталог, где размещены файлы проекта, кодировку файлов, адрес сервера SonarQube, ключ и токен доступа проекта.
В процессе выполнения проверки и передачи данных, в окне командной строки можно наблюдать за ходом выполнения задачи. Успешным окончанием проверки можно считать наличие строки «EXECUTION SUCCESS».
После обработки утилитой всех файлов проектов можно подробнее ознакомиться с результатами проверки. Давайте перейдем к самой интригующей части данного эксперимента.
Агентами ИИ было написано приблизительно одинаковое количество строк кода, а вот человек обошелся в два раза меньшим количеством.
| Cursor | 694 строки |
| 1С:Напарник | 593 строки |
| Claude Code | 532 строки |
| Человек | 273 строки |
Лидером по количеству ошибок является Claude Code, а человек снова проявил себя как разумное существо, заботящееся об объеме безошибочного кода.
| Claude Code | 59 ошибок |
| Cursor | 45 ошибок |
| 1С:Напарник | 40 ошибок |
| Человек | 21 ошибка |
Так, с количеством разобрались. Приступим к качественному разбору и анализу ошибок.
Результаты Claude Code
Ошибки Claude Code вызваны несоответствием следующим правилам проверки кода:
Опечатка (21 ошибка из 59)
Опечатки найдены Сонаром в двух словах: «Недоупакованный» и «Штрихкоды». Данные слова, скорее всего, отсутствуют во встроенном орфографическом словаре, что и послужило причиной маркировки данных строк как ошибочных. Мы же с уверенностью можем не засчитывать Claude ошибки по данному правилу.
Отсутствует описание параметров метода (13 ошибок из 59)
Появление подобных ошибок довольно странно. ИИ-агенты знакомы с обязательным требованием документирования процедур и функций модулей, поэтому подобных ошибок быть не должно. Попробуем детально разобраться.
При составлении описания процедур и функций Claude применяет метод первичного описания параметров, а далее, если параметр передается в другую функцию или процедуру, то вместо описания параметра будет указана ссылка на первичное описание параметра.
Считать ли это ошибкой? Конечно, нет! Продолжаем.
Инициализация параметров вызовом вложенных методов (7 ошибок из 59)
Здесь мы столкнулись с проблемой использования вложенных вызовов в качестве параметров методов. Подобные конструкции действительно затрудняют чтение кода. Однако, компактные вложенные вызовы все же допустимы в определенных случаях.
Магические числа (7 ошибок из 59)
Магические числа в данной категории ошибок вовсе и не являются такими уж загадочными. При использовании квалификаторов мы зачастую прямо указываем размерность и нет необходимости заводить отдельные переменные или константы.
Конструкция «ОБЪЕДИНИТЬ» в запросах (3 ошибки из 59)
В данном случае целью выполнения объединения является получение уникального списка штрихкодов. Поэтому использование метода «ОБЪЕДИНИТЬ» вместо «ОБЪЕДИНИТЬ ВСЕ» оправдано.
Когнитивная сложность (3 ошибки из 59)
Когнитивная сложность напрямую влияет на восприятие кода и усложняет поддержку. К данному правилу проверки стоит прислушиваться и избегать возникновения подобных ошибок.
Использование конструкции Если...Тогда...ИначеЕсли... (2 ошибки из 59)
Применительно к данному правилу, в большинстве случаев необходимо наличие ветви Иначе. Считаем правило полезным, а ошибки засчитанными.
Неиспользуемая локальная переменная (1 ошибки из 59)
Неиспользуемые переменные, несомненно, зло. Но в нашем случае это не является ошибкой. Данная переменная все же задействована в модулях типового решения, которые не подвергались модификации в рамках текущего эксперимента и, соответственно, не попали в поле зрения Сонара. Минус 1 ошибка.
Неиспользуемый локальный метод (1 ошибка из 59)
Данное правило требуется использовать с осторожностью. Возможны ложные срабатывания. Так, например, предопределенная процедура ПриКомпоновкеРезультата была отнесена к неиспользуемым. Уменьшаем ошибки еще на одну позицию.
Повторное использование строкового литерала (1 ошибка из 59)
Снова спорная ошибка. Как и в случае правила «Магические числа» для квалификаторов числа, здесь прямое повторное указание типа «Число» не является ошибкой и не затрудняет восприятие или чтение кода. Да, при сопровождении, если потребуется массово заменить тип «Число» на другой тип, то придется попотеть, найти все вхождения и произвести замену вручную. Но замены такого рода являются редкостью.
Общий итог
Список ошибок, найденных после Claude подошел к концу. Подытожим разобранное, отдельно выделив количество найденных ошибок и ошибок, которые мы не будем считать за ошибки.
| Правило проверки ошибки | Найдено |
Ошибка |
|
|---|---|---|---|
ДА |
НЕТ |
||
| Опечатка | 21 |
21 |
|
| Отсутствует описание параметров метода | 13 |
13 |
|
| Инициализация параметров вызовом вложенных методов | 7 |
7 |
|
| Магические числа | 7 |
7 |
|
| Конструкция «ОБЪЕДИНИТЬ» в запросах | 3 |
3 |
|
| Когнитивная сложность | 3 |
3 |
|
| Использование конструкции Если...Тогда...ИначеЕсли... | 2 |
2 |
|
| Неиспользуемая локальная переменная | 1 |
1 |
|
| Неиспользуемый локальный метод | 1 |
1 |
|
| Повторное использование строкового литерала | 1 |
1 |
|
59 |
12 |
47 |
|
Получилось 12. Двенадцать ошибок, допущенных Клодом. Ну, а что же остальные? Переходим к Курсору.
Результаты Cursor
Сонар сделал Курсору 45 замечаний. Часть замечаний связана с уже разобранными правилами, а другая часть является новыми. Познакомимся с ними поближе.
Буква «ё» в текстах модулей (3 ошибки из 45)
Описание диагностики:
В текстах модулей не допускается использование буквы «ё». Исключения составляют интерфейсные тексты, выводимые пользователю в сообщениях, формах и справке, где употребление буквы «ё» в ряде случаев допустимо.
Да, в некоторых языках подобный запрет есть. А в экосистеме 1С данный запрет входит в стандарт «1С:Совместимо».
Засчитываем как ошибку и продолжаем.
Недопустимый символ (2 ошибки из 45)
Описание диагностики:
В текстах модулей (включая комментарии) не допускается использовать неразрывные пробелы и знак минус «-» в других кодировках (короткое, длинное тире, мягкий перенос и т. д.). Такие символы приводят к ряду сложностей при разработке.
Тут претензий нет. Найденное длинное тире надо заменить.
Сложные выражения в условии оператора «Если» (1 ошибка из 45)
Описание диагностики:
Сложное выражение (содержащее более 3 логических конструкции) необходимо вынести в отдельный метод или переменную.
Прочитать и «удержать» в голове подобное составное условие достаточно сложно. Заносим в базу ошибок.
Ограничение количества параметров метода (1 ошибка из 45)
Описание диагностики
Не рекомендуется объявлять в функциях много параметров (нужно ориентироваться на количество не более семи параметров), при этом не должно быть много параметров со значениями по умолчанию (нужно ориентироваться на количество не более трех таких параметров). В противном случае, читаемость вызывающего кода сильно снижается.
Например, можно легко ошибиться в количестве запятых при передаче необязательных параметров.
Многовато будет. Многовато... ©
При необходимости передавать в функцию большое число параметров рекомендуется группировать однотипные параметры в один или несколько составных параметров с типом Структура. Плюс еще одна ошибка в копилке Курсора.
Сравнение с булевой константой (1 ошибка из 45)
Описание диагностики:
Сравнение выражения с булевой константой Истина или Ложь с помощью операторов = и <> является избыточным и снижает читаемость кода. Если выражение и так имеет тип Булево, то достаточно использовать его напрямую (или с отрицанием НЕ). Кроме того, такая конструкция маскирует возможную ошибку проектирования: если тип выражения по какой-то причине отличается от Булево, то ветка кода может быть выполнена ошибочно.
В большинстве случаев данное правило можно считать верным. Но бывают исключения. И данная ошибка является тому подтверждением. Для заполнения данной структуры используется метод ЗаполнитьЗначенияСвойств(), после вызова которого в свойстве УчитыватьНедоупакованные может находиться значение с типом отличным от «Булево».
Общий итог
Остальные ошибки, допущенные Курсором практически идентичны ошибкам Клода. И отдельно рассматривать мы их не станем. Соберем ошибки в таблицу.
| Правило проверки ошибки | Найдено |
Ошибка |
|
|---|---|---|---|
ДА |
НЕТ |
||
| Опечатка | 27 |
27 |
|
| Отсутствует описание параметров метода | 3 |
3 |
|
| Инициализация параметров вызовом вложенных методов | 2 |
2 |
|
| Когнитивная сложность | 3 |
3 |
|
| Неиспользуемая локальная переменная | 1 |
1 |
|
| Неиспользуемый локальный метод | 1 |
1 |
|
| Буква «ё» в текстах модулей | 3 |
3 |
|
| Недопустимый символ | 2 |
2 |
|
| Сложные выражения в условии «Если» | 1 |
1 |
|
| Ограничение количества параметров метода | 1 |
1 |
|
| Сравнение с булевой константой | 1 |
1 |
|
45 |
12 |
33 |
|
Результаты промежуточного итога: Клод — 12 ошибок, Курсор — 12 ошибок. Хм, одинаковое количество. Что это, слаженность искусственных механизмов или общность подходов?
Результаты «1С:Напарник»
Пришел черед ознакомиться с результатами 1С:Напарника. Какие ошибки найдет Сонар у Напарника и в какую сторону склонится чаша весов количества ошибок? Сейчас узнаем.
Напарник получил 40 замечаний от Сонара. Есть старые знакомые (опечатки, отсутствие описания, повторные использования строковых литералов, магические числа), но есть и новые ошибки.
Использование служебных тэгов (1 ошибка из 40)
Описание диагностики
Диагностика отлавливает использование служебных тегов в комментариях. Список тегов (можно расширить через настройки):
TODO
FIXME
!!
@
MRG
ОТЛАДКА
ДЛЯ ОТЛАДКИ
КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ
КОНСТРУКТОР_ПЕЧАТИ
КОНСТРУКТОР_ВВОДА_НА_ОСНОВАНИИ
Вставить содержимое обработчика
...
Использование служебных тегов оправдано для этапов разработки, отладки. Оставаясь в коде, служебные теги принесут больше проблем, чем пользы.
Ограничение на длину строки (3 ошибки из 40)
Описание диагностики:
При длине строки более 120 символов следует использовать переносы. Строки длиннее 120 символов делать не рекомендуется, за исключением тех случаев, когда перенос невозможен (например, в коде определена длинная строковая константа, которая выводится без переносов в окно сообщений с помощью объекта СообщениеПользователю).
Длинные строки заставляют при чтении кода совершать дополнительные действия, связанные с горизонтальной прокруткой или попросту можно пропустить что-то важное, бегая взглядом по тексту. Также «невидимую» часть длинного комментария можно забыть обновить, что может привести уже к более серьезным последствиям в будущем, когда разработчик увидит комментарий, не соответствующий действительности.
Три ошибки уходят Напарнику.
Цикломатическая сложность (1 ошибка из 40)
Описание диагностики
Цикломатическая сложность показывает минимальное число необходимых тестов. Наиболее эффективным способом снижения цикломатической сложности является декомпозиция кода, дробление методов на более простые, а также оптимизация логических выражений.
Цикломатическая сложность увеличивается на 1 за каждую конструкцию: Если, ИначеЕсли, Иначе, Цикл, Попытка, бинарные операции И, ИЛИ.
Цикломатическая сложность влияет на читаемость кода, усложняет тестирование (сценарии тестирования должны учитывать все ветвления в коде), увеличивает затраты на поддержку (сначала надо разобрать все ветки).
Так что, Напарник, +1 к списку ошибок.
Общий итог
В остальном, Напарник повторил ошибки других агентов ИИ. Отразим все замечания в таблице.
| Правило проверки ошибки | Найдено |
Ошибка |
|
|---|---|---|---|
ДА |
НЕТ |
||
| Опечатка | 14 |
14 |
|
| Отсутствует описание параметров метода | 5 |
5 |
|
| Повторное использование строкового литерала | 3 |
||
| Инициализация параметров вызовом вложенных методов | 2 |
2 |
|
| Использование конструкции Если...Тогда...ИначеЕсли... | 2 |
2 |
|
| Магические числа | 2 |
2 |
|
| Когнитивная сложность | 1 |
1 |
|
| Неиспользуемая локальная переменная | 1 |
1 |
|
| Неиспользуемый локальный метод | 1 |
1 |
|
| Сложные выражения в условии «Если» | 1 |
1 |
|
| Ограничение количества параметров метода | 1 |
1 |
|
| Использование служебных тегов | 3 |
3 |
|
| Ограничение на длину строки | 3 |
3 |
|
| Цикломатическая сложность | 1 |
1 |
|
40 |
14 |
26 |
|
14 принятых замечаний Напарнику. Хуже чем у остальных ИИ-агентов.
Приступим к разбору результатов человеческого труда. Одержит ли победу человеческий разум над бездушной машиной? Читайте далее.
Результаты человека
Человеку Сонар выставил 21 замечание. Рассмотрим замечания, отличающиеся от уже разобранных при анализе работы ИИ-агентов.
Подряд идущие пустые строки (3 ошибки из 21)
Описание диагностики:
Для разделения блоков кода между собой используется вставка пустой строки. Вставка 2-х и более пустых строк не несет данной ценности и приводит к бессмысленному увеличению длины метода или модуля.
Три пустых строки еще можно пережить. А если больше? 5, 10? Только бесполезно занимают место. Не будем поощрять такие огрехи и засчитаем ошибку.
Закомментированный фрагмент кода (1 ошибка из 21)
Описание диагностики
Программные модули не должны иметь закомментированных фрагментов кода, а также фрагментов, которые каким-либо образом связаны с процессом разработки (отладочный код, служебные отметки, например, !!!_, MRG и т. п.) и с конкретными разработчиками этого кода.
По стандарту «1С:Совместимо» закомментированных блоков быть не должно. А мы следуем стандартам.
Обращение к виртуальной таблице без параметров (1 ошибка из 21)
Описание диагностики:
При использовании виртуальных таблиц в запросах, следует передавать в параметры таблиц все условия, относящиеся к данной виртуальной таблице. Не рекомендуется обращаться к виртуальным таблицам при помощи условий в секции ГДЕ и т. п.
Такой запрос будет возвращать правильный (с точки зрения функциональности) результат, но СУБД будет намного сложнее выбрать оптимальный план для его выполнения. В некоторых случаях это может привести к ошибкам оптимизатора СУБД и значительному замедлению работы запроса.
Человек сделал человеческую ошибку. Нарушил и стандарты, и рекомендации. За такие ошибки надо вводить повышающий коэффициент, влияющий на общий результат. Но в данный момент мы исследуем качество кода, а не его производительность (хотя зачастую они переплетаются друг с другом).
— Эй, Человек! Лови еще ошибку!
Ограничение на размер метода (1 ошибка из 21)
Описание диагностики
Существуют громоздкие методы (процедуры и функции), с которыми невозможно эффективно работать именно из-за их огромного размера. Большой метод зачастую возникает, когда разработчик добавляет в метод новый функционал. «Зачем мне выносить проверку параметров в отдельный метод, если я могу написать ее тут?», «Для чего необходимо выделять метод поиска максимального элемента в массиве, оставим его тут. Так код яснее», — и прочие заблуждения.
Мы, конечно, видели коды и побольше. Но правило, есть правило. Заносим замечание в ошибки.
Есть два правила рефакторинга большого метода:
- Если при написании метода хочется добавить комментарий в код, необходимо выделить этот функционал в отдельный метод.
- Если метод занимает более 200 строк кода, следует определить задачи и подзадачи, которые он выполняет, и попробовать вынести подзадачи в отдельный метод.
Соединение с виртуальныи таблицами (1 ошибка из 21)
Описание диагностики:
При написании запросов не следует использовать соединения с виртуальными таблицами. Следует соединять друг с другом только объекты метаданных или временные таблицы.
Данное замечание порождено рекомендациями компании 1С по оптимизации запросов. В статье добавлено важное примечание: «если запрос работает с неудовлетворительной производительностью». Получается, что использовать соединения с виртуальными таблицами можно, но осторожно? Мы не будем играть в «угадайку», а сразу будем считать подобного рода замечания ошибкой.
Уровень вложенности управляющих конструкций (1 ошибка из 21)
Описание диагностики:
Вложенные операторы «Если, «Для», «Для Каждого», «Пока» и «Попытка» являются ключевыми ингредиентами для создания так называемого «спагетти-кода». Такой код трудно читать, рефакторить и поддерживать.
И последнее замечание идет в зачет ошибок человеку.
Общий итог
Соберем замечания разработчика-человека в таблицу.
| Правило проверки ошибки | Найдено |
Ошибка |
|
|---|---|---|---|
ДА |
НЕТ |
||
| Отсутствует описание параметров метода | 5 |
5 |
|
| Инициализация параметров вызовом вложенных методов | 1 |
1 |
|
| Когнитивная сложность | 1 |
1 |
|
| Неиспользуемый локальный метод | 1 |
1 |
|
| Ограничение на длину строки | 4 |
4 |
|
| Подряд идущие пустые строки | 3 |
3 |
|
| Закомментированный фрагмент кода | 1 |
1 |
|
| Обращение к виртуальной таблице без параметров | 1 |
1 |
|
| Ограничение на размер метода | 1 |
1 |
|
| Соединение с виртуальными таблицами | 1 |
1 |
|
| Уровень вложенности управляющих конструкций | 1 |
1 |
|
| Цикломатическая сложность | 1 |
1 |
|
21 |
15 |
6 |
|
Сравнение общих итогов
Вот мы и подошли к моменту, когда мы сможем подвести общий итог и наконец-то ответить на вопрос: чей код «пахнет» сильнее.
| Замечание | Клод |
Курсор |
Напарник |
Человек |
|---|---|---|---|---|
| Инициализация параметров вызовом вложенных методов | 7 |
2 |
2 |
1 |
| Когнитивная сложность | 3 |
3 |
1 |
1 |
| Ограничение на длину строки | 3 |
4 |
||
| Подряд идущие пустые строки | 3 |
|||
| Закомментированный фрагмент кода | 1 |
|||
| Обращение к виртуальной таблице без параметров | 1 |
|||
| Ограничение на размер метода | 1 |
|||
| Соединение с виртуальными таблицами | 1 |
|||
| Уровень вложенности управляющих конструкций | 1 |
|||
| Цикломатическая сложность | 1 |
1 |
||
| Сложные выражения в условии «Если» | 1 |
1 |
||
| Использование конструкции Если...Тогда...ИначеЕсли... | 2 |
2 |
||
| Ограничение количества параметров метода | 1 |
1 |
||
| Использование служебных тегов | 3 |
|||
| Буква «ё» в текстах модулей | 3 |
|||
| Недопустимый символ | 2 |
|||
12 |
12 |
14 |
15 |
По результатам подсчета количества замечаний минимальное количество ошибок у Клода и Курсора. За ними следует Напарник и замыкает цепочку человек. Означает ли это, что Клод и Курсор являются победителями и ИИ одержал победу? Нет, все ИИ-агенты допустили ошибки. Человек же превзошел агентов, как по количеству замечаний, так и по разнородности ошибок.
Все написали код, источающий неприятный аромат. Так что же делать, чтобы код оставался чистым?
Почему SonarQube?
Важно добиться не только чистого кода, но и следить за ростом или деградацией качества кода разработчиков. Вручную данный процесс контролировать достаточно сложно, поэтому далее мы более детально рассмотрим в качестве инструмента для проведения оценки качества кода платформу СонарКуб (SonarQube). С её помощью можно проводить автоматический анализ качества программного кода, проверяя его на несоответствия стандартам (правилам) чистого кода.
Результаты проверки кода можно с помощью API загружать в аналитическую систему для оценки динамики роста или воспользоваться встроенной системой метрик и дашбордом с историей.
Подождите. Вы хотите спросить, почему мы выбрали именно СонарКуб и есть ли еще другие системы аналогичные по функционалу? Вы правы, аналоги существуют, но из поддерживающих язык 1С существует только одно решение.
1С:Автоматизированная проверка конфигураций (АПК)
«1С:Автоматизированная проверка конфигураций» (АПК) — это инструмент, с помощью которого можно автоматически проверять конфигурации и расширения, разработанные на платформе «1С:Предприятие» на соответствие требованиям и стандартам разработки. Данный инструмент существенно дополняет встроенный синтаксический контроль и выполняет все действия без интерактивного запуска проверяемой конфигурации.
АПК рекомендуется использовать для выявления следующих проблем:
- Орфографические и синтаксические ошибки.
- Нарушения стандартов и требований разработки.
- Проблем с правами доступа.
- Возможных проблем при обновлении типовой конфигурации.
«1С:Автоматизированная проверка конфигураций» может частично закрыть наши потребности, но у Сонара есть ряд преимуществ:
- Более глубокий анализ кода. Не только синтаксис и базовые стандарты, но и дублирование кода, уязвимости, качество запросов.
- Измерение качества кода в цифрах.
- Отслеживание динамики изменений.
Друзья, раз альтернатив нет, приступим к разворачиванию Сонара.
Разворачиваем Sonar
Сначала предлагаем сориентироваться в версиях Sonar’а. В первую очередь это ПО, которое можно развернуть на своих мощностях. Базово версии можно разделить на:
- Бесплатную версию Community Build.
- Платные версии SonarQube Server трёх видов: Developer Edition, Enterprise Edition, Data Center Edition.
С видами дистрибутивов можно ознакомиться на странице:
Помимо этого существует облачное решение SonarQube Cloud типа SaaS, без необходимости установки. Поддерживает ряд подписок, в том числе бесплатную с определенными ограничениями (< 50 тыс. строк кода).
В наших экспериментах в сторону облака мы не смотрели потому что, во-первых, хотелось полной управляемости сервиса; во-вторых, не подходили ограничения.
Что касается «приземленных» решений, тут стоит сказать, что основной необходимый функционал, касающийся анализа кода, есть уже в версии Community Build. Версии Developer/Enterprise/Data Center Edition стоит рассматривать с точки зрения:
- Увеличения количества поддерживаемых языков и более глубокого анализа уязвимостей. Но мы нуждаемся только в проверке кода на 1С, а для этого в любых редакциях необходим специализированный плагин.
- Возможностей расширения на множество команд с тысячами репозиториев, и горизонтальным масштабированием нагрузки — такие масштабы для нас не актуальны.
- Лучшей работы с git — в Community Build анализ возможен только для главной ветки main/master, в более продвинутых возможно это делать и для других веток, до слияния с основной.
Можно ознакомиться с таблицами сравнений возможностей разных версий:
- docs.sonarsource.com/sonarqube-community-build/feature-comparison-table
- docs.sonarsource.com/sonarqube-server/2026.1/discovering/sonarqube-server-editions
Для целей демонстрации и с точки зрения доступности нам по всем параметрам подходит Community Build, про него и будет сказ.
Развернуть Sonar Community Build можно множеством способов, мы с вами рассмотрим пару распространенных подходов для установки:
- В контейнер Docker.
- И на виртуальную машину.
И то, и другое под управлением Ubuntu 24.
Компонентно систему можно разделить на:
- SonarCube — основной «ингредиент», это сервер, который собственно обрабатывает код. Как правило подразумевается, что он работает как служба.
- База данных — компонента, в которой будут храниться все результаты работы.
- SonarScanner — клиентский инструмент, считывающий код и отправляющий на сервер Сонара.
SonarScanner не требует установки как таковой, запускается по требованию, мы расскажем о нём после установки. А на базе данных стоит остановиться отдельно.
База данных
SonarCube «из коробки» поставляется со встроенной легковесной базой данных «H2 database» (см. h2database.com). Это позволяет быстро без дополнительных настроек начать работу.
Однако в официальной документации (docs.sonarsource.com/sonarqube-community-build/server-installation/installing-the-database) предостерегают, что база H2 предназначена в первую очередь для тестов и ознакомления. В некотором роде можно сравнить этот режим с файловым вариантом работы платформы 1С. То есть можно применять для ознакомления, небольшой разработки и работы с малым объемом данных и малым количеством пользователей.
В случае полноценной продуктивной эксплуатации всё же предполагается установка и настройка работы с «полновесными» СУБД. Для Community Build поддерживаются следующие:
- PostgreSQL, версии с 15 по 18.
- Microsoft SQL Server, версии 2022 (MSSQL Server 16.0), 2019 (MSSQL Server 15.0), 2017 (MSSQL Server 14.0).
- Oracle, версии 23ai, 21C, 19C, XE Editions.
Для нашего варианта работы в связке с Linux больше всего подходит PostgreSQL, его и будем иметь в виду.
Предварительные настройки в Linux для ElasticSearch
Прежде чем перейдем непосредственно к установке, для корректной работы Sonar на ОС Linux необходимо систему подготовить к такому гостю, иначе он может огорчиться и отказать в запуске.
Дело в том, что в Sonar имеется встроенный модуль ElasticSearch — это поисковый движок, который отвечает за индексацию кода проекта, и используется в случае поиска по коду, фильтрации проблем и тому подобного. И что важно, в своей работе он:
- Открывает очень много файлов — например сегменты индексов и логи. Тем самым занимая много файловых дескрипторов.
- Отображает множество файлов индексов в виртуальную память.
В Linux заложен ряд лимитов на ресурсы и ElasticSearch в этом плане как правило выходит за их пределы.
Согласно документации (docs.sonarsource.com/sonarqube-community-build/server-installation/pre-installation/linux) для ElasticSearch нужно увеличить следующие лимиты.
Ограничения на уровне ядра системы
vm.max_map_count — максимальное количество областей памяти, которые может использовать один процесс.
Необходимо 524288 или более, в то время как в консервативных дистрибутивах Linux может быть ограничение в 65530 областей
fs.file-max — максимальное количество файловых дескрипторов, которое может быть открыто одновременно во всей системе.
Необходимо 131072 или более.
Проверить текущие значения можно командами:
Проверим у себя:
Оказалось параметры у нас уже больше необходимых значений. Немного поискав источник, мы поняли, что размер vm.max_map_count объясняется наличием в нашей сборке Ubuntu дополнительного файла настройки в директории /etc/sysctl.d:
А что с параметром fs.file-max не так? Он у нас вовсе каких-то космических масштабов. Как мы поняли, это также объясняется свежей Ubuntu. Судя по всему в современных версиях сборок данный параметр устанавливают в максимально возможное значение для 64-битной архитектуры, равное 2^63-1, как раз во избежание ошибок связанных с лимитом.
Как быть если ограничения всё же ниже рекомендуемых и их нужно донастроить?
В этом случае, следует прописать в настроечный файл следующие строки:
fs.file-max=131072
- Либо в конец файла /etc/sysctl.conf — тут настраиваются ограничения ядра.
- Либо создать файл настройки в папке /etc/sysctl.d/, например, «99-sonarqube.conf» и указать строки уже в нём. Как в нашем примере выше в файле «10-map-counts.conf».
Ограничения, накладываемые на сеанс и процессы пользователя
Следующие ограничения, которые в документации рекомендуют перепроверить, привязаны к конкретному пользователю:
- Максимальное количество открытых файлов на один процесс.
Проверить можно командой:
ulimit -n- Необходимо 131072 или более.
- Максимальное количество процессов на одного пользователя.
Проверить можно командой:
ulimit -u- Необходимо 8192 или более.
Попробуем посмотреть значения на нашей виртуалке для текущего пользователя:
Маловато...
Эти лимиты можно настроить в файле /etc/security/limits.conf указав строки вида:
<ИмяПользователя> - nofile 131072
<ИмяПользователя> - nproc 8192
Сейчас у нас этот файл не настроен, делаем вывод, что ограничения выведенные для текущего пользователя работают для всех. Поэтому нам нужно также увеличить эти лимиты, но это нужно делать для пользователя, под которым будет запущен Сонар. Забегая немного вперед, мы создадим пользователя с именем «sonar», так что можем прописать для него эти ограничения:
Также предполагаем, что для запуска из контейнера эти ограничения должны быть расширены именно для пользователя, под которым контейнер запущен, об этом, вероятно, придется позаботиться.
Теперь приступим непосредственно к установке.
Установка в контейнер Docker
Начнем с «легковесного» варианта. Про докер-контейнеры сказано уже достаточно, если кратко — данная технология позволяет запустить процесс в некоторой изоляции со своим окружением. Что-то вроде мини-виртуалки. Это необходимо для реализации принципа микросервисной архитектуры «один сервис — один контейнер».
Если хотите погрузиться в дебри контейнеризации рекомендуем ознакомиться со статьями:
- Подробное руководство по контейнеризации в Linux и Windows. Docker для 1С. Часть 1
- Подробное руководство по контейнеризации. Применение Docker для 1С. Часть 2
А мы продолжаем.
Чтобы воспользоваться сей технологией, для начала следует установить Docker.
Установка Docker из репозитория
Пройдемся кратко по установке, для этого будет не лишним обратиться к документации. И поскольку у нас машина работает на Ubuntu — изучаем конкретно ветку этой системы (docs.docker.com/engine/install/ubuntu/#installation-methods).
В этой статье описано несколько способов установки Docker, предлагаем пойти по пути установки из официального репозитория.
Сначала «помоем руки» — обновим информацию о версиях программ, командой:
Далее установим необходимые компоненты:
- ca-certificates — набор корневых сертификатов доверенных центров сертификации, необходимый системам и приложениям для проверки подлинности HTTPS-соединений.
- gnupg — инструмент для работы с криптографическими ключами и подписями, используемый для проверки цифровой подписи репозитория и его пакетов.
- curl — утилита командной строки, используемая для загрузки данных по URL.
Это можно сделать единой командой, указав пакеты в ряд:
Чтобы работать с репозиторием Docker нужно добавить его официальный GPG-ключ в папку отпечатков /etc/apt/keyrings.
Скачиваем ключ утилитой curl:
И для корректной работы apt, выдаем права на чтение ключа:
Теперь нужно добавить информацию о репозитории Docker в источники для менеджера пакетов apt в директории /etc/apt/sources.list.d.
Это можно сделать командой:
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
Говоря простым языком — тем самым мы указываем путь к репозиторию, тип пакета, архитектуру системы и собственно скачанный на прошлом этапе ключ для проверки подлинности пакетов.
После этого ещё раз обновляем информацию о пакетах:
И наконец — установка Docker.
Согласно документации, устанавливаем следующий набор пакетов одной командой:
Если всё прошло успешно, после установки служба docker должна сразу запуститься. Можно проверить её статус командой:
Ура! Всё работает, а это значит можем запускать Sonar в контейнере.
Ой, ещё один нюанс...
Root или не Root?
По умолчанию, работа с докером предполагает использование root-полномочий. Попытка выполнить без sudo команду, например, по созданию тома
Приведет к ошибке:
По сути у нас три варианта:
- Использовать для всех команд sudo.
- Добавить текущего пользователя в группу docker (docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user).
- Либо запустить docker в виде службы (docs.docker.com/engine/security/rootless/).
Для себя мы выбрали подход № 2 — с группой docker.
Можно проверить текущие группы пользователя командой:
Далее добавить текущего пользователя в группу docker командой:
После перелогиниваемся в сеанс ОС, проверяем что группа появилась:
И для проверки можем использовать без sudo команду с запуском тестового образа:
Запуск docker-контейнера с Sonar
Как вы наверное уже догадались, при работе через консоль, мы обращаемся с командами к утилите docker.
Команд у утилиты в изобилии, как обычно рекомендуем ознакомиться с документацией (docs.docker.com/reference/cli/docker/).
Как пример такой базовой командой «docker ps» можно проверить список запущенных контейнеров. Мы пока ничего не запускали, поэтому выводится просто заголовок:
Если же говорить про первый запуск контейнеров, то это можно сделать командой вида (docs.docker.com/reference/cli/docker/container/run/):
Пример самой простой команды для запуска Sonar:
Где:
- --name — в этот параметр передаем произвольное имя контейнера, оно станет его идентификатором, по которому можно производить действия — останавливать, запускать, удалять и т. д.
- -p — параметр побуждает докер пробросить соответствие портов хоста и контейнера. По умолчанию, Сонар в контейнере слушает порт 9000, мы его сопоставили с портом 9002 хоста.
После запуска контейнера, через некоторое время после того как инициализируются все системы, можно постучаться из браузера по адресу машины, на которой запущен докер к порту 9002. В нашем случае это http://192.168.0.106:9002.
И, вот, уже можно работать в Sonar:
Однако такой путь подходит только для разовых экспериментов, мы опустили несколько важных нюансов, давайте осветим их.
Образы
Обратите внимание на последний параметр в команде запуска.
Текст «sonarqube» в данном случае это имя «образа». «Образ» — это готовый слепок контейнера с определенным ПО и окружением. По указанному имени docker будет пытаться искать подходящий образ — сначала на исходной машине, потом в интернете.
Список доступных имен образов можно найти на официальной странице SonarQube на Docker Hub (hub.docker.com/_/sonarqube/tags).
Там вы увидите теги для разных редакций (community, developer, enterprise, datacenter-app) и с конкретными номерами версий, например 26.8.0.126808-community или 2026.4.1-developer.
В команде мы указали только базовое имя программы, на него завязан псевдоним sonarqube:latest, который означает последнюю доступную версию пакета community, на момент написания статьи это 26.9.0.129388-community.
Не всегда последняя версия является самой стабильной, плюс при обновлениях версий может изменяться функциональность, поэтому в некоторых случаях более правильным будет указать конкретную версию образа, например вот так:
Хранение данных — Тома
Следующая важная часть это настройка томов. Процессам в контейнере, как и любым программам, необходимо место для хранения промежуточных и постоянных данных. Докер для этого использует так называемые «тома» — это папки на хосте, которые связываются с папками контейнера. В команде запуска мы ничего не указали, поэтому при удалении контейнера все данные также будут удалены.
В инструкции (docs.sonarsource.com/sonarqube-community-build/server-installation/from-docker-image/prepare-installation) предлагается заранее создать несколько томов, чтобы не потерять данные, например, при обновлении образа на новую версию. А конкретно следующие тома:
- sonarqube_data — файлы данных, например индексы ElasticSearch.
- sonarqube_logs — логи программы.
- sonarqube_extensions — папка для расширений, сюда, например, попадут плагины для 1С, когда мы их установим.
Настраиваются они с помощью таких команд:
Проверить список контейнеров можно командой:
И далее при запуске контейнера можно указать их с ключом «-v»:
С новыми параметрами наша команда будет выглядеть так:
-p 9002:9000 \
-v sonarqube_data:/opt/sonarqube/data \
-v sonarqube_extensions:/opt/sonarqube/extensions \
-v sonarqube_logs:/opt/sonarqube/logs \
sonarqube:26.8.0.126808-community
Пути указанные как «/opt/sonarqube/...» — стандартны для дистрибутива Сонара, и зашиты внутри образа.
Хранение данных — База данных
В команде запуска docker run мы с вами нигде не указывали связь с СУБД. И как мы уже упоминали, в этом случае по умолчанию в SonarQube будет использоваться встроенная база H2.
Чтобы связать запущенный контейнер с уже развернутым кластером на PostgreSQL необходимо указать параметры JDBC:
- SONAR_JDBC_URL — адрес подключения в формате jdbc:postgresql://<Адрес:Порт>/<ИмяБазы>.
- SONAR_JDBC_USERNAME — имя пользователя.
- SONAR_JDBC_PASSWORD — пароль.
Они указываются через ключ «-e». Если добавить их в нашу команду, это будет выглядеть например так:
-p 9002:9000 \
-v sonarqube_data:/opt/sonarqube/data \
-v sonarqube_extensions:/opt/sonarqube/extensions \
-v sonarqube_logs:/opt/sonarqube/logs \
-e SONAR_JDBC_URL=jdbc:postgresql://servername:5432/sonar \
-e SONAR_JDBC_USERNAME=sonar \
-e SONAR_JDBC_PASSWORD=sonarpassword \
sonarqube:26.8.0.126808-community
Подробнее про это можно почитать тут:
- docs.sonarsource.com/sonarqube-community-build/server-installation/from-docker-image/set-up-and-start-container
- docs.sonarsource.com/sonarqube-community-build/server-installation/system-properties/system-properties#general
Запуск Sonar + PostgreSQL через docker compose
Как мы уже говорили, нам по сути нужны две компоненты — это сам Сонар и база данных Постгрес. В теории мы могли бы запустить их в одном контейнере, но принцип докера гласит «один процесс — один контейнер». И как раз для нашего случая был придуман специальный механизм «docker compose» — это технология, которая позволяет запустить несколько контейнеров, связанных общей сетью.
Указывать все параметры в строке запуска несомненно очень удобно, но чтобы воспользоваться docker compose — придется создать специальный настроечный файл в формате yml и перечислить все параметры объединяемых контейнеров в нём.
Для базового примера такого файла можно воспользоваться уже подготовленным в документации Sonar файлом (github.com/SonarSource/docker-sonarqube/blob/master/example-compose-files/sq-with-postgres/docker-compose.yml).
Создадим себе папку под проект, например /etc/sonarqube, и в ней создадим файл sonar-compose.yml:
Мы также взяли базовый файл и немного подредактировали, получился такой текст:
services:
sonarqube:
image: sonarqube:26.8.0.126808-community
container_name: sonarqube_test
depends_on:
db:
condition: service_healthy
environment:
SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonardb
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonarpassword
volumes:
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_logs:/opt/sonarqube/logs
- sonarqube_temp:/opt/sonarqube/temp
ports:
- "9002:9000"
networks:
- ${NETWORK_TYPE:-ipv4}
db:
image: postgres:17
container_name: sonar_postgresql
healthcheck:
test: [ "CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}" ]
interval: 10s
timeout: 5s
retries: 5
environment:
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonarpassword
POSTGRES_DB: sonardb
volumes:
- sonar_postgresql:/var/lib/postgresql
ports:
- "5435:5432"
networks:
- ${NETWORK_TYPE:-ipv4}
volumes:
sonarqube_data:
sonarqube_temp:
sonarqube_extensions:
sonarqube_logs:
sonar_postgresql:
networks:
ipv4:
driver: bridge
enable_ipv6: false
dual:
driver: bridge
enable_ipv6: true
ipam:
config:
- subnet: "192.168.2.0/24"
gateway: "192.168.2.1"
- subnet: "2001:db8:2::/64"
gateway: "2001:db8:2::1"
Если кратко описать структуру файла, то на верхнем уровне указан пункт services, ниже списком идут запускаемые контейнеры, в нашем случае:
- Сонар — это секция sonarqube.
- Постгрес это секция db.
Внутри секций контейнеров указаны свои параметры. На что стоит обратить внимание:
- Параметр «image» — это образы, указаны конкретные версии для Сонара «sonarqube:26.8.0.126808-community», для Постгреса «postgres:17».
- Секция depends_on в блоке Сонара подразумевает, что этот контейнер должен запуститься только после проверки работоспособности контейнера db.
Соответствующая проверка работоспособности healthcheck в секции db — это команда, которая проверяет способность сервер принимать соединения. - В параметрах «ports» мы пробросили порты:
- Для Сонара как и в примерах выше «9002:9000».
- Для Постгреса — «5435:5432» — то есть стандартный порт Постгреса 5432 в контейнере транслируется на порт 5435 на хосте.
Обычно так не следует делать, это в некотором роде понижение безопасности. Но мы хотели ради эксперимента подглядеть из чего именно состоит база, а это проще делать с хоста. Порт 5435 выбран, т. к. стандартный 5432 уже занят, на нашей стендовой виртуалке установлено несколько версий Постгреса.
- Параметры POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB — специальные настройки для Постгреса, запускаемого из образа, определяют соответственно пользователя/пароль и базу данных, которые необходимо инициализировать при запуске. Подробнее можно почитать здесь hub.docker.com/_/postgres.
Чтобы запустить этот «винегрет», находясь в папке с yml-файлом вызываем команду:
Примечание
Существует вариант вызова и без указания файла:
В этом случае будет произведена попытка найти и запустить файлы с названиями «compose» или «docker-compose». То есть имеет смысл сразу назвать файл так, если хотите пользоваться более короткой командой.
Мы запустили команду, и по тексту сообщений видно, что был скачан образ postgres:17, создан ряд томов:
Спустя какое-то время по пути http://192.168.0.106:9002 открылся интерфейс Сонара:
И как обещали, заглянули в psql по порту 5435 в базу Сонара в Постгресе:
Установка Sonar без докера
С докером разобрались. А что, если мы не хотим разбираться с контейнерами, желаем чего-то старомодного, навроде обычной установки из дистрибутива? Их есть у нас.
Сначала займемся окружением:
- Для работы SonarQube Community Build 26.8, как и в случае с докером, нам нужен PostgreSQL версии 15–18.
- Также потребуется установить Java JDK версии 21–25. Раньше мы про него не говорили, потому что в образе для контейнера Сонара пакет Java уже был зашит и отдельно с ним «договариваться» не приходилось.
Примечание
- docs.sonarsource.com/sonarqube-community-build/server-installation/installing-the-database
- docs.sonarsource.com/sonarqube-community-build/server-installation/server-host-requirements
Установка PostgreSQL
У нас на стендовой виртуалке уже установлено две редакции PostgreSQL 13 и 16 версий, но для разнообразия поставим ещё 18 версию, максимальную, которую на текущий момент поддерживает Сонар.
Для установки выполняем команду:
По завершении установки, в случае если на машине не было кластеров PostgreSQL, будет автоматически создан кластер main. Но на нашей виртуалке этого не произошло, создадим кластер 18 версии вручную, командой:
Мы не указали конкретный порт, а стандартный порт 5432 у нас уже занят. Это особенность команды pg_createcluster — при создании кластера, она подбирает следующий свободный порт. И как видно из вывода команды кластеру был назначен порт 5433, это знание нам пригодится.
На всякий случай проверяем состояние службы кластера:
Со службой всё в порядке — статус «active». Поэтому движемся дальше. Теперь поставим Java.
Установка Java
Для начала проверим, вдруг Java у нас уже есть:
Увы, система тонко намекает, что надо бы установить и даже предлагает какие-то пакеты JRE.
В требованиях указан именно пакет JDK, поэтому установим его 21 версию:
Установка прошла без эксцессов. Снова проверяем, вывод команды java —version подтверждает, что всё хорошо:
Теперь переходим к установке Сонара.
Установка Sonar
Сперва следует скачать дистрибутив, его можно найти на официальном сайте sonarsource.com, нужно перейти в раздел PRODUCTS → SonarQube Server, затем выбрать пункт DOWNLOAD. Или перейдите по прямой ссылке на страницу загрузок sonarsource.com/products/sonarqube/downloads.
Нас интересует дистрибутив Community build, скачиваем его по кнопке «Download for free»:
Далее с помощью scp переносим скачанный архив на виртуалку:
После этого перейдем в каталог с полученным архивом и распакуем в папку /opt:
И переименуем папку для удобства:
Внутри папки увидим следующие ключевые директории:
- bin/ — исполняемые файлы для запуска.
- conf/ — конфигурационные файлы.
- logs/ — логи сервера.
- data/ — временные файлы.
- extensions/ — плагины.
На этом установка закончена.
Связь SonarQube с PostgreSQL
Дистрибутивы установлены, теперь наладим взаимоотношения Сонара и Постгреса.
Настройка postgres
В СУБД необходимо создать пользователя и базу данных для Сонара.
Для этого подключаемся к кластеру от имени пользователя postgres, в нашем случае по порту 5433:
И в терминале psql с помощью SQL-команд создаем пользователя «sonar» с указанием пароля, одноименную базу данных, выдаем на неё пользователю все права:
CREATE USER sonar WITH PASSWORD 'sonarpassword';
CREATE DATABASE sonar OWNER sonar;
GRANT ALL PRIVILEGES ON DATABASE sonar TO sonar;
После можно выйти из терминала по команде:
С сего момента будем считать, что PostgreSQL готов впитать в себя все «запахи» нашей кодовой базы, которые распознает Сонар.
Настройки со стороны Сонара
В папке /opt/sonarqube/conf находится основной конфигурационный файл Сонара — sonar.properties. В нём нужно найти строки:
#sonar.jdbc.password=
#sonar.jdbc.url=
Раскомментировать и указать логин и пароль, которые ввели на прошлом этапе, и строку подключения к Постгресу в формате:
В нашем случае получилось так:
sonar.jdbc.password=sonarpassword
sonar.jdbc.url=jdbc:postgresql://localhost:5433/sonar
Таким же образом можно изменить к примеру порт через параметр sonar.web.port:
Подробнее про параметры можно почитать в документации (docs.sonarsource.com/sonarqube-community-build/server-installation/system-properties/system-properties).
Запуск SonarQube
Предлагается два способа запуска сервера Сонара – вручную и в качестве службы.
Для большей управляемости, правильной настройки прав и ограничений, о которых мы писали выше, желательно создать отдельного пользователя, под которым будем запускать Сонар. Поэтому создадим группу и пользователя с именем «sonar» и укажем качестве его родной директории каталог дистрибутива:
Далее назначим пользователя владельцем своей папки:
Запуск вручную
Для того, чтобы запустить Сонар вручную перейдем в папку с исполняемыми файлами:
И от пользователя sonar исполним файл sonar.sh:
Сонар должен запуститься.
После этого можно проверить состояние командой:
После запуска через некоторое время можем обратиться как раньше по порту 9003 нашей виртуалки http://192.168.0.106:9003/.
Остановить выполнение можно такой командой:
Запуск в виде службы
Запуск вручную всё же можно считать опцией, в продуктиве приятнее работать со службой.
К примеру для systemd можно сделать это так.
Создадим файл службы:
Далее нужно его наполнить. В документации (docs.sonarsource.com/sonarqube-community-build/server-installation/from-zip-file/starting-stopping-server/running-as-a-service#on-linux-with-systemd) в качестве базового предлагается следующий текст
[Unit]
Description=SonarQube service
After=syslog.target network.target
[Service]
Type=simple
User=sonarqube
Group=sonarqube
PermissionsStartOnly=true
ExecStart=/bin/nohup /opt/java/bin/java -Xms32m -Xmx32m -Djava.net.preferIPv4Stack=true -jar /opt/sonarqube/lib/sonar-application-26.2.0.119303.jar
StandardOutput=journal
LimitNOFILE=131072
LimitNPROC=8192
TimeoutStartSec=5
Restart=always
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
В нашем случае получился такой файл:
На что следует обратить внимание:
- Нужно указать пользователя/группу, под которым будет запускаться служба. В нашем случае они одноименные sonar/sonar.
- В секции ExecStart нужно указать путь к java и к файлу «jar sonar-application-X.X.X.X.jar».
Конкретный путь к java можно узнать следующей командой:
Команда which показывает символическую ссылку на программу, а readlink возвращает её реальный путь.
В нашем случае:
А файл sonar-application-...jar мы выбрали по аналогии из подпапки /lib дистрибутива.
После записи файла службы, нужно её инициализировать и запустить:
Дальше проверяем состояние командой:
Если всё хорошо, у неё будет статус active:
Спустя пару минут можно заходить на адрес и начинать пользоваться:
Логи/Ошибки
В любой непонятной ситуации, например, если не стартует служба или если стартует, но при этом не открывается страничка Сонара в браузере, можно и нужно смотреть логи.
Найти их можно в директории /logs папки Сонара.
Вот пример пары ошибок, с которыми мы столкнулись в экспериментах.
Так выглядит ошибка некорректного указания имени базы в sonar.properties:
А вот такое сообщение будет при попытке запустить Сонар из-под рута:
Запуск SonarScanner
Теперь кратко пройдем по SonarScanner. Говоря простыми словами, эта утилита нужна для анализа вашего проекта и отправки данных на сервер Сонара. Подробнее можно почитать в документации (docs.sonarsource.com/sonarqube-community-build/analyzing-source-code/scanners/sonarscanner).
Её также как и Сонар можно запускать в двух вариантах — в контейнере и через sh-файл.
В контейнере
Для запуска через контейнер используем уже знакомую команду docker run, указав соответствующий образ. Примерный вид такой:
--network="host" \
-e SONAR_HOST_URL="http://localhost:9002" \
-e SONAR_TOKEN="sqa_..." \
-e SONAR_SCANNER_OPTS="-Dsonar.projectKey=Test" \
-v "<ПУТЬ_К_ПРОЕКТУ>:/usr/src" \
sonarsource/sonar-scanner-cli
Объяснение параметров:
- «--rm» — ключ, который подразумевает удаление контейнера после завершения работы. Предполагается, что SonarScanner утилита разового использования, поэтому по сути при каждом запуске мы пересоздаем контейнер заново.
- SONAR_HOST_URL — адрес вашего сервера Сонара с портом.
- SONAR_TOKEN — токен доступа, в некотором роде это замена логину/паролю. Его нужно предварительно сгенерировать на сервере Сонара, об этом поговорим ниже по статье.
- SONAR_SCANNER_OPTS — здесь нужно указать параметр «sonar.projectKey» — ключ вашего проекта.
- ПУТЬ_К_ПРОЕКТУ — в этом параметре пробрасываем соответствие директории вашего проекта с папкой /usr/src внутри контейнера.
Ну и в довершение указано имя образа «sonarsource/sonar-scanner-cli».
Существует иной вариант запуска. Можно создать в корневой папке проекта файл с именем sonar-project.properties и прописать часть параметров в нём, например, ключ проекта и пути. Образец можно посмотреть в документации (docs.sonarsource.com/sonarqube-community-build/analyzing-source-code/scanners/sonarscanner) или взять с гитхаба SonarSource (github.com/SonarSource/sonar-scanning-examples/blob/master/sonar-scanner/sonar-project.properties).
К примеру, мы указали там параметр sonar.projectKey, теперь можно запустить контейнер не указывая ключ проекта, он автоматически подтянется из файла:
--network="host" \
-e SONAR_HOST_URL="http://localhost:9002" \
-e SONAR_TOKEN="sqa_29d54b949ca1bf86becf9edbe7aba1e1b67e902d" \
-v "<ПУТЬ_К_ПРОЕКТУ >:/usr/src" \
sonarsource/sonar-scanner-cli
Без контейнера
Теперь запустим SonarScanner «вживую». Сначала скачаем его, ссылки можно найти в официальной документации (docs.sonarsource.com/sonarqube-community-build/analyzing-source-code/scanners/sonarscanner).
Мы взяли свежую версию на момент выхода статьи:
sonar-scanner-cli-8.1.0.6389-linux-x64.zip1.
Далее, как в примере с Сонаром, на виртуалке распакуем файл в директорию opt/, и для простоты переименуем получившуюся папку:
Также для упрощения дальнейших запусков имеет смысл прописать папку в пути поиска, используя следующие команды:
source /etc/profile.d/sonar-scanner.sh
Далее в папке conf зайдем в настроечный файл «sonar-scanner.properties», и укажем в нём путь к нашему серверу Сонара через параметр sonar.host.url:
Теперь в любой момент можно перейти в папку проекта и запустить его анализ простой командой, в которой нужно указать только токен доступа:
Уф, коллеги, на этом считаем вопрос установки Сонара закрытым и плавно переходим к следующей части нашей статьи.
Стоит заметить, что дальнейшее повествование с описанием методов работы с командной строкой и других компонентов будет иметь отношение к операционным системам Microsoft Windows.
Правила проверки кода
Соответствие проверяемого кода критериям качества и проблем в СонарКуб осуществляется по специальным правилам (набору проверок), которые анализируют исходный код и выявляют различного рода проблемы. Правила встроены в платформу СонарКуб и поддерживают разные языки программирования.
Правила делятся на несколько категорий:
Код с душком (Code smell).
К этой категории относится сложночитаемый код, длинные методы, дублирование... Проблемы не то, чтобы критические, но лучше исправлять их для улучшения восприятия и поддержки код.
Ошибка (bug).
Категория серьезных проблем. От них нужно избавляться безотлагательно.
Уязвимость (vulnerability).
Код данной категории несет возможную угрозу безопасности. Возможно используются устаревшие библиотеки или методы, которыми могут воспользоваться злоумышленники.
Security hotspot.
«Горячие точки» кода. Самые критичные проблемы с точки зрения безопасности.
Каждое правило имеет свои свойства-характеристики:
- Для какого языка программирования действует правило.
- К какой области качества программного обеспечения относится правило (поддерживаемость, надежность, безопасность).
- Для какого уровня критичности зафиксирована проблема (ошибка, предупреждение, информация).
- Дополнительные метки-теги для удобного поиска.
Платформа СонарКуб поддерживает множество языков программирования. Из коробки в бесплатной версии доступны следующие языки: Java, C#, JavaScript / TypeScript, Kotlin, Ruby, Go, Scala, Python, PHP, HTML, CSS, XML, Visual Basic.NET. А в корпоративной версии и версии для разработчиков список языков расширяется: Cobol, PL/I, Apex, RPG, Visual Basic 6, C, C++, Objective-C, Swift, ABAP, Transact-SQL, PL/SQL.
Язык 1С не входит в список официально поддерживаемых языков платформы СонарКуб и для его проверки используются сторонние правила (плагины), подключаемые к платформе.
Таких наборов правил всего 2.
SonarQube 1C (BSL) Plugin
SonarQube 1C (BSL) Community Plugin
Данные плагины позволяют проверять код, написанный на языке BSL (Business Script Language), производить анализ языка запросов 1С, а также осуществлять проверку структуры метаданных конфигурации.
В своей статье мы будем применять правила (SonarQube 1C (BSL) Community Plugin), разработанные open source сообществом 1c-syntax. Данный плагин распространяется бесплатно и доступен во встроенном маркетплейсе Сонара для скачивания сразу после установки:
«На борту» плагина собралось более 180 правил проверки:
Здесь есть правила проверяющие бесполезность кода, правила, проверяющие наличие описания и комментариев процедур и функций, выполнение запросов в цикле, наличие запрещенных слов и другие проверки.
С каждым правилом можно ознакомиться, уточнить примеры неправильного и правильного написания:
Поскольку список правил очень большой и использовать их все сразу будет затруднительно, настройте правила под свой проект, оставив самые полезные и важные на ваш взгляд, например:
Сопровождаемость
Когнитивная сложность
Цикломатическая сложность
Управляющие конструкции не должны быть вложены слишком глубоко
Двойные отрицания
Избыточное использование «Ссылка» в запросе
...
Надежность
Бесполезный перебор коллекции
Выполнение запроса в цикле
Хранение путей к файлам в коде
...
Безопасность
Хранение ip-адресов в коде
Хранение конфиденциальной информации в коде
...
Создадим новый профиль качества, содержащий нужный нам набор правил. Перейдем в раздел «Профили качества» и с помощью кнопки «Создать» запустим мастер создания профиля:
Выберем язык «1С (BSL)» и укажем имя создаваемого профиля. Подтвердим создание кнопкой «Создать». После создания профиля качества необходимо активировать выбранные ранее правила:
Проверка кода
Состав выполняемых проверок утвержден, можем приступать к этапу знакомства платформы СонарКуб с конфигурацией 1С. Для этого выгрузим конфигурацию в файлы, используя пункт «Выгрузить конфигурацию в файлы» меню «Конфигурация»:
При выполнении данной операции будут выгружены все объекты метаданных конфигурации (модули, формы, макеты...). Но нам для контроля качества кода будет достаточно только файлов, содержащих исходный код модулей. В этом случае необходимо написать скрипт для выполнения в командной строке или внешнюю обработку на 1С, которые оставят только текстовые файлы.
А как быть если необходимо проверить только часть кода? Например, исключив код модулей типовых конфигураций? К сожалению, интерактивный механизм выгрузки в файлы такой возможности не предоставляет. В этом случае можно воспользоваться снова внешней обработкой, которая обработает каталог с выгруженными файлами, удалив ненужное.
Еще можно воспользоваться программной выгрузкой конфигурации в файлы через командную строку, где уже поддерживается выборочная выгрузка объектов, но файл со списком фильтруемых объектов все равно придется формировать или внешней обработкой, или другими средствами.
/F "D:\Bases\FastFood3"
/DumpConfigToFiles "D:\SonarQube\FastFood3" -Format Plain -listFile "D:\Bases\FastFood3\objlist.txt"
Пример содержимого файла objlist.txt:
Проверяя выгруженные файлы конфигурации на качество кода, мы отвечаем на вопрос: «Качественно ли написана наша конфигурация?», но не видим авторов проблем, которых можно было бы отправить на курсы повышения качества кода и заставить переосмыслить написанное.
Проверка кода в разрезе авторов
Проверка кода в разрезе авторов возможна только при использовании хранилища конфигурации и Git-репозитория, синхронизированного с хранилищем.
Пройдемся по этапам, необходимым для выполнения поставленной задачи.
Получаем список версий хранилища в разрезе авторов.
С помощью командной строки формируем отчет по конфигурации в разрезе версий и авторов.
"C:\Program Files\1cv8\8.5.1.1150\bin\1cv8.exe" DESIGNER /WA- /L ru /VL ru
/F "D:\SonarQube\FastFood3"
/ConfigurationRepositoryF "tcp://localhost:3542/FastFood3"
/ConfigurationRepositoryN "admin"
/ConfigurationRepositoryP "pass_admin"
/ConfigurationRepositoryReport "D:\SonarQube\FastFood3\Report.txt"-ReportFormat txtФормат полученного отчета неудобен для дальнейшей обработки. Нам требуется получить линейное представление и желательно сгруппированное по автору и версии.
Сворачиваем полученный отчет по номеру версии и автору (пользователю хранилища), преобразовывая его сразу в формат CSV для удобства дальнейшей работы с этим отчетом. Группировка по версиям одного автора необходима для ускорения процесса загрузки.
Данное действие можно выполнить с помощью внешней обработки 1С, написав соответствующий код, или на другом языке программирования.
Приведем пример промежуточного варианта и уже свернутого:
Обрабатываем свернутый отчет и для каждой уникальной пары версия-автор запускаем выгрузку конфигурации в файлы с последующим помещением изменений в Git, не забыв указать автора.
git config user.name admingit config user.email admin@test.rugit add .git commit -m 'Текст комментария'git push origin masterТем самым в репозитории Git появится версия изменений, закрепленная за конкретным пользователем.
Затем синхронизируем изменения Git с платформой SonarQube, запуская механизм проверки качества кода. Запуск осуществляется с помощью специальной утилиты командной строки «SonarScanner CLI». Скачать актуальную версию утилиты можно по ссылке binaries.sonarsource.com/Distribution/sonar-scanner-cli.
Скачается zip-архив, который нужно развернуть в корне имеющегося жесткого диска. В нашем случае мы выбрали диск «C:\». Теперь можно запускать проверку качества кода и последующую передачу в Сонар.
Выполним скрипт:
"C:\SonarScanner\bin\sonar-scanner.bat"
-D"sonar.projectBaseDir=D:\SonarQube\FastFood3\Файлы"
-D"sonar.sources=./"
-D"sonar.sourceEncoding=UTF-8"
-D"sonar.host.url=http://localhost:9000"
-D"sonar.projectKey=fastfood"
-D"sonar.token=sqp_2381eed993ab6ed1aa1abd91e289cc3e953"
Описанный механизм уже реализован нами в конфигурации 1С-Рарус: СОК
как отдельный сценарий «Выгрузка конфигурации в Git».
Создание конфигурации «Анализ замечаний»
Как передавать и проверять код в Сонар мы научились, а вот для извлечения из этого еще большей пользы нам потребуются дополнительные инструменты анализа результатов проверки.
Создадим шаблон-пример конфигурации, с помощью которой мы сможем отслеживать динамику изменений количества замечаний от Сонара во времени. В дальнейшем данная конфигурация может быть вами доработана или перенесена в другую конфигурацию для развития данного инструмента.
Объекты для хранения данных
Добавим новую пустую конфигурацию 1С для разработки. Создадим объекты, в которых будем хранить данные, полученные от Сонара и используемые для анализа:
Справочник Проект.
В данном справочнике будем хранить информацию о проектах Сонара. Увеличим длину наименования до 150 символов и добавим реквизит Ключ (с типом Строка 100) для хранения уникального имени проекта в системе Сонар.
Справочник Пользователи.
Используем данный справочник для хранения авторов кода, от имени которых исходный код был помещен в Сонар.
Увеличим длину наименования до 150 символов и добавим реквизит Адрес электронной почты (с типом Строка 50). Данный адрес является своего рода идентификатором автора.Справочник Правила проверки.
Правила, по которым Сонар производил проверку также необходимо хранить. Это даст возможность анализа и отбора замечаний в разрезе правил.
Заведем служебные константы, в которых будем хранить информацию для подключения к серверу Сонара по API.
Адрес сервера (строка неограниченной длины).
Хранит URL к серверу Сонар.
Токен доступа (строка неограниченной длины).
Хранит цифровой ключ, подтверждающий права доступа к API Сонара.
Дата загрузки.
Хранит дату последнего загруженного замечания. Именно с этой даты мы будем загружать новые порции замечаний.
Объекты нормативно-справочной информации созданы. Перейдем к реализации регистра, хранящего замечания. Именно он будет использован нами как источник данных для анализа.
Регистр «Результаты проверки»
Создадим непериодический регистр сведений без подчинения регистратору. Назовем регистр Результаты проверки.
В качестве измерений укажем следующие сущности:
- Проект (тип — справочник Проекты).
Проект Сонар. - Правило (тип — справочник Правила проверки).
Правило, в рамках которого производилась проверка. - Автор (тип — справочник Пользователи).
Автор кода с замечанием. - Ключ (тип — строка 100).
Идентификатор замечания в системе Сонар. - Дата создания (тип — Дата).
Дата обнаружения замечания Сонаром.
А в реквизитах будем хранить дополнительную информацию:
- Модуль (строка неограниченной длины). В данном реквизите хранится имя проверенного модуля.
- Номер строки модуля (число). Хранит номер строки модуля, к которой у Сонара есть замечание.
Все необходимое для хранения результатов проверок готово. Можем переходить к созданию механизма загрузки.
Загрузка результатов
Загрузка будет осуществляться с помощью http-запросов, обращающихся к API сервера Сонар для получения данных.
Для доступа к API Сонара нам потребуется специальный цифровой ключ (токен), который будет использован при авторизации http-запроса. Токен можно создать в веб-интерфейсе сервера Сонара, через раздел «Безопасность — Пользователи» главного меню «Администрирование»:
Укажем имя токена и период действия. Подтверждаем создание нажатием кнопки «Сгенерировать»:
Сразу после генерации токена, на экран будет выведено само значение токена, которое надо будет скопировать и сохранить в другом месте. В интерфейсе Сонара мы больше не сможем увидеть значение этого токена!
В процессе загрузки данных мы будем обращаться с помощью http-запросов к различным методам API Сонара. Документация по методам API доступна через вызов пункта «Web API» меню «Помощь» верхней командной панели веб-интерфейса Сонара:
Вернемся к разрабатываемому нами инструменту анализа.
Загрузку данных мы реализуем в обработке. Запуск загрузки будет осуществляться вручную, интерактивно пользователем.
Создаем обработку Загрузка данных, добавляем форму, добавляем команду формы и размещаем кнопку команды на верхней командной панели.
Добавим реквизиты формы, с помощью которых пользователь сможет уточнить служебную информацию, используемую при загрузке:
- Адрес сервера (тип — строка неограниченной длины).
- Токен доступа (тип — строка неограниченной длины).
- Дата загрузки (тип — дата).
Теперь приступим к самому интересному — написанию кода загрузки данных. Откроем обработчик команды «Загрузить данные» и перейдем в обработчик команды, выполняемый в контексте сервера.
Создадим заготовки вызовов процедур и функций, которые будут нами использованы:
&НаСервере
Процедура КомандаЗагрузитьНаСервере()
Правила = СинхронизироватьПравила();
Авторы = СинхронизироватьАвторов();
Проекты = СинхронизироватьПроекты();
СинхронизироватьЗамечания(Проекты, Правила, Авторы);
КонецПроцедуры
С помощью функций СинхронизироватьПравила(), СинхронизироватьАвторов() и СинхронизироватьПроекты() мы будем запрашивать через API соответствующие данные и помещать их в заранее созданные справочники.
А при помощи процедуры СинхронизироватьЗамечания() мы обновим данные регистра сведений Результаты проверки.
Функция СинхронизироватьПравила()
Данная функция выполняет http-запрос к API Сонара, получает данные правил проверки и записывает полученные данные в справочник «Правила проверки».
При обращении к API для получения данных используется метод api/rules/search с отбором по языку программирования (languages=bsl).
&НаСервере
Функция СинхронизироватьПравила(НомерСтраницы = 1)
РезультатЗапроса = ВыполнитьЗапрос(АдресСервера
+ "/api/rules/search?languages=bsl&p="+ НомерСтраницы, "GET");
Правила = Новый Соответствие();
Для Каждого ТекПравило Из РезультатЗапроса.rules Цикл
ПравилоСсылка = НайтиПравило(ТекПравило.key);
Если ПравилоСсылка = Неопределено Тогда
ПравилоОбъект =
Справочники.ПравилаПроверки.СоздатьЭлемент();
ПравилоОбъект.Наименование = ТекПравило.name;
ПравилоОбъект.Ключ = ТекПравило.key;
ПравилоОбъект.Записать();
ПравилоСсылка = ПравилоОбъект.Ссылка;
КонецЕсли;
Правила.Вставить(ТекПравило.key, ПравилоСсылка);
КонецЦикла;
Если РезультатЗапроса.rules.Количество() > 0 Тогда
НомерСтраницы = НомерСтраницы + 1;
СинхронизироватьПравила(НомерСтраницы);
КонецЕсли;
Возврат Правила;
КонецФункции
Для выполнения http-запроса нам потребуется написать функцию ВыполнитьЗапрос(), выполняющую http-запрос и подготавливающую ответ-результат к загрузке.
Функция ВыполнитьЗапрос()
В самом начале функция преобразует URL в структуру, разделяя исходную строку с URL на составляющие адреса: адрес сервера, порт сервера, адрес метода.
Затем создает объект HTTPЗапрос, заполняет заголовки запроса, токен авторизации. Инициирует http-соединение и выполняет запрос, используя метод ВызватьHTTPМетод().
В случае успешного выполнения запроса, мы получаем ответ в виде строки и преобразовываем его в Структуру, с которой и будем дальше работать.
&НаСервере
Функция ВыполнитьЗапрос(URL, HTTPМетод)
СтруктураURI = ПолучитьСтруктуруURI(URL);
HTTPЗапрос = Новый HTTPЗапрос();
HTTPЗапрос.Заголовки.Вставить(
"Content-Type", "application/x-www-form-urlencoded");
HTTPЗапрос.Заголовки.Вставить(
"Authorization", "Bearer " + ТокенДоступа);
HTTPЗапрос.АдресРесурса = СтруктураURI.ПутьНаСервере;
Если ВРЕГ(Лев(URL, 5)) = ВРЕГ("HTTPS") Тогда
HTTPСоединение = Новый HTTPСоединение(
СтруктураURI.Хост,
СтруктураURI.Порт,
,
,
,
,
Новый ЗащищенноеСоединениеOpenSSL);
Иначе
HTTPСоединение = Новый HTTPСоединение(
СтруктураURI.Хост, СтруктураURI.Порт);
КонецЕсли;
HTTPОтвет = HTTPСоединение.ВызватьHTTPМетод(
HTTPМетод, HTTPЗапрос);
ОтветСтрокой = HTTPОтвет.ПолучитьТелоКакСтроку();
Если HTTPОтвет.КодСостояния <> 200 Тогда
ТекстСообщения = "Ошибка выполнения запроса: " + ОтветСтрокой;
ВызватьИсключение ТекстСообщения;
КонецЕсли;
СтруктураJSON = Новый Структура();
Попытка
ЧтениеJSON = Новый ЧтениеJSON();
ЧтениеJSON.УстановитьСтроку(ОтветСтрокой);
СтруктураJSON = ПрочитатьJSON(ЧтениеJSON,, "creationDate");
ЧтениеJSON.Закрыть();
Исключение КонецПопытки;
Возврат СтруктураJSON;
КонецФункции
А для поиска правила по ключу-идентификатору нам потребуется функция НайтиПравило(), с помощью которой мы сможем ответить на вопрос: «Есть ли в нашей конфигурации правило проверки с таким ключом».
Функция НайтиПравило()
&НаСервере
Функция НайтиПравило(Ключ)
Запрос = Новый Запрос("
|ВЫБРАТЬ Ссылка
|ИЗ Справочник.ПравилаПроверки
|ГДЕ Ключ = &Ключ И НЕ ПометкаУдаления");
Запрос.УстановитьПараметр("Ключ", Ключ);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка;
КонецЕсли;
Возврат Неопределено;
КонецФункции
Функция СинхронизироватьАвторов()
Данная функция получает авторов кода, выполняя http-запрос к API Сонара и помещает полученные данные в справочник Пользователи. Функция также использует вызов метода ВыполнитьЗапрос(), который мы уже создали при написании функции синхронизации правил проверки.
При обращении к API для получения данных используется метод api/v2/users-management/users.
&НаСервере
Функция СинхронизироватьАвторов()
РезультатЗапроса = ВыполнитьЗапрос(АдресСервера
+ "/api/v2/users-management/users", "GET");
Авторы = Новый Соответствие();
Для Каждого ТекАвтор Из РезультатЗапроса.users Цикл
АвторСсылка = НайтиАвтора(ТекАвтор.email);
Если АвторСсылка = Неопределено Тогда
АвторОбъект = Справочники.Пользователи.СоздатьЭлемент();
АвторОбъект.Наименование = ТекАвтор.name;
АвторОбъект.АдресЭлектроннойПочты = ТекАвтор.email;
АвторОбъект.Записать();
АвторСсылка = АвторОбъект.Ссылка;
КонецЕсли;
Авторы.Вставить(ТекАвтор.email, АвторСсылка);
КонецЦикла;
Возврат Авторы;
КонецФункции
При загрузке авторов мы использовали функцию НайтиАвтора(), которая определяла наличие автора по адресу электронной почты.
Функция НайтиАвтора()
&НаСервере
Функция НайтиАвтора(АдресЭлектроннойПочты)
Запрос = Новый Запрос("
|ВЫБРАТЬ Ссылка
|ИЗ Справочник.Пользователи
|ГДЕ АдресЭлектроннойПочты = &АдресЭлектроннойПочты
| И НЕ ПометкаУдаления");
Запрос.УстановитьПараметр(
"АдресЭлектроннойПочты", АдресЭлектроннойПочты);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка;
КонецЕсли;
Возврат Неопределено;
КонецФункции
Функция СинхронизироватьПроекты()
С помощью этой функции мы синхронизируем справочник Проекты, обращаясь с помощью http-запросов к API сервера Сонара.
При обращении к API для получения данных используется метод api/projects/search.
&НаСервере
Функция СинхронизироватьПроекты()
РезультатЗапроса = ВыполнитьЗапрос(АдресСервера
+ "/api/projects/search", "GET");
Проекты = Новый Соответствие();
Для Каждого ТекПроект Из РезультатЗапроса.components Цикл
Запрос = Новый Запрос("
|ВЫБРАТЬ Ссылка, Наименование
|ИЗ Справочник.Проекты
|ГДЕ Ключ = &Ключ И НЕ ПометкаУдаления");
Запрос.УстановитьПараметр("Ключ", ТекПроект.key);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ПроектСсылка = Выборка.Ссылка;
Иначе
ПроектОбъект = Справочники.Проекты.СоздатьЭлемент();
ПроектОбъект.Наименование = ТекПроект.name;
ПроектОбъект.Ключ = ТекПроект.key;
ПроектОбъект.Записать();
ПроектСсылка = ПроектОбъект.Ссылка;
КонецЕсли;
Проекты.Вставить(ТекПроект.key, ПроектСсылка);
КонецЦикла;
Возврат Проекты;
КонецФункции
Функция СинхронизироватьЗамечания()
Функция загрузки самых главных данных — результатов проверки. Данные получаются через http-запрос к API Сонара и записываются в регистр сведений «Результаты проверки».
При обращении к API для получения данных используется метод api/issues/search.
&НаСервере
Процедура СинхронизироватьЗамечания(Проекты, Правила, Авторы,
НомерСтраницы = 1, СтрокаУсловия = "")
Если НомерСтраницы = 1 Тогда
Если ЗначениеЗаполнено(ДатаЗагрузки) Тогда
СтрокаУсловия = "&createdAfter="
+ Формат(ДатаЗагрузки, "ДФ=yyyy-MM-dd");
КонецЕсли;
КонецЕсли;
РезультатЗапроса = ВыполнитьЗапрос(АдресСервера
+ "/api/issues/search?p=" + НомерСтраницы + СтрокаУсловия, "GET");
ДатаСоздания = Неопределено;
Для Каждого ТекЗамечание Из РезультатЗапроса.issues Цикл
Автор = Авторы.Получить(ТекЗамечание.author);
Если Автор = Неопределено Тогда
Автор = НайтиАвтора(ТекЗамечание.author);
Если Автор = Неопределено Тогда
АвторОбъект =
Справочники.Пользователи.СоздатьЭлемент();
АвторОбъект.Наименование = ТекЗамечание.author;
АвторОбъект.АдресЭлектроннойПочты =
ТекЗамечание.author;
АвторОбъект.Записать();
Автор = АвторОбъект.Ссылка;
КонецЕсли;
Авторы.Вставить(Автор, ТекЗамечание.author);
КонецЕсли;
Правило = Правила.Получить(ТекЗамечание.rule);
Если Правило = Неопределено Тогда
Правило = НайтиПравило(ТекЗамечание.rule);
Если Правило = Неопределено Тогда
ПравилоОбъект =
Справочники.ПравилаПроверки.СоздатьЭлемент();
ПравилоОбъект.Наименование = ТекЗамечание.rule;
ПравилоОбъект.Ключ = ТекЗамечание.rule;
ПравилоОбъект.Записать();
Правило = ПравилоОбъект.Ссылка;
КонецЕсли;
Правила.Вставить(Правило, ТекЗамечание.rule);
КонецЕсли;
ДатаСоздания = ТекЗамечание.creationDate;
ПрефиксПроект = ТекЗамечание.project + ":";
Модуль = СтрЗаменить(ТекЗамечание.component, ПрефиксПроект, "");
Менеджер =
РегистрыСведений.РезультатыПроверки.СоздатьМенеджерЗаписи();
Менеджер.ДатаСоздания = ДатаСоздания;
Менеджер.Ключ = ТекЗамечание.key;
Менеджер.Автор = Автор;
Менеджер.Проект = Проекты.Получить(ТекЗамечание.project);
Менеджер.Правило = Правило;
Менеджер.Модуль = Модуль;
Менеджер.НомерСтрокиМодуля = ТекЗамечание.line;
Менеджер.Записать();
КонецЦикла;
Если ДатаСоздания <> Неопределено Тогда
Константы.ДатаЗагрузки.Установить(ДатаСоздания);
КонецЕсли;
Если РезультатЗапроса.issues.Количество() > 0 Тогда
НомерСтраницы = НомерСтраницы + 1;
СинхронизироватьЗамечания(
Проекты, Правила, Авторы, НомерСтраницы, СтрокаУсловия);
КонецЕсли;
КонецПроцедуры
Допишем в процедуре КомандаЗагрузитьНаСервере() сохранение параметров доступа к серверу в служебных константах и обновим дату загрузки, т. к. она могла поменяться в процессе выполнения загрузки данных.
&НаСервере
Процедура КомандаЗагрузитьНаСервере()
...
ДатаЗагрузки = Константы.ДатаЗагрузки.Получить();
Константы.АдресСервера.Установить(АдресСервера);
Константы.ТокенДоступа.Установить(ТокенДоступа);
КонецПроцедуры
Также добавим процедуру ПриСозданииНаСервере(), которая будет восстанавливать на форме параметры доступа к серверу после последнего сеанса обмена.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ТокенДоступа = Константы.ТокенДоступа.Получить();
АдресСервера = Константы.АдресСервера.Получить();
ДатаЗагрузки = Константы.ДатаЗагрузки.Получить();
КонецПроцедуры
Ну что же, проверим себя и запустим загрузку? Сохраняем конфигурацию и запускаем в режиме Предприятие.
Вывод результата анализа
В разделе Сервис выбираем пункт «Загрузка данных». Вводим URL-адрес сервера Сонара, токен доступа, который мы заранее создали в системе Сонар и сохранили:
Нажимаем кнопку «Загрузить данные». После завершения загрузки перейдем к данным регистра сведений «Результаты проверки» и убедимся, что данные загрузились.
Данные на месте! А это значит, что мы можем приступить к созданию отчета, с помощью которого мы будем анализировать данные.
Вернемся в Конфигуратор и создадим новый отчет «Анализ замечаний». Отчет будет построен на СКД, предоставляя максимум возможностей для гибкого анализа данных.
Откроем схему компоновки данных и заполним текст запроса — источника данных.
ВЫБРАТЬ
РезультатыПроверки.Проект КАК Проект,
РезультатыПроверки.Правило КАК Правило,
РезультатыПроверки.Автор КАК Автор,
РезультатыПроверки.Ключ КАК Ключ,
РезультатыПроверки.ДатаСоздания КАК ДатаСоздания,
РезультатыПроверки.Модуль КАК Модуль,
РезультатыПроверки.НомерСтрокиМодуля КАК НомерСтрокиМодуля,
1 КАК КоличествоЗамечаний
ИЗ
РегистрСведений.РезультатыПроверки КАК РезультатыПроверки
Создадим ресурс КоличествоЗамечаний, который будет использоваться для подсчета количества ошибок в различных разрезах и укажем функцию агрегирования - в данном случае, просто будем суммировать количество по всем выбранным группировкам:
В качестве визуального отображения данных мы хотели бы видеть диаграмму для наглядности и таблицу для детальной расшифровки. Для этого добавим вариант отчета, в котором опишем, что же мы хотим видеть.
Сначала добавляем Диаграмму.
В качестве точек выбираем поле Автор, а в качестве серий - год возникновения замечания. В составе полей исходного запроса такого поля нет, но мы можем воспользоваться полем «Дата создания», в котором есть поле Год как часть даты.
Затем добавляем Таблицу.
В группировках строк мы хотим видеть правила проверки, а в горизонтальной развертке будем отображать Авторов, причем количество замечаний каждого автора мы еще и развернем по годам.
Добавляем выбранные поля, сохраняем отчет и запускаемся в режиме Предприятие. В разделе Отчеты, выбираем наш отчет и запускаем его формирование.
Проверяем: диаграмма на месте, замечания сгруппировались по авторам и годам.
И таблица выводится как мы и задумали.
Теперь, с помощью данного инструмента и СКД мы можем анализировать замечания в различных аспектах: отбирая по определенным правилам, проектам. Группировать по разным видам периода (месяц, квартал...).
Заключение
Коллеги, на этом мы завершаем наше путешествие в мир запахов кода и ждем Вас во второй части статьи, в которой мы сможем погрузиться еще глубже и разобрать процесс создания правил проверки качества кода.
Все упомянутые в статье бренды принадлежат их правообладателям.
От экспертов «1С-Рарус»
Читайте первыми статьи от экспертов «1С‑Рарус»
Вы можете получать оповещения по электронной почте
Или получайте уведомления в телеграм-боте

