Работа с абстрактным массивом

Публикация № 1473034 07.07.21

Разработка - Практика программирования

Массив абстрактные типы данных функции первого класса

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

Оглавление

Массивы и абстрактные типы данных. 2

Абстрактные алгоритмы.. 2

Функции как объекты первого класса. 2

Сортировка массива. 2

Простые примеры использования. 3

Конструктор. 3

Сортировать (sort) 3

Отобрать (filter) 3

Отобразить (map) 3

Преобразовать (reduce) 3

Текучий интерфейс для абстрактного массива. 3

Мутации. 6

Конструктор абстрактного типа данных массив. 6

Функции первого порядка. 7

Пример повышенной сложности :] 7

Формирование списка подсистем.. 7

Реализация команды "Выбрать объекты подсистемы". 8

Поиск выбранной подсистемы.. 8

Формирование списка объектов метаданных по выбранной подсистеме. 9

Пометка объектов метаданных по выбранной подсистеме. 9

Вывод. 9

Поставка. 10


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

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

В мире программирования известны и другие абстрактные типы данных: Стек, Очередь, Список. Однако и они вполне могут быть реализованы на базе работы с массивом в 1С.

Массив в отличии от структуры данных, является абстрактным типом. На практике в работе с массивами выделяют следующие абстрактные алгоритмы: сортировка, преобразование, отбор и агрегирование.

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

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

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

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

Чего мне сильно не хватает в массивах на 1С - это метода сортировки. Казалось бы можно сортировать списки, даже по значению, сортировать таблицы значений, а вот массивы - нет!

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

Алгоритмы сортировки уже известны давно. Мне не пришлось даже ничего программировать, и я воспользовался публикацией по данной теме. Дальше мне оставалось лишь обобщить алгоритм для абстрактных структур данных. Так у меня появилась функция Сравнить. И здесь я снова ничего не придумал, а взял готовое решение из других языков программирования :)

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

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

Фрукты = РаботаСМассивом.АТДМассив(СтрРазделить("вишня, арбузы, бананы", ", ", Ложь));
Фрукты.ДляКаждого("Сообщить(Элемент)");// [вишня, арбузы, бананы]
Фрукты.Сортировать();
Фрукты.ДляКаждого("Сообщить(Элемент)");// [арбузы, бананы, вишня]
Фрукты.Сортировать("Сравнить(Б, А)");// обратный порядок
Фрукты.ДляКаждого("Сообщить(Элемент)");// [вишня, бананы, арбузы]
Фрукты.Отобрать("СтрНайти(Элемент, ""а"") > 0");
Фрукты.ДляКаждого("Сообщить(Элемент)");// [арбузы, бананы]
Фрукты.Отобразить("ВРег(Лев(Элемент, 1)) + Прав(Элемент, СтрДлина(Элемент) - 1)");
Фрукты.ДляКаждого("Сообщить(Элемент)");// [Арбузы, Бананы]
Количество = Фрукты.Преобразовать("Накопитель + 1", 0);
Сообщить(Количество);// 2

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

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

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

Вот следующие примеры использования классического подхода и функционального при конструировании составного типа из строки и ссылки на справочник Номенклатуры:

МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка. _ДемоНоменклатура "));
МассивТипов.Добавить(Тип("Строка"));
ПараметрыСтроки = Новый КвалификаторыСтроки(20);
ДопустимыеТипы = Новый ОписаниеТипов(МассивТипов, , ПараметрыСтроки);

Конструктор на основе абстрактного массива:

ДопустимыеТипы = Новый ОписаниеТипов(РаботаСМассивом.АТДМассив()
	.Положить(Тип("СправочникСсылка._ДемоНоменклатура"))
	.Положить(ОбщегоНазначения.ОписаниеТипаСтрока(20))
	.ВМассив());

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

Итак, на входе у нас имеется файл в формате похожем на упрощенный markdown. Необходимо на выходе сформировать отчет в формате табличного документа 1С.

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

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

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

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

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

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

Пример решения в функциональном стиле:

Функция ТекстВОбласть(Элемент, Параметры) Экспорт
    ИмяОбласти = Лев(Элемент, 2);
    Если Параметры.Области.Найти(ИмяОбласти) <> Неопределено Тогда
        Область = Параметры.ПолучитьОбласть(ИмяОбласти);
        Область.Параметры.Текст = Прав(Элемент, СтрДлина(Элемент) - 4);
    Иначе
        Область = Параметры.ПолучитьОбласть("Строка");
        Область.Параметры.Текст = Элемент;
    КонецЕсли;
    Возврат Область;
КонецФункции
	
Функция СформироватьОписание()
    ТабличныйДокумент = Новый ТабличныйДокумент;
    Текст = ПолучитьМакет("README").ПолучитьТекст();
    Макет = ПолучитьМакет("Макет");
    РаботаСМассивом.АТДМассив(СтрРазделить(Текст, Символы.ВК + Символы.ПС, Ложь))
        .Отобрать("НЕ ПустаяСтрока(Элемент)")
        .Отобразить("Контекст.ТекстВОбласть(Элемент, Параметры)", ЭтотОбъект, Макет)
        .Положить(Макет.ПолучитьОбласть("Разделитель"))
        .ДляКаждого("Контекст.Вывести(Элемент)", ТабличныйДокумент);
    Возврат ТабличныйДокумент; 
КонецФункции
 
 Текст описания
 
 Отчет

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

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

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

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

Для работы с объектной моделью абстрактного массива необходимо вызвать функцию общего модуля АТДМассив(). В качестве параметра инициализации модели можно передать любую коллекцию, поддерживающую метод обхода элементов ДляКаждого. Обычно абстрактные алгоритмы сразу можно применять к такой коллекции, за исключением метода Сортировать. Последнее связано с тем, что функция сортировки является мутирующей и непосредственно изменяет массив, а значит рассчитана на работу с типом данных Массив.

Для снятия ограничения на работу мутирующих алгоритмов можно использовать метод Массив(). Этот метод преобразует коллекцию в массив элементов коллекции и дальнейшая работа уже может быть продолжена с чистым массивом элементов.

Коллекция может быть преобразована в массив также после использования одной из чистых абстрактных функций. Это возможно потому, что результатом абстрактной функции является массив. Исключением пожалуй здесь может быть функция Преобразовать (map), результатом которой может быть объект любого типа.

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

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

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

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

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

В демообработку я вынес алгоритм заполнения метаданных из обработки Ванессы. На форму добавил выбор подсистемы и команду "Выбрать метаданные по подсистеме".

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

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

Итак задача: необходимо заполнить массив полных имен по всем подсистемам метаданных. Для этого вызовем конструктор абстрактного массива с параметром верхнего узла Метаданные.Подсистемы.

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

Еще одной особенностью переданной функции является то, что она содержит в себе рекурсию через собственное преобразование в абстрактном массиве.

Следующая наша функция - ДляКаждого. Здесь в качестве функции первого порядка использована анонимная функция выполняющая метод списка выбора Добавить() для каждого элемента абстрактного массива. Побочным результатом последнего вызова будет заполненный список подсистем для выбора.

Функция ДополнитьПодсистемыПоИмени(Элемент, Накопитель, Путь = "") Экспорт
    ТекущийПуть = Путь + "\" + Элемент.Имя;
    Накопитель.Положить(ТекущийПуть);
    Если Элемент.Подсистемы.Количество() = 0 Тогда
        Возврат Накопитель;
    КонецЕсли;
    Подсистемы = РаботаСМассивом.АТДМассив(Элемент.Подсистемы)
        .Преобразовать("Контекст.ДополнитьПодсистемыПоИмени(Элемент, Накопитель, Параметры)", РаботаСМассивом.АТДМассив(), ЭтотОбъект, ТекущийПуть)
	.ВМассив();
    Накопитель.ДополнитьМассив(Подсистемы);
    Возврат Накопитель;
КонецФункции

Процедура КомандаЗаполнитьПодсистемыНаСервере()
    СписокВыбора = Элементы.ВыбраннаяПодсистема.СписокВыбора;
    СписокВыбора.Очистить();
    РаботаСМассивом.АТДМассив(Метаданные.Подсистемы)
        .Преобразовать("Контекст.ДополнитьПодсистемыПоИмени(Элемент, Накопитель)", РаботаСМассивом.АТДМассив(), ЭтотОбъект)
        .ДляКаждого("Контекст.Добавить(Элемент)", СписокВыбора);
КонецПроцедуры

На этом заполнение списка подсистем завершено! Перейдем к следующей команде: "Выбрать объекты подсистемы"

Алгоритм команды условно поделен на три части: поиск подсистемы по полному имени, формирование списка объектов метаданных подсистемы и всех ей подчиненных, пометка выбора в дереве объектов метаданных. Рассмотрим их отдельно.

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

//  Поиск подсистемы по полному имени
ОбъектМетаданныхВыбраннаяПодсистема = РаботаСМассивом.АТДМассив(СтрРазделить(ВыбраннаяПодсистема, "\", Ложь))
    .Преобразовать("Накопитель.Подсистемы.Найти(Элемент)", Метаданные);

Следующим на очереди будет задача определить список имен объектов метаданных выбранной подсистемы, включая все подчиненные ей. Для этого создадим абстрактный массив с конструктором по умолчанию. Далее методом Положить() поместим в массив саму выбранную подсистему. Абстрактным методом Преобразовать последовательно сформируем вначале абстрактный массив с подчиненными подсистемами, затем преобразуем подсистемы в массив объектов метаданных этих подсистем. Последовательным вызовом абстрактного метода Отобразить вначале преобразуем массив объектов в массив структур {Тип, Имя}, а затем в массив наименований по шаблону "Тип.Имя" - теперь у нас сформирован полный список имен объектов метаданных по выбранной подсистеме, включая подчиненные ей.

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

//  Добавляет подсистемы рекурсивно
Функция ДополнитьПодсистемы(Элемент, Накопитель) Экспорт
	Накопитель.Положить(Элемент);
	Если Элемент.Подсистемы.Количество() = 0 Тогда
		Возврат Накопитель;
	КонецЕсли;
	Подсистемы = РаботаСМассивом.АТДМассив(Элемент.Подсистемы)
		.Преобразовать("Контекст.ДополнитьПодсистемы(Элемент, Накопитель)", РаботаСМассивом.АТДМассив(), ЭтотОбъект)
		.ВМассив();
	Накопитель.ДополнитьМассив(Подсистемы);
	Возврат Накопитель;
КонецФункции

//  Добавляет состав метаданных подсистемы
Функция ДополнитьСостав(Элемент, Накопитель) Экспорт
	Если Элемент.Состав.Количество() = 0 Тогда
		Возврат Накопитель;
	КонецЕсли;
	Накопитель.ДополнитьМассив(Элемент.Состав, Истина);
	Возврат Накопитель;
КонецФункции

//  Разбивает полное имя объекта метаданных
Функция РазделитьПолноеИмя(Элемент) Экспорт
	Состав = СтрРазделить(Элемент.ПолноеИмя(), ".");
	Возврат Новый Структура("Type, Name", Состав[0], Состав[1]);
КонецФункции

//  Формирование списка объектов метаданных по выбранной подсистеме
ОбъектыМетаданных = РаботаСМассивом.АТДМассив()
    .Положить(ОбъектМетаданныхВыбраннаяПодсистема)
    .Преобразовать("Контекст.ДополнитьПодсистемы(Элемент, Накопитель)", РаботаСМассивом.АТДМассив(), ЭтотОбъект)
    .Преобразовать("Контекст.ДополнитьСостав(Элемент, Накопитель)", РаботаСМассивом.АТДМассив(), ЭтотОбъект)
    .Отобразить("Контекст.РазделитьПолноеИмя(Элемент)", ЭтотОбъект)
    .Отобразить("СтрШаблон(""%1.%2"", Контекст[Элемент.Type], Элемент.Name)", TypeTranslatiton);

Когда мы получили массив объектов метаданных в формате "Тип.Имя" останется найти их по этому имени в дереве метаданных и поставить по ним пометку выбора.

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

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

//  Добавляет только подчиненные строки дерева метаданных
Функция ДополнитьПодчиненныеСтроки(Элемент, Накопитель) Экспорт
	Строки = Элемент.ПолучитьЭлементы();
	Если Строки.Количество() = 0 Тогда
		Возврат Накопитель;
	КонецЕсли;
	Накопитель.ДополнитьМассив(Строки);
	Возврат Накопитель;
КонецФункции

//  Обработка дерева объектов метаданных: пометка объектов метаданных по выбранной подсистеме
РаботаСМассивом.АТДМассив(MetadataList.ПолучитьЭлементы())
    .ДляКаждого("Элемент.Use = Ложь")
    .Преобразовать("Контекст.ДополнитьПодчиненныеСтроки(Элемент, Накопитель)", РаботаСМассивом.АТДМассив(), ЭтотОбъект)
    .ДляКаждого("Элемент.Use = Ложь")
    .Отобрать("Контекст.Найти(Элемент.FullName) <> Неопределено", ОбъектыМетаданных.ВМассив())
    .ДляКаждого("Элемент.Use = Истина");

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

Решение доступно на github. Решение не зависит от БСП и является самодостаточным. Вариант поставки: конфигурация, расширение.

Объект метаданных

Контекст

Комментарий

ОбщийМодуль.РаботаСМассивом

Клиент, Сервер

Библиотека работы с абстрактным массивом

Обработка.АТДМассив

Клиент, Сервер

Реализует объектную модель абстрактного массива

ВнешняяОбработка.ДемоАТДМассив

 

Примеры

 

Обновление от 14.07.2021: добавлена поддержка работы модели в контексте Клиент

Теперь модель абстрактного массива доступна в любом контексте.
Конструктор модели перенесен в модуль РаботаСМассивом. Модуль Общий удален.
Убрана прямая доступность к элементам массива. Для установки элементов теперь можно использовать либо конструктор, либо оператор Установить(Коллекция).
Добавлены терминальные операторы ВМассив(), ВФиксированныйМассив().

Элементы.ДоговорКонтрагентов.СвязиПараметровВыбора = РаботаСМассивом.АТДМассив()
	.Положить(Новый СвязьПараметраВыбора("Отбор.Владелец", "Объект.Организация"))
	.ВФиксированныйМассив();

ДопустимыеТипы = Новый ОписаниеТипов(РаботаСМассивом.АТДМассив()
	.Положить(Тип("СправочникСсылка._ДемоНоменклатура"))
	.Положить(ОбщегоНазначения.ОписаниеТипаСтрока(20))
	.ВМассив());

Добавлены методы: СортироватьПо, ДополнитьМассив.

Следующий пример работает как на клиенте, так и на сервере:

Сотрудники = РаботаСМассивом.АТДМассив()
	.Положить(Новый Структура("Фамилия, Имя, Отчество", "Иванов", "Иван", "Иванович"))
	.Положить(Новый Структура("Фамилия, Имя, Отчество", "Иванов", "Иван", "Гермагенович"))
	.Положить(Новый Структура("Фамилия, Имя, Отчество", "Савельев", "Иван", "Иванович"))
	.Положить(Новый Структура("Фамилия, Имя, Отчество", "Андреев", "Иван", "Иванович"))
	.Положить(Новый Структура("Фамилия, Имя, Отчество", "Андреев", "Андрей", "Андреевич"));
Сотрудники.СортироватьПо("Фамилия, Имя, Отчество");
Сотрудники.ДляКаждого("Сообщить(СтрШаблон(""%1 %2 %3"", Элемент.Фамилия, Элемент.Имя, Элемент.Отчество))"); // [Андреев Андрей Андреевич, Андреев Иван Иванович, Иванов Иван Гермагенович, Иванов Иван Иванович, Савельев Иван Иванович]

Пример с БСП:

Файлы = Новый Массив;
РаботаСФайлами.ЗаполнитьПрисоединенныеФайлыКОбъекту(СсылкаНаДокумент, Файлы);
СсылкаНаПрисоединенныйФайл = РаботаСМассивом.АТДМассив(Файлы)
	.Отобрать("СтрНайти(Элемент.Наименование, ""#БДДС#"") > 0")
	.Отобрать("НЕ Элемент.ПометкаУдаления")
	.Взять();

 

Скачать файлы

Наименование Файл Версия Размер
Работа с абстрактным массивом

.zip 14,33Kb
0
.zip v1.0.4 14,33Kb Скачать

Специальные предложения

Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Darklight 27 07.07.21 13:56 Сейчас в теме
Категорически поддерживаю данную концепцию ведения разработки. Недавно на Инфостарт уже выкладывалинечто подобное. Вам бы скооперироваться вместе с AntonProgma - и пилить сообща единую концепцию в одном (но можно и в нескольких совместимых) решениях. За абстракциями и функциональным подходом - и настоящее, и будущее. Надеюсь когда-нибудь оно настанет официально и в 1С Предприятие.

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

Теперь технические.

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

Для перебора элементов Вы выбрали "встроенную" переменную "Элемент" - не самое удачное имя. Оно занято в 1С Предприятие 8. Да, и вот, если взять Kotlin - то там используют "it" - более универсальное встроенное имя - не только для перебора последовательностей - а вообще - везде, где есть потребность в единственной контекстной переменной - это унифицирует код - делая его более строгим и универсально подходящим для разного использования.
Я согласен, что в переводе на русский "it" может быть и не так благозвучен "Оно", а слово "Элемент" боле понятное. Я бы выбрал "Он" (в отношении Объект, Параметр, Элемент) или "Этот". Но можно ещё подумать.
Кстати, английский дубликат тоже надо ввести на всякий случай.

"Накопитель" - это тоже встроенная переменная? Вы бы хотя бы рассказали про то как оно внутри устроено - хотя бы в общих чертах. Рассказали бы по встроенные переменные и их назначение. Про API вызова и особенности построения анонимных функций.

Цепочки соединённых функций (в стиле LINQ) у Вас как - сразу выполняются - т.е. тут нет генераторов и отложенных вычислений? Если да - то это плохо - так как на этом теряется большая часть смысла такого подхода и в неправильных руках он приведёт к серьёзном снижению производительности.

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

Вот этот код - просто вынос мозга - если цель была упростить написание и читабельность - то получился полный провал!
Общий.АТДМассив(MetadataList.ПолучитьЭлементы())
    .ДляКаждого("Элемент.Use = Ложь")
    .Преобразовать("Контекст.ДополнитьПодчиненныеСтроки(Элемент, Накопитель)", Общий.АТДМассив(), ЭтотОбъект)
    .ДляКаждого("Элемент.Use = Ложь")
    .Отобрать("Контекст.Найти(Элемент.FullName) <> Неопределено", ОбъектыМетаданных.Элементы)
    .ДляКаждого("Элемент.Use = Истина");

Ну никак я не могу понять - если нам просто надо пометить по выбранной подсистеме "Элемент.Use = Истина" - зачем помечаем два набора как "Элемент.Use = Ложь"? В тексте никаких пояснений.
Или это не действие - а отбор (что мне сначала и показалось) - очень трудно воспринимать такой API , тем более без пояснений (если ели понял - что тут идёт некое продолжение предыдущего примера заполнения, отбора и установки пометки "Элемент.Use = Истина".

Зачем Вы постоянно обращаетесь к функции БСП "ОбщегоНазначенияКлиентСервер.ДополнитьМассив" - раз уж ввели расширенный объект-массив - так и придерживались бы такой же концепции - добавили бы данный метод в него.
Аналогично - я бы туда и функцию "СтрРазделить"

Функция "Сортировки" всё-таки должна быть возвращать новый Массив - не ломайте привычный шаблон функционального стиля программирования. Затраты памяти смехотворны (ну только если в массиве не гигантские строки; а для очень больших исходных массивов - ну введите доп аргумент, который их просто будет очищать - коли не нужны).

Что возвращает "Общий.АТДМассив()" - это объект-обработка?
Если да - то как же поддержка на стороне клиента? Вот общий модуль "ОбщийМодуль.РаботаСМассивом" у Вас помечен как поддерживающий клиентский контекст.

Общие модули Вы назвали тоже очень плохо - во первых полностью в разнобой, во вторых слишком уж эгоистично с вероятностью нарваться на такие же в конфигурации, в третьих по сути без префиксов-окончаний.
Уж не говорю зачем надо было назвать конструктор "АТДМассив" а не просто "Массив" - если нужны оба метода то может лучше разнести их по разным API-общим модулям - имена которых должны быть более поясняющими и конкретизирующими - за что они отвечают. Вот я делаю такие "МассивМенеджер_ОДП", "СтруктураМенеджер_ОДП", "ФормаМенеджер_ОДП". А внутри уже функции, например "ВСтруктуру" (хотя, наверное надо было просто "Структура", но ещё думал так называть конструктор, боялся путаницы, как и думал делать ещё и парные варианты типа "ИзСтруктуры"), "Объединить", "Сериализовать", "Создать" (у меня нет расширенных объектов-обработок - пока не дошёл да этого - в силу ограничений платформы в управляемых формах)

Сквозной пример ясно совсем не удался!

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


И ещё. Интересно как у Вас работает вот эта цепочка
ДопустимыеТипы = Новый ОписаниеТипов(Общий.АТДМассив()
	.Положить(Тип("СправочникСсылка._ДемоНоменклатура"))
	.Положить(ОбщегоНазначения.ОписаниеТипаСтрока(20)).Элементы);

Как передаётся квалификатор строки в ОписаниеТипов?


В общем. Идея концепции то правильная. Осталось только правильно её подать!
PowerBoy; nagimo; +2 Ответить
3. kalyaka 726 07.07.21 19:24 Сейчас в теме
(1)
уже выкладывалинечто подобное
видел, решил написать пока тема горячая :)
Статья очень бодро начиналась и её было легко читать
первая часть была простой
но оно остаётся таким же обтекаемым и малопонятным
оставлено на обсуждение, если будет интерес. Заранее не угадаешь, пойдет тема или нет, поэтому тратить много усилий для разъяснений тоже накладно. И не понятно, что именно нужно разъяснить или возможно нужно другой вообще пример разобрать.
Не считаю хорошим дизайном передачу абстрактных функций просто как текст
согласен, это решение компромиссное в рамках возможностей языка 1С. Конечно можно было бы переусложнить, но тогда сложность восприятия кода сведет на нет преимущества. Например, в абстрактном массиве есть функция НайтиЭлемент и в следующем коде
//  Обработка дерева объектов метаданных: пометка объектов метаданных по выбранной подсистеме 
Общий.АТДМассив(MetadataList.ПолучитьЭлементы())     .ДляКаждого("Элемент.Use = Ложь")
     .Преобразовать("Контекст.ДополнитьПодчиненныеСтроки(Элемент, Накопитель)", Общий.АТДМассив(), ЭтотОбъект)
     .ДляКаждого("Элемент.Use = Ложь")
     .Отобрать("Контекст.Найти(Элемент.FullName) <> Неопределено", ОбъектыМетаданных.Элементы)
     .ДляКаждого("Элемент.Use = Истина");
примера у меня был соблазн использовать эту функцию. Однако в попытке выразить в виде текстового выражения вложенное выражение я запутался в кавычках :) и решил использовать метод Найти из контекста. Хотя у меня есть пример и удачного использования функции НайтиЭлемент, возможно я его приведу в следующих публикациях.
Для простых случаев передачу строки тоже можно оставить
да, пока остановимся на простом случае :)
переменную "Элемент"
- в каком контексте занято?
слово "Элемент" боле понятное
согласен
Кстати, английский дубликат тоже надо ввести на всякий случай
пока нет такой необходимости :) Хотя проект открыт и доступен на github - можно и форкнуть :)
"Накопитель" - это тоже встроенная переменная?
скажем так, это предопределенная переменная в контексте исполнения абстрактной функции Преобразовать.
хотя бы рассказали про то как оно внутри устроено
- так вот, смотрите исходники. Я там даже постарался описания для функций сделать.
Цепочки соединённых функций (в стиле LINQ)
не понял идею с отложенными вычислениями. Здесь главная фишка в том, что не нужно хранить контекст (массив элементов, над которым происходят преобразования). В контекст абстрактного массива можно добавить дополнительные настройки, но пока я не придумал какие :) Еще цепочки, на мой взгляд, смотрятся хорошо в коде. В принципе можно использовать и процедурный подход работы с абстрактным массивом:
Фрукты = СтрРазделить("вишня, арбузы, бананы", ", ", Ложь);
РаботаСМассивом.ДляКаждого(Фрукты, "Сообщить(Элемент)");// [вишня, арбузы, бананы]
РаботаСМассивом.Сортировать(Фрукты);
РаботаСМассивом.ДляКаждого(Фрукты, "Сообщить(Элемент)");// [арбузы, бананы, вишня]
РаботаСМассивом.Сортировать(Фрукты, "Сравнить(Б, А)");// обратный порядок
РаботаСМассивом.ДляКаждого(Фрукты, "Сообщить(Элемент)");// [вишня, бананы, арбузы]

не привели ни одного теста производительности и сравнения двух концепций между собой
и не собирался. Однажды я уже сделал такую ошибку и больше повторять ее не собираюсь :) Нет, в принципе конечно можно проводить такие исследования, но нужно понимать, что вы хотите определить. Вот ссылки по теме Продуманная оптимизация, Преждевременная оптимизация.
Вот этот код - просто вынос мозга
этот пример здесь сознательно приведен. Основная фишка этого кода в том, что он работает с деревом значений на форме. В первом операторе в массив помещается коллекция строк верхнего уровня (типы метаданных: Справочники, Документы и т.д.), в следующей функции для каждой строки проставляется значение выбора Ложь, далее строки верхнего уровня преобразуются в массив строк второго уровня, далее происходит сброс в Ложь пометки выбора для уже этих строк. Далее функция Отобрать формирует массив строк, имя в которых совпадает из переданного массива ОбъектыМетаданных. Ну и наконец по отобранным строкам проставляется пометка выбора Истина.
Зачем Вы постоянно обращаетесь к функции БСП
все что можно переиспользовать я стараюсь переиспользовать.
Функция "Сортировки" всё-таки должна быть возвращать новый Массив - не ломайте привычный шаблон
ну это в идеальном мире, а на практике стандартно в JS например это мутирующая функция. Впрочем здесь проблем не должно быть, т.к. для применения функции нужно получить вначале массив. Массив можно получить либо автоматически при использовании любой чистой функции, либо вызвать функцию Массив.
Что возвращает "Общий.АТДМассив()" - это объект-обработка?
это объектная обертка, да, это обработка. Можно использовать вызовы из модуля РаботаСМассивом без обертки (приводил пример в этом ответе выше).
Общие модули Вы назвали тоже очень плохо - во первых полностью в разнобой, во вторых слишком уж эгоистично с вероятностью нарваться на такие же в конфигурации, в третьих по сути без префиксов-окончаний
про разнобой поясните пожалуйста. Префиксы не люблю. Надеюсь либо кто-нибудь, либо уже я сам сделают компилятор по типу webpack, тогда можно будет упаковывать все модули в один вместе с зависимостями.
назвать конструктор "АТДМассив" а не просто "Массив"
- Массив - это зарезервированное слово, нельзя :)
Вот почитайте комментарий - примите к сведенью
по ссылке нельзя найти конкретный комментарий, переход в форум. Приведите, пожалуйста, цитату.
Интересно как у Вас работает вот эта цепочка

ДопустимыеТипы = Новый ОписаниеТипов(Общий.АТДМассив()
    .Положить(Тип("СправочникСсылка._ДемоНоменклатура"))
    .Положить(ОбщегоНазначения.ОписаниеТипаСтрока(20)).Элементы);

Общий.АТДМассив() - пустой конструктор абстрактного массива
.Положить(Тип("СправочникСсылка._ДемоНоменклатура") - добавляет в массив тип номенклатуры и возвращает ссылку на абстрактный массив
.Положить(ОбщегоНазначения.ОписаниеТипаСтрока(20)
- добавляет в массив тип строки с квалификатором длины и возвращает ссылку на абстрактный массив
.Элементы - прямое обращение к массиву в абстрактном массиве
4. Darklight 27 08.07.21 11:21 Сейчас в теме
(3)
оставлено на обсуждение, если будет интерес. Заранее не угадаешь, пойдёт тема или нет

Как тема преподносится - так она и идёт.

Сравните как осуждали прошлую тему от "AntonProgma" и Вашу, как ставили оценки. Там разжевали всё более понятно. Если статья написана плохо - её и читать то не будут, тем более вникать и обсуждать.
2/3 Вашей статьи написано очень мутно - и большинством было просто проигнорировано - даже оценки, в т.ч. отрицательные, народ не стал ставить - просто забил на тему. Да и ничего особо нового (по сравнению с работой "AntonProgma") Вы тут не предложили.


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

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

Однако в попытке выразить в виде текстового выражения вложенное выражение я запутался в кавычках :)

Идей, у меня, на эту тему много, например так

//Гдет-то в глобальном модуле
Функция ВК(Стр, Уровень=1) экспорт
     возврат СтроковыеФункцииКлиентСервер.ДополнитьСтроку("",Уровень,"""","Слева")+Стр+СтроковыеФункцииКлиентСервер.ДополнитьСтроку("",Уровень,"""","Справа")
КонецФункци

//Для вложений больше 2-го уровня нужны по две кавычки т.к. в внутри вызова выражения они будут внутри строрки
Функция ВК2(Стр, Уровень=1) экспорт
     возврат СтроковыеФункцииКлиентСервер.ДополнитьСтроку("",Уровень*2,"""","Слева")+Стр+СтроковыеФункцииКлиентСервер.ДополнитьСтроку("",Уровень*2,"""","Справа")
КонецФункци

АтдМассив.Отобрать(Контекст.НайтиЭлементы(Элемент.FullName).ДляКаждого("+ВК(Элемент.Use = Истина)+")"
Показать


Но вот сейчас бы прям сделал так - ввёл бы в строке абстракцию для вложенных кавычек - отдельно открывающую блок "{" и отдельно закрывающую блок выражения "}" тогда вложенные выражения были бы такими
АтдМассив.Отобрать("Контекст.НайтиЭлементы(Элемент.FullName).ДляКаждого({Элемент.Use = Истина})"

А в строке эти фигурные скобки бы перед выполнением преобразовывал бы к "".

Но это, не очень хороший дизайн. Лучше, конечно использовать комбинации функций
АтдМассив.Отобрать(Функ("Контекст.НайтиЭлементы(Элемент.FullName)").Далее(Функ("ДляКаждого(арг1).УстановитьАргумент("арг1", Функ("Элемент.Use = Истина"))))"


Что-то тоже не очень красиво - ну надо думать....
Может вот так бы получилось
Ф1 = Функ("Контекст.НайтиЭлементы(Элемент.FullName)").Комбайн().ДляКаждого().Аргумент(Функ("Элемент.Use = Истина"),1).Закончить();
АтдМассив.Отобрать(Ф1)"




"переменную "Элемент""
- в каком контексте занято?

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


"Цепочки соединённых функций (в стиле LINQ)"
не понял идею с отложенными вычислениями

Вы не знаете как устроен C# LINQ?
Отложенные вычисления - один из столпов современного функционального стиля программирования - реализация генераторов - когда алгоритм задаётся выражением - но он выполняется только, когда идёт вызов оператора фактического получения данных. То есть сначала строится дерево выражения - потом оно оптимизируется - потом по нему строится алгоритм выполнения, где ряд действий комбинируется, обычно чтобы минимизировать циклы по условно одинаковым выборкам, и только затеем исполняется.

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

Простите. После этого интерес к Вашей публикации резко упал. Без оценки производительности - это просто минное поле через которое идти то и не очень то хотелось!

В первом операторе в массив помещается коллекция строк верхнего уровня (типы метаданных: Справочники, Документы и т.д.), в следующей функции для каждой строки проставляется значение выбора Ложь, далее строки верхнего уровня преобразуются в массив строк второго уровня, далее происходит сброс в Ложь пометки выбора для уже этих строк. Далее функция Отобрать формирует массив строк, имя в которых совпадает из переданного массива ОбъектыМетаданных. Ну и наконец по отобранным строкам проставляется пометка выбора Истина.

Ну никак не пойму - зачем вы "Ложь" устанавливаете?

все что можно переиспользовать я стараюсь переиспользовать

Ещё одна ложка дёгтя. Вы хотели созддать красивый удобный API - или к одному неудобному, не полноценному и жутко не стабильному API (БСП) решили добавить ещё один такой же - и предложить хаотично ими пользоваться - выискивая где что реализовано или не реализовано? Нее - это не интересно никому!

"Функция "Сортировки" всё-таки должна быть возвращать новый Массив - не ломайте привычный шаблон"
ну это в идеальном мире, а на практике стандартно в JS например это мутирующая функция.

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

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

Не понял. У Вас в статье функция "Сортировать()" вызывается у "АТДМассива"

Префиксы не люблю.

Без них тяжело в 1С. Хаотичные имена это плохо. В общем имя общего модуля "Общий" мне категорически не нравится.

- Массив - это зарезервированное слово, нельзя :)

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

Функция Массив(Коллекция, Фикс=Ложь, Результат=неопределено, Позиция=0) экспорт
	Перечислитель = РаботаСКоллекциями_ОДП.ПолучитьПеречилитель(Коллекция);
	Если Перечислитель=неопределено Тогда
		Если Фикс Тогда
			возврат Новый ФиксированныйМассив(Новый Массив());
		Иначе
			возврат Новый Массив();
		КонецЕсли;
	КонецЕсли;
	Если Результат=неопределено Тогда
		Количество = РаботаСКоллекциями_ОДП.ПолучитьКоличество(Коллекция, Истина);
		Рез = Новый Массив(Количество);    
	Иначе
		Рез = Результат;
	КонецЕсли;
	Для каждого Элемент из Перечислитель Цикл
		Значение = РаботаСКоллекциями_ОДП.ПолучитьОдиночноеЗначение(Элемент, Коллекция);
		Рез[Позиция] = Значение;
		Позиция = Позиция + 1;

		Перечислитель = РаботаСКоллекциями_ОДП.ПолучитьПеречилитель(Элемент);
		Если Перечислитель <> неопределено Тогда
			Массив(Коллекция,, Рез, Позиция=0);
		КонецЕсли;
	КонецЦикла;
	
	Если Фикс Тогда
		возврат Новый ФиксированныйМассив(Рез);
	Иначе         
		возврат Рез;
	КонецЕсли;
КонецФункции
Показать


Функция находится в общем модуле "Массив" и вот так могут вызвать потом

М = Массив.Массив(СписокЗначений.Создать(1,2,3,4,5));
М2 = Новый Массив(5);



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

Простите - не ту ссылку вставил - вот этот комментарий посмотрите

ДопустимыеТипы = Новый ОписаниеТипов(Общий.АТДМассив()
.Положить(Тип("СправочникСсылка._ДемоНоменклатура"))
.Положить(ОбщегоНазначения.ОписаниеТипаСтрока(20)).Элементы);


Сначала подумал, что я что-то не знаю - попробовал во так

М2 = Новый Массив(5);
М2[0] = Тип("Дата");
М2[1] = ОбщийМодуль1.ОписаниеТипаСтрока(10);
М2[2] = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(20,ДопустимаяДлина.Фиксированная));
М2[3] = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10,0));
М2[4] = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(5,5));
оп = Новый ОписаниеТипов(М2);
типы = оп.Типы();
Показать


В типах был один тип - "Дата", так что добавление в массив типов значения типа "ОписаниеТипов" для создания нового "ОписаниеТипов" НЕ РАБОТАЕТ, увы :-(
Или у Вас там что-то хитрее - просто - если вы преобразуете вызовом так что в ".Элементы" у Вас "ОписаниеТипов" - то сработает. Но это вряд ли же так
5. kalyaka 726 08.07.21 13:18 Сейчас в теме
(4)
Идей, у меня, на эту тему много, например так
Вот бы Вы еще потратили время на проверку этих идей и выложили бы результаты в виде публикации :)
но уже понял, что клиентский контекст Вы не поддерживаете
поддерживаю, вы не внимательно читали мой предыдущий ответ.
Вы не знаете как устроен C# LINQ
знаю теоретический, практический я все-таки программирую на 1С. Про генераторы интересная тема, можно подумать.
Без оценки производительности - это просто минное поле
здесь я исхожу из того, что вопрос производительности всегда решается в конкретном контексте и ограничений, либо это вопрос связан с измерением количества операций и достижения результата за конечное их количество. Первое требует контекста, второе - зависит от конкретной реализации и уже не будет абстрактным.
Ну никак не пойму - зачем вы "Ложь" устанавливаете?
сбрасываю флаг выбора на форме.
Нее - это не интересно никому!
чего так сразу то за всех? :)
"Массив" - это не зарезервированное слово
ок, действительно можно. У меня где-то была ошибка и запомнилось, что нельзя. Ну и все-таки в текущем наименовании видно отличие от встроенного массива.
Простите - не ту ссылку вставил - вот этот комментарий посмотрите
ну это я видел. У меня везде Вычислить, кроме ДляКаждого - здесь я не придумал как это обойти, может вы подскажите? Хотя для именованных функций можно и Вычислить, а вот для произвольного кода - ничего не придумал. Может добавить ДляКаждогоВычислить для именованных, а для остальных оставить ДляКаждого?
".Элементы" у Вас "ОписаниеТипов" - то сработает. Но это вряд ли же так
именно так :)
11. Артано 713 09.07.21 16:39 Сейчас в теме
Вторая публикация с "супер крутым технологичным кодом, через функцию "Выполнить()". Да что за мода то такая вставлять костыли в 1с которые работают ОДНОЗНАЧНО хуже чем штатный код?

(1) С Darklight соглашусь частично. Концепция имеет право на жизнь, но это же просто откровенные костыли. Тут не то чтобы правильно подать, тут надо свою виртуальную машину делать надо, ну или хотя бы компилятор в байт-код, чтобы костылинг хотя бы по быстродействию не проседал. Делать код просто и абстрактно "красивым" считаю детской болезнью.
vano-ekt; oleganatolievich; +2 Ответить
12. AntonProgma 31 09.07.21 16:55 Сейчас в теме
(11) вызов любой функции замедляет работу 1с. Но для выполнения похожих действий функции все равно пишутся. Для упрощения кода программы.

Фирма 1с сама использует и Выполнить и Вычислить. Нет никакого табу на это. Костыли - это каждый раз писать чуть-чуть другой код через копипаст.
Darklight; +1 Ответить
13. Артано 713 09.07.21 17:10 Сейчас в теме
(12) У функций динамической компиляции произвольного кода есть очень узкая и определенная ниша. Здесь же костыль на их базе позиционируется как универсальное решение, что не есть правда.

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

Из последних - есть такое https://infostart.ru/public/1421272.
Если погуглить, то можно найти примеры классов из разряда мелких, но полезных улучшизмов. И нет там никакой "Выполнить", чего вы в неё уцепились, не пойму.
14. AntonProgma 31 09.07.21 17:14 Сейчас в теме
(13) а вы не могли бы очертить границы использования функции Выполнить в 1с?
15. Артано 713 09.07.21 17:16 Сейчас в теме
(14) Эмм, разве не очевидно? Упрощение переопределения для разовых вызовов кода, где время на компиляцию кода, будет не так заметно на фоне того, что именно будет выполнять скомпилированный код. Наиболее характерный и чистый пример это подсистема печати в БСП-шных конфигурациях
16. AntonProgma 31 09.07.21 17:19 Сейчас в теме
(15) то есть, ограничения только с производительностью связаны? Если она не критична, то выполнять код можно?
17. Артано 713 09.07.21 17:20 Сейчас в теме
(16) Не только, но это уже обсасывали не раз и есть в документации по платформе. Например нужно предусмотреть защиту от инъекций кода.
18. AntonProgma 31 09.07.21 17:26 Сейчас в теме
(17) спасибо. Тогда я все учёл)
19. Артано 713 09.07.21 17:28 Сейчас в теме
(18) Тогда ждём продолжения. Без шуток, слежу с интересом за развитием идеи.
22. kalyaka 726 09.07.21 22:07 Сейчас в теме
(17)
уже обсасывали не раз и есть в документации по платформе
Что ж, обратимся к документации. Единственная проблема с безопасностью может возникнуть, если код построен таким образом, что на клиенте формируется текст исполнения и передается на сервер для исполнения. Так действительно делать не нужно.
Если у вас есть другие кейсы с проблемой безопасности, приведите их пожалуйста.
21. kalyaka 726 09.07.21 21:58 Сейчас в теме
(13)
Из последних - есть такое https://infostart.ru/public/1421272
В публикации по ссылке вообще закрытый коммерческий код, как он работает - это еще вопрос.
Если погуглить, то можно найти примеры классов из разряда мелких, но полезных улучшизмов
Вообще речь не про "мелких, но полезных улучшизмов", а про концепцию абстрактного массива.
46. Артано 713 11.07.21 06:43 Сейчас в теме
(21)
В публикации по ссылке вообще закрытый коммерческий код, как он работает - это еще вопрос.

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

Концепция абстрактного массива есть и была уже давно. Здесь же поправлю - речь про реализацию на базе 1с. И вот именно реализация костыльная. К претензии, как и к самому факту её реализовать претензий нет. Но к самой реализации, где код итератора пишется через "Выполнить", ну извините нет.
Вот еще пример нашел из более старого, но более элегантного решения на тему
https://infostart.ru/public/865839
49. kalyaka 726 11.07.21 19:45 Сейчас в теме
(46) Действительно, интересная идея. Что-то типа делегата, который передается в абстрактный алгоритм и тогда не нужно использовать Выполнить. Однако здесь другая сторона медали - на каждый такой делегат потребуется создать собственную обработку, дать ей имя и добавить в конфигурацию. Т.е. на каждую комбинацию условия фильтра, предиката, функции сортировки потребуется собственная обработка реализующая конкретное поведение.

Что-то в этом есть, однако мне кажется пока не практичным. Может быть только для самых общих случаев.
54. AntonProgma 31 12.07.21 13:16 Сейчас в теме
(49) ну это же просто унификация перебора. Причём здесь анонимные функции, не известно. Но важно, что реализовано без Выполнить!
56. Darklight 27 14.07.21 11:39 Сейчас в теме
(13)Не совсем соглашусь, что очень узкая ниша. Типовой код 1С её как раз и используется как замену лямбда-функциям и анонимным функциям. А то что не так уж часто - ну они сами понимают, что костыли, но странно, что до сих пор в процедурном языке нет анонимных процедур, и ссылок на процедуры с типовой поддержкой! В турбо паскале 80-х годов даже были - а это был классический простой процедурный язык. Хм... ну ссылки точно были а анонимные функции - ну наверное позже появились!
Кстати, если забить на лямбды и анонимные функции - то применение "Выполнить/Вычислить/"ВыполнитьОповещение/ВыполнитьОбработку­Оповещения" только для вызова другой функции (т.е. по принципу делегирования вызова), размещённой в конфигурации или во внешней обработке - вполне себе нормальное использование - не шибко сгижающее проихводительность относительно простого вызова не локальной функции (т.е. с переключением контекста).
Анонимные и лямбда функции тоже можно было бы добавить - но тут уже для эффективности нужна компиляция - как статическая (т.е. нужен препроцессинг),так и возможна динамическая (путём генерации внешней обработки и её подключения к сеансу) - это всё конечно костыли - но что делать, если платформа не развивается, а мир не стоит на месте. Если всё это упаковать в крассивую библиотеку, которая будет это всё эффективно использовать - то это имеет права на жизнь, пусть и ограниченную.
Артано; AntonProgma; +2 Ответить
20. kalyaka 726 09.07.21 21:53 Сейчас в теме
(11)
ОДНОЗНАЧНО хуже чем штатный код
штатный код не поддерживает функциональную парадигму. Про "хуже" вы скорее всего имели в виду производительность? Тогда ответ ищите в (5), статья не про производительность
2. bulpi 185 07.07.21 14:01 Сейчас в теме
Интересно, забавно, практически бесполезно.
oleganatolievich; DoctorRoza; PowerBoy; DrAku1a; DJ_Codebase; Yashazz; Altavista.roman; zqzq; vano-ekt; Alex17; TMV; BigB; +12 Ответить
6. AntonProgma 31 08.07.21 21:35 Сейчас в теме
(2) Почему же бесполезно? Я так понял, автор придумал, где применить.
7. AntonProgma 31 08.07.21 21:52 Сейчас в теме
Не думал, что так скоро смогу сам критиковать решение с анонимными функциями. Очень рад это сделать!

1. Всё-таки, вычисляемые выражения являются скорее не функциями, а вставками кода. Простое занудство с моей стороны.
2. Сортировку лучше делать над массивами индексов значений, а не над массивами значений. Так должно тратиться меньше системных ресурсов при перестановках.
3. Подумываю объединить функцию filter и map в одну. В Питоне есть очень удобная конструкция [v + 1 for v in arr if v > 5] - очень часто нужна. Возможно, ту да же запихнуть sort, чтобы коллекция накапливалась уже отсортированная.
4. Модуль Общий не нужен.
23. kalyaka 726 09.07.21 22:13 Сейчас в теме
(7) 1. Ндя :)
2. Не знаю как это можно реализовать
3. Так это Преобразовать (reduce)!
4. Здесь он нужен для лаконичности. Сравните: АТДМассив = Обработки.АТДМассив.Создать(); или АТДМассив = Общий.АДТМассив();
28. AntonProgma 31 10.07.21 09:00 Сейчас в теме
(23)
2. У сортируемого массива есть индексы элементов.: 0, 1, 2. И эти индексы хранятся и переставляются во временном массиве, а сравнение идет по значениям, получаемым из сортируемого массива по индексу. То есть, в перестановках участвуют числа, которые являются ключом для получения значения.

3. Интересно. Я привык, что reduce возвращает одно значение (например, итого). И у вас используется Накопитель, видимо, для накопления результата. Я же думаю, не объединить ли map и filter в одну функцию с двумя входящими выражениями.

4. Мне интуитивно кажется, что API работы с абстрактными массивами должен включать и функцию Создать. Это по крайней мере легче ложится с в понятие модульности. АТДМассив = РаботаСМассивами.новыйАТДМассив(). Конечно, если нет какого-нибудь неочевидного клиент-серверного правила, запрещающего так делать.
8. sfaqer 09.07.21 01:53 Сейчас в теме
https://github.com/sfaqer/onec-fluent

Я просто оставлю это здесь
oleganatolievich; Артано; user1211160; nixel; +4 Ответить
24. kalyaka 726 09.07.21 22:15 Сейчас в теме
(8) это не на встроенном языке 1С. Не понятно для чего это здесь? Возможно имелось в виду сделать также на встроенном языке 1С?
27. sfaqer 10.07.21 03:31 Сейчас в теме
(24) ну т.е по ссылке репозиторий с выгруженной в файлы конфигурацией 1С, это не на встроенном языке?
29. kalyaka 726 10.07.21 09:40 Сейчас в теме
(27) извините, вы так молча оставили ссылку, что я подумал что вы подсунули мне известную ссылку fluent. Судя по истории коммитов мы с вами сделали похожие решения в разницу пару дней (ок, вы раньше :))
31. sfaqer 10.07.21 13:22 Сейчас в теме
(29) Ну и оно работает все же не только с массивом, но и с ТЗ/ДФК и т.д только мап пока нет, их надо отдельно подумать. Но в целом это и есть известный fluent только допиленный по местам чтоб работало в 1С)
33. kalyaka 726 10.07.21 13:47 Сейчас в теме
(31) ну с этим у меня тоже нет ограничений, главное чтобы коллекция поддерживала обход ДляКаждогоИз
34. sfaqer 10.07.21 14:11 Сейчас в теме
(33) ну тоже не совсем так, если например передано ТЗ и вызвана сортировка по умолчанию без предиката то он немного развалится
35. kalyaka 726 10.07.21 14:15 Сейчас в теме
(34) я думаю реализовать выбор предиката по умолчанию в зависимости от типа первого элемента. Если это структурный объект, то реализовать универсальную функцию Сравнить по полям объекта, по-умолчанию сделать по всем полям из 1-го объекта.

Либо добавить функцию СортироватьПо и там выбирать предикат по-умолчанию для структурных объектов.
37. sfaqer 10.07.21 15:13 Сейчас в теме
(35) ну вот во флюенте (что для оскрипта что для 1С, в целом без разницы апи одинаковый) сделано как раз СортироватьПо
30. kalyaka 726 10.07.21 09:47 Сейчас в теме
(8)
	#Если Клиент Тогда
		ПроцессорКоллекций = ПолучитьФорму("Обработка.ПроцессорКоллекций.Форма.Форма");
	#Иначе
		ПроцессорКоллекций = Обработки.ПроцессорКоллекций.Создать();
	#КонецЕсли
Классное решение! С ним текучий интерфейс доступен и на клиенте, замечательно!
32. sfaqer 10.07.21 13:23 Сейчас в теме
(30) Спасибо.) Да, создание формы это пожалуй единственный известный мне вариант создания собственного "класса" на клиенте
36. kalyaka 726 10.07.21 14:42 Сейчас в теме
(8)интересное решение с терминальным оператором и отложенным вычислением. Типа возможно вычисление и не понадобится, но конвейер будет продекларирован? Или это сделано с заделом на оптимизацию конвейерных вычислений?

Еще одно замечание по поводу предиката, у вас я так понял для вычисления предиката используется Выполнить, и соответственно для него требуется не выражение, а код. Ну наверное это более универсальное решение, однако у Выполнить больше ограничений, чем у Вычислить. Например Выполнить не доступен на веб-клиенте.
38. sfaqer 10.07.21 15:20 Сейчас в теме
(36) разделение на конвейерные/терминальные операторы в целом обусловлено тем с чего черпалось вдохновение, а именно StreamAPI в java.
Ну и сделано в частности для того что по итогу конвейер может выработать не всю коллекцию, например после Первые(2) все методы будут вызвано соответсвенно только по 2 раза.
Ну и есть небольшой задел на будущее в части разделение на барьерные/не барьерные операции, т.е если в конвеере не встретится например сортировка, то не зависимо от количества операций весь конвеер можно пройти за один обход массива (возмонжо даже не полный).
Сейчас для простоты каждый этап конвеера барьерный (т.е должен обработать всю пришедшую коллекцию внутри себя, перед передачей в следующий этап), в будущем поведение изменится.
Ну и под оптимизации, например часть конвеерных методов может быть проигнорирована, в случае если терминальный метод например Количество() то условную сортировку можно проигнорировать так как она не повлияет на результат.
Такие размышления
41. kalyaka 726 10.07.21 15:27 Сейчас в теме
(38)Замечательно! Приму на вооружение, спасибо за идею! :)
39. sfaqer 10.07.21 15:22 Сейчас в теме
(36) да, там Выполнить, сделано это в частности что бы на клиенте можно было принимать честный ОписаниеОповщения как предика, и апи при этом был одинаковый на сервере и на клиенте
40. kalyaka 726 10.07.21 15:26 Сейчас в теме
(39) вот этот момент тоже поясните, пожалуйста. Зачем потребовалось использовать ОписаниеОповещения?
42. sfaqer 10.07.21 15:33 Сейчас в теме
(40) ну предположим у меня на клиенте есть процедура, которую я бы хотел использовать в качестве предиката для сортировки например, я создаю нативное описание оповещения, и передаю его в качестве предиката в конвейерный метод сортировать, тогда при сортировке, пол капотом будет выполнено нативное ВыполнитьОписаниеОповщения(), что в итоге не приведен к вызову Выполнить/Вычислить, что с одной стороны не потребует дополнителных динамических компиляций, с другой стороны более безопасно.
43. kalyaka 726 10.07.21 15:41 Сейчас в теме
(42) Понятно! Есть конечно и плюсы, но и минусы :)

Диалог с вами получается самый продуктивный на форуме. Спасибо!
44. sfaqer 10.07.21 15:46 Сейчас в теме
(43) Ну, тут любое решение это компромис.)

Пожалуйста.)
9. Yashazz 4070 09.07.21 10:09 Сейчас в теме
После фразы "Список значений - узкоспециализированный тип под задачи преставления списков в интерфейсе." читать дальше не смог. Если автор в первых же строках несёт такую ахинею, то дальше читать как-то не хочется.
26. kalyaka 726 09.07.21 22:32 Сейчас в теме
(9)
несёт такую ахинею
По всей видимости для вас Список значений - это абстрактный список, типа массива? Список значений появился еще в 1С 77 и там мог быть одновременно и визуализирован и использовался в коде. В 1С 8 список стал составной частью расширения элемента формы и утратил свою прямую визуализацию как элемент, однако у него сохранились методы по работе с интерфейсом: ВыбратьЭлемент, ОтметитьЭлементы + Метод формы ПоказатьВыборИзМеню - все эти методы ориентированы на структуру данных: Значение, Картинка, Пометка, Представление - такая структура говорит о специализации.
45. Yashazz 4070 10.07.21 22:30 Сейчас в теме
(26) Азы вы знаете, вижу. Но вы несколько упускаете из виду, что интерфейсная ипостась списка значений - не единственная и далеко не главная его возможность. Кстати, напомню, в 7.7 он мог работать почти эквивалентно нынешним структуре/соответствию.
Список значений, например, можно использовать как связный список, причём с сортировкой по обоим элементам кортежа, да ещё и с использованием бинарных флагов, да ещё с возможностью цеплять двоичные данные. Смотрите шире, интерфейсом мир не ограничивается)
Сам факт, что 1С сделала отдельную сериализацию списков, как бы намекает, что не совсем интерфейсный это объект)
Артано; +1 Ответить
48. kalyaka 726 11.07.21 19:40 Сейчас в теме
(45)ок, не совсем узкоспециализированный :))
10. DrAku1a 1451 09.07.21 13:40 Сейчас в теме
Ничего принципиально нового данные алгоритмы не делают. С другой стороны, код, написанный в одну строку плохо читается и отлаживается.
25. kalyaka 726 09.07.21 22:19 Сейчас в теме
(10)
принципиально нового данные алгоритмы не делают
Согласен! Я здесь ничего и не придумывал и об этом прямо признался в статье.
С другой стороны, код, написанный в одну строку плохо читается и отлаживается.
Так не надо писать в одну строку. Или вы имеете в виду продолжение строки в текучем интерфейсе?
47. oleganatolievich 148 11.07.21 11:23 Сейчас в теме
Очередные костыли на "выполнить" и "вычислить".
Без реализации средствами платформы - неотлаживаемый, потенциально опасный код без бизнесовой необходимости. Просто потому что захотелось анонимные функции в 1С?
Пишите в телеграмм, @platform_suggestions, может быть и внедрят в платформу, раз 1С идет по пути JS.
На инфостарте это бесполезная публикация, на вас выльют ушат помоев про "выполнить", а в платформе ничего не изменится и под каждым постом какой-нибудь упорный пионер 1С будет со всеми спорить.
so-quest; +1 Ответить
50. kalyaka 726 11.07.21 19:53 Сейчас в теме
(47)
Очередные костыли
Похоже на заклинание :)
51. oleganatolievich 148 11.07.21 20:26 Сейчас в теме
52. AntonProgma 31 12.07.21 10:27 Сейчас в теме
53. AntonProgma 31 12.07.21 12:01 Сейчас в теме
(52) единственная ассоциация такой фразы: js это электропоезд, а 1с идет по его путям)
55. starik-2005 2388 13.07.21 16:05 Сейчас в теме
Хороша статья. Не совсем ясно, за что влепили минусы. Автор, пеши есчо!
Оставьте свое сообщение

См. также

Безопасная работа с транзакциями во встроенном языке Промо

Практика программирования v8 1cv8.cf Абонемент ($m)

Разбираемся с опасностями использования транзакций во встроенном языке 1С. Познаем ошибку "В данной транзакции уже происходили ошибки". Учимся защищаться от них.

1 стартмани

25.03.2019    44749    tormozit    58    

Пример создания документа с движениями в ERP 2.5.7

БСП (Библиотека стандартных подсистем) Практика программирования v8 ERP2 Россия УУ Абонемент ($m)

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

1 стартмани

10.08.2021    1742    maraty    10    

Семеро одного не ждут? Асинхронное исследование асинхронности

Практика программирования Работа с интерфейсом v8 1cv8.cf Абонемент ($m)

Все уже, наверное, знают о появлении в новых версиях платформы асинхронных функций и конструкций Асинх/Ждать. Многие, возможно, уже их используют. Но что будет, если создать свои асинхронные функции, запустить и не дожидаться окончания их выполнения? Неужели можно запустить несколько процессов параллельно?

1 стартмани

08.06.2021    5255    Alxby    45    

Динамическая расшифровка СКД (на примере отчета)

Практика программирования v8 v8::СКД 1cv8.cf Абонемент ($m)

Предлагаю Вашему неподкупному вниманию вариант более-менее унифицированной реализации динамически формирующейся расшифровки СКД на примере простейшего отчета для конфигурации УТ 11.

1 стартмани

08.12.2020    1476    mr_sav    2    

Как выполнить отчет на СКД через COM и получить данные отчета? Промо

Практика программирования v8 УПП1 Россия Абонемент ($m)

Для чего это нужно. Например, нужно в одной базе получить какой-либо показатель из другой базы. Этот показатель вычисляется в каком-либо сложном отчете, который написан на СКД. Можно, конечно, "скопипастить" текст запроса из другой базы, немного подправить его и выполнять в том же COM подключении. Но с этим теряется гибкость: если отчет изменился, то нужно помнить о том, что где-то есть его "немного модифицированная" копия. В статье будет рассмотрен пример получения данных из базы ЗУП.

2 стартмани

08.05.2018    31184    wowik    3    

СКД: все, что вы хотели знать о подмене схемы компоновки данных в отчетах и обработках

Практика программирования v8 v8::СКД 1cv8.cf Абонемент ($m)

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

1 стартмани

07.12.2020    4902    user1502278    18    

Cбор и анализ ошибок при помощи Sentry, или как упростить жизнь себе и пользователям

Практика программирования Интеграция v8 Абонемент ($m)

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

1 стартмани

09.10.2020    7072    hexhoc    12    

Программная корректировка при выводе отчета СКД

Практика программирования v8 v8::СКД 1cv8.cf Абонемент ($m)

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

1 стартмани

08.10.2020    10387    dabu-dabu    16    

Как нарисовать граф на 1С Промо

Практика программирования v8 Абонемент ($m)

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

1 стартмани

09.08.2013    73305    ildarovich    117    

Загрузка, скачивание, удаление файлов с помощью НачатьПомещениеФайлаНаСервер() и НачатьПолучениеФайлаССервера()

Практика программирования v8 1cv8.cf Абонемент ($m)

В платформе 8.3.15 появились новые методы НачатьПомещениеФайлаНаСервер() и НачатьПолучениеФайлаССервера(). В данной статье рассмотрено готовое решение проверенное и прекрасно работающее на тонком и веб-клиенте.

1 стартмани

25.07.2020    11112    Flashill    15    

Универсальная печатная форма Приказа/Договора с возможностью настройки макета в пользовательском режиме

Практика программирования Универсальные печатные формы v8 1cv8.cf Абонемент ($m)

В данной статье я опишу реализацию универсальной (в кавычках) печати Приказа (Договора или чего пожелаете) с возможностью настройки выводимого текста с параметрами из пользовательского режима

1 стартмани

24.06.2020    2328    BuriyLesha    0    

Методика обновления формы объекта данных при изменении объекта

Практика программирования v8 v8::УФ 1cv8.cf Абонемент ($m)

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

1 стартмани

09.03.2020    19480    tormozit    16    

Простой способ индексирования интервалов Промо

Практика программирования v8 Абонемент ($m)

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

1 стартмани

28.09.2016    41854    ildarovich    22    

Отправка уведомлений с помощью командной строки, Оповещения с сервера на клиент с помощью командной строки

Практика программирования v8 1cv8.cf Россия Абонемент ($m)

Отправка уведомлений с помощью команды командной строки msg. Оповестить пользователей из серверного модуля или регламентного задания, с помощью командной строки msg.

1 стартмани

05.03.2020    7983    user5300    3    

Вывод сообщений в HTML поле средствами 1С

Практика программирования v8 v8::УФ Абонемент ($m)

Пример использования вывода большого количества сообщений в поле HTML. С возможностью открывать ссылочные объекты и создавать новые объекты передавая параметры прямо из HTML поля. Протестировано на релизах 8.3.12 и 8.3.15+

2 стартмани

31.01.2020    9930    burni4    16    

Краткое руководство по внесению изменений в конфигурацию

Практика программирования v8 1cv8.cf Абонемент ($m)

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

1 стартмани

13.01.2020    22418    sapervodichka    41    

Бесплатная проверка контрагентов в ФНС (общий модуль с алгоритмом). На примере выводим статус в список справочника контрагентов Промо

Практика программирования v8 1cv8.cf Абонемент ($m)

Если вам интересно проверить контрагенте в ФНС, вам поможет данная публикация. Весь алгоритм работы строится на основе данных, полученных с сервиса http://npchk.nalog.ru совершенно бесплатно.

1 стартмани

01.02.2018    38077    rpgshnik    53    

Универсальные функции: разложение произвольной строки адреса в структуру

Практика программирования Универсальные функции v8 1cv8.cf Абонемент ($m)

Процедуры и функции раскладывают произвольную строку адрес в структуру по ключевым словам.

1 стартмани

30.12.2019    5818    vik070777    10    

"Живые" картинки со Snap.SVG

Практика программирования WEB Работа с интерфейсом v8 Абонемент ($m)

В статье рассмотрен пример использования http-сервисов для визуализации данных

1 стартмани

24.10.2019    15051    blackhole321    7    

RLS - дубли условий в запросах к СУБД

Практика программирования Роли и права v8 v8::Права 1cv8.cf Абонемент ($m)

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

1 стартмани

07.10.2019    9906    geron4    4    

БСП: Дополнительная обработка (Регламенты), примеры от простого к сложному Промо

Практика программирования БСП (Библиотека стандартных подсистем) v8 1cv8.cf Абонемент ($m)

Очень много попадается странных решений, которые можно решить через БСП:Дополнительные отчеты и обработки. Я бы вообще БСП из-за этой подсистемы переименовал в «Большое Спасибо Программистам». Поработаем с подсистемой в части написания регламентных заданий.

1 стартмани

10.05.2018    53477    dsdred    46    

Полное копирование одной формы в другую

Практика программирования Универсальные обработки Работа с интерфейсом v8 1cv8.cf Абонемент ($m)

Однажды я столкнулся с необходимостью открыть форму ЛЮБОГО документа с определенными изменениями, не зависящими от структуры объекта (например, заблокировать все кнопки). В интернете решения я не нашел. Обычно на форумах на запросы подобного рода отвечают чем-то вроде "покажи первоначальную задачу, а не спрашивай как реализовать то, что ты придумал". Тем не менее, мне стало интересно, как это можно сделать.

1 стартмани

03.10.2019    7811    nekit_rdx    25    

Многопоточная обработка данных на примере перепроведения документов

Обработка документов Практика программирования v8 ERP2 УТ11 КА2 Абонемент ($m)

Дальнейшее развитие темы фоновой обработки данных - проведение документов в потоках. Настройка параметров и запуск основного процесса (менеджера потоков). Разбивка документов для проведения на не связанные друг с другом наборы и запуск дополнительных фоновых заданий для отдельных потоков. Отслеживание выполнения каждого потока в родительском сеансе.

1 стартмани

17.09.2019    12602    ids79    46    

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

Документооборот и делопроизводство Практика программирования v8 ДО УУ Абонемент ($m)

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

1 стартмани

15.09.2019    8665    pavelpribytkin96    8    

Некоторая работа с данными через COM Промо

Практика программирования v8 Абонемент ($m)

В статье приведены примеры работы с Платформой 8.X через COM (точнее, через объект COMConnector). Примеры кода были использованы при реализации прикладных задач в процессе трудовой деятельности.

2 стартмани

05.12.2012    59845    wowik    32    

Описание формата внутреннего представления данных 1С в контексте обмена данными

Практика программирования Внешние источники данных v8 v8::УФ 1cv8.cf Абонемент ($m)

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

1 стартмани

06.09.2019    21629    Dementor    31    

Удобный просмотр результата запроса с большим количеством временных таблиц

Практика программирования v8 Абонемент ($m)

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

1 стартмани

27.08.2019    12743    ids79    22    

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

Практика программирования v8 1cv8.cf Абонемент ($m)

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

2 стартмани

24.08.2019    16700    BenGunn    22    

Работа со схемой запроса Промо

Инструментарий разработчика Практика программирования v8 v8::Запросы Абонемент ($m)

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

1 стартмани

24.04.2018    51645    kalyaka    41    

Изменяющееся контекстное меню в 1С 8.3

Практика программирования Работа с интерфейсом Разработка v8 v8::УФ Абонемент ($m)

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

1 стартмани

06.08.2019    22048    signum2009    16    

Процедура ПриКомпоновкеРезультата

Практика программирования v8 1cv8.cf Абонемент ($m)

Коллекция кода

1 стартмани

26.07.2019    57654    vasilev2015    66    

10 способов получить модуль числа (а может, и больше)

Практика программирования Разработка v8 1cv8.cf Абонемент ($m)

Пишем функцию вычисления модуля числа. Сколько способов существует? Давайте посчитаем!

1 стартмани

11.07.2019    13932    sam441    32    

Многопоточность. Универсальный «Менеджер потоков» (фреймворк) с отслеживанием зависимости объектов Промо

Практика программирования Математика и алгоритмы Универсальные функции Производительность и оптимизация (HighLoad) v8 1cv8.cf Россия Абонемент ($m)

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

26.05.2017    51310    DarkAn    86    

Ловец дедлоков СУБД

Производительность и оптимизация (HighLoad) Практика программирования ЦУП v8 Россия Абонемент ($m)

Анализ простейшего дедлока СУБД в рабочей базе с использованием ЦУП (центра управления производительностью) и profiler MS SQL (Microsoft SQL Server). Эта статья будет полезна людям, изучающим вопросы оптимизации работы 1С, или тем, у кого возникают дедлоки в рабочей базе. UPD 09.07.2019 добавлено воспроизведение блокировки в случае установки управляемой блокировки перед чтением набора записей регистра сведений. UPD 10.07.2019 добавлена тестовая база с примером.

1 стартмани

08.07.2019    12567    azazana    80    

Мониторинг производительности и искусственный интеллект

Производительность и оптимизация (HighLoad) Практика программирования Искусственный интеллект (AI) v8 Абонемент ($m)

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

1 стартмани

01.07.2019    10264    ivanov660    28    

"Убер на складе": динамический расчет маршрутов с учетом реальных расстояний

Учет ТМЦ Практика программирования Учет ТМЦ v8 УУ Абонемент ($m)

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

3 стартмани

24.06.2019    19432    informa1555    17    

Агрегатное суммирование строк в запросе – сложно, но не невозможно Промо

Математика и алгоритмы v8 Абонемент ($m)

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

1 стартмани

09.09.2013    84312    ildarovich    57    

1С:Ассемблер. Немного летнего веселья!

Практика программирования Разработка v8 1cv8.cf Абонемент ($m)

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

1 стартмани

21.06.2019    33828    Evil Beaver    145    

Простые примеры сложных отчетов на СКД

Практика программирования v8 v8::СКД 1cv8.cf Абонемент ($m)

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

1 стартмани

12.06.2019    36388    Hatson    32    

Создание внешней печатной формы в формате документа Word

Практика программирования Разработка v8 1cv8.cf Абонемент ($m)

В статье написано, как создать внешнюю печатную форму (для конфигураций с БСП) в формате Word.

1 стартмани

17.05.2019    23544    ВикторП    22    

Новый запрос и новая таблица значений как функции Промо

Практика программирования v8 Абонемент ($m)

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

1 стартмани

27.11.2012    46345    ildarovich    49    

Поле адреса в своем справочнике на примере 1С:Бухгалтерия 3

Практика программирования Разработка v8 v8::БУ БП3.0 Россия Абонемент ($m)

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

1 стартмани

17.05.2019    8176    vasilievil    5    

Пример настройки шаблонов и реализации печати отчетов в документ MS Word используя функциональную часть "Библиотеки Стандартных Подсистем 1С" (БСП)

Практика программирования Разработка v8 Россия Абонемент ($m)

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

1 стартмани

23.04.2019    8698    olegpkc    11    

Ops средствами 1С:Предприятие

Практика программирования Разработка v8 1cv8.cf Абонемент ($m)

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

1 стартмани

23.04.2019    18573    blackhole321    28    

Уровни, глубина, прародители, циклы и аналоги запросом Промо

Практика программирования v8 1cv8.cf Абонемент ($m)

В продолжение публикации «Транзитивное замыкание запросом» [http://infostart.ru/public/158512/] добавлены другие варианты использования того же приема. Приведены запросы для быстрого определения уровней всех элементов справочника, максимальной глубины справочника, прародителей произвольных элементов справочника, запрос для быстрого определения циклов (на примере справочника спецификаций «1С:Управление производственным предприятием») и определения множеств аналогов номенклатуры (также на примере конфигурации «1С:Управление производственным предприятием»).

1 стартмани

13.11.2012    119766    ildarovich    102    

1C + Python + Django Rest Framework + Vue.js. Опыт несложной full-stack разработки

Практика программирования Внешние источники данных Обмен через XML WEB Разработка v8 1cv8.cf Абонемент ($m)

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

1 стартмани

22.04.2019    40610    riposte    68    

Вывод вариантов СКД в таблицы на управляемой форме

Практика программирования Работа с интерфейсом v8 v8::УФ v8::СКД 1cv8.cf Абонемент ($m)

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

05.04.2019    13127    artkor    1    

[EnterpriseData] Антисвертка характеристик номенклатуры при выгрузке в Бухгалтерию

Практика программирования Перенос данных из 1C8 в 1C8 Разработка v8 v8::ПВХ КД УНФ БП3.0 Россия БУ Абонемент ($m)

Рассмотрена выгрузка каждой пары значений Номенклатура - Характерстика из УНФ 1.6 в отдельную номенклатуру в Бухгалтерию 3.0 путём доработки правил обмена в формате EnterpriseData.

1 стартмани

27.03.2019    5920    nforce    6    

Неоплаченные долги при распределении оплаты по правилу ФИФО одним запросом и намного быстрее, чем Вы думали Промо

Практика программирования Дебиторская и кредиторская задолженность Дебиторская и кредиторская задолженность v8 v8::СКД КА1 УТ10 УПП1 УУ Абонемент ($m)

Предлагается метод для быстрого нахождения неоплаченных долгов при распределении оплаты по правилу ФИФО, основанный на дихотомии. Описывается реализация метода в виде достаточно простого запроса, решающего за линейное время указанную задачу, считавшуюся ранее существенно более трудоемкой. Приводятся примеры использования запроса в отчетах на СКД для конфигураций УТ, КА, УПП.

1 стартмани

28.02.2014    70896    ildarovich    131    

Интеграция 1С и SharePoint

Практика программирования Разработка v8 УНФ ДО ERP2 БП3.0 УТ11 УХ КА2 Россия Абонемент ($m)

Заказчики поставили задачу автоматизации согласования заявок на оплату в программе 1С:Бухгалтерия предприятия 3.0. Согласно ТЗ, данные должны подтягиваться из действующей электронной системы документаоборота на MS SharePoint (в дальнейшем СЭД MS SP).

1 стартмани

22.03.2019    7025    -I-    5    

Пример использования СКД и данных расшифровки на мобильной платформе

Практика программирования Разработка v8 v8::Mobile v8::СКД 1cv8.cf Россия Абонемент ($m)

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

1 стартмани

12.03.2019    6181    majoram    0    

Программное создание реквизита управляемой формы с помощью механизма расширений

Практика программирования Разработка v8 v8::УФ 1cv8.cf Абонемент ($m)

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

1 стартмани

12.03.2019    54106    ni_cola    34