Неочевидные нюансы записи управляемой формы

21.05.21

Разработка - Механизмы платформы 1С

Разберем несколько нюансов записи управляемой формы.

Содержание

 

Предисловие ^

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

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

 

В каждой форме, у которой основным реквизитом указан редактируемый объект базы данных, есть метод "Записать()"

 

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

 

 

Это самое универсальное описание метода. Но в разных типах данных появляются свои "предопределенные" значения в структуре ПараметрыЗаписи. 

Больше всего для нашего изучения подойдет документ:

 

 

Для экспериментов в базе-пустышке создадим ТестовыйДокумент.

Файловая или серверная - не важно. Описываемые нюансы работают и там, и там. 

 

 

 

Должна вернуть признак успеха. Но не обязана ^

 

Одно из отличий методов "Записать" формы и самого объекта заключается в этом:

Да, метод формы - это функция. Которая возвращает признак успеха записи. Но так ли это? Как показала практика, не всегда стоит доверять справке. 

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

А может нам просто нужно после какого-то действия сохранить данные формы? Вполне обычная практика.

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

 

 

В обработчике кнопки простой код:

&НаКлиенте
Процедура ЗаписатьПрограммно(Команда)
	
	УдалосьЗаписать = Записать();
	Если УдалосьЗаписать Тогда
		ТекстПредупреждения = "Ура, удалось записать!";
	Иначе
		ТекстПредупреждения = "Жаль, но не вышло!";
	КонецЕсли;
	
	ПоказатьПредупреждение(, ТекстПредупреждения);
	
КонецПроцедуры

 

Если записать форму удалось, то метод должен вернуть Истина. Проверяем эту теорию:

 

 

Прекрасно! А теперь попробуем сделать что-то, что не даст документу записаться. Например, очистим обязательный реквизит "Дата".

 

 

Упс... Мы такого в коде не писали. Нажмём "Подробно":

 

 

Что произошло? Для 1С это выглядит как обычное исключение метода. Как ошибка в коде. Как если бы метод Записать() вызывал исключение. 

Но ведь в справке описано иначе:

 

 

Ещё раз. Метод формы Записать() должен вернуть Истина, если записать удалось. Это мы проверили - всё работает. Но также метод должен вернуть Ложь в противном случае.

 

 

Давайте попробуем другую ситуацию. В модуле объекта самого документа добавим процедуру ПередЗаписью и установим в ней отказ. 

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
	
	Отказ = Истина;
	
КонецПроцедуры

Проверим, как поведёт себя метод в данном случае. 

 

 

Метод опять не вернул Ложь. А просто выдал ошибку, словно это исключение в коде. 

Более того. Если зайти в журнал регистрации, то можно увидеть эти ошибки:

 

 

Каждая такая "ошибка" фиксируется в журнале регистрации

То есть, если разработчик, опираясь на описание метода платформы, не оборачивает Записать() в Попытка\Исключение, то отказы в ПередЗаписью() будут фиксироваться в ЖР. И засорять его бессмысленными ошибками. Почему бессмысленными? Потому что чаще всего это будет незаполненность какого-то обязательного реквизита, или какой-нибудь отказ в обработчике объекта. Это всё обычные штатные ситуации, которые не нужны администраторам. Это просто ошибки, которые выводятся пользователю, чтобы он мог поправить свой документ.

Неужели описанная функция возвращает только Истина, а при неудаче всегда падает в ошибку?

А вот и нет! Всё ещё интереснее =)

Я провёл эксперименты и составил табличку. Что будет, если присвоить Отказ = Истина в одном из методов.
 

Поведение метода Форма.Записать() при отказе в событии

Модуль Событие Поведение
МодульОбъекта  ОбработкаПроверкиЗаполнения Возвращает Ложь
МодульОбъекта ПередЗаписью Вызывает исключение
МодульОбъекта ПриЗаписи Вызывает исключение
МодульОбъекта ОбработкаПроведения Вызывает исключение
МодульФормы ОбработкаПроверкиЗаполненияНаСервере  Возвращает Ложь
МодульФормы ПередЗаписью Возвращает Ложь
МодульФормы ПередЗаписьюНаСервере Возвращает Ложь
МодульФормы ПриЗаписиНаСервере Возвращает Ложь

 

Какие выводы? 

  • Метод возвращает Ложь, если сделать отказ в любом из событии формы.
  • Но при отказе в событиях объекта - падает в исключение.
  • Но если это событие объекта ОбработкаПроверкиЗаполнения(), то тоже вернет Ложь
  • Но если отказ происходит самой платформой, то будет вызвано исключение. 

Что такое "отказ самой платформой"? Это, как мы приводили пример выше, платформенная проверка заполнения реквизита. Или, например, попытка провести документ, который помечен на удаление. Или попытка изменить документ, который уже кто-то поменял ранее, пока пользователь держал форму открытой.

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

Но все ответы сводились примерно к этому:

Если подвести итоги ответа, то позиция 1С такая: "это нештатная ситуация". 

В данном случае "нештатной" считается:

  1. Установка Отказ = Истина в событиях модуля объекта (кроме ОбработкаПроверкиЗаполнения)
  2. Неуказанный пользователем обязательный реквизит
  3. Попытка пользователем провести помеченный на удаление документ
  4. Попытка изменить документ, который уже поменял другой пользователь
  5. ???


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

 

 

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

Все это значит, что на возвращаемое значение стоит опираться только если Записать() обернуть в попытку. В идеале нужно хотя бы в примечании справки описать возможность возникновения исключения. Но поддержка 1С, к сожалению, отказалась добавлять примечание в справку 😣 Поэтому, остается надеяться, что программисты будут читать эту статью 😅

Для своих нужд я использую небольшой метод в общем модуле:

// Записывает объект формы. Возвращает признак успеха. 
// Нужен для обхода недокументированного поведения платформы.
//  В СП описано, что метод формы Записать() возвращает признак успеха. 
//  Истина - успешно записан; Ложь - в противном случае.
//  Но это происходит не во всех случаях.
//  Подробнее: //infostart.ru/public/1396380/?ref=1159
//
// Параметры:
//  Форма - ФормаКлиентскогоПриложения - Форма, объект которой нужно записать
//  ПараметрыЗаписи  - Структура - ПараметрыЗаписи метода Записать() формы
//  СообщитьПриИсключении - булево - нужно ли сообщать ОписаниеОшибки() при возникновении исключения
//
// Возвращаемое значение:
//   Булево   - Истина - успешно записан; Ложь - в противном случае.
//
Функция ЗаписатьФорму(Форма, ПараметрыЗаписи, СообщитьПриИсключении = Истина) Экспорт
	
	Попытка
		ЗаписанУспешно = Форма.Записать(ПараметрыЗаписи);
	Исключение
	    ЗаписанУспешно = Ложь;
		Если СообщитьПриИсключении Тогда
			Сообщить(ОписаниеОшибки());
		КонецЕсли;
	КонецПопытки;
	
	Возврат ЗаписанУспешно;
	
КонецФункции

 

 

ПараметрыЗаписи ≠ ДополнительныеСвойства ^


Когда появляется задача записать объект с передачей доп.свойств, самым логичным кажется, что для этого достаточно просто передать в метод эти самые доп.свойства. Например:

ДополнительныеСвойства = Новый Структура;
ДополнительныеСвойства.Вставить("МоеСвойство", Истина);
Записать(ДополнительныеСвойства);

Но, естественно, это не так. Ведь ПараметрыЗаписи - это не ДополнительныеСвойства. Но как передать дополнительные свойства объекта в метод формы Записать()? 

Платформа сама не предоставляет такой возможности, но мы можем это сделать сами в методе ПередЗаписьюНаСервере().

Например:

&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
	
	Для Каждого КлючИЗначение Из ПараметрыЗаписи Цикл
	    ТекущийОбъект.ДополнительныеСвойства.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение);
	КонецЦикла;
	
КонецПроцедуры

 

 

Нельзя просто так передать РежимЗаписи ^

 

 

Что если мы хотим программно провести форму документа? Для этого нужно просто передать РежимЗаписи:

&НаКлиенте
Процедура ЗаписатьПрограммно(Команда)
	
	ПараметрыЗаписи = Новый Структура;
	ПараметрыЗаписи.Вставить("РежимЗаписи", РежимЗаписиДокумента.Проведение);
	Записать(ПараметрыЗаписи);
	
КонецПроцедуры

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

Не все так просто. Дело в том, что у формы документа есть "особенность". 

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

 

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

 

Режим записи подменился. Мы передали методу "Запись", а платформа заменила его на "Проведение". 

Почему так? Всему виной свойство формы "ПриЗаписиПерепроводить

 

 

Эта галочка отвечает за то, будет ли документ перепроводиться при нажатии на кнопку "Запись".

Про это поведение самой кнопки знают многие. Стандартно, если документ проведен, то нажатие кнопки "Записать" будет приводить к повторному проведению. 

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

И вполне логичным было бы это поведение, происходи оно только в том случае, когда разработчик НЕ передавал напрямую РежимЗаписи. Но, по факту, даже если программист настаивает на режиме записи "Запись", то платформа проигнорирует его требование. И сама подменит режим записи на "Проведение".

Можно ли как-то это обойти? Очередным костылем. 

 

&НаКлиенте
Процедура ЗаписатьПрограммно(Команда)
	
	ЗаписатьПрограммноНаСервере();
	
КонецПроцедуры

Процедура ЗаписатьПрограммноНаСервере()

	ПриЗаписиПерепроводить = Ложь;
	
	ПараметрыЗаписи = Новый Структура;
	ПараметрыЗаписи.Вставить("РежимЗаписи", РежимЗаписиДокумента.Запись);
	Попытка
		Записать(ПараметрыЗаписи);
	Исключение
		Сообщить(ОписаниеОшибки());
	КонецПопытки;
	
	ПриЗаписиПерепроводить = Истина;

КонецПроцедуры

 

Здесь мы сначала отключаем свойство ПриЗаписиПерепроводить. А потом (после самой попытки записи) включаем снова.

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

Как думаете, есть более "правильный" способ? Напишите об этом в комментариях.

А пока я сразу скажу "минус" данного подхода. Дело в том, что вызов метода Форма.Записать() на сервере тоже имеет свои "нюансы"...

 

При вызове на сервере пропускаются клиентские события ^

 

Из самого заголовка можно понять смысл данного "нюанса". 

Дело в том, что если мы попытаемся вызвать метод формы Записать() на сервере, то платформа не будет выполнять клиентские события.

Давайте проверим. Для эксперимента я реализовал такой код:


&НаКлиенте
Процедура ЗаписатьНаКлиенте(Команда)
	Записать();
КонецПроцедуры

&НаКлиенте
Процедура ЗаписатьНаСервере(Команда)
	ЗаписатьНаСервереНаСервере();
КонецПроцедуры

&НаСервере
Процедура ЗаписатьНаСервереНаСервере()	
	Записать();
КонецПроцедуры


&НаСервере
Процедура ОбработкаПроверкиЗаполненияНаСервере(Отказ, ПроверяемыеРеквизиты)
	Сообщить("ОбработкаПроверкиЗаполненияНаСервере");
КонецПроцедуры

&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
	 Сообщить("ПередЗаписью");
КонецПроцедуры

&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
	Сообщить("ПередЗаписьюНаСервере");
КонецПроцедуры

&НаСервере
Процедура ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
	Сообщить("ПриЗаписиНаСервере");
КонецПроцедуры

&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
	Сообщить("ПослеЗаписиНаСервере");
КонецПроцедуры

&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
	Сообщить("ПослеЗаписи");
КонецПроцедуры

 

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

 

Записывать будем проведенный документ, чтобы отработали все события.

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

События формы при вызове метода Записать()

Событие НаКлиенте НаСервере
ПередЗаписью +
ОбработкаПроверкиЗаполненияНаСервере    + +
ПередЗаписьюНаСервере + +
ПриЗаписиНаСервере + +
ПослеЗаписиНаСервере + +
ПослеЗаписи +

 

Как видим, в управляемой форме есть два клиентских события, которые задействованы в записи данных. ПередЗаписью() и ПослеЗаписи(). Эти события отрабатываться не будут, если метод формы Записать() вызван на сервере. 

С одной стороны это логично. Ведь мы находимся на сервере и не можем "вызвать" клиент.

Но с другой - неочевидно. Можно, не подумав об этом последствии, вызывать метод Записать() на сервере, а потом удивляться, почему часть кода не выполняется. 

Такое бы стоило отражать в примечании к методу. Как думаете? 😁

 

Урезанная ОбработкаПроверкиЗаполненияНаСервере() ^

 

На этот раз "особенность" касается не только программной записи. 

Для начала прочтем справку:

 

ФормаКлиентскогоПриложения (ClientApplicationForm)

ОбработкаПроверкиЗаполненияНаСервере (FillCheckProcessingAtServer)

Синтаксис:

ОбработкаПроверкиЗаполненияНаСервере(<Отказ>, <ПроверяемыеРеквизиты>)

Параметры:

<Отказ>

Тип: Булево.
Признак отказа от записи. Если в теле процедуры-обработчика установить данному параметру значение Истина, то запись выполнена не будет.
Значение по умолчанию: Ложь.

<ПроверяемыеРеквизиты>

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

Описание:

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

 

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

Давайте добавим нашему документу обязательный реквизит Сумма.

 

И установим точку останова на ОбработкаПроверкиЗаполненияНаСервере()

 

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

Мы НЕ можем в форме документа отменить проверку реквизита Сумма.

Можно только отменить всю проверку целиком. Но в таком случае метод объекта ОбработкаПроверкиЗаполнения() просто вообще не выполнится. А ведь там может быть какая-то очень важная логика!

Неужели технически невозможно никак отменить проверку реквизита объекта из формы? Можно. Но никогда так не делайте! 

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

 

Да, Вы, наверное, уже догадались. В данном куске кода разработчик отменяет штатный вызов метода объекта ОбработкаПроверкиЗаполнения(), но далее сам же и вызывает его с передачей доп.параметра.

В самом же модулей объекта происходит такое:

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

 

 

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

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

То есть, если у нас на форме есть реквизит (не объекта, а именно формы), то мы можем сделать его "обязательным". Или наоборот разрешить его не указывать. Но только реквизиты самой формы.

 

 

Событие После_УСПЕШНОЙ_ЗаписиНаСервере() ^

Да, речь идёт про событие формы ПослеЗаписиНаСервере(). Оно уже вне транзакции. В нём нельзя отменить запись, потому что она уже была завершена. Очень удобное событие, которое позволяет как-то донастроить форму сразу после записи объекта.

И удобство этого обработчика ещё в том, что он имеет доступ к записываемому объекту:

 

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

Но, к сожалению, разработчики забывают, что это событие срабатывает только после УСПЕШНОЙ записи. То есть, если в одном из событий был установлен Отказ, то обработчик выполняться не будет. И код, который нужен для обновления формы, не выполнится. И данные из самого объекта получить не удастся. 

Об этом можно догадаться по описанию:

Описание: Вызывается после записи объекта на сервере и после завершения транзакции.

Используя слово "завершения", авторы подразумевали, что транзакция может быть завершена только успешно. А при ошибке - она отменена. 

Но всё равно, встречаются такие решения, когда разработчики, не поняв этой особенности, думают, что событие отработает всё равно.

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

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

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

 

 

Понравилась статья? ^

Информация в ней будет пополняться. Поставьте лайк плюс, оставьте комментарий. 

И переходите к другим публикациям:

 

Управляемые формы записать программно ошибка исключение ОбработкаПроверкиЗаполненияНаСервере ПослеЗаписи лайфхак заметка нюанс баг

См. также

Сервисы интеграции без Шины и интеграции

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

Пример использования «Сервисов интеграции» без подключения к Шине и без обменов.

13.03.2024    3420    dsdred    16    

65

Как готовить и есть массивы

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

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

24.01.2024    7974    YA_418728146    25    

69

Планы обмена VS История данных

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

Вы все еще регистрируете изменения только на Планах обмена и Регистрах сведений?

11.12.2023    8197    dsdred    44    

120

1С-ная магия

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

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    20397    SeiOkami    46    

125

Дефрагментация и реиндексация после перехода на платформу 8.3.22

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

Начиная с версии платформы 8.3.22 1С снимает стандартные блокировки БД на уровне страниц. Делаем рабочий скрипт, как раньше.

14.09.2023    14343    human_new    27    

77

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

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

28.08.2023    10742    YA_418728146    7    

149

Внешние компоненты Native API на языке Rust - Просто!

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

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

20.08.2023    7152    sebekerga    54    

101
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. ilyaleontyev 02.04.21 08:33 Сейчас в теме
Отличная работа, я считаю.
user717534; JasonT; Artem-B; dabu-dabu; vulli; Wishich; DrAku1a; Sashares; Jeka44; Darklight; ipoloskov; CyberCerber; portwein; artbear; v25i85; SeiOkami; frkbvfnjh; +17 Ответить
2. frkbvfnjh 798 02.04.21 08:39 Сейчас в теме
Да я тоже попался на проверку заполнения. Даже ветку форума делал на Инфостарте. И мне несколько раз пытались объяснить, что обработка проверки заполнения у каждой стороны своя. И только раз на третий я понял, как это работает, и как то сразу отпало желание пользоваться этим замечательным механизмом, каковым он казался по началу.
Но вот кто мне объяснит, почему при переходе на управляемое приложение разработчики решили что в метод Записать() параметры теперь нужно передавать структурой? Я серьёзно не понимаю, что мешало оставить всё как раньше или какие преимущества это дает? Если это позволяет передать куда-то какие-то дополнительные данные, то почему просто не добавить дополнительный, третий, не обязательный параметр, зачем так кардинально менять подход к использованию самых ходовых методов?
savant; v25i85; +2 Ответить
8. Darklight 32 02.04.21 11:08 Сейчас в теме
9. Darklight 32 02.04.21 11:11 Сейчас в теме
(2)Передача параметров Структурой очень удобна в семи случаях:
1. Когда много параметров (особенно не обязательных, а много - в некоторых книжках по чистому коду - это более 3-х) - возможно тут когда-то будет более 3-х предопределённых параметров
2. Когда в будущем могут появиться новые параметры, чтобы было проще совмещать старый код и новый (всё-таки жёсткий порядок фиксированных/необязательных параметров бывает очень неудобен, особенно когда позже добавляются новые параметры)
3. Когда можно передавать свои произвольные параметры - а тут так можно - и обрабатывать их в некоторых обработчиках
4. Когда нужно сделать унификацию вызова метода с другими методами - когда у разных объектов могут быть свои предопределённые параметры, и от объекта к объекту они разнятся - и чтобы универсальные алгоритмы не думали о том кому и какие параметры нужно передавать - могли бы скопом передавать универсальные значения для всех (как вариант) - лишнее будет просто проигнорировано. Так же, замечу, что такой подход (передача параметров в виде Структуры) применяется в Управляемых формах и в некоторых других методах - так что это уже просто некий общий паттерн, который позволяет быстрее осваивать вызовы таких методов с параметрами. И, скажу так, мне он нравится - я тоже часто применяю такой паттерн в своих обычных функциях
5. Передача значений аргументов функции через единый параметр типа "Структура" ещё и очень нагляден - сразу видно какие аргументы какие значения получили.(особенно если н злоупотреблять такой записью: Записать(Новый Структура("РежимЗаписи, РежимПроведения", РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный); - хотя тут, конечно, всё понятно - но будь аргументов больше, а их значения однороднее - было бы куда хуже)
6. Передача одного значения в единый аргумент функции очень удобно для разного рода универсального кода - особенно когда это значение передаётся из функции в функции (или где-то хранится в переменных/реквизитах/коллекциях). Это особенно удобно, когда нужно вызывать функцию, эмулируя функцилнальный подход через функцию "Вычислить" или через "ВыполнитьОбработкуОповещения" (незаменимую под мобильным клиентом/приложением под iOS)
7.Когда нужно передавать "сквозные" параметры через несколько вложенных функций единой Структурой параметров. Это вообще очень мощный Паттерн - особенно, когда, вдруг у вложенных функций появляется потребность в новых аргументах (да ещё и не обязательных и нужных только для небольшого числа случаев вызова), задавать которые нужно где-то несколькими уровнями вложенности выше. Чтобы не переписывать заголовки и вызовы промежуточных функций (где по сути ничего не меняется; особенно когда они ещё и типовые находятся в модулях на поддержке). Этот Паттерн настолько мощен - что, по хорошему, вообще нуждается в платформенной особой поддержек такого рода вызовов функций со сквозной передачей общих параметров контекста текущего вызова! Сейчас можно только выкручиваться условно через "глобальные" переменные - но клиент-серверном коде это часто не годное решение!

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

Всё это, конечно, платформенные костыли - вместо того, чтобы сделать:
а. Передачу именованных аргументов: Записать(РежимПроведения = РежимПроведенияДокумента.Неоперативный, РежимЗаписи = РежимЗаписиДокумента.Проведение)
б. Оставить передачу именованных аргументов структурой-словарём (что-то типа как в Python: Записать(*СтруктураПараметровЗаписи); или Записать(СтруктураПараметровЗаписи); если изначально аргументы определены как словарь функция Записать(**ПараметрыЗаписи) )
в. Сделать, поддержку ссылок на функции:
Функция ПрограмноЗаписать(Метод, Параметры)
     возврат Метод(**ПараметрыЗаписи);
КонецФункции

функЗаписать = &Объект.Записать;  //Здесь вместо "&" Хотел написать собачку - но движок Инфостарта этот символ не пропускает :-(
ПарамЗаписи = Новый Структура(...); //Тут какие-то значения
ПрограмноЗаписать(функЗаписать, ПарамЗаписи);
Показать

г. Сделать возможность вместо "Структур" создавать типовые/свои фиксированные классы (и дата-классы; с наследованием), чтобы аргументы можно было передавать через них, с применением инициализатора полей через конструктор по умолчанию (правда это уже спорное преимущество):
Записать(Новый ПараметрыЗаписиДокумента() 
{
      РежимПроведения = РежимПроведенияДокумента.Неоперативный,
      РежимЗаписи = РежимЗаписиДокумента.Проведение
}
)


Беря во внимание возможности ннекоторых языков можно бы и сократить, почти не теряя понятности

Записать(Новый() { РежимПроведения = .Неоперативный, РежимЗаписи = .Проведение } )



Но что имеем, то имеем

А за статью, автору, конечно, спасибо большое - очень познавательно!
(2)
Ali1976; mickey.1cx; vulli; alevnev; triviumfan; SeiOkami; +6 Ответить
12. frkbvfnjh 798 02.04.21 11:36 Сейчас в теме
(9) :) как по мне - все 6 аргументов = меньше писать кода = удобнее кодить. Следуя Вашей логике, возникает вопрос - почему тогда разработчики не переписали все методы объектов и встроенные функции на вызов с одним параметром в виде структуры? Или все в которых больше 3-х параметров? А вообще было бы идеально если бы они в каждом новом релизе, все параметры, уже имеющегося метода, заменяли на один в виде структуры (что по сути и произошло), если их количество начинает превышать 3. Или они решили все перевести на один параметр и начали с метода Записать(), но дальше "чёта лыжи не едут". И все Ваши плюсы перечеркиваются одним жирным минусом - я не могу через Ctrl+Пробел посмотреть состав параметров и соответственно не могу быстро понять что вообще туда можно передать. Так что я думаю причина такого изменения касательно метода Записать() наверное в чем то другом. Но если все именно так, как Вы пишите, то я сочувствую разработчикам платформы и всем кто связал свою жизнь с разработкой на 1С.
zaic; apic; +2 Ответить
13. frkbvfnjh 798 02.04.21 11:45 Сейчас в теме
(12) Тоже самое касается работы с деревом значений на стороне клиента - это вообще мрак. Все методы и свойства отличаются чуть больше чем полностью, хотя многие выполняют то же самое, а многих методов и свойств вообще нет, хотя не понятно, что мешало их реализовать? Сроки поджимали? Или почему бы не взять за основу уже имеющуюся объектную модель и добавить не достающие методы, и убрать те которые не возможно выполнить на стороне клиента (хотя таких нет, потому что все что нужно, можно самому докодить). И разработчиком прикладных решений было бы куда проще жить. Так что с деревом они тоже пошли явно по какой-то другой ветке эволюции.
dabu-dabu; zaic; apic; +3 Ответить
14. Darklight 32 02.04.21 12:06 Сейчас в теме
(12)
как по мне - все 6 аргументов = меньше писать кода = удобнее кодить

Не могу Вас понять - можете продемонстрировать на примере это удобство?

возникает вопрос - почему тогда разработчики не переписали все методы объектов и встроенные функции на вызов с одним параметром в виде структуры

Наверное, ответ очевиден - сложность "переписать" не сопоставима с возможным профитом. Да и вопрос совместимости старых алгоритмов останется (их переносимости). ну и переучиваться уж очень глобально всем придётся. Нее - переписывать не вариант. Куда эффективнее было бы оставить поддержку обоих подходов - просто доработав платформу - чтобы можно был передавать аргументы именовано, и в виде структуры - но оставив возможность описывать их поаргуменнтно - вот описывать поаргументно - это, как раз, правильный подход! Хотя возможность делать неопределённые (бесконечные) спсики аргументов - тоже очень полезная фишка! Причём в ряде методов самой платформы она есть!

если их количество начинает превышать 3

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

я не могу через Ctrl+Пробел посмотреть состав параметров и соответственно не могу быстро понять

В EDT можете (но это должно быть описано в справке/специальных комментариях к функции)
И как я написал выше - определять функцию, всё-таки лучше списком параметров. А вот, передавать аргументы - хорошо бы иметь возможность разными способами! И последние пункты - где фиксированные типы аргумента в виде класса - так там умная подсказка вполне себе тоже работает в других IDE. Так что тут уже вопросы ущербности IDE 1С Конфигуратора, описаний функций и синтаксиса языка 1С - а не самой идеи передачи одним аргументом!

Так что я думаю причина такого изменения касательно метода Записать() наверное в чем то другом

Может и в другом. Может это связано с техническим удобством сериализации при клиентс-серверных вызовах внутри платформы (ведь данный паттерн применяется как раз ТОЛЬКО в таких функциях, именно в Управляемых формах).
Но, тем не менее, некоторые описанные мной соображения, думаю, тоже имели место при переходе 1С на данный паттерн - пусть и очень выборочном переходе (но это не только метод "Записать").

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

Вы не сочувствуйте - а лучше заработайте свою платформу - лучше - пусть там не будет таких неудобных моментов!
3. v25i85 3 02.04.21 08:42 Сейчас в теме
// Дружище,
ЕСЛИ (Текущая_логика_проверки_заполнения_документа_соответствует_п­ервоначальной_задумке_Архитектора) ТОГДА
Смирись(); // !!!
Иначе
СнимайПоддержкуДокумента();
ДорабатывайДляСвоихНужд();
ЕСЛИ (После_доработок_появились_баги) ТОГДА
Сделай_как_было_Создай_свой_документ_и_не_ругай_Архитектора(); // !!!
КОНЕЦЕСЛИ;
КОНЕЦЕСЛИ;
hodytone; aleks.public; Deslime; Ali1976; DrAku1a; rusmil; portwein; artbear; +8 Ответить
4. RustIG 1644 02.04.21 09:37 Сейчас в теме
(3) архитектора как такого нет. есть группа разработчиков платформы. в команде люди непонятно с каким опытом. разработчикам как всегда не хватает опыта внедренцев, которые дорабатывают типовые функции...
53. CheBurator 3125 08.10.21 15:23 Сейчас в теме
(4) "Я вел жаркую переписку с сотрудником поддержки. Как показалось, он сам не знал о таком поведении,"
так давно известно и это уже практически не шутка что понабирали "таджиков" и в поддержку и в разработку.
54. RustIG 1644 08.10.21 16:36 Сейчас в теме
(53) Сергей, не, не могу так сказать про разработчиков 1с - есть толковые, а вот чтобы еще в полях побывали у клиента - таких не хватает... тем более не могу так говорить про близких мне по национальности братьев таджиков...сам я татарин...
:)
5. RustIG 1644 02.04.21 09:45 Сейчас в теме
Допустим, нам понадобилось записать форму документа программно. В реальных ситуациях это возможно, когда разработчик сначала хочет задать вопрос перед записью формы, а потом (после ответа пользователя) запись эту продолжить. В таких случаях, после обработки вопроса потребуется программно вызвать запись с теми же параметрами. Или же отказываться от стандартных кнопок записи и создавать свои, которые также будут программно вызывать запись. Подробнее можно прочитать на ИТС.


Да, прочитал ИТС по ссылке - они намудрили так , что стало всем только хуже...

...Оказываясь в обработчике ПередЗакрытием платформа знает что надо закрыть форму...

Но в обработчике ПередЗаписью такой однозначной информации нет. В этот обработчик попадаю: когда пользователь нажимает "Записать" или "Записать и закрыть". То есть дальнейший сценарий платформа не знает. Определить его стандартными способами платформа не умеет....

Для разработчиков платформы это тупик и ограничение. Для внедренца вроде меня это ТЗ - надо посадить два разных сценария на две разные кнопки "Записать" и "Записать и закрыть"...

Вопрос будет решен...
6. SeiOkami 3466 02.04.21 09:49 Сейчас в теме
(5)


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


Всегда удивляло это ограничение платформы. Неужели так сложно передать флаг в ПараметрыЗаписи? Платформа же знает о нём. Она же потом и закрывает форму.

Кстати, действительно, я упомянул об этом в статье, но не расписал подробнее. А ведь это тоже вполне себе "нюанс" записи формы 😁
7. artbear 1555 02.04.21 09:58 Сейчас в теме
(0) Люблю такие статьи с анализом интересных проблем.
Большое спасибо!
10. axelerleo 343 02.04.21 11:19 Сейчас в теме
Противоречивые ощущения от статьи. Большая часть - интересная и полезная. А вот про метод Записать() который должен вернуть Истина или Ложь - ну такое себе.
Нет, серьезно:
Разработчики, которые будут опираться на описание метода в справке, могут не догадаться, что обычный отказ в модуле объекта (по мнению 1С - "нештатная ситуация"), будет вызывать ошибку.


Читаем справку

СправочникОбъект.<Имя справочника> (CatalogObject.<Catalog name>)
ПередЗаписью (BeforeWrite)
Синтаксис:
ПередЗаписью(<Отказ>)
Параметры:
<Отказ>
Тип: Булево.
Признак отказа от записи элемента. Если в теле процедуры-обработчика установить данному параметру значение Истина, запись элемента выполнена не будет и будет вызвано исключение.

Или вы будете утверждать, что раз в справке написано - возвращает ложь, то программный код "ВызватьИсключение" не должен выдавать ошибку?
Тут и эксперименты проводить не надо - это все написано в справке к методам - но на этот раз к методам объекта :)
Вызов отказа в транзакционной цепочке в модуле объекта приведет к откату всей транзакции записи объекта - не важно, перед записью, при записи или в обработке проведения. И форма тут как бы совсем ни при чем.
MarinaLed; zqzq; gzharkoj; oleg-m; mitia.mackarevich; SlavaKron; +6 Ответить
11. SeiOkami 3466 02.04.21 11:32 Сейчас в теме
(10) Прочитайте ещё раз справку из метода формы.



Ложь - в противном случае

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

Или вы считаете, что разработчик, читая справку одного метода, должен переходить по всем вызываемым платформой событиям и перечитывать справку по ним?
mrChOP93; sulfur17; craftytigra; DrAku1a; Darklight; +5 Ответить
15. gzharkoj 509 02.04.21 12:31 Сейчас в теме
(11) Конкретно в данном случае разработчик должен знать последовательность вызова событий, то есть тут целый стек вызовов и исключение генерируется на более нижнем уровне, события платформы не должны обрабатывать исключения не платформы (конфигурации), иначе тогда действительно будут недокументированные поведения. Так что на мой взгляд описание корректно, которое действует в поле видимости метода.
Если рассматривать проблему того, что где-то отказ это исключение, а где-то нет, то это все описано в справках. Если у вас претензия к тому, что это не однообразно, то это имеет место быть и хотелось бы однообразия, но как ждать однообразия, если платформа развивалась от толстого клиента к тонкому на одной базе с принципиально разными архитектурными требованиями.
zqzq; DrAku1a; Leon75; +3 Ответить
26. axelerleo 343 02.04.21 16:58 Сейчас в теме
(11) Какое примечание? Что где-то внутри кода (в подписке на события, в обработке проведения, просто в какой-то процедуре, которая вызывается в процессе записи объекта) может сработать исключение?

Ок, давайте копнем глубже. Возьмем коллекцию Массив. Метод Получить.

Получить (Get)
Синтаксис:
Получить(<Индекс>)
Параметры:
<Индекс> (обязательный)
Тип: Число.
Индекс элемента.
Возвращаемое значение:
Тип: Произвольный.
Описание:
Получает значение по индексу. Работает аналогично оператору [].

Но внезапно, мы делаем так

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

массив = Новый массив;
стр = массив[3];

КонецПроцедуры

Ошибка при выполнении обработчика - 'ПередЗаписью'
по причине:
Индекс находится за границами массива
{Документ.Событие.МодульОбъекта(9)}: стр = массив[3];

Это тоже предлагаете добавить в примечание?
Повторюсь - исключение в коде, не важно чем оно вызвано - делением на ноль, кодом "вызватьИсключение", или "Отказ = истина" - отрабатываются платформой одинаково - как исключения. :)

Теперь насчет метода "Записать" у расширения формы. Давайте псевдокодом схематично ее изобразим так:

Функция Записать()

Результат = Ложь;
ПередЗаписью();
Результат = Истина;

Возврат Результат;

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

Процедура ПередЗаписью()
ВызватьИсключение;
КонецПроцедуры
Показать


В этом случае компилятор просто не дойдет до строки "Возврат Результат", потому что вывалится по ошибке. То же самое с Отказ = Истина, делением на ноль и обращением к индексу за границами массива, и т.п.
Поэтому и не вернет метод Записать() ни истину, ни ложь. Такое мое ИМХО. :)
charushkin; +1 Ответить
28. SeiOkami 3466 02.04.21 17:02 Сейчас в теме
(26) ещё раз про контракт

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

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

Советую почитать про правила разработки кода (в Чистом коде и т.п.)
31. axelerleo 343 02.04.21 17:11 Сейчас в теме
(28) Верно ли я понял, что для 100%-го возврата управления в функцию, чтобы она могла вернуть злополучный результат "Ложь", она должна выполняться платформой в попытке? Просто эксепшен где-то во внутренностях никак не отрабатывается, в результате и имеем то что имеем. Это вы имели в виду?
32. SeiOkami 3466 02.04.21 17:31 Сейчас в теме
(31) если так заявляет метод, то - да. Это и есть смысл фразы Ложь - в противном случае
36. SlavaKron 02.04.21 20:02 Сейчас в теме
(28)
Стр = Новый Структура;
Результат = Стр.Свойство(0);
Интересно ваше мнение, в справку по методу структуры "Свойство" тоже следует внести уточнение, что результат может отличаться от Ложь или Истина?
Прикрепленные файлы:
SeiOkami; +1 Ответить
37. SeiOkami 3466 02.04.21 20:05 Сейчас в теме
(36) сигнатура метода. Снова советую почитать про практики программирования. В описании метода указано, что первый параметр является строкой. Классическая задачка
38. SlavaKron 02.04.21 20:59 Сейчас в теме
(37) То есть моя ошибка в том, что я передал число, не строку, понятно, но исключение может быть вызвано и со строкой, например: Стр.Свойство("Имя ключа").
40. SeiOkami 3466 03.04.21 04:48 Сейчас в теме
(38) ваша ошибка в том, что вы передаёте не то, что указано в описании метода. В данном случае это тоже не ключ свойства. И поэтому поведение
платформы корректно.

Покажите, где я при вызове метода формы Записать () указывал некорректные (исходя из описания) параметры, которые и вызвали поведение платформы, отличное от описанного в методе?
42. SlavaKron 03.04.21 08:25 Сейчас в теме
(40) Да я понимаю ход ваших умозаключений=) и отчасти разделяю их. В том числе соглашусь, что для "неожиданного" поведения платформы при вызове метода Записать() отлично подходит слово "нюанс". Лично у меня вопросы возникают не к методу или описанию в СП, а к тому, почему отмена записи (вполне штатный сценарий) в модуле объекта реализована через исключение.
43. SeiOkami 3466 03.04.21 08:29 Сейчас в теме
(42) при этом интересно, что если установить Отказ в ПриЗаписиНаСервере у формы, то исключения не будет. Метод вернет Ложь.
Создается впечатление, что когда разрабатывали управляемые формы, то решили отказаться от исключений, но в модуле объекта их оставили для совместимости (или потому что сложно все переделывать)
47. Darklight 32 05.04.21 09:26 Сейчас в теме
(36)Простите, а когда метод (функция) "Структура.Свойство(ИмяСвойства, ЗначениеСвойства)" может возвращать, что-то отличное от значений типа "Булево"?
В вашем примере будет сгенерировано исключение!
И да - плохо, что об этом не написано в справке. Ведь, например "Соотвествие.Получить(Ключ)" в этом случае не генерирует исключение (но тут любой тип допускается). Просто явное нарушение API вызова - конечно, явно может создавать исключение

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

В хороших справка к API функции всегда документируются исключениями, которые они могут генерировать (и даже когда они возникают), и делают отсылки к другим типам - если они внутри функций тоже могут генерировать исключения. Тем самым показывая - что функция не всегда отрабатывает без исключений. Но в данном случае, т.к. 1С никогда не делает таких описаний исключений в справке, правильно было бы пояснить именно случаи, когда возвращается "Ложь" и сделать пометку - что в функции могут возникать не обрабатываем исключения при её выполнении
48. SlavaKron 05.04.21 09:39 Сейчас в теме
(47) Всё правильно, никогда (В общем-то как и в случае Записать). В моём сообщении под результатом лучше понимать не результат самого метода, а скажем, "ожидаемое поведение" в гуманитарном смысле.
16. SeiOkami 3466 02.04.21 12:38 Сейчас в теме
(15) я считаю, что здесь необходимо добавить примечание, чтобы не нарушать контракт описания метода. Это же базовые принципы программирования.

Например, я пишу метод, который выполняет какое-то действие и возвращает признак успеха. Удалось сделать "что_то" ?
Не важно что и не важно как, но если я в описании указываю в качестве сигнатуры возвращаемого значения признак успеха, то метод должен его возвращать. Если при этом возможны исключения, то должно быть сие указано. Это классическое правило программирования, когда ты не заставляешь другого разработчика читать код твоего метода для того, чтобы понять как он должен работать. Жаль, что такие вещи в среде программистов 1С редко учитываются. И приходится читать справку по всем событиям цепочки действий, чтобы понять, что описание недоговаривает.
17. gzharkoj 509 02.04.21 13:02 Сейчас в теме
(16) Как раз базовые принципы - это исключения и их обработка, которые могу происходит, где угодно. Принципы разработчик должен знать и понимать. Когда вы записываете документ, очевидно, что это может произойти и не по вине 1С, скажем сработала блокировка и возник deadlock. Будет сгенерировано исключение и как его обработать, если метод вернет ложь? В архитектуре 1с никак, так как принцип обработки исключений классический и он не менялся.
В описании, на вашем скриншоте есть переход к методу объекта Записать, где кстати пример приведен записи через попытку, что тоже должно навести на определенные мысли.
18. SeiOkami 3466 02.04.21 13:06 Сейчас в теме
(17) в методе Записать() объекта нет возвращаемого значения Ложь в противном случае
Поэтому контракт не нарушен и вполне логично использовать Попытку.
49. Yashazz 4751 05.04.21 11:05 Сейчас в теме
(16) Целиком согласен. Да и в стандартах разработки рекомендовали указывать, что будет возвращено в случае исключения, произошедшего внутри функции и обработанного в ней. И просто хороший тон этого требует.
19. gzharkoj 509 02.04.21 13:22 Сейчас в теме
(18) Речь о методе Записать, который вы привели на скриншоте, как раз там и написано "Ложь в противном случае". Я за контекстно-зависимое понимание и свои доводы привел. Если такое выражение принципиально меняет понимание для вас, думаю, 1с вас услышит и поправит справку, если вы им напишите конкретно с этой проблемой.
20. SeiOkami 3466 02.04.21 13:27 Сейчас в теме
(19)
Речь о методе Записать, который вы привели на скриншоте

В методе формы Записать() нет примера с попыткой\исключением. Это есть в методе объекта. Это другой метод и другая сигнатура. В одном при ошибке вызывается исключение (и указано это), а в другом - возвращается Ложь без какого-либо намека на возможные исключения.

Если такое выражение принципиально меняет понимание для вас, думаю, 1с вас услышит и поправит справку, если вы им напишите конкретно с этой проблемой.

Писал поддержке об этом, отказали. Поэтому и дальше будут встречаться ошибки разработчиков, которые поверили описанию метода, но не проверили его. Поэтому сей нюанс описан в статье. Чтобы уменьшить возможное количество ошибок и упростить понимание для программистов.
22. gzharkoj 509 02.04.21 13:43 Сейчас в теме
(20)
В методе формы Записать() нет примера с попыткой\исключением. Это есть в методе объекта. Это другой метод и другая сигнатура. В одном при ошибке вызывается исключение (и указано это), а в другом - возвращается Ложь без какого-либо намека на возможные исключения

В методе формы есть в описании, что вызов передается дальше в метод объекта Записать. Это же не разорванные вещи, это система со стеком вызовов.

(20)
Поэтому сей нюанс описан в статье. Чтобы уменьшить возможное количество ошибок и упростить понимание для программистов.

Ну тут уж простите, должен быть нижний предел какой-то. И я уверен, что большая часть ошибок не из-за "Ложь в противном случае".

То, что вы написали, потратили время - это отлично, пишите еще.
23. SeiOkami 3466 02.04.21 13:44 Сейчас в теме
(22)
То, что вы написали, потратили время - это отлично, пишите еще.

Это прям классический ответ со стороны службы поддержки 1С 🤣👍
24. gzharkoj 509 02.04.21 13:47 Сейчас в теме
(23) Классический ответ от 1с - это просто не отвечать или начать максимально тянуть время. В моем предложении не было сарказма.
25. SeiOkami 3466 02.04.21 13:48 Сейчас в теме
(24) согласен, мне просто фраза понравилась )
21. Yashazz 4751 02.04.21 13:36 Сейчас в теме
Блин. Не запись формы, а запись объекта, являющегося основным реквизитом формы. Грамотная формулировка - начало грамотного разбора.

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

Годно. Спасибо.

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

Я на тему поведения формы констант собирался свою публикацию сделать, но уже ясно, что не успеваю. Поэтому: взаимоотношения со служебными формочками констант, наличие в дереве метаданных, наличие в свойствах при выгрузке конфы в файлы, само понятие "форма констант" как носитель набора констант или как служебная; блокировки, которые накладывает запись набора относительно "установить" либо записи через менеджер константы - всё это на разбор тому, кто хочет)
zqzq; Артано; SeiOkami; +3 Ответить
27. grumagargler 724 02.04.21 17:00 Сейчас в теме
> Да, это очень плохо и вызывает кровотечение из глаз. И поэтому не делайте так. А если найдете альтернативный способ отменить проверку реквизита объекта из самой формы, то пишите в комментариях
Для отказа от проверки заполнения реквизита объекта, можно удалить его из списка массива ПроверяемыеРеквизиты, в обработчике ОбработкаПроверкиЗаполнения в модуле объекта. Этот способ еще и предпочтителен тем, что вы таким образом позволяете пользователю сохранить данные, закрыть форму и продолжить работу. А при попытке провести документ (из журнала, по правому клику) - сообщите пользователю, что сумму все-таки нужно заполнить.
29. SeiOkami 3466 02.04.21 17:05 Сейчас в теме
(27) к сожалению, вы не поняли задачи.
Речь шла о том, что в форме нельзя отменить повлиять на состав проверяемых полей в модуле самого объекта.
Безусловно, можно просто убрать проверку везде, но бывают случаи, когда проверку нужно отключить только в форме и при определенных ситуациях
33. grumagargler 724 02.04.21 17:59 Сейчас в теме
(29) Возможно, я действительно не понял задачи. Для меня, поле Сумма не является реквизитом формы, и проверяться обработчиком ОбработкаПроверкиЗаполненияНаСервере не должен, и это документировано, поэтому я не понимаю какие могут быть тут вопросы. В документации написано, что в ОбработкаПроверкиЗаполненияНаСервере вы можете реализовать свою логику проверки, но вы же пытаетесь сделать не это, вы пытаетесь повлиять на стандартный механизм проверки, просунув свое поле через параметры обработчика.
В сухом остатке, или по чесноку проверяйте поле если Сумма = 0 тогда, либо спускайте параметры логики на уровень модуля объекта, где там решите что с этим делать.
30. user1534961 02.04.21 17:06 Сейчас в теме
Ничего не понимаю. А если надо в обработке проверки заполнения указать вилку (для чисел) или родителя/реквизиты (для справочника)?
34. PerlAmutor 129 02.04.21 18:11 Сейчас в теме
Поправьте меня, может я чего-то не понимаю. Событие называется ПослеЗаписиНаСервере(). Если произошел отказ или исключение, то никакой записи не было. Тогда в чем претензия? Не успешных записей не бывает.

Я о том, что любая ошибка прерывает цепочку других событий.
35. SeiOkami 3466 02.04.21 18:19 Сейчас в теме
(34) претензий никаких нет, это лишь пояснение, которое дает более четкое понимание логики события.
39. user925427 124 02.04.21 23:08 Сейчас в теме
Отличная статья. Автор нашёл убедительный способ продемонстрировать то, о чём все догадываются и с чем периодически сталкиваются. Недочёты в руководствах и документации, увы, неотъемлемая часть работы имеющих дело с 1С. Будь ты программист, консультант или пользователь. Но 1С это не законченный продукт. Платформа и типовые конфигурации постоянно развиваются и это развитие определяет отставание в документировании. Се ля ви. Автору респект!
41. DrAku1a 1726 03.04.21 07:28 Сейчас в теме
Но поддержка 1С, к сожалению, отказалась добавлять примечание в справку 😣 Поэтому, остается надеяться, что программисты будут читать эту статью 😅
Считаю это головотяпством со стороны техподдержки 1С.
Вообще, ситуация с Записать() напомнила метод Abort() в Delphi. Он вызывал тихое исключение (без показа ругательств), с помощью которого можно было выйти из огромного числа вложенных вызовов. И он также отлавливался через TRY-EXCEPT... По-сути это аналог использования GOTO для того чтобы выйти из нескольких вложенных циклов. Только вот, в арсенале разработчиков платформы видимо нет такого понятия как "тихое исключение", но вот GOTO-шники, видимо, есть.

Вообще, основа клиент-серверного взаимодействия в том, что клиент вызывает сервер, но не наоборот (сервер никогда напрямую не обращается к клиенту, в идеале - вообще не хранит данные о клиенте между вызовами, хотя в 1С это не совсем так). Передача от сервера на клиент происходит только по завершении вызова (параметры процедуры и результаты функций). Эта основа архитектуры клиент-сервер, которая применяется не только в последних версиях 1С, но и, например, в веб-программировании. В обычных формах сервер мог вызывать клиент (не всегда, в модуле который выполнялся НаСервере - тоже не работает вызов клиента), но там была более простая архитектура. На этом основывается тот факт, что запись на сервере не вызывает событий на клиенте.
Ну и ещё, объект (модуль объекта) - ничего не знает о форме (модуле формы), потому как в общем случае - формы может и не быть...
44. triviumfan 94 04.04.21 15:45 Сейчас в теме
Ничего полезного не смог взять из статьи. Докапываться до мелочей платформы можно бесконечно. И то большинство здесь высосано из пальца.
45. SeiOkami 3466 04.04.21 15:49 Сейчас в теме
(44) Спасибо, но я лишь показываю нюансы, с которыми можно столкнуться любому разработчику. Если Вам именно это не показалось полезным, то прошу прощения за потраченное время 😁
46. almas 254 05.04.21 08:53 Сейчас в теме
Отличная статья. Жаль, что разработчики 1с в "режиме страусов" - нестандарное поведение платформы это диагноз последних лет 3х. И это далеко "не докапываться до платформы", а очень грамотный разбор, на базе которого 1с просто ОБЯЗАНА исправить свои баги. Но позиция 1с нам известна: "кому должен всем прощаю"(44) .
50. skv_79 365 21.05.21 16:13 Сейчас в теме
Отличная статья. Только тут небольшая опечатка Дело в том, что вызов метода Форма.Запись()
51. SeiOkami 3466 21.05.21 16:15 Сейчас в теме
(50) спасибо, поправил очепятку
52. chipazawra 27.05.21 14:33 Сейчас в теме
Мне кажется есть во всём этом логика когда метод формы Записать() возвращает истину или ложь.

Вернуть Ложь метод может лишь тогда когда дело не дошло до начала транзакции записи объекта в БД из того и следует что при установке отказа в проверке заполнения объекта мы не получаем исключение т.к. транзакция ещё не начата. После начала транзакции т.е. ПередЗаписью() прервать транзакцию и отменить изменения мы можем только вызовом исключения.

Если посмотреть описание метода Объект.Записать() то он ни каких значений не возвращает.

Под капотом грубо говоря происходит такое:

 Если Объект.ПроверитьЗаполнение() Тогда
  
	НачатьТранзакцию();
	//События записи объекта
	ЗафиксироватьТранзакцию();
	
	Возврат Истина;
  
  Иначе
  
	Возврат Ложь;
  
  КонецЕсли;
Показать


Платформа намерено не оборачивает транзакцию в попытку.
55. user1654204 17.04.22 12:46 Сейчас в теме
Спасибо за статью!! Очень полезная!
Раньше вроде была кнопка "Сказать спасибо". Чтобы вас рейтинг увеличить.. Сейчас какая-то ерунда!
56. SeiOkami 3466 17.04.22 12:48 Сейчас в теме
(55) сейчас для поднятия рейтинга можно поставить статье плюсик)
sapervodichka; +1 Ответить
Оставьте свое сообщение