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

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 текучие утверждения текучий интерфейс

См. также

Работа с интерфейсом Системный администратор Программист Платформа 1С v8.3 Управляемые формы 1C:Бухгалтерия Платные (руб)

Механизм «Динамическое управление доступом к элементам форм объектов 1С8» предназначен для обеспечения возможности оперативного управления видимостью и доступностью элементов форм документов и справочников продуктов фирмы «1С» «1С:Предприятие 8». Решение универсальное, встраивается в любую конфигурацию с минимальными доработками, что позволяет без проблем обновлять типовые решения.

5000 руб.

14.01.2016    55500    17    23    

43

Работа с интерфейсом Программист Платформа 1С v8.3 1C:Бухгалтерия 1С:ERP Управление предприятием 2 Платные (руб)

Обработка предназначена для создания и управления дашбордами.

2400 руб.

29.06.2020    19801    28    6    

44

Механизмы платформы 1С Программист Платформа 1С v8.3 Бесплатно (free)

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

06.03.2023    36771    dsdred    80    

217

Механизмы платформы 1С Программист Платформа 1С v8.3 Россия Бесплатно (free)

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

29.07.2022    75606    zeltyr    25    

216

Работа с интерфейсом Программист Платформа 1С v8.3 1C:Бухгалтерия Абонемент ($m)

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

1 стартмани

05.07.2022    7581    kalyaka    6    

33

Механизмы платформы 1С Системный администратор Программист Платформа 1С v8.3 1C:Бухгалтерия Бесплатно (free)

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

09.05.2022    37003    Infostart    84    

250

WEB-интеграция Работа с интерфейсом Пользователь Платформа 1С v8.3 1С:Розница 2 Платные (руб)

Связка из веб-приложения и расширения для конфигурации 1С:Розница 2.3.

3600 руб.

29.04.2022    14343    2    10    

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

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


чем

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


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

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

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

Идея с ООП интересная, в профессионализме автора не сомневаюсь, но такой подход к написанию кода не поддерживаю.
Revachol; user1334089; Prom-komplekt; dabu-dabu; tsmult; asupsam; Трактор; bayselonarrend; Ks_83; Prometeus2011; Sashares; Brawler; borda4ev; +13 Ответить
6. alex_sayan 55 03.02.25 15:12 Сейчас в теме
(3) а какие сложности с чтением текучего интерфейса?
10. e9504100606 92 03.02.25 15:33 Сейчас в теме
(6) Это же очевидно
15. alex_sayan 55 03.02.25 15:57 Сейчас в теме
(10) ну у меня, например, текучий интерфейс не вызывает абсолютно никаких сложностей с чтением
18. slknnk 77 03.02.25 16:47 Сейчас в теме
(15) Согласен. С чтением тут наоборот все более чем понятно.
7. bayselonarrend 2448 03.02.25 15:14 Сейчас в теме
(3) Такой подход чаще всего используют в готовых универсальных модулях. Те же фреймворки для автоматизированного тестирования используют его в 9/10 случаях для механизма проверки условий. Но такие инструменты обычно целиком обособленные от основной конфигурации и имеют докумментацию. Благодаря этому все это идет в плюс, а без этого действительно все может быть неочевидно
27. Ks_83 259 03.02.25 22:44 Сейчас в теме
(3) Абсолютно верно. Статься из серии вредных советов. Такой код код-ревью не пройдет. Выпендрежи и выкрутасы на крупных проектах категорически не приветствуются.
28. bayselonarrend 2448 03.02.25 23:01 Сейчас в теме
(27)

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


У кого?

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


Те же фреймворки для автоматизированного тестирования (используемые, кстати, чаще всего на крупных проектах) используют этот подход и никого это не смущает. В любом случае, я не имел ввиду, что это абсолютно универсальная вещь, которую необходимо использовать везде и везде она будет полезна
KirillZ44; alex_sayan; sleemp; Трактор; +4 Ответить
4. acces969 366 03.02.25 14:59 Сейчас в теме
Какие преимущества дает такой способ написания кода?
5. bayselonarrend 2448 03.02.25 15:07 Сейчас в теме
(4) Ну этакий синтаксический сахар. Меньше кода, лаконично
8. alex_sayan 55 03.02.25 15:17 Сейчас в теме
(4) текучий интерфейс хорош для "конвейерного" кода. Это когда есть некоторый набор методов, которые могут вызываться в разной комбинации и/или в разном порядке порядке
bayselonarrend; +1 Ответить
33. acces969 366 04.02.25 07:10 Сейчас в теме
(8) Что то вроде функционального программирования получается?
38. alex_sayan 55 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);		
		КонецЕсли;	
	КонецЦикла;

в этом примере наверно не очевидны преимущества, но когда большая вложенность Цикл...Если...Цикл...Если, конвейерный код получается намного компактнее
Artem-B; pavlov_dv; +2 Ответить
12. starik-2005 3098 03.02.25 15:43 Сейчас в теме
Плюс. Не за саму статью, а за поднятие темы. Я так 30 лет назад писал, когда объекты были в виде таких библиотек, так TurboVision.
ЗЫ: В турбовижине используется несколько иной подход, когда в конструктор засовывается конструктор, в который засовывается конструктор, в который ... И так "одной строкой кода" рисуется форма целиком со всеми добавленными на нее полями.
ЗЫЗЫ: Ща такое повсеместно, по крайней мере во флаттере с этим вот прям беда была - я тупо путался, после какой запятой что рисовать.
pavlov_dv; +1 Ответить
13. SerVer1C 868 03.02.25 15:52 Сейчас в теме
Помню, что где-то уже видел аналогичную дичЪ
Конечно, лучше юзать общий модуль вместо объекта обработки.
Хотел бы я посмотреть на тех, кто в ж0лтом проде применяет подобные извраты ))
14. starik-2005 3098 03.02.25 15:54 Сейчас в теме
(13)
Хотел бы я посмотреть на тех, кто в проде применяет подобные извраты
Да весь джаваскрипт такой, если прилично асинхронить. Не знаю, дошло ли до питона, но точно местами не миновало...
pavlov_dv; +1 Ответить
16. alex_sayan 55 03.02.25 16:10 Сейчас в теме
(14) справедливости ради, код на жаваскрипте, работающий с CSS/HTML, выглядит в сто раз лаконичнее, чем если бы он был написал на 1с в привычном нам процедурном стиле. Код на 1с, собирающий HTML из кусочков, та ещё вырвиглазная лапша
17. SerVer1C 868 03.02.25 16:11 Сейчас в теме
(14) Про то не знаю, но Linq в шарпе отличная штука!
86. wertep 31 06.02.25 11:28 Сейчас в теме
(13) Общий модуль не подходит по той простой причине что он не инкапсулирует данные. Объект обработки при создании имеет свои данные, а модуль нет. Поэтому вызвав какую-то функцию где тоже этим попользуются, после возврата из нее результат будет неожиданным.
88. SerVer1C 868 06.02.25 12:04 Сейчас в теме
(86) Если бы вы внимательно прочитали дичЪ - то там есть такие строки: "...контекст между функциями гуляет через ПараметрыСеанса, закэшированные через повторноиспользуемый модуль..."
89. wertep 31 06.02.25 12:44 Сейчас в теме
(88)
закэшированные через повторноиспользуемый модуль

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

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

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

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

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


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

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


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

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

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

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

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

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


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


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


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

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


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

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

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


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

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


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

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

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

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

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


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

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


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

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


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

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


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

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


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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

Всем добра!
bayselonarrend; +1 Ответить
35. tormozit 7254 04.02.25 09:23 Сейчас в теме
Ударю ниже пояса - как точки останова ставить будешь? Текучий код убивает отладку в случае 1С. Без отладки тут жизни нет.
36. bayselonarrend 2448 04.02.25 09:24 Сейчас в теме
(35) Да, это актуальная проблема) Только если ставить внутри обработки или идти через F11
37. bayselonarrend 2448 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 через возврат нового экземпляра обработки (это не я придумал, а есть такой стандартный вариант).
В примере с калькулятором это непонятно зачем, но при сложной/ресурсоемкой инициализации объекта закономерно желание его переиспользования, начиная с первоначального состояния.
Жолтокнижниг; bayselonarrend; +2 1 Ответить
41. bayselonarrend 2448 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 35 05.02.25 23:45 Сейчас в теме
(44)
А вот если просто тупо теряем время на получение этих самых данных

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

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

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

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

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

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


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

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

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


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

Ответ = Ложь;

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

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

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

    КонецЕсли;

КонецЕсли;

Возврат Ответ
Показать
60. miniogn 42 04.02.25 19:09 Сейчас в теме
(43)
Ответ = Ложь;

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

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

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

    КонецЕсли;

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


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

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

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

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


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

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


 

вот и код получился заметно сложнее
52. bayselonarrend 2448 04.02.25 14:00 Сейчас в теме
45. sir 18 04.02.25 12:06 Сейчас в теме
меня например смутило "Результат = ТекучийКалькулятор.Значение;"

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

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

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

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

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

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

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

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

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