Куда течет интерфейс?

03.02.25

Разработка - Работа с интерфейсом

Про ООП в 1С и о том, как сделать свой код более кратким и выразительным при помощи использования текучего интерфейса (fluent interface).

Текучий интрефейс (fluent interface) - это способ организации функций в классе таким образом, чтобы их можно было вызывать через точку друг от друга, т.е. использовать цепочки методов

Возможно, если вы сталкивались с автоматизированным тестированием в 1С или OneScript, вроде YaxUnit, xUnitFor1C, Vanessa-Add, Asserts и т.п., то слышали термин "текучие утверждения". Так вот это частный случай текучего интерфейса, когда с его помощью реализуются разнообразные проверки истинности утверждений - например, результатов тестирования:

 

Ожидаем.Что(НекийМассив.Количество()).Минимум(9);

 

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

 

ООП и 1С

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

 

...не реализует. Но выход есть - использовать модуль объекта обработки

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

 

Пишем код

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

Для наглядности создадим новую обработку. Она будет представлять из себя некоторый "текучий калькулятор", благодаря которому мы сможем выполнять математические действия одно за другим через точку. Да, очень просто, но зато понятно.

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

 

Перем Значение Экспорт;

#Область ПрограммныйИнтерфейс

// Функция - Установить значение
//
// Параметры:
//  ЧисловоеЗначение - Число - Начальное значение
// 
// Возвращаемое значение:
//  ОбработкаОбъект.ТекучийКалькулятор - Этот объект
Функция УстановитьЗначение(Знач ЧисловоеЗначение) Экспорт
	
	Значение = ПривестиЧисло(ЧисловоеЗначение);	
	Возврат ЭтотОбъект;
	
КонецФункции

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

Функция ПривестиЧисло(Знач ЧисловоеЗначение) Экспорт
	
	ОТЧ = Новый ОписаниеТипов("Число");
	Возврат ОТЧ.ПривестиЗначение(ЧисловоеЗначение);

КонецФункции

#КонецОбласти

 

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

 

// Функция - Прибавить
//
// Параметры:
//  ЧисловоеЗначение - Число - Значение для прибавления
// 
// Возвращаемое значение:
//  ОбработкаОбъект.ТекучийКалькулятор - Этот объект
Функция Прибавить(Знач ЧисловоеЗначение) Экспорт
	
	Значение = Значение + ПривестиЧисло(ЧисловоеЗначение);
	Возврат ЭтотОбъект;
	
КонецФункции

// Функция - Отнять
//
// Параметры:
//  ЧисловоеЗначение - Число - Значение для вычитания
// 
// Возвращаемое значение:
//   ОбработкаОбъект.ТекучийКалькулятор - Этот объект
Функция Отнять(Знач ЧисловоеЗначение) Экспорт
	
	Значение = Значение - ПривестиЧисло(ЧисловоеЗначение);
	Возврат ЭтотОбъект;
	
КонецФункции

 

Отлично - у нас есть некоторый базовый интерфейс. Рассмотрим его:

  • Первое, что бросается в глаза - все функции возвращают ЭтотОбъект. Это, как мы уже обсуждали, и позволяет делать цепочки вызовов
  • Второе - это переменная значение. Она служит для хранения результата между операциями и получения конечного значения

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

 

	ТекучийКалькулятор = Обработки.ТекучийКалькулятор.Создать();
	
	ТекучийКалькулятор.УстановитьЗначение(0)
		.Прибавить(20) // 20
		.Отнять(10)    // 10
		.Прибавить(5)  // 15
		.Отнять(3);    // 12
		
	Результат = ТекучийКалькулятор.Значение; // 12

 

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

Думаю, тут нет необходимости в особенных объяснениях: мы вызываем функции, которые меняют экспортную переменную Значение, а затем получаем ее содержимое. Таким образом можно реализовать множество разнообразных процессов, в том числе и сугубо 1Сных: мы используем обработку, как самый очевидный объект метаданных для подобных изысканий, но на самом деле ничего не мешает нам реализовывать подобное и в модулях объектов справочников или документов. Например, для их заполнения

 

Обработка ошибок

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

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

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

  • В модуле обработки мы добавим еще одну переменную - Ошибка
  • В каждую нашу функцию добавим Возврат в том случае, если Ошибка заполнена

Вот как выглядит наш обновленный модуль:

 

Перем Значение Экспорт;
Перем Ошибка Экспорт;

#Область ПрограммныйИнтерфейс

// Функция - Установить значение
//
// Параметры:
//  ЧисловоеЗначение - Число - Начальное значение
// 
// Возвращаемое значение:
//  ОбработкаОбъект.ТекучийКалькулятор - Этот объект
Функция УстановитьЗначение(Знач ЧисловоеЗначение) Экспорт
	
	Если ЗначениеЗаполнено(Ошибка) Тогда Возврат ЭтотОбъект КонецЕсли;
	
	Значение = ПривестиЧисло(ЧисловоеЗначение);	
	Возврат ЭтотОбъект;
	
КонецФункции

// Функция - Прибавить
//
// Параметры:
//  ЧисловоеЗначение - Число - Значение для прибавления
// 
// Возвращаемое значение:
//  ОбработкаОбъект.ТекучийКалькулятор - Этот объект
Функция Прибавить(Знач ЧисловоеЗначение) Экспорт
	
	Если ЗначениеЗаполнено(Ошибка) Тогда Возврат ЭтотОбъект КонецЕсли;
	
	Значение = Значение + ПривестиЧисло(ЧисловоеЗначение);
	Возврат ЭтотОбъект;
	
КонецФункции

// Функция - Отнять
//
// Параметры:
//  ЧисловоеЗначение - Число - Значение для вычитания
// 
// Возвращаемое значение:
//   ОбработкаОбъект.ТекучийКалькулятор - Этот объект
Функция Отнять(Знач ЧисловоеЗначение) Экспорт
	
	Если ЗначениеЗаполнено(Ошибка) Тогда Возврат ЭтотОбъект КонецЕсли;
	
	Значение = Значение - ПривестиЧисло(ЧисловоеЗначение);
	Возврат ЭтотОбъект;
	
КонецФункции

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

Функция ПривестиЧисло(Знач ЧисловоеЗначение) Экспорт
	
	ОТЧ = Новый ОписаниеТипов("Число");
	Возврат ОТЧ.ПривестиЗначение(ЧисловоеЗначение);

КонецФункции

#КонецОбласти

 

Для проверки необходимо спровоцировать какое-нибудь исключение. Добавим для этого функцию деления:

 

// Функция - Разделить на
//
// Параметры:
//  ЧисловоеЗначение - Число - Делитель
// 
// Возвращаемое значение:
//   ОбработкаОбъект.ТекучийКалькулятор - Этот объект
Функция РазделитьНа(Знач ЧисловоеЗначение) Экспорт
	
	Если ЗначениеЗаполнено(Ошибка) Тогда Возврат ЭтотОбъект КонецЕсли;

	Делитель = ПривестиЧисло(ЧисловоеЗначение);
	
	Попытка
		Значение = Значение / Делитель;
	Исключение
		Ошибка = ОписаниеОшибки();
	КонецПопытки;
	
	Возврат ЭтотОбъект;
	
КонецФункции

 

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

 

	ТекучийКалькулятор = Обработки.ТекучийКалькулятор.Создать();
	
	ТекучийКалькулятор.УстановитьЗначение(0)
		.Прибавить(20)  // 20
		.Отнять(10)     // 10
		.Прибавить(5)   // 15
		.РазделитьНа(0) // Ошибка
		.Отнять(3);     
		
	Ошибка = ТекучийКалькулятор.Ошибка;
	
	Если ЗначениеЗаполнено(Ошибка) Тогда
		Результат = Ошибка;
	Иначе
		Результат = ТекучийКалькулятор.Значение;
	КонецЕсли;
	
	// Деление на 0
	Сообщить(Результат);

 

Таким же нехитрым образом, кроме текста ошибки, мы можем сохранить и другую информацию об исключении: например, добавить переменную для записи имени функции, которая привела к ошибке или счетчик, увеличивающийся на 1 после вызова каждой функции цепи, чтобы определить, какое "звено" было последним

 

Получение результата

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

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

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

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

 

// Функция - Получить результат
// 
// Возвращаемое значение:
//  Структура - Описание результата
//    * Ошибка - Булево       - Признак ошибки выполнения
//    * Данные - Строка,Число - Полученное значение или текст ошибки
Функция ПолучитьРезультат() Экспорт
	
	ЭтоОшибка = ЗначениеЗаполнено(Ошибка);
	
	Возврат Новый Структура("Ошибка,Данные"
		, ЭтоОшибка
		, ?(ЭтоОшибка, Ошибка, Значение));
	
КонецФункции

 

... и немного изменить вызов

 

	ТекучийКалькулятор = Обработки.ТекучийКалькулятор.Создать();
	
	// И никаких экспортных переменных :)
	Результат = ТекучийКалькулятор.УстановитьЗначение(0)
		.Прибавить(20)  
		.Отнять(10)     
		.Прибавить(5)   
		.РазделитьНа(0) 
		.Отнять(3)
		.ПолучитьРезультат();  

 

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

 

В заключение

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

 

 
 Текучий калькулятор

 

Спасибо за внимание!

 

 

Другие мои статьи:

Открытый пакет интеграций для популярных API: Telegram, VK, Viber, Bitrix24 и многих других 

Open-source набор библиотек интеграции с популярными сервисами: методы для 20-ти популярных API, поставка в виде расширения, OneScript-пакета и даже полноценного приложения для командной строки, подробная документация. И все это абсолютно бесплатно!

 

Автоматизация редактирования изображений в ImageMagick - это просто!

На что способен ImageMagick и некоторые неочевидные моменты при интеграции его в 1С.

 

 

 Мой GitHub:    https://gitub.com/Bayselonarrend 
 OpenYellow:    https://openyellow.notion.site
 Лицензия MIT:  https://mit-license.org

 

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

разработка ООП fluent текучие утверждения текучий интерфейс

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

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

См. также

Работа с интерфейсом Анализ учета Мониторинг 1С:Предприятие 8 1С 8.3 1C:Бухгалтерия 1С:Бухгалтерия 3.0 1С:ERP Управление предприятием 2 1С:Управление холдингом 1С:Зарплата и Управление Персоналом 3.x 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Управление торговлей 11 Платные (руб)

Создайте свой функциональный интерфейс в любой конфигурации 1С с помощью расширения Infostart Dashboard. Настраивайте панели виджетов с метриками, индикаторами и показателями на начальном экране. Узнайте возможность внедрения подсистемы у себя в конфигурации с помощью бесплатной обработки "Анализ внедрения подсистемы 1С Infostart Dashboard"!

31720 руб.

27.03.2025    92191    69    44    

77

Консолидация данных Работа с интерфейсом Разработчик Пользователь 1С:Предприятие 8 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 1C:ERP Узбекистан Беларусь Кыргызстан Россия Казахстан Платные (руб)

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

6088 руб.

17.10.2025    3625    3    0    

2

Разработка Инструментарий разработчика Работа с интерфейсом Адаптация типовых решений Нейросети 1C:Бухгалтерия 1C:ERP 1С:ЗУП 1С:КА 1С:УНФ 1С:УТ 1С:Розница 1С:ДО 1С:ERP Управление предприятием 2 Платные (руб)

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

36600 руб.

28.08.2025    10292    2    2    

6

Механизмы платформы 1С Разработчик 1С:Предприятие 8 Бесплатно (free)

Давайте разберемся в механизме «История данных» и поэкспериментируем для наглядности. Сравним «Версионирование объектов» и «Историю данных».

06.03.2023    75528    dsdred    105    

247

Механизмы платформы 1С Разработчик 1С:Предприятие 8 Россия Бесплатно (free)

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

29.07.2022    144818    zeltyr    28    

229

Работа с интерфейсом Разработчик 1С:Предприятие 8 1C:Бухгалтерия Абонемент ($m)

"MVC плохо применима в 1С" - познакомьтесь с моделью состояния и, возможно, ваше мнение поменяется! Представленное решение является эволюционным развитием идеи реализации MVC для 1С. В новой версии добавлены DSL для описания модели состояния, а также параметризация свойств параметров и элементов формы.

1 стартмани

05.07.2022    17923    kalyaka    8    

36

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

Копнем глубже в тему "Что же такое динамическое обновление" и почему оно может привести к проблемам. И может ли?

09.05.2022    55062    Infostart    85    

262

Инструментарий разработчика Рефакторинг и качество кода Групповая разработка (Git, хранилище) Механизмы платформы 1С Разработчик Стажер Бесплатно (free)

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

29.11.2021    83169    mrXoxot    63    

501
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. deplatoon 28 03.02.25 13:20 Сейчас в теме
Отличная статья, вкину факт - большая часть стандартной библиотеки в 1С Элементе реализована для флюент апи из коробки, очень приятно использовать
koropo; bayselonarrend; +2 – Ответить
2. dhurricane 03.02.25 14:20 Сейчас в теме
Обработко-ориентированное программирование. :) Жаль без извратов работает только на сервере.
saddy; TitBit_infostart; vlaskin; adhocprog; kMidas; Sergik_D; ixijixi; +7 – Ответить
9. alex_sayan 71 03.02.25 15:30 Сейчас в теме
Чутка подушню. Пример с калькулятором выглядит как-то уж совсем вырожденно. И даже вводит в заблуждение. Проще написать

Результат = 0 + 20 - 10 + 5 / 0 - 3;


чем

Результат = ТекучийКалькулятор.УстановитьЗначение(0)
		.Прибавить(20)  
		.Отнять(10)     
		.Прибавить(5)   
		.РазделитьНа(0) 
		.Отнять(3)
		.ПолучитьРезультат();


При правильном подходе, текучий интерфейс сокращает количество кода. Тут же получилось будто кода больше
artbear; EvilMilko; ivanov660; +3 –1 Ответить
11. bayselonarrend 3214 03.02.25 15:42 Сейчас в теме
(9) Да, это нереалистичный пример, но простой, чтобы было понятно
user1827801; +1 – Ответить
47. ivanov660 4989 04.02.25 12:24 Сейчас в теме
(11)
1. Желательно приводить что-то реалистичное. Иначе посидели и поговорили, а практически так делать никто не будет.
2. И как раз рассмотренный пример, говорит об обратном - как сделать код более сложным и объемным. Так что надо подходить более аккуратно к примерам. Привели бы пример с тестированием, вопросов бы не возникло (наверное).
3. Мне стало интересно как вы перепишите пример со скобочками (если не сложно)? Результат = 0 + ((20 - 10)*3 + 5 / 0) - 3;
shetill; bayselonarrend; +2 –1 Ответить
48. bayselonarrend 3214 04.02.25 12:29 Сейчас в теме
(47) И да, и нет: пример с тестированием имел бы скорее всего много кода и был бы не очень понятным, т.к. механизм непростой. Я рассчитывал, что читатель приложит объясненный на простом примере механизм на свою задачу)
50. ivanov660 4989 04.02.25 13:24 Сейчас в теме
(48) Цель ясна, но пример все равно немного не удачный.
Но не любят у нас в сообществе ООП и что-то с этим связанное. Отчасти виной этому сам вендор. Как всегда разворачивается холивар, только успевай шапку подставлять
bayselonarrend; +1 – Ответить
3. _imba1C_9504100606_ 101 03.02.25 14:43 Сейчас в теме
Статья интересная, но есть же стандарты разработки 1С и еще корпоративные стандарты и собственная отечественная культура.
Писать код вот так - допустимо в маленькой задачке, где на чтение "чужого кода" и понимание функционала не требуется много времени.

На больших проектах сложности будут на этапе отладки - время на анализ кода возрастет.
Чтобы доработать - нет промежуточных переменных, где можно наложить условия по доп.требованиям задачи. Можно внести изменения в эти "общие методы", но опасно - придется тестировать везде, где "общий метод" применяется. Либо закомментировать всю строку целиком и написать собственную строку или создать ветки условий и код станет еще сложнее.

За 9 лет работы в 1С убедился, что чем проще код читать и дорабатывать, тем он эффективнее (качество + экономия временим на все циклы разработки).

Идея с ООП интересная, в профессионализме автора не сомневаюсь, но такой подход к написанию кода не поддерживаю.
alex_zemlyansky; Shmell; investec; ДимокШ; shetill; AlexGr00vy; Krivoruchko_O; Prom-komplekt; dabu-dabu; tsmult; asupsam; Трактор; bayselonarrend; Ks_83; Prometeus2011; Sashares; Brawler; borda4ev; +18 –2 Ответить
6. alex_sayan 71 03.02.25 15:12 Сейчас в теме
(3) а какие сложности с чтением текучего интерфейса?
10. _imba1C_9504100606_ 101 03.02.25 15:33 Сейчас в теме
(6) Это же очевидно
15. alex_sayan 71 03.02.25 15:57 Сейчас в теме
(10) ну у меня, например, текучий интерфейс не вызывает абсолютно никаких сложностей с чтением
18. slknnk 81 03.02.25 16:47 Сейчас в теме
(15) Согласен. С чтением тут наоборот все более чем понятно.
7. bayselonarrend 3214 03.02.25 15:14 Сейчас в теме
(3) Такой подход чаще всего используют в готовых универсальных модулях. Те же фреймворки для автоматизированного тестирования используют его в 9/10 случаях для механизма проверки условий. Но такие инструменты обычно целиком обособленные от основной конфигурации и имеют докумментацию. Благодаря этому все это идет в плюс, а без этого действительно все может быть неочевидно
27. Ks_83 268 03.02.25 22:44 Сейчас в теме
(3) Абсолютно верно. Статься из серии вредных советов. Такой код код-ревью не пройдет. Выпендрежи и выкрутасы на крупных проектах категорически не приветствуются.
28. bayselonarrend 3214 03.02.25 23:01 Сейчас в теме
(27)

Такой код код-ревью не пройдет


У кого?

Выпендрежи и выкрутасы на крупных проектах категорически не приветствуются


Те же фреймворки для автоматизированного тестирования (используемые, кстати, чаще всего на крупных проектах) используют этот подход и никого это не смущает. В любом случае, я не имел ввиду, что это абсолютно универсальная вещь, которую необходимо использовать везде и везде она будет полезна
Viktor_Ermakov; KirillZ44; alex_sayan; sleemp; Трактор; +5 – Ответить
4. acces969 381 03.02.25 14:59 Сейчас в теме
Какие преимущества дает такой способ написания кода?
5. bayselonarrend 3214 03.02.25 15:07 Сейчас в теме
(4) Ну этакий синтаксический сахар. Меньше кода, лаконично
Viktor_Ermakov; +1 – Ответить
8. alex_sayan 71 03.02.25 15:17 Сейчас в теме
(4) текучий интерфейс хорош для "конвейерного" кода. Это когда есть некоторый набор методов, которые могут вызываться в разной комбинации и/или в разном порядке порядке
Viktor_Ermakov; bayselonarrend; +2 – Ответить
33. acces969 381 04.02.25 07:10 Сейчас в теме
(8) Что то вроде функционального программирования получается?
38. alex_sayan 71 04.02.25 10:02 Сейчас в теме
(33) ну не совсем. Но в конвейерном коде часто используются лямбда-выражения (элемент ФП).Типичный конвейерный код выглядит как-то так (Java):
List<EmailAddress> addresses = library.getReaders().stream()
       .filter(Reader::isSubscriber)
       .filter(reader -> reader.getBooks().size() > 1)               
       .map(Reader::getEmail).map(EmailAddress::new)
       .collect(Collectors.toList());


на 1с такой код будет выглядет так:
	ЧитателиБиблиотеки = ВсеЧитателиБиблиотеки();
	АдресаEmail = Новый Массив;
	Для каждого ИнфоОЧитателе Из ЧитателиБиблиотеки Цикл	
		Если ИнфоОЧитателе.Подписчик И ИнфоОЧитателе.Книги.Количество() > 1 Тогда
			АдресаEmail.Добавить(ПреобразоИнфоОЧитателе.Email);		
		КонецЕсли;	
	КонецЦикла;

в этом примере наверно не очевидны преимущества, но когда большая вложенность Цикл...Если...Цикл...Если, конвейерный код получается намного компактнее
kalyaka; kotofot; Artem-B; pavlov_dv; +4 – Ответить
12. starik-2005 3309 03.02.25 15:43 Сейчас в теме
Плюс. Не за саму статью, а за поднятие темы. Я так 30 лет назад писал, когда объекты были в виде таких библиотек, так TurboVision.
ЗЫ: В турбовижине используется несколько иной подход, когда в конструктор засовывается конструктор, в который засовывается конструктор, в который ... И так "одной строкой кода" рисуется форма целиком со всеми добавленными на нее полями.
ЗЫЗЫ: Ща такое повсеместно, по крайней мере во флаттере с этим вот прям беда была - я тупо путался, после какой запятой что рисовать.
pavlov_dv; +1 – Ответить
13. SerVer1C 1146 03.02.25 15:52 Сейчас в теме
Помню, что где-то уже видел аналогичную дичЪ
Конечно, лучше юзать общий модуль вместо объекта обработки.
Хотел бы я посмотреть на тех, кто в ж0лтом проде применяет подобные извраты ))
14. starik-2005 3309 03.02.25 15:54 Сейчас в теме
(13)
Хотел бы я посмотреть на тех, кто в проде применяет подобные извраты
Да весь джаваскрипт такой, если прилично асинхронить. Не знаю, дошло ли до питона, но точно местами не миновало...
PaStrel; pavlov_dv; +2 – Ответить
16. alex_sayan 71 03.02.25 16:10 Сейчас в теме
(14) справедливости ради, код на жаваскрипте, работающий с CSS/HTML, выглядит в сто раз лаконичнее, чем если бы он был написал на 1с в привычном нам процедурном стиле. Код на 1с, собирающий HTML из кусочков, та ещё вырвиглазная лапша
126. skyadmin 96 25.02.25 17:57 Сейчас в теме
(16) Я использую такой, удобненько
	Строитель = Обработки.Веб_Строитель.НовыйСтроитель();
	Строитель.ДобавитьСтили(ВебИнтерфейсКлиент.СтильДокумента(,,,Истина));
	Строитель.ДобавитьСтили(ВебИнтерфейсКлиент.СтильСсылкаКакКнопкаКоманднойПанели());

	Строитель.ДобавитьТег("html")
		.ДобавитьТег("head")
			.ВставитьСтили().ЗакрытьТег()
			.ДобавитьТег("body", , Новый Структура("style", "background: #FCFAEB;"))
				.ДобавитьТег("div",, Новый Структура("style", "white-space: nowrap;"))
					.ДобавитьТег("img",,Новый Структура("src, style",КартинкаURL,"object-fit: contain; width:16px; height:16px; margin-right: 2px;")).ЗакрытьТег()
					.ДобавитьТег("a", "В приход").ЗакрытьТег()
				.ЗакрытьТег()
			.ЗакрытьТег()
		.ЗакрытьТег()
	.ЗакрытьТег();
	
	ДокументHTML = Строитель.ПолучитьHTML();
	ЭлементыФормы.ПолеВПриход.УстановитьТекст(ДокументHTML);
Показать
Прикрепленные файлы:
Веб_Строитель.epf
shibudo; delphiman4@gmail.com; kalyaka; brr; afk; Viktor_Ermakov; +6 –1 Ответить
17. SerVer1C 1146 03.02.25 16:11 Сейчас в теме
(14) Про то не знаю, но Linq в шарпе отличная штука!
86. wertep 32 06.02.25 11:28 Сейчас в теме
(13) Общий модуль не подходит по той простой причине что он не инкапсулирует данные. Объект обработки при создании имеет свои данные, а модуль нет. Поэтому вызвав какую-то функцию где тоже этим попользуются, после возврата из нее результат будет неожиданным.
88. SerVer1C 1146 06.02.25 12:04 Сейчас в теме
(86) Если бы вы внимательно прочитали дичЪ - то там есть такие строки: "...контекст между функциями гуляет через ПараметрыСеанса, закэшированные через повторноиспользуемый модуль..."
89. wertep 32 06.02.25 12:44 Сейчас в теме
(88)
закэшированные через повторноиспользуемый модуль

ДичЪ и правда не стал читать, судя по цитате дичь еще та. Особенно если вдруг серверу приспичит сбросить повторное использование.
19. kit_extreme 77 03.02.25 17:24 Сейчас в теме
Cлишком ресурсозатратно:
1. Постоянный вызов одного и того же модуля и возврат к модулю из которого происходит вызов.
2. Постоянно возвращается объект (чтоб выполнить следующий вызов), если это ещё и тяжелый объект, то избыточный расход по памяти

Это не стоит того чтоб использовать. В редких случаях использовать очень осторожно. Всегда нужно следить за ресурсами, добавится у объекта реквизит с файлом в пару Гб и всё, будешь долго попрыгаешь через точку
17808849; miniogn; +2 –1 Ответить
23. JohnyDeath 302 03.02.25 19:25 Сейчас в теме
(19)
2. Постоянно возвращается объект (чтоб выполнить следующий вызов), если это ещё и тяжелый объект, то избыточный расход по памяти

Объект же не создается каждый раз новый. О каком расходе памяти идет речь?
Всё высосано из пальца и какая-то экономия на спичках.

Про первый пункт вообще не понял. Что плохого в вызове другого модуля? ) Это прям что-то новенькое в области оптимизации 1С! Давайте вернемся к 7.7, где был один глобальный модуль на всё! Сразу заживем и скорости возрастут ))
kalyaka; untru; brr; Viktor_Ermakov; STivO; Artem-B; comptr; pavlov_dv; alex_sayan; sleemp; Evg-Lylyk; bayselonarrend; +12 –1 Ответить
20. mszsuz 349 03.02.25 17:54 Сейчас в теме
Если кому интересно - вот практическое применение: https://infostart.ru/1c/tools/1161402/
brr; artbear; wertep; kuntashov; comptr; alex_sayan; asupsam; JohnyDeath; +8 – Ответить
21. miniogn 48 03.02.25 19:19 Сейчас в теме
Если 1С не поддерживает из коробки такие возможности, то лучше не использовать. Имеем дополнительный уровень вложенности, существенно усложняющий отладку.
Не спорю, в каких-то отдельных случаях может быть, но в целом нет.
22. bayselonarrend 3214 03.02.25 19:23 Сейчас в теме
(21) С одной стороны, я согласен, что это не универсальный метод, который нужно применять везде. С другой, я не очень понимаю, что значит "не поддерживает из коробки", если это написано на чистом 1С
61. miniogn 48 04.02.25 19:20 Сейчас в теме
(22) Написан, похож. Но это не оно. Тут у каждого метода возвращается обработка. А должно было бы работать для каждого типа, например:
Результат = "123".КонвертироватьВЧисло().Прибавить(5);

Вот это было бы честной поддержкой 1С.
63. bayselonarrend 3214 04.02.25 19:27 Сейчас в теме
(61) Это ни в одном языке так не работает
93. alex_sayan 71 06.02.25 13:47 Сейчас в теме
(61) так в ООП в 90% (может 95% или 98%) случаев класс возвращает ссылку на самого себя. А в 1с ничто не мешает одной обработке начать возвращать другую обработку
24. bayselonarrend 3214 03.02.25 19:30 Сейчас в теме
(19)
1. Постоянный вызов одного и того же модуля и возврат к модулю из которого происходит вызов.
2. Постоянно возвращается объект (чтоб выполнить следующий вызов), если это ещё и тяжелый объект, то избыточный расход по памяти


Я не уверен, что это создает накладные расходы, если не происходит передачи с сервера на клиент, но могу ошибаться

добавится у объекта реквизит с файлом в пару Гб


Это было бы очень странно, если мы говорим об обработке. Думаю, в типичном сценарии это не будет отнимать каких-либо заметных ресурсов сверх того, что тратят обычные вызовы
29. dhurricane 03.02.25 23:27 Сейчас в теме
(21)
существенно усложняющий отладку
А Вы пробовали?
alex_sayan; +1 – Ответить
40. miniogn 48 04.02.25 11:05 Сейчас в теме
(29) Очень даже напробовался. Даже в простом, широко встречающемся, варианте: Функция1(Функция2()), в цикле, когда что бы только дойти до точки останова в нужной итерации, кучу действий делаешь для запуска и ждешь. А тут приходится ещё возится с переходами, и одно неверное движение и опять 10 минут для того, что бы только дойти до этого места повторно.
25. VGHOST 171 03.02.25 21:51 Сейчас в теме
Ух-ты, тянучий интерфейс!
Всего 20 лет как американская жвачка пришла в Россию, а уже и до 1С добралась))

Вопиющее извращение ООП, вытянутое из левой ноздри (если кто не знает - там, за ноздрёй - мозг, а в нём - умные мысли!) каким-то скриптинг гаем.
И все как дети - подхватывают самое плохое, а элементарную логику и необходимый порядок - игнорируют. Потому что скучно, или просто - потому что...

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

Пусть будет ещё один костыль - код-то уже практически нечитаем...

Не в обиду автору - статья прикольная, и сама фишка.
Но непрактичная, как некоторые доистерические языки, в которых код состоял из одних скобок и операторов.
И да спасёт нас оператор With от подобной ереси, аминь!
17808849; wertep; miniogn; +3 –8 Ответить
26. bayselonarrend 3214 03.02.25 22:16 Сейчас в теме
(25) 1000 символов - 0 конкретики

Ух-ты, тянучий интерфейс!
Всего 20 лет как американская жвачка пришла в Россию, а уже и до 1С добралась))


Это можно было делать с тех пор, как в 1С появились обработки и я не первый это придумал


Вопиющее извращение ООП, вытянутое из левой ноздри (если кто не знает - там, за ноздрёй - мозг, а в нём - умные мысли!) каким-то скриптинг гаем.


Чистое имхо + словесный фарс: тысяча и одна технология в программировании использует этот подход для сокращения и улучшения читаемости кода. Видимо все кто делал и используют LINQ, jQuery, Pandas и Spring Boot извращенцы, которые не понимают, что это на самом деле плохо и неудобно

Впрочем, как тут и написано - в 1С нет ООП, как нет и элементарной логики


Единственный язык с чистым ООП - это Smalltalk. Все остальные языки имеют ООП той или иной степени этой чистоты. В 1С ООП очень слабое и действительно ООП языком его нельзя назвать, но как раз пример с обработкой о том, что отдельные части парадигмы выполняются. Иначе и нельзя было бы реализовать fluent api

Про логику это вообще какой-то холостой выстрел ни о чем

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


Можно подумать, что если завтра в язык завезут нового сахара, то костыли закончатся. Как вообще можно связать "идеологов платформы", которые теперь делают что-то не так и "заняты пендостанскими хрендами", хотя язык уже десятилетие не меняется, и прикладников, которые лепят костыли на предметном уровне под меняющиеся процессы?

Но непрактичная, как некоторые доистерические языки, в которых код состоял из одних скобок и операторов


Как связаны старые языки с популярным способом организации методов в классах? Никак, очевидно, просто "непрактичная" и все
movled; brr; Viktor_Ermakov; STivO; Artem-B; KirillZ44; comptr; pavlov_dv; alex_sayan; koropo; +10 –1 Ответить
30. VGHOST 171 03.02.25 23:53 Сейчас в теме
(26) То есть, неочевидная подмена естественного и интуитивно понятного возвращаемого методом значения ссылкой на объект ради того чтобы не писать "with" - это "популярный способ организации"? А ты сиди и чеши репу - это ты метод исходного объекта вызвал, или того ХЗ которое он вернул? Запоминать какие методы возвращают нормальное значение, а какие владельца? Это - "для сокращения и улучшения"?
Для сокращения - это точно. Но где тут читабельность? Ну прочитал это колбасу на пару страниц вправо, и тут же представил себе результат выполнения, ага.
А ошибки вылавливать из этого вот, особенно в нетипизированных языках? Рантайм план покажет?

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

Зато имеем целый выводок языков, созданных непонятно кем и непонятно зачем, и ни одного по настоящему качественного, проработанного на научной основе, генерирующего байт-код, пригодный для дальнейшей глубокой оптимизации под любую платформу (и этих бы выводок сократить, до одной!), а не просто для максимального упрощения конечного компилятора (Жаба).
Что-то реализовано в Си, что-то в Питоне, что-то Аде, что-то в Жабе, что-то в LLVM. Это долбанные лебедь, рак и щука. Никаких стандартов, зато широчайший выбор для желающих свихнуться при выборе и высокопроизводительных авторов говнокода! Капитализма, мать...

В 1С нужно завозить не сахар, а полный пересмотр архитектуры, включая язык, который два десятилетия не меняется.
Криворуких прикладников не убавится, но те немногие, которые способны и хотят писать качественно, а не "больше всех", получат возможность реализовать что-то полезное и долгоиграющее. Например, переделают мега-костыль БСП в нормальную библиотеку классов, и сделают одно мощное модульное строго стандартизованное решение вместо выводка убогих калек, которые кое-как продаются и кое-как удовлетворяют клиентов, да и то - потому что альтернативы не наблюдается.
Тогда, возможно, приложения 1С научатся потреблять больше 1% ЦПУ и меньше 100% РАМ, и чуток экономить дисковое пространство (в текущей реализации база 1С состоит на 2/3 из ссылок, из которых половина не нужна вовсе, а вторую можно поделить на 4+, если не совать ГУИДы в каждое ссылочное поле).
А мне не придётся сидеть ночами, отлавливая чужие баги в совершенно нечитаемом коде, или по полчаса ждать пока мастер настройки обмена вычитает и в сотый раз перегрузит в таблицы всю посылку оппонента после очередного нажатия что на ОК, что на Х.

Впрочем, о чём это я? 1С - КОММЕРЧЕСКОЕ приложение. А следовательно, не стоит ждать ни соли, ни сахара. Только расходов, и не только денежных.
А ведь, "системообразующее" предприятие... За страну обидно! И за логику. Внедряем импортное потреблядство, все живут как проще, а на выходе - всеобщий гемор, который неизбежно закончится всеобщей задницей. Будет весело!
Ничего, третья мировая генофонд прочистит, и торгашам достанется. Чуток осталось - лет 10-15, если у какого-нибудь идиота палец на кнопке не дрогнет. Жаль, организаторов этого бардака не достанет, как и в прошлую ядерную...
TanyTany; skif-m; 17808849; wertep; miniogn; Valerich; bolikov; +7 –3 Ответить
31. bayselonarrend 3214 04.02.25 00:24 Сейчас в теме
(30)
интуитивно понятного возвращаемого методом значения ссылкой на объект ради того чтобы не писать "with" - это "популярный способ организации"?


Да, это он и есть. То, что вы это так трактуете не означает, что это так на самом деле. Или вы всерьез считаете, что проблема в слове with

А ты сиди и чеши репу - это ты метод исходного объекта вызвал, или того ХЗ которое он вернул? Запоминать какие методы возвращают нормальное значение, а какие владельца? Это - "для сокращения и улучшения"?


Если класс реализует fluent api, то ВСЕ методы возвращают self. Проблема, которой не существует

Ну прочитал это колбасу на пару страниц вправо, и тут же представил себе результат выполнения, ага.


Прекрасно представляю, потому что fluent надо использовать там, где он к месту, т.е. где последовательно выполняются манипуляции, завязанные на один объект. Как правило, речь идет о взаимодействии с какими-нибудь отдельными сторонними блоками или библиотеками

Из-за таких вот (в) попу лярвных "технологий" компы сейчас выполняют на 80% больше (и это не предел, млин!) инструкций, чем необходимо для реализации конкретной задачи.


Статистические данные сами собрали?

Зато имеем целый выводок языков, созданных непонятно кем и непонятно зачем, и ни одного по настоящему качественного, проработанного на научной основе, генерирующего байт-код, пригодный для дальнейшей глубокой оптимизации под любую платформу (и этих бы выводок сократить, до одной!), а не просто для максимального упрощения конечного компилятора (Жаба).
Что-то реализовано в Си, что-то в Питоне, что-то Аде, что-то в Жабе, что-то в LLVM. Это долбанные лебедь, рак и щука. Никаких стандартов, зато широчайший выбор для желающих свихнуться при выборе и высокопроизводительных авторов говнокода! Капитализма, мать...


Это просто поток сознания. Да, вы представляете, кто угодно может создать язык и, если вы знаете его название, то это в первую очередь означает, что им пользуются люди. Иначе вы бы о нем не знали. Получается, не непонятно зачем? Язык же, о котором вы говорите, знаете почему не существует? Потому что никто не готов за такое платить. День невероятных открытий

Чтобы заявлять такие вещи, нужно как минмум иметь серьезный авторитет в этих вопросах. Иначе это просто выглядит как болезненное брюзжание. Есть языки, люди ими пользуются - что делает вас лучше их, чтобы решать?

Если даже вернуться к неоптимальности и "80%": да, мир устроен так, что кто программы платит, тот их и танцует. И если бизнес, который обычно и платит, видит, что цена ОЗУ меньше человекачаса программиста и риска простоя из-за ошибок при работе на низком уровне (для недопуска которых нужны более дорогие специалисты), то, внезапно, большая часть программистов будет писать на непроизводительных, но простых и безопасных языках. Очевидное невероятное

И это все при том, что из-за "проклятого капитализма", есть целая куча хороших языков низкого уровня на любой вкус, от Rust до Nim. Тоже недостаточно хороши для реализации вашего гения?

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


Вы за это заплатите? Или может заплатит бизнес, который 10 лет автоматизировал все чтобы начать с нуля? Полиграф Полиграфович плачет, читая это

Остальное - просто какие-то абстрактные рассуждения на вольную тему, не представляю, зачем вы на меня их выливаете. Пожалеть вас, что мир не такой идеальный, как вам хотелось бы?
movled; kalyaka; koropo; +3 –1 Ответить
32. alex_sayan 71 04.02.25 01:11 Сейчас в теме
(30) слов много, но одна вода. Так-то в языках программирования ничего принципиально не меняется годов с 80-х. И вряд ли когда-то изменится. Растут вычислислительные мощности, развиваются фреймворки, но "стержень" у языков программирования всё тот же. Надо учиться писать понятный код, а не пенять на инструменты
49. VGHOST 171 04.02.25 12:48 Сейчас в теме
(32) Изменится, если успеет.
Бардак должен закончиться, хотя бы потому что из него уже становится сложно извлекать прибыль.
Плюс методологический кризис по всем наукам, если производство коммерческого говнокода можно отнести к научным дисциплинам.
Единственный субъект в мире, который способен взяться за такую проблему - это Россия (как государство, или скорее как ИП Путин - опять у нас всё держится на одном гвозде, повторяем 20век). Потому что только у нас внедрение потреблядства идёт с большими проблемами - ещё есть шанс вывернуться самим и вывернуть наизнанку долбанный мир.

А про понятный код - вы давно заглядывали в исходники типовых?
Раньше на 1С можно было писать более или менее понятный код, теперь вместо него пишут бесконечные обработчики ожидания и пятиуровневые вызовы через модули с разными атрибутами, чтобы мимо серверного контекста не попасть.
Не было нормальной многопоточности - ладно, не так часто это нужно. Но запретить модальность, вместо того чтобы реализовать её по-человечески - это блин забота о прикладниках и пресловутой экосистеме?
И таких нюансов несколько сотен можно наскрести. Архитектура платформы просто вынуждает прибегать к извращениям и потом тратить время на отладку этого дерьма.

Сейчас задумали в четвёртый раз менять интерфейс. Опять садимся всё переписывать. Это для кого всё?
Да ни для кого - для прибыли. Качает насос бабло со всей России - мало, надо соседей подтягивать, а для этого неплохо бы мимикрировать под им привычное.

Я уже написал выше, чем заканчивается гребля под себя. И так оно и будет. В который раз уже, только памяти хватает на 2-3 поколения. Колония одноклеточных, блин.
Либо биомасса начнёт уже организовываться и координировать усилия, либо - Матрица.Перезагрузка().
Пожалуй, эти вопросы для другой песочницы. Всё никак не усвою, что в большинстве случаев лучше молчать, чем мычать...
TanyTany; skif-m; +2 –6 Ответить
57. comptr 57 04.02.25 14:31 Сейчас в теме
(49)
Но запретить модальность, вместо того чтобы реализовать её по-человечески - это блин забота о прикладниках и пресловутой экосистеме?

Модальность запрещена не потому что так захотелось разработчикам платформы, а потому что она запрещена в браузерах.
Если пишите свою нетленку и не планируете использовать веб-клиент, используйте модальные окна, кто вам запретит-то? Или используйте Асинх вместо ОписаниеОповещения.

Единственный субъект в мире, который способен взяться за такую проблему ...

И тут Остапа понесло...
fatman78; KirillZ44; bayselonarrend; +3 – Ответить
72. VGHOST 171 05.02.25 03:03 Сейчас в теме
(58)
(57)
потому что она запрещена в браузерах

Это можно и нужно было реализовать на уровне платформы, а не заставлять прикладников заниматься онанизмом. Вслед за Гуголом, которому тоже проще было скинуть гемор на конечных потребителей фреймворка, чем реализовывать независимые многоуровневые блокировки для каждого модального элемента и связанную с этим многопоточность.
Пытаются всех и вся впихнуть в мобильник с Андроидом, в котором для нормальных окон места нет. Причём тут полноразмерные браузеры? Да при унификации - чудо-меню-Пуск Win8 - про то же.
А остальные тупо повторяют ошибку, не пытаясь хотя-бы её изолировать на своём уровне. Гуглу, понятно, пенять бесполезно, а остальные браузерокопипастеры пользуются, чем дали - халява же...

Или используйте Асинх

Это-то недоразумение чем лучше? Мертворождённая многопоточность, которую ещё лет 10 допиливать и выпрямлять будут. Если вообще будут, с учётом объёма необходимых изменений в платформе.

Остапа понесло

Всё зависит от точки зрения. С моей - понесло остальной мир, а Остап за что-то зацепился...
Как правильно замечал покойный Задорнов - вперёд, в пропасть. А я бы сказал вернее - в унитаз. Не достойны мы порядочной пропасти. В сотый раз уже разводят популяцию, а результат - один. Впрочем, свою задачу она выполняет, но это уже отдельная история, совсем не про 1С.
TanyTany; +1 – Ответить
58. alex_sayan 71 04.02.25 14:48 Сейчас в теме
(49) опять какие-то пространные рассуждения
73. VGHOST 171 05.02.25 03:48 Сейчас в теме
(58) "Это - норма" © Малышева.
Когда-то, в допотопном СССР, людей попытались научить думать, но потом испугались результата...
Теперь модно делать, неважно что, но - быстро и много. А потом - впаривать "продукт" своей жизнедеятельности, эффективно и дорого. Вот это - конкретика!

Вот, например, "fluent interface" придуман как костыль для языка, в котором отсутствовал аналог with.
Кто-то увидел в этом "упрощение" - на кнопки же нажимать меньше! - и понеслась коза по рельсам.
Впендюрили во все языки, где надо и не надо, название вот придумали...
При этом никто не считает, насколько раздуются стеки, как возрастёт нагрузка на кеш и потребление мозгов, сколько от этого произойдёт тормозов и, блин, расхода электроэнергии и прочего жизненного ресурса.
А ведь таких "оптимизаций" многие тысячи - достаточно поотлаживать любую прогу сложнее блокнота да помониторить её обращения к ресурсам ОС. Что M$, что 1С, даже великие и непревзойдённые производители огрызков - все используют и приумножают говнокод. Что уж говорить про опенсорсников, которые держатся на энтузазизме, народных подаяниях и подачках конкурентов.

Я понимаю, что хрень в основном используется для сокращения каких-то рутинных часто повторяемых операций в узких областях, где эффективность (якобы) не нужна, а отладка не важна.
Но в любом случае - это костыль, который лечится либо With, либо макросом, либо - нормальным планированием API, в котором все рутинные операции реализованы одним вызовом, а не трехметровой колбасой.
Одни делают кривые фреймворки, другие придумывают костыли, чтобы их "почти выпрямить". Некоторые даже сами делают и сами выпрямляют! И этот бардак преподносится как общепринятый стандарт кодирования, просто потому что "все так делают"...
76. alex_sayan 71 05.02.25 09:26 Сейчас в теме
(73) чувак, тебе поговорить не с кем? Ещё и выдумал какие-то якобы проблемы с производительностью, которых в реальности нет
82. VGHOST 171 06.02.25 00:15 Сейчас в теме
(76) Да реальности вообще нет. Есть только комп, с ним и разговариваю. Естественно, ему пофиг, куда провалится то, чего нет - иных ответов и не ожидал...
92. alex_sayan 71 06.02.25 13:41 Сейчас в теме
(82)

Даже если вы хорошо знаете, как работает система, занимайтесь не гаданием, а замерами. Полученная информация в девяти случаях из десяти покажет, что ваши предположения были ошибочными!
- Рон Джеффрис
117. VGHOST 171 07.02.25 17:43 Сейчас в теме
(92) Аллилуйя!
Это же одна из 10 заповедей Говнокодинга!
Пиши как попало, а рантайм с профайлером выпрямят, когда нибудь...

Я не говорю, что профилировать не надо, но замеры показывают только то, как справляется конкретная железка с конкретной узкой задачей. На компе у пользователя тайминги, как правило, гораздо печальнее. Особенно, если смотреть не на относительный вклад, а на секунды. И профилировать не только прикладной код, но и библиотеки, а также поинтересоваться, чего и как делают интерпретаторы и компиляторы, которые умеют гадить в код не хуже прикладников.
Никакой профайлинг не заставит говнокодера понять, что та же задача могла быть выполнена втрое быстрее и с вдвое меньшим потреблением ресурсов. "А чо, у меня на компе оперативы много, и проц топовый - пускай работают. А я отдохну, пожалуй...".
TanyTany; +1 – Ответить
118. alex_sayan 71 07.02.25 20:30 Сейчас в теме
(117) ты даже цитату понять не осилил. Продолжай заниматься гаданиями и фантазированием, у тебя это хорошо получается
Gesperid; +1 – Ответить
77. alex_sayan 71 05.02.25 09:35 Сейчас в теме
(73)
Но в любом случае - это костыль, который лечится либо With, либо макросом, либо - нормальным планированием API, в котором все рутинные операции реализованы одним вызовом, а не трехметровой колбасой.

Ну покажи тот же калькулятор в виде макроса или "нормального API", или одного вызова? Сидишь и написываешь всякую ерунду
83. VGHOST 171 06.02.25 00:17 Сейчас в теме
(77) Показываю: а=5+7*10;
Или вот: Мегакалькулятор.Мегафункция(5, 7, 10);
Или особо запущенный случай: With Мегакалькулятор do Сложить(5, Умножить(7,10));
Один длиннее и запутаннее другого, не правда ли?

Макросы стараюсь не использовать и уже забыл синтаксис - догадайтесь сами.
TanyTany; +1 – Ответить
90. alex_sayan 71 06.02.25 13:37 Сейчас в теме
(83) Н-да. Ты на каждую комбинацию действий собрался по мегафункции писать?

With Мегакалькулятор do Сложить(5, Умножить(7,10));

А это читается хуже текучего интерфейса
114. VGHOST 171 07.02.25 17:21 Сейчас в теме
(90) Тут толковали про #мегачастоиспользуемыевызовы. Если же все вызовы хаотичны - это повод пересмотреть общую архитектуру, где-то что-то не так поделили.

Вот и не читай - от этого говорят мозг необратимо структурируется!
123. alex_sayan 71 15.02.25 10:24 Сейчас в теме
(114)

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

Как ты сам себе представляешь строгий порядок действий в том же калькуляторе?
97. Alxby 1161 06.02.25 18:06 Сейчас в теме
(73) Справедливости ради, многие фокусы были придуманы в эпоху оптимизирующих компиляторов. Компилятор умный, он сам из нашего кода сделает конфетку. Он и рекурсию в цикл развернет, и часто используемые значения закэширует, и static переменные будет правильно использовать, и inline функции где надо применит. А вот осознать, что не все такие фокусы пригодны для скриптовых языков могут далеко не все...
115. VGHOST 171 07.02.25 17:30 Сейчас в теме
(97) Боюсь что тягучие фокусы никакому компилятору не по зубам...
Я бы вообще жёстко запретил известные фокусы и стилистические извращения на уровне синтаксического анализатора, чтобы их потом не оптимизировать. Оптимизировать нужно соответствие структуры байткода возможностям машинного, а выкрутасы по трансформации рекурсий и подобные сильно усложняют компилятор и иногда приводят к очень интересным, но весьма неприятным детским неожиданностям)
116. Alxby 1161 07.02.25 17:37 Сейчас в теме
(115) для строго типизированных языков - вполне можно и развернуть цепочку. А компилятор пусть работает - ночь длинная, ночной билд все-равно только завтра понадобится... А интересные эффекты после оптимизации бывают, да. Кто-то как-то с помощью оптимизации компилятором своей программы великую теорему Ферма "доказал".
79. triviumfan 103 05.02.25 13:58 Сейчас в теме
(25) Где ты эту траву берешь? Поделись!
84. VGHOST 171 06.02.25 00:35 Сейчас в теме
(79) Дык, сам выращиваю. Секретный рецепт!
Открывает глазки на то, чего нет.
Кризиса нет, проблем нет, всё хорошо! Спи.
34. RustIG 1990 04.02.25 09:22 Сейчас в теме
Функция УстановитьЗначение(Знач ЧисловоеЗначение) Экспорт

Если ЗначениеЗаполнено(Ошибка) Тогда Возврат ЭтотОбъект КонецЕсли;

Значение = ПривестиЧисло(ЧисловоеЗначение);
Возврат ЭтотОбъект;

КонецФункции


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

Что возвращать- объект-структуру, объект-соответствие или объект-обработку - зависит от возможностей "объекта" (какие типы умеет хранить) и самой задачи.

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

Я на обычных формах много раз использовал обработку в качестве центрального объекта для выгрузки на сайт (туда-сюда обмен), для расчета АВС-показателей.

Всем добра!
bayselonarrend; +1 – Ответить
35. tormozit 7393 04.02.25 09:23 Сейчас в теме
Ударю ниже пояса - как точки останова ставить будешь? Текучий код убивает отладку в случае 1С. Без отладки тут жизни нет.
36. bayselonarrend 3214 04.02.25 09:24 Сейчас в теме
(35) Да, это актуальная проблема) Только если ставить внутри обработки или идти через F11
37. bayselonarrend 3214 04.02.25 09:58 Сейчас в теме
(35)
Текучий код убивает отладку в случае 1С


Это не совсем так, потому что есть как минимум стек вызовов.

Вообще, я уже 10 раз пояснил, что fluent это не для всего и никто не говорит, что это нужно использовать везде при работе. Fluent это про отдельный блок, выполняющий комплексную параметризированную обработку по шагам: проверка условий в Unit-тестах, http-запросы, ORM и пр.

Я сам написал порядком тестов на YaxUnit и могу сказать, что без текучих утверждений это было бы на порядок менее удобно. Разносить этот подход как непригодный для обычной повседневной доработки конфигураций - война с ветряными мельницами
39. booksfill 04.02.25 10:58 Сейчас в теме
Как по мне, статья полезная.

По-моему, fluent interface вполне применим в 1С и никаких костылей, ну почти, не вижу.
Наоборот, даже если не знать всех этих умных слов любой junior сразу поймет как работает цепочка.

ПолучитьКурсыВалют()
.ПреобразоватьВJSON()
.ЗаписатьВЛог()
.РасчитатьКонтрольнуюСумму()
.ОтправитьПоПочте().

Что тут сложного (даже если не откидывать, как это сделал я, передачу параметров)?
Более того, интуитивно понятно, что цепочка является гибкой и может быть частично изменена или прервана досрочно, или прервана, а потом возобновлена.
Т.е. по сути имеем дело с internal DSL.

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

"Если класс реализует fluent api, то ВСЕ методы возвращают self."

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

И еще, не уверен, что это реально будет полезно, но, неплохо бы упомянуть про возможность получения не this, а immutable через возврат нового экземпляра обработки (это не я придумал, а есть такой стандартный вариант).
В примере с калькулятором это непонятно зачем, но при сложной/ресурсоемкой инициализации объекта закономерно желание его переиспользования, начиная с первоначального состояния.
brr; Жолтокнижниг; bayselonarrend; +3 –1 Ответить
41. bayselonarrend 3214 04.02.25 11:06 Сейчас в теме
(39)
В вашем же примере, если я верно понял, ПолучитьРезультат() - возвращает структуру, непонятно зачем прерывая работу цепочки


ПолучитьРезультат - этакий геттер, защищающий переменную. Его действительно проблематично реализовать без прерывания, разве что ввести еще одну переменную экспортную только для этого. Но это единственное исключение без self и вызывается 1 раз в самом конце

возможность получения не this, а immutable через возврат нового экземпляра обработки


Это интересно, но я не очень понимаю, как потом вернутся к оригинальному объекту для продолжения обработки. Может, непрвильно понял идею
44. booksfill 04.02.25 11:42 Сейчас в теме
(41)
Это интересно, но я не очень понимаю, как потом вернутся к оригинальному объекту для продолжения обработки. Может, неправильно понял идею


Все просто - вместо возврата ЭтотОбъект в возвращаемом методе создаем новую копию обработки, инициализируем ее текущими значениями и возвращаем.

Методы цепочки при таком подходе будут "портить" результаты уже не текущей обработки, а "своей собственной"

Думаю понятно, что если у нас гигантские объемы данных и т.п, то так делать не стоит.

А вот если просто тупо теряем время на получение этих самых данных/тратим денежку за вызов API и т.п , то вполне себе вариант.

Вот пример на JavaScript, думаю будет понятно. там цепочка нарисована невнятно, но от этого более понятен принцип (ну или вместо const kitten1 = new Kitten() .setName('Salem'); рассмотрите:
const kitten1 = new Kitten().setName('Salem').setColor('black');)

class Kitten {
  constructor() {
    this.name = 'Garfield';
    this.color = 'orange';
  }

  setName(name) {
    const copy = new Kitten();
    copy.color = this.color;
    copy.name = name;
    return copy;
  }

  setColor(color) {
    const copy = new Kitten();
    copy.name = this.name;
    copy.color = color;
    return copy;
  }

  // ...
}

// use it
const kitten1 = new Kitten()
  .setName('Salem');

const kitten2 = kitten1
  .setColor('black');

console.log(kitten1, kitten2);
Показать



(41)
Его действительно проблематично реализовать без прерывания, разве что ввести еще одну переменную экспортную только для этого. Но это единственное исключение без self и вызывается 1 раз в самом конце


Да не надо вводить экспортных переменных, просто передавайте в методах цепочки внешний параметр - и там получайте промежуточные состояния.

Можно сделать и иначе, не возвращать ссылку на объект, а возвращать структуру типа "Результат, Then", где then - ЭтотОбъект.

Тогда цепочка будет выглядеть хуже, поэтому и не могу рекомендовать, но не намного.
рез = ПолучитьКурсыВалют().then
.ПреобразоватьВJSON().then
.ЗаписатьВЛог().then
.РасчитатьКонтрольнуюСумму().then
.ОтправитьПоПочте().

При этом рез.Результат - ваши текущие результаты вычисления.
А если хотите продолжить цепочку, то, например,
рез.then.ПреобразоватьВXМL()
bayselonarrend; +1 – Ответить
81. comptr 57 05.02.25 23:45 Сейчас в теме
(44)
А вот если просто тупо теряем время на получение этих самых данных

А на копирование объекта, да ещё и инициализацию уже заполненными полями, мы время (и память) не тратим?
И я не уловил, о каком получении идёт речь? О получении объекта? А копию мы не получаем?
85. booksfill 06.02.25 09:28 Сейчас в теме
(81)
(81)
А на копирование объекта, да ещё и инициализацию уже заполненными полями, мы время (и память) не тратим?

Тратим.
Поэтому никто не предлагает использовать этот прием, только потому, что он возможен. Не говоря уж о том, что его даже модным не назовешь - он уже известен не один десяток лет.

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

Иногда удобно одно, иногда другое. It's up to you. Вот есть такие варианты - вам решать нужно ли оно вообще.

Чтобы было понятней, вот есть такой прием в том же 1С, когда вместо конкатенация строк "плюсиком", используют
СтрСоеденить или ЗаписьXML. Лично я, если надо сложить пару строк пользуюсь "плюсиком", не пытаясь сэкономить микросекунды (и даже прводить исследования, на сколько микросекунд будет разница).
По мне так читаемость кода здесь важней.

То же самое в обсуждаемой теме, если оно вам не надо, скорее-всего, она вам действительно не надо.
102. Жолтокнижниг 314 07.02.25 00:34 Сейчас в теме
(41)
Это интересно, но я не очень понимаю, как потом вернутся к оригинальному объекту для продолжения обработки. Может, непрвильно понял идею


Насколько я понимаю:
* Сохранение в переменную, таким образом ветвим в нужных местах цепочку
* Использование стека и метод pop
101. Жолтокнижниг 314 07.02.25 00:30 Сейчас в теме
(39) Идея с immutable очень хороша и может выручить в ряде сценариев, которые правда очень редко встречаются. Есть у меня как раз один такой, попробую туда примерить.
42. miniogn 48 04.02.25 11:13 Сейчас в теме
Чем предложенный вариант существенно лучше. чем обычный, или ради экономии несколько байтов текста?

тк = Обработки.ТекучийКалькулятор.Создать();
тк.УстановитьЗначение(0);
тк.Прибавить(20)  ;
тк.Отнять(10)     ;
тк.Прибавить(5)   ;
тк.РазделитьНа(0) ;
тк.Отнять(3);
Результат = тк.ПолучитьРезультат();  
Показать
43. bayselonarrend 3214 04.02.25 11:28 Сейчас в теме
(42) Это вопрос элементарности примера, который должен быть простым для понятности, а не технологии. Если вы возьмете какую-нибудь реальную реализацию, вроде ассертов для проверки утверждений, то даже несложный пример, вроде

Возврат ОжидаетЧто(Результат).ИмеетТип("Структура").Заполнено().НетСвойства("error")


Превратится в

Ответ = Ложь;

Если ИмеетТип(Результат, "Структура") Тогда

    Если ЗначениеЗаполнено(Результат) Тогда

        Ответ = НетСвойства(Результат, "error");

    КонецЕсли;

КонецЕсли;

Возврат Ответ
Показать
kalyaka; brr; +2 – Ответить
60. miniogn 48 04.02.25 19:09 Сейчас в теме
(43)
Ответ = Ложь;

Если ИмеетТип(Результат, "Структура") Тогда

    Если ЗначениеЗаполнено(Результат) Тогда

        Ответ = НетСвойства(Результат, "error");

    КонецЕсли;

КонецЕсли;
Показать


Вот так и должен выглядеть тривиальный код на 1С. Для чего вводить еще один уровень.
Что сделаете, если в рекомендуемом коде понадобится ветка Иначе с установкой каких-то переменных?
62. bayselonarrend 3214 04.02.25 19:24 Сейчас в теме
(60) Блин, я уже подустал одно и то же отвечать если честно)

1. Да, так и должен выглядеть тривиальный 1С код - если вы вносите изменения в типовую конфигурацию, то надо писать вот так
2. Fluent не универсален: он нужен к месту вроде как здесь. Мне не нужна и никогда не будет нужна ветка иначе, потому что я использую блок с утверждениями - специальный отдельный модуль для специальной отдельной задачи определения истинности или ложности произвольного набора утверждений
3. Если я добавлю в это сборное условие еще 5 подусловий, то при использовании обычного кода это будет 5 раз вложенное Если...Тогда или 5 раз прокинутые выражения через Или. А если мне нужно будет несколько таких сборных условий, то это будет когнитивный ад. С текучеми утверждениями это будет просто еще одна строка в модуле, который будет маленьким и удобоваримым, даже если я напишу там 100 таких проверок

Fluent хорош, когда есть обособленная универсальная абстракция: вот есть обработка отвечающая за какой-то процесс, который может состоять из отдельных действий в произвольном порядке. Например, формирование http-запроса, где в него в произвольном порядке нужно просто закинуть тело, заголовки, установить URL и вызвать. Это хороший кейс для этого и, насколько я помню, такая реализация существует. Если же это типичный 1Сный сценарий правки в середине, где нудно доработать обычный код в конфе под конкретный уникальный случай (который может еще и 10 раз поменяться), то текучий интерфейс не подойдет
64. miniogn 48 04.02.25 20:16 Сейчас в теме
(62)
я уже подустал одно и то же отвечать если честно

Ну так и споров было бы меньше, если бы эта информация была в статье. Мол не увлекайтесь...
Так то я и не против того, что бы использовать но очень и очень взвешенно.
65. bayselonarrend 3214 04.02.25 20:24 Сейчас в теме
(64)
Ну так и споров было бы меньше, если бы эта информация была в статье


Да, это так) Я просто не ожидал, что будет такой холивар и прямо нужен отдельный дисклеймер что "решение не универсально, все трюки выполнены каскадерами!"
kasper076; Жолтокнижниг; miniogn; +3 – Ответить
109. wertep 32 07.02.25 10:08 Сейчас в теме
(43) А что мешает использовать
Ответ = ИмеетТип(Результат, "Структура")
		И ЗначениеЗаполнено(Результат)
		И НетСвойства(Результат, "error");
119. alex_sayan 71 07.02.25 20:41 Сейчас в теме
(109) ты потерял имя модуля

Ответ = Проверки.ИмеетТип(Результат, "Структура") И Проверки.Заполнено(Результат) И Проверки.НетСвойства(Результат, "error"); 


 

вот и код получился заметно сложнее
120. wertep 32 09.02.25 15:34 Сейчас в теме
(119) Нет никаких проблем дописать.
Ответ = Проверки.ИмеетТип(Результат, "Структура")
        И Проверки.ЗначениеЗаполнено(Результат)
        И Проверки.НетСвойства(Результат, "error");

При этом код не потерял в читаемости и понятности.
Зато выиграл в потреблении ресурсов и производительности минимум в 3 раза.
В компиляторах разных языков присутствует выбор оптимизации "по производительности" или "по памяти". Что означает более быстрый код, но больше потребление памяти, или наоборот меньше памяти и меньше производительности.
Вы же предлагаете чуть меньше букв написанных разработчиком, и при этом производительность меньше и потребление ресурсов больше. Соотнеся то, что разработчик потратится на это один раз, а выполняться код будет миллиарды и более раз, какая-то мягко говоря сомнительная оптимизация.
121. alex_sayan 71 10.02.25 11:33 Сейчас в теме
(120) ну вот теперь и сравни тот вариант:
ОжидаетЧто(Результат).ИмеетТип("Структура").Заполнено().НетСвойства("error")

со своим.
При этом код не потерял в читаемости и понятности

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

голословные заявления. Вот что про это пишут умные люди:
Даже если вы хорошо знаете, как работает система, занимайтесь не гаданием, а замерами. Полученная информация в девяти случаях из десяти покажет, что ваши предположения были ошибочными!
- Рон Джеффрис
kalyaka; brr; +2 – Ответить
52. bayselonarrend 3214 04.02.25 14:00 Сейчас в теме
45. sir 20 04.02.25 12:06 Сейчас в теме
меня например смутило "Результат = ТекучийКалькулятор.Значение;"

по ходу статьи, мы так к переменной модуля обратиться не можем.
46. bayselonarrend 3214 04.02.25 12:12 Сейчас в теме
(45) В начале статьи можем - там экспортная переменная. Потом, в конце, она становится не экспортной и заменяется на ПолучитьРезультат()
55. sir 20 04.02.25 14:08 Сейчас в теме
(46) сорян, моя невнимательность.
51. tormozit 7393 04.02.25 13:59 Сейчас в теме
Если уж так хочется ужать частые обращения к переменной, то используйте временный псевдоним "я" и будет примерно то же самое, но без извращений и ограничений.
НормальныйКалькулятор = Обработки.НормальныйКалькулятор.Создать();
// Эмуляция With начало
я = НормальныйКалькулятор;
я.УстановитьЗначение(0);
я.Прибавить(20);
я.Отнять(10);
я.Прибавить(5);
я.РазделитьНа(0);
я.Отнять(3);  
я = Неопределено;
// Эмуляция With конец
Результат = НормальныйКалькулятор.ПолучитьРезультат();
Показать
17808849; miniogn; _imba1C_9504100606_; +3 – Ответить
53. bayselonarrend 3214 04.02.25 14:01 Сейчас в теме
54. bayselonarrend 3214 04.02.25 14:04 Сейчас в теме
(51) Хотя даже так я вообще не вижу, чем это лучше. Если это такой же вызов процедур, меняющих переменные объекта, то архитектурно это такое же "извращение", только еще и уродливое
59. alex_sayan 71 04.02.25 15:40 Сейчас в теме
(51) несколько методов могут распологаться в одну строку, как бы подчёркивая их связанность между собой. Условный пример:
	Счета = ПланыСчетов.Хозрасчетный;
	Субконто = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные;	
	
	ПостроительПроводок = Обработки.ПостроительПроводок.Создать();
	ПостроительПроводок.НовыйНаборЗаписей(Шапка.Ссылка);
	
	// Значения попадут в измерения каждой проводки
	ПостроительПроводок.ОрганизацияПоУмолчанию(Шапка.Организация);
	ПостроительПроводок.ПодразделениеПоУмолчанию(Шапка.Подразделение);
		
	//Д т 90.02.1 - Кт 41.01 
	ПостроительПроводок.НоваяПроводка()
		.СчетДт(Счета.СебестоимостьПродажНеЕНВД)
		.СубконтоДт(Субконто.НоменклатурныеГруппы, Шапка.Группа)
		.СчетКт(Счета.ТоварыНаСкладах)
		.Сумма(Товары.Итог("Себестоимость")).Содержание("Отражение себестоимости товаров");
		
	// Дт 62.01 - Кт 90.01.1
	ПостроительПроводок.НоваяПроводка()
		.СчетДт(Счета.РасчетыСПокупателями)
		.СубконтоДт(Субконто.Контрагенты, Шапка.Контрагент).СубконтоДт(Субконто.Договоры, Шапка.Договор)
		.СчетКт(Счета.ВыручкаНеЕНВД)
		.СубконтоКт(Субконто.НоменклатурныеГруппы, Шапка.Группа).СубконтоКт(Субконто.СтавкиНДС, Перечисления.СтавкиНДС.НДС20);
		.Сумма(Товары.Итог("Сумма")).Содержание("Отражение выручки");
		
	// Дт 90.03 - Кт 68.02
	ПостроительПроводок.НоваяПроводка()
		.СчетДт(Счета.Продажи_НДС)
		.СубконтоДт(Субконто.НоменклатурныеГруппы, Шапка.Группа).СубконтоДт(Субконто.СтавкиНДС, Перечисления.СтавкиНДС.НДС20);
		.СчетКт(Счета.НДС)
		.СубконтоКт(Субконто.ВидыПлатежейВГосБюджет, Перечисления.ВидыПлатежейВГосБюджет.Налог)
		.Сумма(Товары.Итог("СуммаНДС")).Содержание("Отражение НДС");

	НаборЗаписей = ПостроительПроводок.НаборЗаписей();
Показать
56. sir 20 04.02.25 14:13 Сейчас в теме
Вообще решение в виде

Результат = ТекучийКалькулятор.УстановитьЗначение(0)
.Прибавить(20)
.Отнять(10)
.Прибавить(5)
.РазделитьНа(0)
.Отнять(3)
.ПолучитьРезультат();

мне нравится - 1. это оригинально 2. достаточно лаконично 3. заставило задуматься о применимости.
66. Alxby 1161 04.02.25 22:07 Сейчас в теме
Подобный подход можно применять разными способами...
Можно использовать объект обработки (и не только обработки, а например объект справочника, почему нет?) - и все это будет работать на сервере. Хотим на клиенте - пожалуйста, аналогично используем для этого клиентскую форму. Не хотим связываться с созданием тяжелых объектов? Не вопрос - используем для этой цели общий модуль, а в цепочке экспортных функций в параметрах протягиваем структуру для сохранения и накопления результата.
... но зачем? Да, это необычно, оригинально, но каких-то особых преимуществ не дает ни в скорости, ни в компактности кода, ни в возможностях поддержки/отладки.

Сравните с классическим подходом и попробуйте назвать преимущества:
Перем Р;
ТК = ТекучийКалькулятор; // общий модуль
ТК.УстановитьЗначение(Р, 0);
ТК.Прибавить(Р, 20) // 20
ТК.Отнять(Р, 10)    // 10
ТК.Прибавить(Р, 5)  // 15
ТК.Отнять(Р, 3);    // 12
Результат = Р;
Показать
triviumfan; +1 – Ответить
67. bayselonarrend 3214 04.02.25 22:11 Сейчас в теме
(66) Я так свихнусь скоро, реально))

(42)
(51)
(62)
artbear; dhurricane; RustIG; +3 – Ответить
68. Alxby 1161 04.02.25 22:32 Сейчас в теме
(67)
Не надо свихиваться, кто будет тогда писать статьи?)
3. Если я добавлю в это сборное условие еще 5 подусловий, то при использовании обычного кода это будет 5 раз вложенное Если...Тогда или 5 раз прокинутые выражения через Или. А если мне нужно будет несколько таких сборных условий, то это будет когнитивный ад. С текучеми утверждениями это будет просто еще одна строка в модуле, который будет маленьким и удобоваримым, даже если я напишу там 100 таких проверок

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

- все это ведь можно использовать в (66) или нет? Если нет, то почему? Если да, то зачем усложнять и привлекать объект обработки?
69. bayselonarrend 3214 04.02.25 22:36 Сейчас в теме
(68) В (43) есть пример, когда код реально отличается.

В целом, причина этого вопроса у многих в том, что я привел плохой пример в статье: я думал он будет простой, чтобы было все понятно, но в итоге он не показывает реальных приемуществ подхода
70. Alxby 1161 04.02.25 22:50 Сейчас в теме
(69) Однострочная компактная запись - действительно преимущество для некоторых случаев. Но недостатки могут перевесить - невозможность точно поставить точку останова, нельзя передать "объект" (под объектом я здесь понимаю любую замену объекта ООП) между клиентом и сервером, нельзя сериализовать и сохранить его, накладные расходы на создание "объекта" могут быть несоразмерны решаемой задаче, надо учитывать права доступа.
triviumfan; +1 – Ответить
71. bayselonarrend 3214 04.02.25 23:06 Сейчас в теме
(70)
Однострочная компактная запись - действительно преимущество для некоторых случаев.


Дело не только в том, что все записывается в одну строку. Главное преимущество: возможность для разных задач комбинировать в разном порядке и количестве функции класса в цепи вызовов. Поэтому такой подход и любят во всяких готовых модулях, вроде ORM, где удобно использовать разные ВыбратьПоле("Имя").ВыбратьПоле("Фамилия").Отбор("Возраст").Больше(30).Получить()

невозможность точно поставить точку останова


Да

нельзя передать "объект" (под объектом я здесь понимаю любую замену объекта ООП) между клиентом и сервером


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

нельзя сериализовать и сохранить его


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

накладные расходы на создание "объекта" могут быть несоразмерны решаемой задаче


Это надо на Pentium II наверное сидеть, чтобы ощутить накладные расходы от одноразового создания обработки)

надо учитывать права доступа


Имхо, тоже будто бы из пальца высосано
74. Alxby 1161 05.02.25 08:29 Сейчас в теме
(71)
Главное преимущество: возможность для разных задач комбинировать в разном порядке и количестве функции класса в цепи вызовов.

а разве я не могу комбинировать в разном порядке и количестве вызовы функции общего модуля?
Модуль.ВыбратьПоле(Контекст, "Имя");
Модуль.ВыбратьПоле(Контекст, "Фамилия")
Модуль.Отбор(Контекст, "Возраст");
Модуль.Больше(Контекст, 30);

и из Контекста получить накопленный результат? Кроме многострочности и некоторой повторности идентификаторов "Модуль" и "Контекст" разницы особой не вижу.
можно передать финальный результат. Все равно цепочка вызовов это про обработку где-то в одном конкретном месте

верно до тех пор, пока не придется в одной цепочке использовать, например данные из ИБ (например реквизит объекта) и данные клиентской формы (например текущая строка)
Это надо на Pentium II наверное сидеть, чтобы ощутить накладные расходы от одноразового создания обработки)

верно до тех пор, пока какой-нибудь деятель не превратит этот код в библиотеку (мы же против велосипедов и за переиспользование кода), а другой деятель не будет его вызывать в цикле из 10000 итераций (он же не обязан изучать содержимое такой библиотеки и просто использует ее API)
надо учитывать права доступа


Имхо, тоже будто бы из пальца высосано

опять же, все хорошо до тех пор, пока эту функциональность не начнет использовать пользователь, которому забыли дать права на обработку. А кто из админов базы может представить, что чтобы сформировать, к примеру, по определенной процедуре текст запроса к сервису, нужно давать пользователю какие-то дополнительные права? это слишком необычная ситуация.
В целом, не подумайте, что я резко против этого подхода, я и сам что-то подобное применял. Но разработчик перед решением об использовании этого механизма должен взвесить все плюсы и минусы для данной конкретной задачи и в данной конкретной ситуации. Использовать же нестандартный механизм бездумно, просто потому что он понравился или потому что он используется в другом языке или из-за "вау-эффекта" на мой взгляд непрофессионально. В статье не хватает информации о подводных камнях и о примерах задач, в которых такой подход предпочтительнее, с обоснованием такой предпочтительности.
PS: в 1С:Исполнителе, в отличие от платформы 1С, текучий интерфейс - штатная возможность, не требующая создания промежуточных прикладных объектов. Там такой механизм не выглядит чужеродным.
75. bayselonarrend 3214 05.02.25 09:15 Сейчас в теме
(74)
а разве я не могу комбинировать в разном порядке и количестве вызовы функции общего модуля?


Можно. Не вижу никаких приемуществ, это просто по-другому

верно до тех пор, пока не придется в одной цепочке использовать, например данные из ИБ (например реквизит объекта) и данные клиентской формы (например текущая строка)


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

верно до тех пор, пока какой-нибудь деятель не превратит этот код в библиотеку (мы же против велосипедов и за переиспользование кода), а другой деятель не будет его вызывать в цикле из 10000 итераций


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

он же не обязан изучать содержимое такой библиотеки и просто использует ее API


Весь код такой библиотеки находится в самом объекте. И если он использует ее API, то он сначала создает объект, а потом вызвает его методы. Где здесь подводный камень, при котором не очевидно что ты создаешь обработку несколько раз в цикле? В любом случае любое действие начинается с Обработки.Обработка.Создать() и это явно видно

Не говоря о том, что сделать код, который вызывать в цикле возможно, но не стоит, можно при любом подходе

опять же, все хорошо до тех пор, пока эту функциональность не начнет использовать пользователь, которому забыли дать права на обработку


Обработки не появились в тот день, когда я написал про fluent. Их миллион в типовых и много кто их использует для разных задач, так что это будто бы камень не в тот огород

должен взвесить все плюсы и минусы для данной конкретной задачи и в данной конкретной ситуации


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

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


Этому нестандартному механизму сто лет в обед, в том числе и в 1С. Есть пулл задач, которые он упрощает, поэтому я о нем рассказываю. Идея была в том, что каждый сам приложит это уже на свою работу


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


У вас какое-то странное понятие об объектах: единственное отличие 1С от других языков и исполнителя в том, что в 1С нельзя программно объявлять классы, а нужно создавать объект метаданных. В остальном обработка - это такой же ООП класс, только без наследования. Вы точно также создаете описание полей и функций в любом ООП языке, просто в том языке это буде ограничено конструкцией class Name{}, а в 1С рамками модуля объекта. И потом этот класс точно также нужно будет инициализировать (создавать объект). Если в исполнителе можно от некоторых базовых подкапотных классов сразу писать через точку, то это просто означает создание подобия объекта внутри, которое скрыто от ваших глаз
104. Жолтокнижниг 314 07.02.25 00:58 Сейчас в теме
(68) Попробую ответить, зачем же нужно усложнение:
* На fluent не редко строят api. которым пользуются другие разработчики.
* Используют его для инкапсуляции внутреннего состояния
* Да можно создать метод инициализации состояния, хранить его в переменной, которую пробрасывать в вызовы
* Состояние прячут, чтобы конечный разработчик-пользователь не вмешивался и не менял внутреннее состояние, чтобы не сломать механизм.
* Зачем прятать? Чтобы упростить себе жизнь, приватные реквизиты для того и приватные, чтобы к ним не имели доступ снаружи. Таким образом ограничивается набор возможных состояний, выполняются проверки при установке свойств и обеспечивется консистентность.
* Плюс есть ситуации, когда метод fluent'а возвращает не этот же объект, а другой fluent.

Причины есть, но не всегда они актуальны особенно в 1с.
artbear; bayselonarrend; alex_sayan; +3 – Ответить
105. Alxby 1161 07.02.25 08:27 Сейчас в теме
(104) Верно, только это в основном преимущества ООП, а никак не fluent. В процедурном программировании нет инкапсуляции свойств объектов, так как там объектов нет. А инкапсуляция процедур - вполне себе есть, инкапсуляция данных процедур - тоже.
107. alex_sayan 71 07.02.25 08:45 Сейчас в теме
(105) ну как же нет инкапсуляции? В модуле обработки добавляй переменные, храни в них что хош, а доступ будет только через экспортные профедуры/функции. Вот тебе и инкапсуляция в чистейшем виде
Обработка - это объект. Реквизиты и ТЧ обработки - публичные свойства обработки. Переменные модуля - приватные свойства обработки
108. Alxby 1161 07.02.25 09:25 Сейчас в теме
(107) Да, и это преимущества объекта-обработки, а не текучего интерфейса. Так же как и преимущества использования переменных модулей форм, если мы захотим сделать текучий интерфейс на клиенте. Текучий интерфейс на основе общих модулей - по прежнему будет текучим, но инкапсуляцией обладать не будет.
В статье рассказано одновременно о двух принципах: 1) использование текучего интерфейса для компактной записи кода (других преимуществ не вижу) и 2) использование обработки как объекта для сокрытия промежуточных данных (других преимуществ опять же не вижу). Каждый принцип кроме достоинств имеет и недостатки, применять их надо вдумчиво, использовать их можно как вместе, так и по отдельности.
127. brr 184 30.10.25 18:35 Сейчас в теме
(104) Флюентом удобно работать с деревьями, потому что он может запоминать состояние.
78. RustIG 1990 05.02.25 09:51 Сейчас в теме
(67) я испытывал подобное чувство на ИС - когда отвечал на комменты.... лучше тогда вам на неделю перестать следить за веткой :) спокойствие дороже...
Выделите некоторые комментарии как лучшие - для акцента мыслей.
Допишите в шапке статьи - что метод не универсальный, но полезный в практике 1С, особенно для расширения кругозора - чтобы у всех сразу отпали вопросы...
alex_sayan; JohnyDeath; +2 – Ответить
103. Жолтокнижниг 314 07.02.25 00:41 Сейчас в теме
(67) Про fluent писалось уже не раз, но тебе знатно повезло)
106. Alxby 1161 07.02.25 08:28 Сейчас в теме
(103) ну так многие уже попробовали, и поняли что в 1С это не такая замечательная штука как кажется на первый взгляд
94. alex_sayan 71 06.02.25 15:10 Сейчас в теме
(66) а что тут классического? Это процедурный стиль. К тому же общий модуль не сможет хранить каких-нибудь вспомогательных данных, придётся закостыливать через параметры сеанса, хранилище значений или ещё как. А обработка отлично хранит данные у себя на борту. Вот подумай, что у тебя получится, если завтра понадобится не только выплёвывать готовый результат, но ещё и иметь возможность выплюнуть примененную формулу (например, для логирования или показа пользователю)? В обработке можно хранить стек действий, а с общим модулем как?
95. Alxby 1161 06.02.25 17:39 Сейчас в теме
(94) Классический для 1С конечно же.
Для других языков классическим вполне может быть текучий интерфейс. Для лиспа например классическим является многократная вложенность, а для питона - строгое соблюдение отступов.
80. SpiegelWiegel 5 05.02.25 20:12 Сейчас в теме
Я повсеместно использую данный подход в программном формировании формы. Вот одна из реализаций такого подхода)
https://infostart.ru/1c/articles/1979960/
87. wertep 32 06.02.25 12:02 Сейчас в теме
Главным в "текучем интерфейсе" является не возможность многократно через точку вызывать функции. Главное читаемость кода, все остальное вторично и является конкретной реализацией.
Вот это красиво и читаемо.
Ожидаем.Что(НекийМассив.Количество()).Минимум(9);

Вот это не красиво и не читаемо.
	ТекучийКалькулятор = Обработки.ТекучийКалькулятор.Создать();
	
	ТекучийКалькулятор.УстановитьЗначение(0)
		.Прибавить(20) // 20
		.Отнять(10)    // 10
		.Прибавить(5)  // 15
		.Отнять(3);    // 12
		
	Результат = ТекучийКалькулятор.Значение; // 12
Показать

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


Да и к ООП то что реализовано имеет очень отдаленно отношение, потому что в 1С этого не заложено. А именно поэтому применение в реальных разработках это можно применить только ради самого применения.

Прикольно, но бесполезно.
91. alex_sayan 71 06.02.25 13:39 Сейчас в теме
(87) почему же бесполезно-то? Если код станет проще/понятнее/убоднее в переиспользовании, то это уже сама по себе польза
96. Alxby 1161 06.02.25 17:47 Сейчас в теме
(91) если в результате мы не можем перейти к определению функции (по F12), не работает подсказка по параметрам и автодополнение, усложнён поиск вызовов, появляются вопросы с синтаксическим анализом и проверкой, то говорить об удобстве поддержки и переиспользования слегка преждевременно :).
tormozit; +1 – Ответить
98. Alxby 1161 06.02.25 18:26 Сейчас в теме
(96) Кстати, именно отсутствие автокомплита и подсказок по параметрам в свое время привело меня к отказу от использования текучего интерфейса. Правда использовал я именно общие модули а не объекты обработок.
99. alex_sayan 71 06.02.25 18:40 Сейчас в теме
(96) не работает где? Как-минимум в EDT всё отлично работает и никаких проблем не возникает. Даже анализаторы кода на ура переваривают сию возможность (ибо прием используется во многих языках)
100. Alxby 1161 06.02.25 20:16 Сейчас в теме
(99) А в конфигураторе - нет, а он все-таки пока больше распространен. Вернее работает только для первого элемента цепочки. Если в EDT автокомплит работает с любым элементом, да еще и показывает ошибки, например в количестве параметров - отлично. А Вы уверены что АПК и Сонар для 1С
переваривают сию возможность
? Скажем, смогут ли они определить какой метод из числа методов объекта не используется? Если не сложно - проверьте, было бы полезно эту информацию видеть в обсуждении.
tormozit; +1 – Ответить
111. wertep 32 07.02.25 10:33 Сейчас в теме
(91)
проще/понятнее/убоднее в переиспользовании

Это еще не все.
В языках где есть поддержка ООП объект имеет одну копию и передается ссылка на него, 1С при каждом использовании возвращает весь объект целиком. О ресурсах тоже иногда полезно думать, хотя часто думают "подумаешь пару копий, у нас памяти дофига".
Действительно красивый пример применения приведен в (20) вот тут.
А теперь посчитаем. В красивом коде создано 38 объектов. А если работает 100 пользователей? 3800 лишних объектов, стоит ли настолько платить за красоту. При этом наличие БСП сильно упрощает код приведенный в качестве примера изначального обходясь меньшими затратами.
124. alex_sayan 71 15.02.25 10:30 Сейчас в теме
(111) опять выдуманные проблемы с производительностью
110. muskul 07.02.25 10:18 Сейчас в теме
Что вы прицепились к этому ООП как к манне небесной.
Во первых она тормозит и это уже показано и доказано не раз и не два.
во вторых уже достаточно первого
113. dsdred 4355 07.02.25 14:29 Сейчас в теме
(110) Вас не смущают темы в которых все, что не попадя в поле HTML документа впендюривают?
И BI и мессенджеры и чуть не сайты...
Автор просто показал подход реализовав его на 1с.
Он не заставляет его использовать и про "манну небесную" он не писал.
alex_sayan; +1 – Ответить
112. dsdred 4355 07.02.25 14:25 Сейчас в теме
Я в шоке... Зачем напали на автора!?
Он же не написал, что делать только так и не иначе!

Он вам дал пищу для размышления и не больше того.
Что вы на него набросились?
artbear; sir; alex_sayan; fatman78; +4 – Ответить
122. WasiliyMay 8 10.02.25 15:38 Сейчас в теме
В ЗУП 3 используется похожий подход с обработкой "МенеджерРасчетаЗарплаты".
125. artbear 1590 17.02.25 16:05 Сейчас в теме
Подытожу - автор молодец, спасибо за статью, текучий интерфейс бывает полезным.
в комментариях есть ссылки

но пример с калькулятором очень уж неудачный!

(0) Предлагаю добавить полезные ссылки на примеры текучего интерфейса в конец статьи.
- https://infostart.ru/1c/articles/1979960/
- https://infostart.ru/1c/tools/1161402/
brr; alex_sayan; dsdred; +3 – Ответить
Для отправки сообщения требуется регистрация/авторизация