|   |   | 
| 
 | Использование Знач в процедурах и функциях | ☑ | ||
|---|---|---|---|---|
| 0
    
        МаксимМП23 05.05.15✎ 14:53 | 
        Ковыряя одну конфу от Раруса, обратил внимание, что очень много параметров процедур и функций в общих модулях описаны с использованием ключевого слова Знач. Такое описание делается даже в тех случаях, когда 100% с данные только читаются (т.е. исключено изменение объекта).
 Подумалось следующее. А не фича ли это? Ведь Знач (в случае передачи ссылки) на уровне СУБД по сути одним запросом выберет копию объекта и передаст в процедуру/функцию, где уже можно спокойно с ней работать, без дергания сервера мелкими запросами при обращении к свойствам объекта по ссылке. Прав ли я или тут закопан какой-то другой смысл? | |||
| 18
    
        EvilBeaver 15.06.15✎ 18:22 | 
        (17) "По ссылке" означает, что если вы перезапишете переменную внутри функции, то она изменится и в точке вызова.
 Если "По Значению", то в точке вызова останется то же значение. Если передали "По значению" коллекцию, внутри метода вызвали Очистить(), то в точке вызова она тоже будет очищена. Вы не перезаписали переменную коллекции, а вызвали метод, который изменил внутренности объекта. Т.е. агрегат (коллекция) как бы ни передавался - если вы меняете состояние объекта - оно меняется везде. | |||
| 19
    
        spock 15.06.15✎ 19:45 | 
        (18) молодец, теперь мой вопрос перечитай.     | |||
| 20
    
        Рэйв 15.06.15✎ 19:52 | 
        Вот правда вы как школьники.
 Это же основы программирования. С Знач копия объекта создается в процедуре и там же умирает. Без Знач- передается ссылка(и это может быть ссылка на объект с возможностью изменения) . Вот тут возможны варианты когда работать или не будет или не оптимально. | |||
| 21
    
        13Дима13 15.06.15✎ 20:36 | 
        (3) где на сайте 1с можно найти "Заметки из зазеркалья" на главной странице?     | |||
| 22
    
        Cyberhawk 15.06.15✎ 20:52 | 
        (21) нигде + первоистоки этой ссылки - на партнерке     | |||
| 23
    
        Asmody 15.06.15✎ 23:22 | 
        Вот не знаю как там внутре 1С, некоторые другие языки создают копию объекта только в момент изменения. Если вы понимаете о чем я. 
 Но на самом деле это не имеет значения. Хотя изредка очень хочется, чтобы про типобезопасность и имьютабилити платформа "думала" сама. | |||
| 24
    
        SilentMan 15.06.15✎ 23:31 | ||||
| 25
    
        Asmody 16.06.15✎ 00:44 | 
        В контексте ветки внимание, вопрос: зачем нужна такая функция:
 Функция Присвоить(а, Знач б) Экспорт а = б; Возврат а; КонецФункции | |||
| 26
    
        Serg_1960 16.06.15✎ 01:03 | 
        На ИТС есть же статья "Передача параметров по ссылке и по значению при вызове процедур и функций"? Там всё подробно разжёвано.     | |||
| 27
    
        Asmody 16.06.15✎ 01:14 | 
        (26) да-да-да, и ссылка аж двумя постами раньше висит     | |||
| 28
    
        Ненавижу 1С гуру 16.06.15✎ 09:26 | 
        я что-то не понял
 Разве код не меняет количество элементов в массиве? М = Новый Массив(); Чтото(М); Процедура Чтото(Знач М) М.Добавить(0); КонецПроцедуры | |||
| 29
    
        ДенисЧ 16.06.15✎ 09:39 | 
        (28) нет     | |||
| 30
    
        ДенисЧ 16.06.15✎ 09:40 | 
        По крайней мере не должен     | |||
| 31
    
        Бубка Гоп 16.06.15✎ 09:50 | 
        Расставим точки,
 применение Знач везде где можно - хороший тон программирования? | |||
| 32
    
        spock 16.06.15✎ 09:52 | 
        (29) ?     | |||
| 33
    
        spock 16.06.15✎ 09:53 | 
        (31) поправил: "применение Знач везде, где нужно - хороший тон программирования".     | |||
| 34
    
        Бубка Гоп 16.06.15✎ 09:53 | 
        (33) если можно применить Знач, значит - нужно :)     | |||
| 35
    
        Бубка Гоп 16.06.15✎ 09:55 | 
        т.е. создание копии изменяемого объекта - гораздо менее трудоемкая задача, чем его сериализация при возврате?     | |||
| 36
    
        Stepa86 16.06.15✎ 09:58 | 
        (25) Чтоб на этапе отладки менять переменные
 (28) меняет. У коллекций то передается ссылка на коллекцию. | |||
| 37
    
        ДенисЧ 16.06.15✎ 10:04 | 
        (34) нет     | |||
| 38
    
        Ненавижу 1С гуру 16.06.15✎ 10:05 | 
        (29) спецом полез проверить:
 Процедура КнопкаВыполнитьНажатие(Кнопка) М = Новый Массив(); Сообщить("М.Количество()="+М.Количество()); // выдает 0 Чтото(М); Сообщить("М.Количество()="+М.Количество()); // выдает 1 КонецПроцедуры Процедура Чтото(Знач М) М.Добавить(0); КонецПроцедуры | |||
| 39
    
        Бубка Гоп 16.06.15✎ 10:06 | 
        (38) коллекция же     | |||
| 40
    
        Stepa86 16.06.15✎ 10:10 | 
        (38) на этой фишке основан гвнокодистый способ реализации временных глобальных переменных.
 В общем модуле с кешированием на сеанс пишется функция Функция ГлобальныеПеременные() Экспорт Возврат Новый Структура(); КонецФункции А потом в других местах с ней работают кеш.ГлобальныеПеременные().Вставить( "НовПараметр", 3 ); и при следующем обращении там будет этот параметр | |||
| 41
    
        Провинциальный 1сник 16.06.15✎ 10:11 | 
        (33) Хорошим тоном будет вообще отказ от изменения значений через параметры. У функции должна быть одна точка возврата - возвращаемое значение. Если их много - можно использовать структуру. Радикально повышает читаемость и отлаживаемость кода.     | |||
| 42
    
        Jokero 16.06.15✎ 10:13 | 
        (41) так и до ООП дойдем))     | |||
| 43
    
        spock 16.06.15✎ 10:16 | 
        (41) Ты, конечно, недальновидно это заявил, но право на свое мнение, ты, естественно, имеешь.     | |||
| 44
    
        fisher 16.06.15✎ 10:18 | 
        (25) Ума не приложу. Примитивные типы всегда присваиваются по значению, а коллекции всегда по ссылке. Поэтому фишки именно со "Знач" я тут не просекаю.     | |||
| 45
    
        Бубка Гоп 16.06.15✎ 10:24 | 
        (40) прям альтернатива ПараметрамСеанса     | |||
| 46
    
        Asmody 16.06.15✎ 10:26 | 
        (38) За такое поведение, конечно, разработчикам платформы надо что-то отстреливать.     | |||
| 47
    
        fisher 16.06.15✎ 10:27 | 
        (46) Не согласен. Это, конечно, менее похоже на более другие языки, зато применительно к зергам-одинэсникам более безопасно.     | |||
| 48
    
        ДенисЧ 16.06.15✎ 10:27 | 
        (38) Ну лоханулся. Не проснулся ещё.
 (46) А что, на более другом языке такого нет? | |||
| 49
    
        Asmody 16.06.15✎ 10:28 | 
        (40) Тут нет гарантии, что платформа не почистит кеш когда ей вздумается. А ей ведь вздумается…     | |||
| 50
    
        Asmody 16.06.15✎ 10:31 | 
        (48) Концептуально, переданное по значению должно умереть вместе с функцией.     | |||
| 51
    
        Stepa86 16.06.15✎ 10:31 | 
        (49) а я и говорю, что так себе способ. Кеш живет чот минут 20, вроде, во всяком случае я на этот срок ориентируюсь при использовании кешируемых методов.     | |||
| 52
    
        Stepa86 16.06.15✎ 10:33 | 
        (50) а если аналогичный пример, но не с коллекцией? Тут тоже пометка удаления должна откатится?
 Процедура ПометитьНаУдаление( Знач пСсылка ) об = пСсылка.ПолучитьОбъект(); об.УстановитьПометкуУдаления(Истина); КонецПроцедуры | |||
| 53
    
        Asmody 16.06.15✎ 10:42 | 
        (52) Ты оперируешь уже с другим объектом.
 По-честному, пСсылка должен стать внутри процедуры "только для чтения". | |||
| 54
    
        Бубка Гоп 16.06.15✎ 10:42 | 
        (53) дык он её итак только читает     | |||
| 55
    
        ДенисЧ 16.06.15✎ 10:44 | 
        (50) И в каком языке дохнет объект, ссылку на который передают по значению?     | |||
| 56
    
        Asmody 16.06.15✎ 10:44 | 
        Например, 
 Процедура ЧтоНибудь(пСсылка) пСсылка = Справочники.Номенклатура.ПустоеЗначение(); КонецПроцедуры ЧтоНибудь(КакаяТоНоменклатура.ПолучитьОбъект().Ссылка); это верный способ выстрелить себе в ногу? | |||
| 57
    
        Asmody 16.06.15✎ 10:45 | 
        (55) А где указано, что ты передаешь ссылку?     | |||
| 58
    
        ДенисЧ 16.06.15✎ 10:46 | 
        (57) MyFunc(&MyVar)     | |||
| 59
    
        Asmody 16.06.15✎ 10:46 | 
        Получается, что передача, например, массива без или с Знач не имеет разницы.     | |||
| 60
    
        Asmody 16.06.15✎ 10:46 | 
        (58) Так это не передача по значению!     | |||
| 61
    
        ДенисЧ 16.06.15✎ 10:47 | 
        (60) Это передача по значению ссылки, а не объекта )     | |||
| 62
    
        Asmody 16.06.15✎ 10:48 | 
        (61) Значит ты и в функции ожидаешь ссылку, а не значение. 
 Сигнатура функции какая у тебя будет? | |||
| 63
    
        ДенисЧ 16.06.15✎ 10:48 | 
        (62) void MyFunc(MyObject* MyVar)     | |||
| 64
    
        Asmody 16.06.15✎ 10:51 | 
        (63) Ну так это и есть передача по ссылке.
 Другое дело, что в сях коллекции только так и можно передавать. | |||
| 65
    
        Asmody 16.06.15✎ 10:57 | 
        java в этом плане честнее. Там нет никаких "знач" и всё передается по значению. Только оговаривается, что "значением" объекта является ссылка на объект в куче.     | |||
| 66
    
        Asmody 16.06.15✎ 10:58 | 
        Кстати, как отработает (38) в клиент-сервере?     | |||
| 67
    
        Asmody 16.06.15✎ 10:58 | 
        (66)+ в смысле, в УФ     | |||
| 68
    
        Stepa86 16.06.15✎ 11:01 | 
        (66) так же     | |||
| 69
    
        Бубка Гоп 16.06.15✎ 11:02 | 
        (68) а вот и нет
 0 0 | |||
| 70
    
        Enterprise 16.06.15✎ 11:02 | 
        (59) при передачи агрегатных параметров по значению, их можно изменять     | |||
| 71
    
        Бубка Гоп 16.06.15✎ 11:03 | 
        Если с клиента на клиент, то
 0 1 Если с клиента на сервер, то 0 0 | |||
| 72
    
        Enterprise 16.06.15✎ 11:05 | 
        (66) 0 будет     | |||
| 73
    
        Asmody 16.06.15✎ 11:08 | 
        (71) Спасибо 1Су за "радости" отладки.     | |||
| 74
    
        Бубка Гоп 16.06.15✎ 11:09 | 
        Выходит, что при клиент-серверном взаимодействии, Знач отрабатывает "честно" даже с коллекциями     | |||
| 75
    
        Бубка Гоп 16.06.15✎ 11:10 | 
        (73) Примечательно, что про эти особенности СП умалчивает, ну или я не там смотрю     | |||
| 76
    
        Stepa86 16.06.15✎ 11:14 | 
        (71) а вот сейчас обидно было     | |||
| 77
    
        Asmody 16.06.15✎ 11:15 | 
        Проверил на 2014, файловая. Не подтверждается (71)     | |||
| 78
    
        Stepa86 16.06.15✎ 11:16 | 
        (77) а где у тебя сервер в файловой?     | |||
| 79
    
        Бубка Гоп 16.06.15✎ 11:16 | 
        (77) а я на клиент-серверной     | |||
| 80
    
        Бубка Гоп 16.06.15✎ 11:16 | 
        правда, у меня 8.2.19     | |||
| 81
    
        Stepa86 16.06.15✎ 11:17 | 
        Ну вообще (71) объясняется в (3)     | |||
| 82
    
        Бубка Гоп 16.06.15✎ 11:19 | 
        (81) это все понятно, меня интересует ответ на (35)     | |||
| 83
    
        Asmody 16.06.15✎ 11:22 | 
        А, не, подтверждается! Это я косякнул.     | |||
| 84
    
        Stepa86 16.06.15✎ 11:22 | 
        (82) Когда среда не меняется (клиент-клиент, сервер-сервер), то у коллекции передается ссылка, а вот при смене среды передается весь объект, потому что его тупо на сервере нет. Если стоит знач, то назад ничего не передается, если не стоит, то этот весь объект возвращается.
 Я так это понимаю. | |||
| 85
    
        Asmody 16.06.15✎ 11:22 | 
        Вот код, можете проверить:
 &НаСервереБезКонтекста Процедура Команда1НаСервере() м=Новый Массив(); Сообщить(м.Количество()); Фигакс(м); Сообщить(м.Количество()); Фигакс1(м); Сообщить(м.Количество()); КонецПроцедуры &НаКлиенте Процедура Команда1(Команда) Команда1НаСервере(); КонецПроцедуры &НаКлиенте Процедура Команда2(Команда) м=Новый Массив(); Сообщить(м.Количество()); Фигакс(м); Сообщить(м.Количество()); Фигакс1(м); Сообщить(м.Количество()); КонецПроцедуры &НаКлиентеНаСервереБезКонтекста Процедура Фигакс(Знач мм) мм.Добавить(0); КонецПроцедуры &НаСервереБезКонтекста Процедура Фигакс1(Знач мм) мм.Добавить(0); КонецПроцедуры | |||
| 86
    
        Asmody 16.06.15✎ 11:24 | 
        Даже на файловой.     | |||
| 87
    
        Enterprise 16.06.15✎ 11:27 | 
        (84) Только не сам объект передается, а его копия     | |||
| 88
    
        Asmody 16.06.15✎ 11:29 | 
        Усугубим ситуацию:
 
 | |||
| 89
    
        Enterprise 16.06.15✎ 11:30 | 
        (86) Что файловая, что клиент-серверная, работа одинаковая     | |||
| 90
    
        Бубка Гоп 16.06.15✎ 11:31 | 
        (89) не всегда     | |||
| 91
    
        Asmody 16.06.15✎ 11:34 | 
        Исходя из вышеизложенного, легко видеть, что Знач не защищает вас от случайной "порчи" объекта внутри процедуры.     | |||
| 92
    
        Enterprise 16.06.15✎ 11:35 | 
        (90) "При работе в файл-серверном варианте клиент и сервер представляют собой один компьютер, но на логику взаимодействия это не влияет"     | |||
| 93
    
        Asmody 16.06.15✎ 11:35 | 
        Продолжаем издевательства:
 
что выведет этот код? | |||
| 94
    
        Enterprise 16.06.15✎ 11:40 | 
        (93) массивы     | |||
| 95
    
        Enterprise 16.06.15✎ 11:45 | 
        (93) "Например, если в процедуру по значению передан массив, то можно очистить этот массив методом Очистить(), но нельзя изменить в вызывающей процедуре само значение параметра"     | |||
| 96
    
        Ненавижу 1С гуру 16.06.15✎ 11:46 | 
        (71) идиоты     | |||
| 97
    
        fisher 16.06.15✎ 12:34 | 
        (96) Ну почему? Логика тут есть. Смотри (3).
 На клиенте коллекции только по ссылке ходят (чтобы не гоняли через стек большие коллекции), но при серверном вызове это выливается в то, что коллекция поползет обратно с сервера и десериализуется, что зачастую абсолютно лишнее. Вот и сделали другое поведение. Хотя путаницу вызывает, да. | |||
| 98
    
        Phace 16.06.15✎ 13:15 | 
        Если подытожить, то Рарус из (0) был прав, массово используя Знач.     | |||
| 99
    
        Ненавижу 1С гуру 16.06.15✎ 16:09 | 
        (97) это неправильно потому что функция/процедура ведет себя по-разному, в зависимости от места вызова     | |||
| 100
    
        Drac0 16.06.15✎ 16:16 | 
        (73) Сериализация же. Вполне логично :)     | |||
| 101
    
        Phace 16.06.15✎ 16:19 | 
        (99) А мне очень понравилась фраза из (3) :)
 "В-четвёртых, использование ключевого слова Знач при объявлении параметров процедур и функций. Дело в том, что при клиент-серверном взаимодействии ЭТО КЛЮЧЕВОЕ СЛОВО ЗНАЧИТ СОВСЕМ НЕ ТО, что при работе внутри одного компьютера, клиентского или серверного. | |||
| 102
    
        GROOVY 16.06.15✎ 16:22 | 
        Чувствую себя на уроке информатики в 9том классе.
 Реально, никто не задавался вопросом, как передача параметров работает? Не могу поверить. | |||
| 103
    
        Phace 16.06.15✎ 16:25 | 
        Да все наверное задавались, но, думаю, многие не знали, например (71).     | |||
| 104
    
        Ненавижу 1С гуру 16.06.15✎ 16:28 | 
        (102) для элементарных типов: числа, строки, булево, даты - поведение одинаковое как для клиент/серверной передачи, так и для внутри одного клиента (или сервера) - со Знач не возвращает измененный параметр, без - возвращает
 для объектов: для клиент/серверной передачи сериализуется в копию объекта, при этом со Знач в одну только сторону, а без - в обе внутри клиента (или сервера) - передается ссылка на объект, соответственно со Знач в одну сторону, без - в обе | |||
| 105
    
        Phace 16.06.15✎ 16:35 | 
        (102) Указание ЗНАЧ, вовсе не означает что передается ЗНАЧЕНИЕ параметра, а не ссылка на него (а ведь это и должно происходить), все зависит от условий вызова функции.     | |||
| 106
    
        GROOVY 16.06.15✎ 16:37 | 
        (105)  Так это и без 1с понятно.     | |||
| 107
    
        Phace 16.06.15✎ 16:41 | 
        (106) Логичнее было бы заменить ключевое слово ЗНАЧ, скажем, на НЕВОЗВР.     | |||
| 108
    
        Asmody 16.06.15✎ 16:46 | 
        (107) логичнее было бы вообще запретить возвращать параметры процедур, либо указывать это явно.     | |||
| 109
    
        Phace 16.06.15✎ 16:46 | 
        (107)+ ...либо наоборот, по умолчанию, без ключевых слов движение параметра только в процедуру/функцию, а если нужно вернуть значение параметра обратно, то использовать перед ним какой-нибудь ВОЗВР.     | |||
| 110
    
        Phace 16.06.15✎ 16:54 | 
        Глянул сейчас в типовой "Управление Скромной Фирмой" форму документа "ПриходнаяНакладная", и о, ужас, из нескольких десятков процедур, где есть передача ссылок на объекты (договор, валюта, контрагент), только в одной процедуре есть ключевое слово ЗНАЧ:
 Процедура ОбработатьИзмененияПоКнопкеЦеныИВалюты(Знач ВалютаРасчетовПередИзменением, ПересчитатьЦены = Ложь) Все остальное НЕОПТИМИЗОРОВАНО согласно (3), хотя конфигурация на УФ изначально делалась. | |||
| 111
    
        fisher 17.06.15✎ 09:35 | 
        (99) С точки зрения прозрачности - да, неправильно. Но тут из двух зол выбирали меньшее. Была бы статическая типизация - компилятор просто ругался бы при попытке указания Знач не для примитивных типов на клиенте и всё было бы совсем ок.     | |||
| 112
    
        fisher 17.06.15✎ 09:44 | 
        А, не. Гоню. Для объектных типов на клиенте Знач работает как final в java. Объект передается по ссылке, но переназначить ссылку нельзя. А без Знач - можно.     | |||
| 113
    
        Гобсек 17.06.15✎ 09:48 | 
        (108)+1     | |||
| 114
    
        fisher 17.06.15✎ 09:51 | 
        Вернее, не совсем так. Запутался.
 Короче без Знач - ссылка на объект передается напрямую. А со Знач - помещается в стек, что гарантирует неизменность исходной ссылки. | |||
| 115
    
        MadProg 17.06.15✎ 09:59 | 
        Вот она старая добрая Миста, с глобальными вопросами, а не пустым трепом про бог знает что...     | |||
| 116
    
        Бубка Гоп 17.06.15✎ 11:35 | 
        Если Знач - добро, почему оно редко встречается в типовых? Причем именно там, где можно обойтись без возврата параметра процедур? Может, выигрыш в производительности, если он есть, ничтожен?     | |||
| 117
    
        Phace 17.06.15✎ 13:06 | 
        (116) Если передавать ссылки на объекты, то да, выигрыш ничтожен (но он есть), а если коллекции, то тут различия в производительности серьезные.     | 
| Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |