Обратная связь, атомарность и масштабируемость

10.09.24

Разработка - Рефакторинг и качество кода

В статье рассматривается отказ от использования процедур и унификация формата ответа функций. Способ описывается на примере развития абстрактной информационной системы, работающей с PDF файлами.

Проблема многих систем - тесное сплетение процедур и функций, отсутствие четких границ между слоями, слабая прослеживаемость внутренних операций и как результат - большое количество ресурсов для поддержания и расширения такой системы. Если для старых легаси такое допускается, то разработка новой функциональности в таком стиле - ни в коем случае.

В статье описывается необычный способ построения связей функций, выработанный мной в процессе многолетнего опыта разработки программных продуктов. В рамках статьи будет создана небольшая система, которую мы будем расширять, используя только рассматриваемый паттерн.

Следует понимать, что абстрактный пример для статьи максимально упрощен, при этом применение паттерна гипертрофировано. В реальной практике количество кода, узлов и условий намного больше, а использование любых паттернов, включая этот - взвешено и при необходимости.

 

Вводные

Нам поставлена задача - по содержимому файлов PDF создавать данные в информационной базе. Операция несложная, состоит из трех этапов - распознать содержимое документа PDF, создать по содержимому стандартизированные таблицы с данными, а затем реализовать бизнес-логику в учетной системе по этим данным.

 

 

Программный код, который это реализует, будет выглядеть примерно так:

 
 Внутренняя реализация - простейший способ

 

Такой способ реализации прост, последователен, логичен, удобочитаем. Но все это начнет исчезать, когда система поработает некоторое время. Выяснится, что некоторые файлы не обрабатываются. Разработчик заменит процедуру на функцию для возвращения признака успешного выполнения. Затем потребуется видеть, на каких этапах операции возникают ошибки обработки. В коде начнут появляться вставки с выводом сообщений, находиться вставки будут в различных местах кода, на различных слоях.
И даже при таком расширении функциональности (с уже потерянной элегантностью кода) проблемы не решатся - выясниться, к примеру, что вызов производится в некоторых случаях не пользователем, а автоматически, и сообщения некому читать.

 

Обратная связь обработчиков

Решить такого рода эскалацию проблем можно, введя расширенный формат ответа обработчиков. Каждый обработчик в программном коде должен возвращать следующую информацию:

  • Удалось ли выполнить операцию так, как от него это ожидалось?

  • Информационные сообщения, появившиеся в процессе работы;

  • Непосредственно сам результат обработчика (если требуется);

  • Прочая дополнительная информация, требуемая в контексте функциональности (если требуется).

Удобно для этого использовать ответ в виде структуры со следующими ключами:

Ответ = Новый Структура;
Ответ.Вставить("ВыполненоУспешно", Ложь);  // Односложный ответ, всегда булево
Ответ.Вставить("МассивСообщений", Новый Массив); // Всегда массив, может быть пустым
Ответ.Вставить("Результат", Неопределено); // То, что ожидается от функции. При неудаче - Неопределено

Система с таким паттерном информативна, удобна для отладки во всех слоях, замена обработчиков, возможно введение обработчиков возникающих проблем, сбор появившихся сообщений и их сортировка (мы ведь не собираемся выводить пользователю сообщения со всех слоев системы).

Реализация такого подхода:

 

 

 
 Внутренняя реализация с обратной связью

 

Взглянув на программный код выше, возникает разумный вопрос - не избыточна ли такая функциональность?

 - Нет.

Атомарность

Увеличив количество строк кода более, чем в 4 раза, мы создали функцию, которая теперь не только поддерживает масштабируемость собственной внутренней реализации, но так-же может быть легко встроена в часть другой системы, использующей описываемый паттерн. Унифицированный формат ответа исключает различные виды связей процедур и функций, определенных разработчиком локально, и неприменимых в других местах. В некоторых случаях процедуры и функции настолько тесно сплетены, что превращаются в монолит, полностью исключающий их атомарность.

При правильном использовании паттерна напротив, система состоит из автономных обработчиков, которые получают некоторые данные в виде параметров, и всегда возвращают данные в едином формате.

 

Рассмотрим это на примере нашей системы:

Наша разработка по работе с файлами PDF нашла признание в глазах заказчика, и он расширяет ее применение. Поступают новые требования:

1. Файлов теперь будет очень много, система должна справляться с нагрузкой;

2. Поддержка файлов PDF с новым типом таблиц, разделенных табуляцией (TSV);

3. Полноценное использование модуля из внешних систем, в т.ч. с Интернет-сайта заказчика;

4. Просмотр состояния выполнения обработки каждого файла в интерактивном режиме.

 

Масштабируемость

Для системы, не поддерживающей расширение функциональности, пункты 3 и 4 означали бы полное перестроение архитектуры, в некоторых случаях - написание программы с нуля. В нашем же случае атомарность всех обработчиков позволяет разрывать их цепь в любом месте на разные потоки.

 

Пример реализации, когда обработка файла разорвана на отдельные последовательности операций:

  • Получение файла и создание задания на отложенную обработку файла (API - POST);

  • Преобразование данных файла в таблицы значений и сохранение их (регламентное задание 1);

  • Запись данных таблиц значений в информационную базу (регламентное задание 2);

  • Запрос подробного состояния обработки файла и формирование отчета о выполнении (API - GET).
 

 

 
 Создание задания на обработку регламентными заданиями
 
 Преобразование файлов в данные
 
 Формирование отчета о выполнении задания

 

Вызов обработчиков и сами они никак не изменились, хотя сама система теперь значительно расширена. Задачи для регламентных заданий мы регистрируем записями в регистрах сведений, появляющиеся сообщения обработчиков и промежуточные результаты обработчиков сохраняем для передачи в другие потоки. Получаем эти данные другим потоком и продолжаем работу.

Если проанализировать код, видно, что он весь пронизан таким способом построения кода. Код стал шаблонным, однообразным, и как следствие, удобочитаем.

 

Заключение

Описываемый способ особенно актуален при работе с внешними сервисами и/или в многослойной архитектуре приложения. Однако использование его в тех местах, где это не требуется, может привести к определенным проблемам. Разработчик определяет, опираясь на систему сдержек и противовесов, собственного опыта и правил разработки, как паттерны использовать.

Вступайте в нашу телеграмм-группу Инфостарт

разработка программирование чистая архитектура паттерн обратная связь атомарность масштабируемость расширяемость

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Инструментарий разработчика Рефакторинг и качество кода Программист 1С 8.3 1С 8.5 1С:Документооборот 1С:Бухгалтерия 3.0 1С:Управление нашей фирмой 3.0 Россия Абонемент ($m)

Внешняя обработка для статического анализа исходников 1С без изменения данных базы. Помогает перед релизом или публикацией быстро проверить код на рискованные вызовы, интеграции, файловые операции и возможные секреты. Проверяемый код не выполняется, найденные пароли и токены маскируются.

2 стартмани

08.07.2026    401    4    NikolayMaerov    0    

4

Рефакторинг и качество кода Обновление 1С Программист 1С:Предприятие 8 1С:ERP Управление предприятием 2 Бесплатно (free)

На проекте сложного обновления 1С:ERP 2.4.14.181 до версии 2.5.22.106 нам было нужно уложить обновление в технологическое окно 48 часов (выходные). Исходный замер, с учетом промежуточных релизов 2.5.8.443, 2.5.12.270, 2.5.17.234, 2.5.22.106, показал требуемое время в 659 часов…

07.07.2026    2359    1c-izh    19    

19

Рефакторинг и качество кода Обновление 1С Программист 1С 8.3 Бесплатно (free)

Обновление ролей в расширении 1С отличается от аналогичного процесса в основной конфигурации. Ситуация осложняется, когда доработки вносятся не в «обычное», а в поставляемое расширение.

26.06.2026    825    1c-izh    3    

5

Рефакторинг и качество кода Программист Россия Бесплатно (free)

Code review в 1С часто превращается в спор вкусов: “мне не нравится”, “переделай”, “так не делают”. В статье разбираю другой подход: проверять не разработчика, а риск для системы. Показываю, как формулировать замечания без токсичности, где заканчивается личное предпочтение и начинается реальная проблема, почему ревью должно развивать разработчика, а не только исправлять код

24.06.2026    761    NikolayMaerov    4    

6

Нейросети Рефакторинг и качество кода Программист Бесплатно (free)

Показываем, как встроить ИИ-помощника в code review 1С без Git, SonarQube и EDT – только с Конфигуратором, RAG-контекстом и набором MCP-инструментов. Разбираем архитектуру решения на Open Web UI и OpenRouter, методику сравнения моделей по Precision, Recall, BonusRate и PenaltyRate, а также объясняем, почему контекст влияет на качество ревью сильнее, чем выбор самой модели. На реальных примерах показываем, какие ошибки ИИ находит хорошо, где все еще нужен архитектор и почему на старте пилота время ревью может не сократиться, а вырасти. В финале делимся метриками внедрения и выводами для команд, которые хотят повторить такой подход у себя.

17.06.2026    1026    NVyunova    1    

3

Нейросети Рефакторинг и качество кода Программист Бесплатно (free)

Кажется, что code-review с помощью искусственного интеллекта устроено просто: достаточно отправить код в LLM, задать промт и получить список замечаний. На практике такой подход быстро упирается в недетерминированность результата, неверную оценку критичности ошибок в 1С-коде и рекомендации, которые сложно отличить от полезных замечаний. Описываем гибридный подход к автокод-ревью: статический анализатор работает вместе с LLM, а база знаний из стандартов 1С превращается в набор машиночитаемых норм. Такая архитектура помогает снизить количество галлюцинаций, точнее определять критичность нарушений и постепенно развивать качество ревью через итеративное пополнение правил.

09.06.2026    1964    Repich    5    

9

Рефакторинг и качество кода Программист Бесплатно (free)

Чем активнее развивается старая система, тем страшнее бывает её менять. Снаружи всё выглядит живым: релизы выходят, бизнес получает новые функции, пользователи работают. Но внутри уже появляются фразы, после которых разговор заканчивается: «это лучше не трогать», «там когда-то всё упало», «давайте сделаем рядом». И в какой-то момент становится непонятно: система ещё развивается — или команда уже просто учится обходить опасные места.

04.06.2026    1051    IgorVasilyev    29    

5

Инструментарий разработчика Рефакторинг и качество кода Программист 1С 8.3 Абонемент ($m)

MetaVision for 1C PRO — профессиональная версия статического анализатора и визуализатора кода. Загружает выгрузки конфигураций, расширения и внешние файлы, за секунды строит графы функций, находит уязвимости безопасности и подсвечивает проблемы производительности. В арсенале: визуализация логики в виде графов условий, циклов, транзакций и вызовов, статический аудит безопасности с поиском RCE, SSRF, COM-инъекций и паролей в коде, выявление запросов в циклах и вложенных блокировок, полнотекстовый поиск по всем модулям, встроенный редактор с конвертером запросов и автоформатированием, а также честная статистика по объектам и функциям. Главное новшество PRO — до пяти конфигураций одновременно с мгновенным переключением, наложение до пяти расширений как в конфигураторе, анализ внешних файлов в единой связке с основной конфигурацией и пять тем оформления. Инструмент для тех, кто ведёт несколько проектов параллельно и хочет видеть полную картину в одном окне — быстро, наглядно и безопасно.

7 стартмани

19.05.2026    3348    35    KHoroshulinAV    7    

13
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Aitbay 13.09.24 10:36 Сейчас в теме
Хорошо описано, по идее мысль не новая, но полезная
acces969; +1 Ответить
2. SirStefan 55 18.09.24 14:32 Сейчас в теме
Тогда уж так, для масштабируемости:
Функция НовыйСтруктураОтвета()
      Возврат Новый Структура("ВыполненоУспешно, МассивСообщений", Ложь, Новый Массив);
КонецФункции
acces969; +1 Ответить
3. acces969 381 30.09.24 08:53 Сейчас в теме
(2) Да, хороший способ. Можно в глобальный модуль добавить. Делаю похожее с непериодическими регистрами сведений, если требуется периодически менять значения ключа записи. Две процедуры находятся в модуле регистра сведений и реализуют чтение/запись в него. Это позволяет исключить проблему, когда трудно найти, в каком месте в коде записываются какие-либо данные в регистр сведений.

Первая функция возвращает пустую структуру, которая затем принимается второй процедурой для непосредственной записи/обновления ключа:

Функция ИнициализацияДанныхКлюча() Экспорт
	
	ДанныеКлюча = Новый Структура;
	ДанныеКлюча.Вставить("КлючBase64", "");
	ДанныеКлюча.Вставить("ПредставлениеКлючаПодписи", "");
	ДанныеКлюча.Вставить("Пароль", "");
	ДанныеКлюча.Вставить("КлючBase64Аутентификации", "");
	ДанныеКлюча.Вставить("ПредставлениеКлючаАутентификации", "");
	ДанныеКлюча.Вставить("ПарольАутентификации", "");
	
	Возврат ДанныеКлюча;
	
КонецФункции

Процедура ОбновитьДанныеКлюча(Ключ, ДанныеКлюча, Запись = Неопределено, ЗаписыватьЗапись = Ложь) Экспорт
	
	Если Запись = Неопределено Тогда
		Запись = РегистрыСведений.ДанныеКлючей.СоздатьМенеджерЗаписи();
		Запись.Ключ = Ключ;
		Запись.ПредставлениеКлючаПодписи = ДанныеКлюча.ПредставлениеКлючаПодписи;
		Запись.ПредставлениеКлючаАутентификации = ДанныеКлюча.ПредставлениеКлючаАутентификации;
		Запись.ДанныеКлюча = Новый ХранилищеЗначения(ДанныеКлюча);	
	Иначе
		Запись.ПредставлениеКлючаПодписи = ДанныеКлюча.ПредставлениеКлючаПодписи;
		Запись.ПредставлениеКлючаАутентификации = ДанныеКлюча.ПредставлениеКлючаАутентификации;	
		Запись.ДанныеКлюча = Новый ХранилищеЗначения(ДанныеКлюча);
	КонецЕсли;
	
	Если ЗаписыватьЗапись Тогда
		Запись.Записать(Истина);   
	КонецЕсли;
	
КонецПроцедуры
Показать


В зависимости от требований и состава регистра сведений, процедура записи может отличаться. Структура инициализации в свою очередь может содержать только данные, необходимые для бизнес-логики, а не все поля записи регистра сведений.
4. SirStefan 55 30.09.24 09:44 Сейчас в теме
Тогда
Функция НовыйСтруктураОтвета()
      Возврат Новый Структура("ВыполненоУспешно, МассивСообщений, Данные", Ложь, Новый Массив, Новый Структура);
КонецФункции
...
Ответ = НовыйСтруктураОтвета();
Ответ.Данные = ИнициализацияДанныхКлюча();


И тогда Ответ.Данные можно и в ЗаполнитьЗначенияСвойств использовать. Или передавать как массив, так и таблицу значений для пакетной записи...
Для отправки сообщения требуется регистрация/авторизация