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

Публикация № 1396380 02.04.21

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

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

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

Содержание

 

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

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

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

 

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

 

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

 

 

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

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

 

 

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

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

 

 

 

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

 

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

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

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

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

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

 

 

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

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

 

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

 

 

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

 

 

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

 

 

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

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

 

 

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

 

 

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

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

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

 

 

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

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

 

 

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

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

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

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

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

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

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

 

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

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

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

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

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

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

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

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


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

 

 

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

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

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

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

 

 

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


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

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

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

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

Например:

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

 

 

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

 

 

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

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

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

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

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

 

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

 

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

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

 

 

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

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

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

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

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

 

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

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

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

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

 

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

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

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

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

 

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

 

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

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

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


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

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

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


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

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

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

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

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

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

 

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

 

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

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

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

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

 

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

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

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

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

 

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

 

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

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

 

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

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

Синтаксис:

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

Параметры:

<Отказ>

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

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

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

Описание:

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

 

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

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

 

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

 

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

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

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

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

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

 

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

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

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

 

 

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

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

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

 

 

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

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

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

 

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

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

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

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

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

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

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

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

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

 

 

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

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

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

 

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

Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. ilyaleontyev 02.04.21 08:33 Сейчас в теме
Отличная работа, я считаю.
Artem-B; dabu-dabu; vulli; Wishich; DrAku1a; Sashares; Jeka44; Darklight; ipoloskov; CyberCerber; portwein; artbear; v25i85; SeiOkami; frkbvfnjh; +15 Ответить
2. frkbvfnjh 617 02.04.21 08:39 Сейчас в теме
Да я тоже попался на проверку заполнения. Даже ветку форума делал на Инфостарте. И мне несколько раз пытались объяснить, что обработка проверки заполнения у каждой стороны своя. И только раз на третий я понял, как это работает, и как то сразу отпало желание пользоваться этим замечательным механизмом, каковым он казался по началу.
Но вот кто мне объяснит, почему при переходе на управляемое приложение разработчики решили что в метод Записать() параметры теперь нужно передавать структурой? Я серьёзно не понимаю, что мешало оставить всё как раньше или какие преимущества это дает? Если это позволяет передать куда-то какие-то дополнительные данные, то почему просто не добавить дополнительный, третий, не обязательный параметр, зачем так кардинально менять подход к использованию самых ходовых методов?
savant; v25i85; +2 Ответить
8. Darklight 27 02.04.21 11:08 Сейчас в теме
9. Darklight 27 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 617 02.04.21 11:36 Сейчас в теме
(9) :) как по мне - все 6 аргументов = меньше писать кода = удобнее кодить. Следуя Вашей логике, возникает вопрос - почему тогда разработчики не переписали все методы объектов и встроенные функции на вызов с одним параметром в виде структуры? Или все в которых больше 3-х параметров? А вообще было бы идеально если бы они в каждом новом релизе, все параметры, уже имеющегося метода, заменяли на один в виде структуры (что по сути и произошло), если их количество начинает превышать 3. Или они решили все перевести на один параметр и начали с метода Записать(), но дальше "чёта лыжи не едут". И все Ваши плюсы перечеркиваются одним жирным минусом - я не могу через Ctrl+Пробел посмотреть состав параметров и соответственно не могу быстро понять что вообще туда можно передать. Так что я думаю причина такого изменения касательно метода Записать() наверное в чем то другом. Но если все именно так, как Вы пишите, то я сочувствую разработчикам платформы и всем кто связал свою жизнь с разработкой на 1С.
zaic; apic; +2 Ответить
13. frkbvfnjh 617 02.04.21 11:45 Сейчас в теме
(12) Тоже самое касается работы с деревом значений на стороне клиента - это вообще мрак. Все методы и свойства отличаются чуть больше чем полностью, хотя многие выполняют то же самое, а многих методов и свойств вообще нет, хотя не понятно, что мешало их реализовать? Сроки поджимали? Или почему бы не взять за основу уже имеющуюся объектную модель и добавить не достающие методы, и убрать те которые не возможно выполнить на стороне клиента (хотя таких нет, потому что все что нужно, можно самому докодить). И разработчиком прикладных решений было бы куда проще жить. Так что с деревом они тоже пошли явно по какой-то другой ветке эволюции.
dabu-dabu; zaic; apic; +3 Ответить
14. Darklight 27 02.04.21 12:06 Сейчас в теме
(12)
как по мне - все 6 аргументов = меньше писать кода = удобнее кодить

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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


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


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

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


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

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

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



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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

См. также

Аналог PIVOT в запросе 1С (как выполнить транспонирование таблицы в запросе 1С) Промо

Практика программирования v8 Бесплатно (free)

В статье показывается простой метод реализации аналога оператора PIVOT в запросе 1С без использования соединений.

12.12.2020    4157    Eugen-S    23    

Что за ? в коде, или Секретный оператор в 1С

Практика программирования v8 Платформа 1C v8.2 Платформа 1С v8.1 1cv8.cf Бесплатно (free)

Инкремент, модуль и прочая магия, которая скрыта под символом "?"

21.10.2021    5400    SeiOkami    33    

Управление платформенными обработками (расширение для типовых)

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

Расширение использует недокументированную возможность для управления платформенными обработками. Например, чтобы подменить "Активные пользователи" или доработать "Конструктор запросов".

1 стартмани

07.10.2021    2651    5    SeiOkami    23    

Полезные примеры СКД, ч.2

Практика программирования v8 v8::СКД Бесплатно (free)

Еще несколько примеров решения задач в СКД.

06.04.2021    10295    Neti    8    

Использование классов .Net в 1С для новичков Промо

Практика программирования Разработка внешних компонент Универсальные функции v7.7 v8 Бесплатно (free)

Руководство для новичков. Написав статью http://infostart.ru/public/238584/, я понял, что многие не понимают того, что написано. Поэтому в этой статье постараюсь более подробно остановиться на азах и без кода на вражеском языке (C#)

27.01.2016    85319    Serginio    115    

Обзор полезных методов БСП 3.1.4

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

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

25.03.2021    38446    rayastar    51    

Звуковое управление в 1С 8.3

Практика программирования v8 1cv8.cf Бесплатно (free)

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

16.03.2021    6993    velemir    33    

Наследование свойств элементов, или Как пользователь может сломать вашу форму

Практика программирования v8 Платформа 1C v8.2 1cv8.cf Бесплатно (free)

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

12.01.2021    3917    SeiOkami    25    

Использование программных перечислений, ч.1: строковые константы Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Часто ли у вас возникает необходимость в коде выполнять сравнение на строку?

10.12.2016    40966    unichkin    74    

Доработка проведения в ERP 2.5. (Регистры накопления, Регистры сведений)

Практика программирования v8 ERP2 БУ Бесплатно (free)

Покажу точки входа для доработки "типового" проведения документов в ERP для регистров оперативного учета. Рассмотрим три основные ситуации: нужно изменить имеющееся проведение документа; нужно сделать записи в существующие регистры; нужно с нуля описать алгоритм проведения в добавленный регистр. Пример реализован на 1С:ERP Управление предприятием 2 (2.5.4.120)

10.01.2021    10459    BuriyLesha    10    

Serverless (Faas) в 1С. Создание и вызов Yandex Cloud Functions

Универсальные функции Практика программирования v8 Бесплатно (free)

"Я не могу просто взять и скопировать код с гитхаба", "у нас 1С микросервисами окружена", "возможностей мало" - частые фразы 1С разработчиков. которым не хватает возможностей платформы в современном мире. Faas, конечно, история не новая, но нас сдерживало 152ФЗ и задержки по пингам. Для того, чтобы действительно использовать в 1С код, к примеру, на Python, надо было приложить усилия. Теперь всё намного проще - берём и используем.

28.12.2020    8702    comol    31    

Базовые вещи БСП, которые облегчат жизнь программисту 1С

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

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

30.08.2020    19702    quazare    34    

Вспомогательные инструкции в коде 1С Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Помогаем редактору кода 1С помогать нам писать и анализировать код.

15.10.2018    35920    tormozit    106    

Новое отображение ошибок в 1С

Практика программирования v8 1cv8.cf Бесплатно (free)

Рассмотрим развитие механизма отображения ошибок в 1С (начиная с 8.3.17)

10.08.2020    17909    SeiOkami    35    

Форма выбора (подбор) в управляемых формах

Практика программирования v8 v8::УФ 1cv8.cf Россия Бесплатно (free)

Разбор небольших примеров того, как правильно открывать форму выбора (подбора) в управляемых формах, не прибегая к модальным окнам.

08.05.2020    74561    user5300    19    

Оформление и рефакторинг сложных логических выражений Промо

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

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

20.09.2012    82703    tormozit    131    

Как ограничить поля отбора в динамическом списке и ничего не сломать

Практика программирования v8::УФ 1cv8.cf Бесплатно (free)

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

06.05.2020    8464    SeiOkami    3    

Ограничения полей, или как обмануть СКД?

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Каждое из ограничений полей можно обойти. Рассмотрим варианты обхода и способы обезопасить свой отчет.

15.04.2020    15656    SeiOkami    41    

Программная работа с настройками СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

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

27.01.2020    63942    ids79    26    

Запись значения в поле ввода/формы со срабатыванием события ПриИзменении Промо

Практика программирования v8 1cv8.cf Россия Бесплатно (free)

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

11.07.2007    54172    tormozit    51    

[СКД] Программное создание схемы компоновки данных

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

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

15.01.2020    42781    John_d    22    

Последовательности событий при проведении документа 1С. Шпаргалка + про формы + про расширения

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

Собрал информацию о событиях/подписках/расширениях в одном месте.

30.12.2019    34443    kuzyara    38    

30 задач. Странных и не очень

Практика программирования v8 Бесплатно (free)

30 задач на знание языка программирования 1С и некоторого поведения платформы. Маленьких. Странных и не очень.

02.12.2019    23905    YPermitin    62    

Как сделать из &НаКлиентеНаСервереБезКонтекста почти &НаКлиентеНаСервере Промо

Практика программирования v8 1cv8.cf Россия Бесплатно (free)

Как сделать метод формы, доступный на клиенте и на сервере одновременно, и сохранить при этом удобство разработки

10.09.2017    50933    tormozit    74    

Как передать IP адрес, который вызвал HTTP запрос в 1C (для веб-сервера Apache)

Практика программирования v8 Бесплатно (free)

Столкнулся с задачей получения IP адреса, который вызывает http сервис 1С. Итак, решение:

22.11.2019    12155    Sibars    19    

Полезные процедуры и функции для программиста

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

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

07.10.2019    39318    HostHost    41    

Таблица значений. Нюансы

Практика программирования v8 Бесплатно (free)

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

01.10.2019    52218    Yashazz    56    

Выгрузка документа по условию Промо

Практика программирования Разработка v8 Бесплатно (free)

Что делать, если документы нужно выгружать не все подряд, а по какому-то фильтру: статусу, дате, набору условий... А что если он соответствовал этим условиям, а потом перестал? А если потом опять начал? Такие ситуации заставили попотеть не одного программиста.

25.04.2019    17938    m-rv    3    

О программе Postman для тестирования API и для чего она нужна 1С-нику

Практика программирования Программное обеспечение (software) v8 Бесплатно (free)

Для чего нужна программа Postman для тестирования API и какая от него польза для 1С-программиста.

24.09.2019    19788    budidich    31    

Оповещения боту из 1С за 31 минуту

Практика программирования Интеграция v8::УФ 1cv8.cf Бесплатно (free)

Поделюсь опытом, как быстро сделать бота с оповещениями в Телеграмм из 1С без лишних затрат.

18.09.2019    20046    feva    44    

[Шпаргалка] Программное создание элементов формы

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

Программное создание практически всех популярных элементов формы.

06.09.2019    99499    rpgshnik    75    

Как прикрутить ГУИД к регистру сведений Промо

Практика программирования Перенос данных из 1C8 в 1C8 Разработка v8 Бесплатно (free)

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

16.04.2019    23228    m-rv    18    

Агрегатные функции СКД, о которых мало кто знает

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Пользуетесь ли Вы всеми возможными агрегатными функциями, которые предоставляет система компоновки данных? Если Вы используете только: СУММА, КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ, то эта статья для Вас.

05.09.2019    76391    ids79    56    

Регистры бухгалтерии. Общая информация

Практика программирования Математика и алгоритмы v8 v8::БУ БУ Бесплатно (free)

Общая информация о внутреннем устройстве регистров бухгалтерии.

05.09.2019    45839    YPermitin    25    

Три костыля. Сказ про фокусы в коде

Практика программирования v8 Бесплатно (free)

Три интересных (или странных) костыля в коде, которые могут помочь в повседневных и не очень задачах.

03.09.2019    30059    YPermitin    81    

Как сделать запрос на изменение данных Промо

Практика программирования v8 v8::Запросы 1cv8.cf Бесплатно (free)

В статье приведены особенности внутренней архитектуры и примеры работы с расширением языка запросов 1С.

01.06.2018    36652    m-rv    23    

Отслеживание выполнения фонового задания

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

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

17.08.2019    44720    ids79    22    

Функции СКД: ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

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

08.08.2019    148729    ids79    75    

Фоновое выполнение кода в 1С - это просто

Практика программирования v8 1cv8.cf Бесплатно (free)

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

02.08.2019    59636    avalakh    26    

Метод формирования движений в типовых регистрах нетиповыми регистраторами Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

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

05.12.2017    30708    itriot11    34    

Разбираемся с параметрами редактирования СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Связь по типу, Параметры выбора, Связи параметров выбора

31.07.2019    41027    json    17    

СКД - наборы данных и связи между ними, создание собственной иерархии, вложенные отчеты

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

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

26.07.2019    103608    ids79    16    

СКД - использование расширений языка запросов, секция ХАРАКТЕРИСТИКИ

Инструментарий разработчика Практика программирования v8 v8::СКД Бесплатно (free)

Автоматическое и не автоматическое заполнение полей компоновки данных. Использование расширений языка запросов для СКД «{…}», секция ВЫБРАТЬ, секция ГДЕ, параметры виртуальных таблиц. Автоматизированное использование дополнительных данных в запросе: секция ХАРАКТЕРИСТИКИ.

17.07.2019    47891    ids79    27    

Регистры сведений. За кулисами

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Небольшие заметки по внутреннему устройству регистров сведений.

09.07.2019    33586    YPermitin    14    

"Меньше копипаста!", или как Вася универсальную процедуру писал

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Программист Вася разбирает подход создания универсальных методов на примере программного вывода СКД.

04.07.2019    22447    SeiOkami    53    

Работа с настройками системы компоновки данных

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

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

02.07.2019    82824    ids79    18    

Создание отчетов с помощью СКД - основные понятия и элементы

Практика программирования Математика и алгоритмы v8 v8::СКД Бесплатно (free)

Основные принципы работы СКД. Понятия схемы компоновки и макета компоновки. Описание основных элементов схемы компоновки: наборы данных, поля, вычисляемые поля, ресурсы, параметры.

25.06.2019    75177    ids79    28    

Регистры накопления. Структура хранения в базе данных

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Структура хранения регистров накопления в базе данных для платформы 1С:Предприятие 8.x. Первая часть в серии публикаций.

16.05.2019    62863    YPermitin    31