Разработчики, приходящие в сферу 1С из других языков программирования, часто ищут специализированную литературу по алгоритмам и структурам данных, адаптированную под встроенный язык «1С:Предприятия». В классическом программировании есть признанные труды (например, книги Никлауса Вирта, Роберта Лафоре или Роберта Мартина), но существует ли их прямой аналог для 1С? Разберем, где искать лучшие практики, стандарты разработки и какие хитрости используют опытные специалисты для оптимизации и повышения читаемости своего кода.
В экосистеме 1С платформа развивается очень динамично, поэтому классические бумажные книги по конкретным фичам быстро теряют актуальность. Тем не менее, существуют фундаментальные источники знаний, которые должен изучить каждый разработчик:
Рассмотрим подробнее практические приемы, архитектурные паттерны и лайфхаки, которые обсуждают практикующие специалисты.
Один из самых полезных архитектурных лайфхаков для написания расширяемого кода — это правило возврата структуры из экспортных или сложных локальных функций. Выясним, почему классический возврат простого значения (например, Истина или Ложь) часто ведет к проблемам при долгосрочной поддержке конфигурации.
Представим, что мы пишем функцию проверки возможности отгрузки товара. На первом этапе нам достаточно знать только результат проверки (да/нет). Мы пишем простую функцию, которая возвращает булево значение. Однако через месяц бизнес требует выводить пользователю детальную причину отказа (например, «нет свободных остатков» или «превышен лимит кредита»). Если функция возвращала простое булево значение, нам придется переписать логику вызова этой функции во всех местах, где она используется.
Проанализируем альтернативный подход: функция всегда возвращает структуру, содержащую флаг успешности, описание ошибки или другие полезные данные. Посмотрим на пример реализации такого паттерна:
Функция ПроверитьВозможностьОтгрузки(ПараметрыПроверки) Экспорт
РезультатПроверки = Новый Структура;
РезультатПроверки.Вставить("Успешно", Истина);
РезультатПроверки.Вставить("ОписаниеОшибки", "");
РезультатПроверки.Вставить("ДополнительныеДанные", Неопределено);
// Пример логики проверки
Если ПараметрыПроверки.Товар.Остаток < ПараметрыПроверки.Количество Тогда
РезультатПроверки.Успешно = Ложь;
РезультатПроверки.ОписаниеОшибки = "Недостаточно товара на складе!";
Возврат РезультатПроверки;
КонецЕсли;
Возврат РезультатПроверки;
КонецФункции
Преимущества данного подхода:
Разработчики в 1С часто сталкиваются с тем, что при написании кода Конфигуратор не предлагает подсказки для методов объектов, переданных в качестве параметров функций. Платформа 1С использует динамическую типизацию, поэтому среда разработки «не знает», какой тип объекта будет передан в переменную ТабЗначения на этапе выполнения.
Рассмотрим изящный лайфхак, который заставит платформу активировать автодополнение методов (например, предлагать методы Добавить(), НайтиСтроки() для таблиц значений).
Для этого в начале процедуры или функции мы можем объявить псевдоинициализацию объекта внутри условия, которое гарантированно никогда не выполнится на этапе исполнения, но будет проанализировано синтаксическим редактором Конфигуратора. Посмотрим на пример:
Процедура ОбработатьТаблицу(ТабЗначения)
#Если Сервер И НЕ Сервер Тогда
// Этот код никогда не выполнится, но Конфигуратор поймет тип переменной
ТабЗначения = Новый ТаблицаЗначений;
#КонецЕсли
// Теперь при вводе "ТабЗначения." будет работать контекстная подсказка
НоваяСтрока = ТабЗначения.Добавить();
КонецПроцедуры
Использование директивы компиляции #Если Сервер И НЕ Сервер Тогда является наиболее «кошерным» вариантом, так как этот блок кода отсекается еще на этапе компиляции модуля и никак не влияет на производительность системы в рабочем режиме.
При написании логических ветвлений в алгоритмах важно четко понимать, как платформа осуществляет приведение типов. Незнание этих нюансов часто приводит к трудноуловимым багам.
Разберем поведение условного оператора Если при работе с числовыми переменными:
а = -430;
б = 0;
Если а Тогда
// Данный блок выполнится, так как любое число, отличное от нуля, приводится к Истине
Сообщить("Это истина");
КонецЕсли;
Если б Тогда
// Данный блок НЕ выполнится, так как 0 приводится к Ложь
Сообщить("Это ложь");
КонецЕсли;
Особое внимание стоит уделить работе встроенной функции ЗначениеЗаполнено(). Многие разработчики допускают ошибку, путая поведение булевых значений и чисел. Посмотрим на важные отличия:
// Числа
РезультатДляНоля = ЗначениеЗаполнено(0); // Возвратит Ложь, так как 0 считается незаполненным числом
// Булево
РезультатДляЛожь = ЗначениеЗаполнено(Ложь); // Возвратит Истина!
Важно: Функция ЗначениеЗаполнено() возвращает Истина для значения Ложь, поскольку для булевого типа оба состояния (и Истина, и Ложь) являются валидными и заполненными значениями. На это поведение часто натыкаются новички при проверке флагов в настройках.
При реализации сложных алгоритмов разбора текстовых данных часто требуется разделить строку в массив по определенному разделителю. В современных версиях платформы 1С (начиная с 8.3.6) для этого есть штатная эффективная функция СтрРазделить().
Однако в старых конфигурациях или для понимания истории развития платформы полезно знать исторический «лайфхак» быстрого разделения строк, который работал в разы быстрее, чем классический обход строки в цикле с поиском символов. Этот хак использовал недокументированные возможности внутреннего формата сериализации 1С через функцию ЗначениеИзСтрокиВнутр():
Функция БыстрыйСплит(ПереданнаяСтрока, Разделитель) Экспорт
СтрокаДанных = ПереданнаяСтрока;
СтрокаДанных = СтрЗаменить(СтрокаДанных, """", """""" );
ЧислоВхождений = СтрЧислоВхождений(СтрокаДанных, Разделитель);
СтрокаДанных = СтрЗаменить(СтрокаДанных, Разделитель, """},{""S"",""" );
// Формируем системную строку внутреннего формата для преобразования в Массив
СтрокаДанных = "{""#"",51e7a0d2-530b-11d4-b98a-008048da3034,{" + СтрЗаменить(ЧислоВхождений + 1, Символы.НПП, "" ) + ",{""S"",""" + СтрокаДанных + """}}}";
Возврат ЗначениеИзСтрокиВнутр(СтрокаДанных);
КонецФункции
В современном коде всегда используйте штатную функцию СтрРазделить(Строка, Разделитель, ВключатьПустые), так как она написана на C++ на уровне платформы и работает максимально быстро и безопасно.
Чтобы не держать в голове сотни правил оптимизации и стандартов ИТС, современному 1С-разработчику крайне важно внедрять в свою практику инструменты автоматического статического анализа кода:
Использование этих инструментов совместно с изучением стандартов ИТС и книги «Профессиональная разработка» позволит вам писать быстрые, стабильные и легко поддерживаемые алгоритмы на платформе «1С:Предприятие 8».