Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Вычисление логических выражений в операторах встроенного языка



Работа со значениями агрегатных типов во встроенном языке

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

Каждое значение агрегатного типа в системе 1С: Предприятие включает две составляющие:

внутренний идентификатор объекта данных;

ссылка на объект доступа.

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

выполнения оператора

A = B;

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

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

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

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

Тов = Док.Товар; // Объект доступа еще не создан, при условии, что ранее не было обращений к атрибутам и методам;

Тов2 = Док.Товар; // Аналогично

Цена = Тов.Цена; // Для переменной Тов создается объект доступа

Цена2 = Тов2.Цена; // Для переменной Тов2 создается объект доступа. Тов и Тов2 ссылаются на разные объекты доступа

Тов3 = Тов; // Тов и Тов3 ссылаются на один объект доступа

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

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

Тов = 0; // Удалена ссылка на объект доступа

Тов2 = 0; // Уничтожен первый объект доступа

Тов3 = 0; // Уничтожен второй объект доступа

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

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

Цена = Док.Товар.Цена;

В этом случае, исполняющая система встроенного языка получает значение реквизита Товар документа, представленного значением переменной Док. При этом полученное значение не будет содержать ссылки на объект доступа. Затем, исполняющая система создает объект доступа, соответствующий реквизиту Товар, и, затем, с помощью созданного объекта, получает значение реквизита Цена. Затем объект доступа удаляется, так как ни одна из переменных после выполнения указанного оператора на объект не ссылается. Таким образом, при выполнении последовательности операторов

Наимен = Док.Товар.Наименование;

Цена = Док.Товар.Цена;

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

Тов = Док.Товар; // Присваивается реквизит документа. Объект доступа еще не создан

Наимен = Тов.Наименование; // Для переменной Тов создается объект доступа

Цена = Тов.Цена; // Используется созданный ранее объект доступа

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

Выбор разрядности для данных числовых типов

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

При установке формата числового типа данных, разрядность должна обеспечивать возможность хранения чисел необходимой величины. Например, если у нас реквизит " Цена" имеет формат (8.2), то при записи в него значения 10000 * 26.85 мы получим переполнение числа (99999.99).

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

Вычисление логических выражений в операторах встроенного языка

В условных операторах и операторах цикла встроенного языка системы 1С: Предприятие для определения последовательности выполняемых действий используются логические выражения. Логическим выражением может быть элементарное логическое выражение (сравнение двух значений) или более сложные конструкции полученные из элементарных логических выражений при помощи логических операций И/ИЛИ/НЕ.

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

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

Процедура Обработать(Об)

Если (ТипЗначенияСтр(Об) = " Справочник" ) И (Об.Вид() = " Товары" ) Тогда

// Некоторые действия

КонецЕсли;

...

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

Если в качестве значения параметра, передаваемого в данную процедуру, будет фигурировать элемент справочника любого вида, то процедура будет работать нормально, но если в качестве параметра будет передано значение типа " Число" или " Дата", то выполнение процедуры будет аварийно завершено. В логическом выражении, используемом в операторе 'Если' только составляющая ТипЗначенияСтр(Об) = " Справочник" будет корректно функционировать независимо от типа передаваемого параметра, а составляющая Об.Вид() = " Товары" сможет нормально работать только в том случае, если в качестве параметра в процедуру передано значение агрегатного типа и для данного агрегатного типа определен метод Вид(). Дело в том, что при вычислении логических выражений встроенный язык системы 1С: Предприятие 7.х сначала вычисляет элементарные логические выражения (операции сравнения), а затем производит вычисление логического выражения в целом (операции И/ИЛИ/НЕ).

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

Процедура Обработать(Об)

Если ТипЗначенияСтр(Об) = " Справочник" Тогда

Если Об.Вид() = " Товары" Тогда

// Некоторые действия

КонецЕсли

КонецЕсли

...

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

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

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

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

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

При этом следует учитывать следующие особенности данных процедур:

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

2. Вызовы указанных предопределенных процедур не объединены с выполняемым действием единой транзакцией. Это означает, что в случае интерактивного удаления документа, само удаление документа выполняется в транзакции, отдельной от действий, которые могут выполняться в процедуре " ПриУдаленииДокумента". И если в процедуре " ПриУдаленииДокумента" действия будут выполняться в раках одной, явно определенной в процедуре транзакции, то все равно приходится говорить о двух транзакциях:

- удаление документа;

- действия, выполняемые в процедуре " ПриУдаленииДокумента"

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

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

Заметим, что описанные выше особенности предопределенных процедур не распространяются на предопределенные процедуры " ОбработкаПроведения" и " ОбработкаУдаленияПроведения". Эти предопределенные процедуры вызываются непосредственно в транзакции проведения (отмены проведения) и выполняемые в них алгоритмы логически связанны с самим выполняемым действием. Кроме того, в отличие от других предопределенных процедур эти предопределенные процедуры выполняются и в случае проведения (отмены проведения) средствами встроенного языка.


Поделиться:



Последнее изменение этой страницы: 2020-02-16; Просмотров: 189; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.023 с.)
Главная | Случайная страница | Обратная связь