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

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 Абонемент ($m)

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

10 стартмани

19.05.2026    1737    15    KHoroshulinAV    4    

8

Запросы Рефакторинг и качество кода Программист Стажер 1С:Предприятие 8 Бесплатно (free)

Есть запросы, которые сразу вызывают подозрение: десятки соединений, множество временных таблиц, объединения, группировки и длинный список условий. Но чаще проблемы прячутся в другом месте — в запросах, которые выглядят вполне приемлемо. Пара обращений через точку, отбор после виртуальной таблицы, РАЗЛИЧНЫЕ «чтобы убрать дубли», большой список в параметре, реквизит регистратора через составной тип — и вот уже на тестовой базе все летает, а в рабочей базе отчет открывается минуту. Разберу такие случаи из практики: не синтаксические ошибки, а именно запросы, которые формально нормальные, но на больших данных начинают вести себя плохо.

04.05.2026    1354    YA_2060655612    11    

9

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

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

29.04.2026    788    _apelsin4ik    0    

5

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

Код в 1С редко начинает тормозить сразу. Намного чаще он долго выглядит нормальным, а проблемы проявляются позже — когда растут данные, пользователи и количество доработок. В статье разбираю типичные причины такой деградации: запросы в цикле, лишние ПолучитьОбъект(), тяжёлые формы и обработку “по одному”. Статья практическая: с примерами, типичными ошибками и понятными признаками того, что код уже плохо масштабируется.

21.04.2026    1801    YA_2060655612    6    

11

Инструментарий разработчика Рефакторинг и качество кода Программист 1С:Предприятие 8 Бесплатно (free)

Инструмент для тех, кто устал читать модули по 50 тысяч строк и искать ошибки глазами. MetaVision загружает выгруженные файлы конфигурации и за секунды строит графы функций, находит уязвимости и подсвечивает проблемы производительности. Ключевые возможности: Визуализация логики функций (графы условий, циклов, транзакций и вызовов). Статический аудит безопасности (RCE, SSRF, COM-инъекции, пароли в коде). Поиск проблем производительности (запросы в циклах, вложенные блокировки). Полнотекстовый поиск по всем модулям конфигурации. Статистика по объектам и функциям. Безопасность: Программа работает строго локально. Код вашей конфигурации не отправляется в интернет и не анализируется на сторонних серверах. Попробуйте MetaVision сегодня — узнайте, что скрывает ваш код.

20.04.2026    10380    1091    KHoroshulinAV    55    

86

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

Как быстро разобраться в чужом коде? Как не забыть через полгода алгоритм работы своего собственного кода? Как наглядно проектировать? Ответам на эти вопросы посвящена данная публикация.

17.04.2026    736    chuprina_as    4    

4

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

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

20.03.2026    1511    ksnik    4    

5

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

ИИ действительно помогает команде ускориться: быстрее разбирать код, быстрее входить в сложные участки, быстрее запускать доработки. Проблема в том, что вместе со скоростью он может ускорять и другое — накопление скрытой сложности, рост цены изменений и потерю управляемости. В статье разбираю, почему первые успехи с ИИ так легко опьяняют, когда система начинает выставлять счёт и что нужно сделать, чтобы ускорение не превратилось в новый виток технического долга.

17.03.2026    2081    IgorVasilyev    54    

27
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
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 Сейчас в теме
Тогда
Функция НовыйСтруктураОтвета()
      Возврат Новый Структура("ВыполненоУспешно, МассивСообщений, Данные", Ложь, Новый Массив, Новый Структура);
КонецФункции
...
Ответ = НовыйСтруктураОтвета();
Ответ.Данные = ИнициализацияДанныхКлюча();


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