Имя: Пароль:
1C
 
Как функции вернуть несколько значений
0 vi0
 
03.10.16
05:32
1. Возврат структуры 50% (11)
2. Свой вариант 45% (10)
3. Возврат одного значения и изменение параметров 5% (1)
Всего мнений: 22

Поделитесь, какими способами вы пользуетесь при необходимости возврата функцией нескольких значений. И почему.
11 vi0
 
03.10.16
06:26
(9) так ты поддерживаешь то, то в (8) написано или нет?
12 Sammo
 
03.10.16
06:26
(7) Ну вот пример - функция должна вернуть несколько значений, которые потом будут использовать как фильтрующие параметры. Можно вернуть список значений, а можно передать менеджер и сделать временную таблицу
13 vi0
 
03.10.16
06:27
(12) ну с временной таблицей это отдельная песня
14 KSergey1C
 
03.10.16
06:34
(11) В целом да, но я бы не стал это возводить в абсолют.
15 Aleksey
 
03.10.16
06:41
А вариант глобальных перемен это какой вариант?
16 vi0
 
03.10.16
06:47
(15) плохой)
17 Sammo
 
03.10.16
06:54
(15) В рамках модуля объекта еще туда-сюда.
Более глобальные - не стоит, имхо.
18 vcv
 
03.10.16
06:59
Возврат какого-нибудь списка значений тоже не ахти вариант. Сложней в разборе результата функции. Нет подсказки по возвращаемому значению. Легко перепутать "имена" возвращаемых значений. Было бы понятие типа "структуры" - вопросов бы не возникало.
19 KSergey1C
 
03.10.16
07:04
(18) 1. Это кто с 7.7 не работал в которых структур не было.
2. Обращаться можно по [0],[1]
20 DrZombi
 
гуру
03.10.16
07:04
Да чего тут думать? :)

Возврат структуры
21 vcv
 
03.10.16
07:14
(19) И что, через полгодика вы вспомните, что функция возвращает в [0]? А тем более, если кто-то другой читать код будет. Варианты типа [0] крайне не рекомендуются во всех приличных местах/языках. Варианты типа ["НомерСтелажа"] тоже, слишком велика вероятность опечатки.
22 KSergey1C
 
03.10.16
07:33
(21) Так написано же КУДА она её возвращает.
23 vcv
 
03.10.16
07:36
(22) Где написано? В коде вы видите что-то типа:
Парам = ПолучитьИтогиДокумента(Накладная);
Наценка = Парам[3]*Парам[2]/Парам[1];
Ну и как этот код читать? За такое в приличных местах уволить нафиг могут.
24 Jokero
 
03.10.16
07:36
Идеологически правильнее наверное структурой, но параметрами так удобно))

Возврат структуры
25 Провинциальный 1сник
 
03.10.16
07:38
(21) Список значений с представлениями позволяет обращаться по имени представления. По сути имитация структуры, которой в семерке нет.
26 Провинциальный 1сник
 
03.10.16
07:39
(23) 7.7 - Парам.Получить("Количество")*Парам.Получить("Цена").. как-то так.
27 vcv
 
03.10.16
07:47
(25) (26) Ага-ага. А когда-нибудь потом, через полгодика, вы узнаете, что в каком-то нечасто выполняющемся куске кода вместо "Количество" вы написали "Клоичество". И хорошо еще если эта ошибка будет быстро замечена, а не приведёт к постоянным косякам за большой период.
По моему, функции, изменяющие свои параметры, это плохо, но возврат списка или структуры - еще хуже.
Если бы в языке был соответствующий тип вроде сишного union - тогда метод возврата структуры был бы хорош.
28 vi0
 
03.10.16
08:13
(27) а чем структура плоха? опечатка приведет к исключению
29 Irbis
 
03.10.16
08:17
По частоте использования:
1. Структура, например, если нужно получить что-то связанное с объектом (периодические значения), но получать сам объект не имеет смысла.
2. Функция с параметром, определяющим значение чего будет возвращено.
3. Несколько функций.

(28) Исключение в данном случае благо. Может привести к неверной работе алгоритма, без ошибок времени выплонения.
30 vi0
 
03.10.16
08:17
(29) про это и говорю, что благо, и проблемы здесь нет с опечатками
31 gigi789
 
03.10.16
08:18
winapi стаил. Функция возвращает истина/ложь  (удачно/не удачно). А в параметры кладем значения возврата. В 1с аналог свойство() для структуры.

Возврат одного значения и изменение параметров
32 jsmith
 
03.10.16
08:20
Разбить ф-ию
33 Azverin
 
03.10.16
08:22
часто вижу этот прием в типовых.

Возврат структуры
34 jsmith
 
03.10.16
08:22
cdecl плохо
35 jsmith
 
03.10.16
08:24
Если структура не класс (семантически), лучше разбить ф-ию.
36 gigi789
 
03.10.16
08:25
(33)ни о чём не говорит типовые сейчас достаточно странные люди пишут.
37 vi0
 
03.10.16
08:27
(32) не получиться разбить в связанных значениях
например возвращается также ТекстОшибки
38 vcv
 
03.10.16
08:34
(28) Структура плоха тем что:
1. Нельзя использовать автодополнение, выше вероятность опечатки
2. Что бы при чтении кода понять, какие параметры могут возвращаться, приходится переходить к определению функции и читать комментарии к ней. Если они еще есть.
3. На опечатки нельзя проверить формально, надеемся на то, что упомянутое вами исключение выскочит при тестировании у разработчика, а не повалит у пользователей в том куске, который разработчик недостаточно протестировал.
3.1. А бывают еще любители избыточного использование Попытка Исключение. Получается вообще взрывоопасная смесь.
4. При рефакторинге могут возникнуть большие проблемы по переделке кучи мест в коде. Не решаемые полуинтеллектуальным поиском с заменой и прочими подобными инструментами.
... можно еще продолжать про недостатки, но юзверя звонят...
39 craxx
 
03.10.16
08:38
(0) структура либо массив
40 zak555
 
03.10.16
08:39
(0) соответствие быстрее структуры
41 jsmith
 
03.10.16
08:44
Не знал, что map быстрее struct
42 jsmith
 
03.10.16
08:46
Хеш-таблицы, понятно
43 zak555
 
03.10.16
08:47
(41) вчера об этом на семинаре говорили
44 ovrfox
 
03.10.16
09:33
Смотря что имеется в виду под вопросом
Если нужно вернуть все перестановки какого -либо множества, то лучше сделать так, чтобы следующая перестановка возвращалась на основании предыдущей без изменения каких либо параметров.
Если нужно вернуть линейный размеры объект - тогда лучше структура (а еще лучше - сам объект)
А если нужно вернуть сто случайных значений от 0 до 1, то лучше всего возвращать массив.
Т.е. что лучше зависит от контекста вопроса больше, чем от самого вопроса.

Свой вариант
45 Лефмихалыч
 
03.10.16
09:43
Если функции надо вернуть несколько РАЗНЫХ значений, не объединенных семантически в какое-то целое, значит у тебя косяк в архитектуре и это две функции, а не одна.

А, если эти значения - это атрибуты какого-то одного объекта, то возвращай структуру да и всё.

Свой вариант
46 vi0
 
03.10.16
10:00
(38)
> 1. Нельзя использовать автодополнение, выше вероятность опечатки
Автодополнение в 1с много где нет? это вопрос тестирования

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

> 3. На опечатки нельзя проверить формально, надеемся на то, что упомянутое вами исключение выскочит при тестировании у разработчика, а не повалит у пользователей в том куске, который разработчик недостаточно протестировал.
Это совсем другой вопрос - вопрос тестирования.

>  3.1. А бывают еще любители избыточного использование Попытка Исключение. Получается вообще взрывоопасная смесь.
Без комментариев

> 4. При рефакторинге могут возникнуть большие проблемы по переделке кучи мест в коде. Не решаемые полуинтеллектуальным поиском с заменой и прочими подобными инструментами.
Например какие проблемы?
47 vi0
 
03.10.16
10:04
(44) пример такой:
функция возвращает ссылку на объект
если вернуть ссылку не получилось, то также нужно вернуть текст ошибки
48 ovrfox
 
03.10.16
10:29
(47) При данном примере оптимальнее всего возвращать сылку отдельным параметром, а ошибку - результатом функции. (если ошибка пустая - значит параметр содержит ссылку)
49 Мимохожий Однако
 
03.10.16
10:35
От ситуации зависит. п.1 будет следующим по убыванию

Свой вариант
50 IlyaSR
 
03.10.16
10:51
1

Возврат структуры
51 Mort
 
03.10.16
11:45
Функция должна возвращать одно значение. Если даже это структура.

Свой вариант
52 vi0
 
03.10.16
11:47
(51) аргументируйте пожалуйста
53 Mort
 
03.10.16
11:50
(48) А возвращать в параметрах ещё отстойней.

(52) Кратко пересказать книжки М.Фаулера и Р.Мартина ?
54 SoulPower
 
03.10.16
11:52
(53) Да.

Возврат структуры
55 Mort
 
03.10.16
11:55
(47) Если функция не нашла значение потому что его нет - возвращается пустое значение, если возникла ошибка из-за неверных параметров, функция должна генерить исключение. Как это исключение будет обрабатывать вызывающая сторона - уже пофиг. Если вызывающая сторона подходит ответственно к параметрам вызова функции, она не должна париться над текстом в принципе.


(54) Там много опирается на то, что функция должна делать что-то одно. А если функция должна делать что-то одно, откуда взяться чему-то второму что можно вернуть?
56 MetaDon
 
03.10.16
11:56
Возврат одного значения и изменение нужных глобальных переменных

Свой вариант
57 Mort
 
03.10.16
11:56
+(55) *над текстом ошибки
58 vi0
 
03.10.16
11:57
(53) не нужно пересказывать, просто аргументируйте своими словами
59 Mort
 
03.10.16
12:03
(58) См(55). Если не убедил - просто посмотри как работает типовая Справочник.XXX.НайтиПоКоду() и аналогичные. Ни одна функция в здравом уме не возвращает текст ошибки и т.п.
60 novichok79
 
03.10.16
12:05
возвращаю данные в соответствии или структуре.

Возврат структуры
61 vi0
 
03.10.16
12:12
(59) а если речь идет о взаимодействии между системами?
1с - драйвер оборудования
1с - 1с по веб-сервсису
и т.п.
62 Loky9
 
03.10.16
12:14
(52) Чтобы она могла быть rvalue.
63 SiAl-chel
 
03.10.16
12:18
Чаще всего использую возврат структуры, но бывает, что в параметрах возвращал значение, а сама функция возвращала статус успешное завершения функции.

Возврат структуры
64 Mort
 
03.10.16
12:18
(61) Тогда Попытка + ВызватьИсключение особенно часто используются.
65 Torquader
 
03.10.16
14:05
В общем случае, возврат нескольких значений - это массив, соответственно, структура, список и т.п. это более упрощённое понимание массива.
Но, реального возврата нескольких значений из функции всё равно нет - вы возвращаете один объект. И, самое главное, что он создаётся, а потом разрушается, что медленнее, чем если передавать эти несколько параметров в функцию или процедуру по ссылке.

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

Передача же параметров в вызов функции по значению проще для читателя, так как он понимает, что будет возвращено и может не подставлять переменные для тех значений, которые ему не нужны.
66 Dmitry1c
 
03.10.16
14:22
}{оливар устроили

Свой вариант
68 vi0
 
04.10.16
05:27
(65) это все хорошо, но вопрос был:  какими способами вы пользуетесь
69 youalex
 
04.10.16
09:24
Структура/Неопределено.
Т.к считать параметры в каждом вызове - напрягает.

Возврат структуры
70 пипец
 
04.10.16
09:26
при желании и процедурой можно значения возвращать ))) (вернее получать в переменную)
71 dmpl
 
04.10.16
09:27
(8) Математически операция А = А + 1 недопустима. Так что не стоит математику переносить на программирование.
72 dmpl
 
04.10.16
09:30
(10) В Си процедур не бывает. Только функции с возвратом типа void. Так что и мешанины быть просто не может.
73 dmpl
 
04.10.16
09:36
(23) Естественно уволить - нет проверки деления на 0.
74 dmpl
 
04.10.16
09:38
(27) Ну создавай структуру с нужными строками в общем модуле отдельной функцией. Тогда очепятка или будет везде, или нигде.
75 Torquader
 
04.10.16
09:50
(71) Для математики это будет рекурсия A<-A+1
Просто в математике = это оператор равенства.
76 Nuobu
 
04.10.16
10:08
Вставлю своё имхо:
Когда нужно передавать по ссылке и там менять:
1. Когда меняешь движения, дописываешь данные в таблицу, список.
2. Когда у тебя есть большая структура, которая содержит несколько параметров, которые ты будешь использовать и тебе нужно дополнить её.
3. Когда передаёшь "Отказ" и там меняешь его на Ложь.
4. Когда передаёшь форму и добавляешь на неё свои элементы.
5. Когда передаёшь МенеджерВременных таблиц.

Это то, что смог вспомнить.

Во всех остальных случаях нужно возвращать.

Свой вариант
77 Mort
 
04.10.16
10:21
(76) из всех примеров возврат значения в параметре только там где "отказ" (отстойная конструкция этот отказ). В остальных случаях это изменение состояния существующего объекта, которое в отсутствие ООП приходится выполнять именно так.
78 vi0
 
04.10.16
10:23
(76) это ты описываешь, больше процедуры чем функции, по логике
79 Провинциальный 1сник
 
04.10.16
13:14
(72) Я знаю. Именно это и создает мешанину в мозгах, когда сишник садится писать на более структурированных языках. У него уже в прошивке отложилось что функция может и должна менять параметры.
80 dmpl
 
04.10.16
13:48
(79) В Си как раз все замечательно. Объявил параметр const - значит менять нельзя. Не объявил - значит он может быть изменен. Потому что с учетом требований с скорости работы может потребоваться и результат вернуть, и параметры поменять.
81 Torquader
 
04.10.16
21:28
(79) (80) В Си как раз всё просто - если параметр передан по значению (засунут в стек), то в функции будет его копия, а если по указателю, то в функции будет указатель на переменную, которую по указателю можно менять.
А вот в Си++ появились ссылки, когда передаётся как бы значение, но внутри это реализовано как указатель - то есть то, что мы имеем в 1С, если не написали Знач.

И не забываем, что написав Знач, мы получим копию строки - и, если она очень длинная, то можно получить существенное замедление работы.
82 vi0
 
05.10.16
04:13
(81) это все круто, конечно, но оффтоп
83 Провинциальный 1сник
 
05.10.16
06:29
(81) Суть не в механизме передачи параметров, а именно в том что в Си нет процедур, и для изменения параметров приходится использовать функцию. Именно поэтому пришедшие из Си и создают функции, меняющие параметры. Паскалисты бы так поступать не стали, а написали бы процедуру.
84 dmpl
 
05.10.16
08:03
(83) Дык а если надо и параметры изменить, и значение вернуть? Что использовать? А если надо вернуть значение, параметры не менять, но поменять не параметры (например, добавить записи в базу)? Деление на процедуры и функции чисто условное, иначе сам ЯП не давал бы менять параметры в функции.
85 notebug
 
05.10.16
09:34
В зависимости от решаемой задачи

Свой вариант
86 organizm
 
05.10.16
10:01
(85) БИНГО!!!
87 organizm
 
05.10.16
10:02
но мне кажется структура отбирает больше памяти, чем просто переменные.
88 Провинциальный 1сник
 
05.10.16
10:03
(84) "Деление на процедуры и функции чисто условное, иначе сам ЯП не давал бы менять параметры в функции."
А лучше бы не давал. С точки зрения парадигмы функционального программирования изменение формальных параметров - жуткая ересь)
89 dmpl
 
05.10.16
10:19
(88) А ты с многопоточным программированием и реентрантностью работал? Когда один и тот же код и одни и те же переменные могут использоваться одновременно несколькими потоками? И тогда единственный способ не конфликтовать потокам - это передавать указатель на некую структуру со всем контекстом потока в качестве параметра функции? И, соответственно, параметр там в процессе работы меняется.
90 Loky9
 
05.10.16
10:43
(89) А с распределёнными вычислениями?
Процедуре передавать аргументы по ссылке можно.
91 cybfyv
 
05.10.16
11:04
В Джаве например вообще нельзя передаваемые параметры менять, только возвращать
92 dmpl
 
05.10.16
11:05
(90) В том-то и дело, что как только начинается реальная жизнь - вся академичность летит к чертям. Так зачем все усложнять? В процедуре априори должен выполняться код, который не может сгенерировать ошибку (возврат результата через перереданные параметры - это же неакадемично, для возврата результата предназначена функция). Много такого кода в реальных задачах?
93 dmpl
 
05.10.16
11:07
(91) Это помогло ей завоевать звание тормозящей и памятежрущей.
94 Torquader
 
05.10.16
11:18
(91) Но, в той же java прекрасно как параметры передаются объекты-контейнеры (BOX) в которых можно менять содержимое, не меняя самого контейнера, то есть так они реализовали указатели.

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

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

(93) Там просто сборка мусора работает тогда, когда памяти стало очень мало - в результате - если память есть, то её будут жрать, пока не надоест. Но, есть ключи запуска, где всё это можно ограничить. И ваша java побыстрее 1С будет.
95 spock
 
05.10.16
11:27
(89) Я дико извиняюсь, а в каком языке программирования практикуется подход обращения к общим переменным из разных потоков?
96 dmpl
 
05.10.16
11:36
(95) Это скорее особенность компилятора. Локальная переменная функции адресуется по контретному смещению (типа [EDI + 0x10h]. Т.о. если 2 процессора выполняют один и тот же код с одним и тем же значением регистра EDI - физически 2 потока будут обращаться к одной и той же ячейке памяти. В принципе, можно для каждого потока использовать свое значение регистра EDI - но тогда для каждого потока придется создавать свою копию всего контекста приложения.
97 spock
 
05.10.16
11:42
(96) не буду утомлять наводящими вопросами и приведу сразу ссылку на race condition: https://ru.wikipedia.org/wiki/Состояние_гонки
98 dmpl
 
05.10.16
11:48
(97) Как минимум в некоторых реализациях C++ локальная переменная не поможет, поскольку она во всех потоках будет иметь одинаковый адрес. Собственно, так я и познакомился с этой особенностью многопоточной работы.
99 spock
 
05.10.16
11:50
(98) Может быть потому что эта локальная переменная (переменная-член класса) была объявлена, как static?
100 spock
 
05.10.16
11:57
(0) Все зависит от ситуации.
Если нужно "набрать" несколько значений, то Структурой их очень удобно возвращать.
В другой случае, через параметры принимаем значение, и через них же возвращаем (типа по ссылки).

Свой вариант
101 dmpl
 
05.10.16
12:03
(99) Не, в том коде вообще не было классов (как и ООП - чисто в стиле Си был код), а переменные были объявлены как int. Только отладка с показом дизассемблерного кода позволила выявить эту особенность. На это, кстати, напарывались и серьезные производители. Например, у некоторых контроллеров Promise драйвер включал кеширование - так вот оно на многопроцессорных системах иногда путало подключенные к нему диски и писало не на тот диск по случайным секторам, если в момент записи была одновременная активность по нескольким дискам.

P.S. С классами как раз все в порядке было, ЕМНИП. Т.к. обращения к обычным членам класса через ECX идут, который для каждого экземпляра класса различается.
102 Loky9
 
05.10.16
12:29
(95) А в каких ситуациях применяются объекты синхронизации?
103 spock
 
05.10.16
12:32
(102) Так я на это и намекал. Что если есть общие для потоков ресурсы, то без объектов синхронизации нельзя. Иначе будут гонки.
104 Torquader
 
05.10.16
12:46
На самом деле, проблема многопоточного обращения появилась из того, что изначально регистры были 16-битными, а переменные 32-битными - в итоге, второй поток мог обращаться к переменной посреди операции.
Например, когда число переходит с 65535 в 65536 за несколько операций, то второй потом получает 0.
Не забываем, что оптимизатор кода может создавать копии значений в стеке, чтобы не обращаться к ним напрямую (особенно, если разыменовывается несколько указателей) и, в итоге, получается совсем не то, что хотел программист.
Опять же, если мы работаем с объектом и меняем его свойства, то желательно, чтобы второй поток нас ждал иначе будет каша.
Встроенных объектов для синхронизации в любой операционной системе предостаточно, так что всё можно сделать и решить, только получается, что если программист не очень хорошо думал, то все потоки друг друга ждут на объектах синхронизации, а программа работает медленнее чем однопоточная.
105 SiMBa_R38
 
05.10.16
13:19
Структура/Неопределено.
Т.к считать параметры в каждом вызове - напрягает.
1. Возврат структуры
106 KSergey1C
 
05.10.16
19:37
Как насчет такой задачи: происходит чтение из табличного файла и в нем разные данные(в разных колонках).

И это все надо преобразовать из текстового значения в строки(хотя бы лишние пробел обрезать или допустим в файле ратикул "00001", а в 1С "000000001"), числа, даты, справочники. Т.е. код, примерно такой


тзДанныеДляЗагрузки.Сумма = ПолучитьЧисло(стрФайла.Сумма);
тзДанныеДляЗагрузки.Колво = ПолучитьЧисло(стрФайла.Колво);
тзДанныеДляЗагрузки.ДатаДок = ПолучитьДату(стрФайла.Дата);
тзДанныеДляЗагрузки.НомерДок = ПреобразоватьНомерДок(ПолучитьНомер(стрФайла.Номер));
тзДанныеДляЗагрузки.Контрагент = НайтиКонтрагента(стрФайла.ИНН);
тзДанныеДляЗагрузки.ЕдИз= НайтиЕдИз(стрФайла.ЕдИз);

Но в файле бывают ошибки. И ошибки разные, есть кртические после которых такую таблицу вообще нельзя загружать, есть те котоыре можно руками поправить, Желательно получить сообщения типа: "В строке Х, не заполнено поле Сумма". Так же допустим ИНН несколько раз встречается проблемный.
Выводить сообщения
НЕ найден контрагент с ИНН 1234567890
НЕ найден контрагент с ИНН 1234567890
НЕ найден контрагент с ИНН 1234567890
НЕ найден контрагент с ИНН 1234567890
НЕ найден контрагент с ИНН 1234567890

Не красиво, желательно, чтобы был отдельный список проблемных ИНН и чтобы не выводить по несколько раз.

Конечно можно написать чере структуру
струкКонтрагент = НайтиКонтрагента(стрФайла.ИНН);

тзДанныеДляЗагрузки.Контрагент = струкКонтрагент .Значение;
БылаОшибка = струкКонтрагент .Ошибка;
БылаКритическаОшибка= струкКонтрагент.БылаКритическаОшибка;

струкСумма = = ПолучитьЧисло(стрФайла.Сумма);;

тзДанныеДляЗагрузки.Сумма= струкСумма .Значение;
БылаОшибка = струкСумма.Ошибка;
БылаКритическаОшибка = струкСумма .БылаКритическаОшибка;
и  т.д.

Получается засорение кода.
107 Провинциальный 1сник
 
06.10.16
03:05
(96) А разве локальные переменные не в стеке хранятся?
108 Провинциальный 1сник
 
06.10.16
03:33
(106) "Получается засорение кода."
А вы не засоряйте. Со структурой можно писать красиво и понятно. Придумывайте осмысленные имена переменных и функций, не дублируйте поля структуры переменными без необходимости.
109 vi0
 
06.10.16
07:38
(77) > отстойная конструкция этот отказ
почему?
110 KSergey1C
 
06.10.16
07:40
(108) В том тои  дело, что разные  функции должны выдавать одинаковые переменные.

Я, например, такое сделал через глобальные переменные.
Здесь можно обсудить любую тему при этом оставаясь на форуме для 1Сников, который нужен для работы. Ymryn