Использование программных перечислений

Опубликовал Роман Уничкин (unichkin) в раздел Программирование - Практика программирования

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

Например - при загрузке некоего файла, в зависимости от статуса загружаемой абстрактной заявки надо выполнить некое действие:

// Чтение файла Excell, получение и обработка статуса заявки текущей строки
СтатусЗаявки = СокрЛП(Excel.Cells(1, Сч).Text);

Если СтатусЗаявки = "НаУтверждении" Тогда
	//...	
ИначеЕсли СтатусЗаявки = "ТоварВПути" Тогда
	//...	
ИначеЕсли СтатусЗаявки = "КОтгрузке" Тогда	
	//...	
КонецЕсли;

Здесь пока все очень просто, и вроде бы на виду. Но вот поступает дополнительно пожелание от клиента, и где-нибудь на 100 строк ниже понадобилось  добавить:

Если СтатусЗаявки = "Котгрузке" Тогда
	//...
ИначеЕсли СтатусЗаявки = "Отказ" Тогда	
	//...	
КонецЕсли; 

Наметанный глаз сразу увидит будущий косяк. Строка "КОтгрузке" не равна "Котгрузке" - налицо ошибка программиста (буква "О" <> "о"). Можно лечить это приведением переменной к нижнему регистру. Посмотрите какой код мы после этого получим:

СтатусЗаявки = нРег(СокрЛП(Excel.Cells(1, Сч).Text));

Если СтатусЗаявки = "наутверждении" Тогда
	//...
ИначеЕсли СтатусЗаявки = "товарвпути" Тогда
	//...	
ИначеЕсли СтатусЗаявки = "котгрузке" Тогда	
	//...	
КонецЕсли; 

//...

// Еще любят делать вот так, тысячи раз вызывая функцию при обработке данных:
Если СтатусЗаявки = нРег("КОтгрузке") Тогда
	//...
ИначеЕсли СтатусЗаявки = нРег("Отказ") Тогда	
	//...	
КонецЕсли; 

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

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

Еще один неочевидный, но на самом деле очень неудобный момент - мы не можем видеть всех возможных значений переменной. Т.е. в примере значение поля "СтатусЗаявки" уже может иметь четыре значения. А вдруг, где-то в коде есть и пятое, и шестое?.. Зачем нужно их видеть - затем, чтобы убедиться, что все возможные значения учтены. К примеру возникли какие-то ошибки в вновь пришедшем на загрузку файле -  добавилось еще одно значение статуса заявки - "ВНаборе". Чтобы убедиться что это действительно новое значение - при таком подходе понадобится прошерстить весь имеющийся код.

А что если не сравнивать тупо на строку? Что если загнать все возможные значения входящих статусов в структуру?

СтруктураСтатусыЗаявок = Новый Структура;
СтруктураСтатусыЗаявок.Вставить("НаУтверждении" , "НаУтверждении");
СтруктураСтатусыЗаявок.Вставить("ТоварВПути"    , "ТоварВПути");
СтруктураСтатусыЗаявок.Вставить("КОтгрузке"     , "КОтгрузке");
СтруктураСтатусыЗаявок.Вставить("Отказ"         , "Отказ");

//... Цикл по строкам
СтатусЗаявки = СокрЛП(Excel.Cells(1, Сч).Text);

Если СтатусЗаявки = СтруктураСтатусыЗаявок.НаУтверждении Тогда
	//...	
ИначеЕсли СтатусЗаявки = СтруктураСтатусыЗаявок.ТоварВПути Тогда
	//...
ИначеЕсли СтатусЗаявки = СтруктураСтатусыЗаявок.КОтгрузке Тогда	
	//...
КонецЕсли; 

Уже все становится интереснее, не правда ли? Но пойдемте дальше. К примеру код по загрузке очень большой, разделен на пять разных методов, и обьявлять в каждом структуру - это дублирование кода. Можно сделать ее глобальной пременной, но сколько может быть таких структур? И ведь каждая может состоять из большого количества элементов, все это будет в теле основной программы (разделе инициализации). Гораздо логичнее объявить метод "СтатусыЗаявок()". Этот метод будет возвращать структуру, и в коде пишем уже СтатусыЗаявок().НаУтверждении и т.п. Но это означает, что каждое обращение к методу создает новую структуру. Выход - кэширование.

Если работа ведется в обработке  - то можно объявить глобальную переменную, я ее привык называть "мСтруктураКэшПрограммныхПеречислений" (префикс "м" - флаг глобальной переменной). И кэшировать в нее все программные перечисления. Кроме того, по рекомендации коллеги BUDIVAL, которую он отправил в ЛС - лучше возвращать фиксированную структуру. Тогда можно быть 100% уверенным что коллекция заполняется именно в отвечающем за это методе. Вот как в итоге может выглядеть модуль объекта обработки для загрузки заявок:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ВнешняяОбработка.ЗагрузкаЗаявок.МодульОбъекта
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Перем мСтруктураКэшПрограммныхПеречислений;

#Область ПрограммныйИнтерфейс

Функция ДанныеФайлаУспешноСчитаны() Экспорт
	
	//...
	СтатусЗаявки = СокрЛП(Excel.Cells(1, Сч).Text);

	Если СтатусЗаявки = СтатусыЗаявок().НаУтверждении Тогда
		//...		
	ИначеЕсли СтатусЗаявки = СтатусыЗаявок().ТоварВПути Тогда
		//...		
	ИначеЕсли СтатусЗаявки = СтатусыЗаявок().КОтгрузке Тогда	
		//...		
	КонецЕсли; 

	Возврат Истина; 		
	
КонецФункции

Функция КонтрагентыОтказныхЗаявок() Экспорт
	
	//...	
	Если СтатусЗаявки = СтатусыЗаявок().Отказ Тогда
		//...
	КонецЕсли; 	
	
КонецФункции
 
#КонецОбласти 


#Область СлужебныеПроцедурыИФункции

#Область ПрограммныеПеречисления

Функция СтатусыЗаявок()
	
	Если НЕ мСтруктураКэшПрограммныхПеречислений.Свойство("СтатусыЗаявок") Тогда		
		СтруктураСтатусыЗаявок = Новый Структура;
		СтруктураСтатусыЗаявок.Вставить("НаУтверждении" , "НаУтверждении");
		СтруктураСтатусыЗаявок.Вставить("ТоварвПути"    , "ТоварВПути");
		СтруктураСтатусыЗаявок.Вставить("КОтгрузке"     , "КОтгрузке");
		СтруктураСтатусыЗаявок.Вставить("Отказ"         , "Отказ");
					
		мСтруктураКэшПрограммныхПеречислений.Вставить("СтатусыЗаявок", Новый ФиксированнаяСтруктура(СтруктураСтатусыЗаявок));
	КонецЕсли; 
	
	Возврат мСтруктураКэшПрограммныхПеречислений.СтатусыЗаявок;
		
КонецФункции
 
#КонецОбласти 

#КонецОбласти 

мСтруктураКэшПрограммныхПеречислений = Новый Структура;

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

  • рассчет значения будет выполнен только один раз - при первом обращении;
  • нигде не будет дублирования кода;
  • все используемые значения коллекции определяются только в одном месте.

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

Функция ИдентификаторПоКодуСчета(КодСчета)
	Возврат "сч" + СтрЗаменить(КодСчета, ".", "_");		
КонецФункции

Функция ИспользуемыеСчета()
	
	Если НЕ мСтруктураКэшПрограммныхПеречислений.Свойство("ИспользуемыеСчета") Тогда
		СтруктураИспользуемыеСчета = Новый Структура;
		
		// Чтобы добавить счет, добавьте сюда его код
		СтрокаКодовСчетов = "10, 10.3, 19, 60.1, 60.2, 62, 51, 51, 70, 70.1, 76.АВ, 90, 90.01, 90.02";
		
		МассивКодовСчетов = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(СтрокаКодовСчетов, ", ");		
		Для каждого КодСчета Из МассивКодовСчетов Цикл
			КлючСчета = ИдентификаторПоКодуСчета(КодСчета);
			СтруктураИспользуемыеСчета.Вставить(КлючСчета, ПланыСчетов.Управленческий.ПустаяСсылка());			
		КонецЦикла; 
		
		Запрос = Новый Запрос;
		Запрос.Текст = 
			"ВЫБРАТЬ
			|	Управленческий.Ссылка,
			|	Управленческий.Код
			|ИЗ
			|	ПланСчетов.Управленческий КАК Управленческий
			|ГДЕ
			|	Управленческий.Код В(&МассивКодовСчетов)";
		
		Запрос.УстановитьПараметр("МассивКодовСчетов", МассивКодовСчетов);
		
		РезультатЗапроса = Запрос.Выполнить();
		
		Выборка = РезультатЗапроса.Выбрать();		
		Пока Выборка.Следующий() Цикл			
			КлючСчета = ИдентификаторПоКодуСчета(Выборка.Код);
			СтруктураИспользуемыеСчета.Вставить(КлючСчета, Выборка.Ссылка);		
		КонецЦикла;					
		
		мСтруктураКэшПрограммныхПеречислений.Вставить("ИспользуемыеСчета", Новый ФиксированнаяСтруктура(СтруктураИспользуемыеСчета));
	КонецЕсли; 	
	
	Возврат мСтруктураКэшПрограммныхПеречислений.ИспользуемыеСчета;
	
КонецФункции

// Пример использования:
Если ВыборкаПоОстаткам.Счет = ИспользуемыеСчета().сч90_01 Тогда
	//...
ИначеЕсли ВыборкаПоОстаткам.Счет = ИспользуемыеСчета().сч90_02 Тогда
	//...	
КонецЕсли; 

Новая переменная добавляется простым редактированием строки кодов счетов. Какие плюсы:

  • Это гораздо быстрее, чем писать ПланыСчетов.Управленческий.<ИмяПредопределенногоСчета> 
  • Имя предопределенного элемента еще надо узнать - я не встречал таких гуру, которые по коду счета помнят идентификатор предопределенного элемента. Обычно в голове сидит именно код счета, а идентификатор узнается через предопределенный список элементов плана счетов, т.е. туда надо провалиться, найти код счета, скопировать имя... - долго, добавить код в строку гораздо быстрее.
  • Счет может и не быть предопределенным. В таких случаях часто используют конструкцию "НайтиПоКоду", причем вызывают ее десять раз подряд, при чем не гнушаются циклом.... Мрак:)

Желаю всем приятной работы, и чистого кода.

См. также

Вознаграждение за ответ
Показать полностью
Комментарии
1. Виталий Чебан (VitaliyCeban) 209 12.12.16 12:31 Сейчас в теме
Хорошее решение, разве что только скобки () глаза мусолят, но это терпимо.
Вот бы сделали "свойства", как в C#. С виду, обычные поля, а на деле - методы.
Хотя, если уж вносить изменения в встроенный язык 1С, то относительно этой задачи, надо сразу enum'ы делать.
3. Константин Гейнрих (CyberCerber) 109 12.12.16 14:06 Сейчас в теме
Главная проблема, что для этого перечисления не сработает контекстная подсказка. Т.е. все равно придется идти и смотреть, какие значения бывают, копировать, вставлять...
pikachu94; TreeDogNight; minimajack; Yakud3a; Zhilyakovdr; 7OH; Krio2; Danila-Master; herfis; kraynev-navi; tormozit; mindcannon; +12 Ответить
4. Виктор Григоренко (JohnGalt) 2 12.12.16 16:56 Сейчас в теме
Актуальная проблема. Исходя из собственного опыта, лучше все настройки, в том числе и сравнения "повесить" на пользователя. Назначить ответственных за механизмы/процессы. Для этого лучше всего сделать справочник или несколько с набором реквизитов/табличных частей для различных настроек. И настройки получать, например, ПриНачалеРаботыСистемы()
5. Роман Уничкин (unichkin) 303 12.12.16 17:12 Сейчас в теме
(4) Ну, тут речь не совсем об этом. Вам к уже введенным настройкам надо как-то обращаться в коде. То что должен быть момент передачи ответственности - полностью согласен, как и с тем что лучше такое реализовать пользовательской настройкой. Только имхо, это не взлетит в 90% случаев фикси. Но это уже тема для отдельной беседы)
6. Алекс Кон (alex-l19041) 7 12.12.16 17:16 Сейчас в теме
(1)
Хорошее решение
- можно уточнить о чем идет речь ? (обсуждается какая-то публикация ?)
7. Роман Уничкин (unichkin) 303 12.12.16 17:26 Сейчас в теме
Что-то на ИС с комментариями, не видел (1) и (2)
(1) Ну да, мозолят) Идея использовать структуру для этих целей и появилась после того как прочитал чей-то коммент про отсутствие таких вещей в 1С, там тоже человек с любовью С вспоминал)
(6) я так понимаю, текущая ;)
8. Роберт В е р т и н с к и й (v3rter) 12.12.16 17:29 Сейчас в теме
9. rjhev korum (корум) 297 12.12.16 17:35 Сейчас в теме
(8) это скорей не автор забыл, а движок инфостарта заглючил...
10. Роберт В е р т и н с к и й (v3rter) 12.12.16 17:49 Сейчас в теме
Если взять не общий случай - ветвление кода, а частный - выбор набора параметров или макета, то чем плох обыкновенный справочник?
11. shurik_shurik (shurik_shurik) 12.12.16 17:57 Сейчас в теме
Это очень хорошо, если во входящем файле статусы заявок без пробелов записаны. А если с пробелами, как тогда поступать?
Идея конечно интересная.
13. Сан Саныч (herfis) 54 12.12.16 18:16 Сейчас в теме
Честно говоря, профита не так много как хотелось бы.
Но уже одно то, что в рантайме упадет сразу в том месте, где была ошибка в названии перечисления, дорогого стоит.
Т.е. в сложных случаях имеет смысл использовать. В простых - вряд ли.
the1; 7OH; zqzq; +3 Ответить 1
14. Роман Уничкин (unichkin) 303 12.12.16 19:20 Сейчас в теме
(8)(10) не понял вопросов?
(11) Любую коллекцию параметров удобно так использовать - посмотрите последний пример с планом счетов. В примере - сравниваются значения структуры. Ну добавьте такой элемент:
СтруктураСтатусыЗаявок.Вставить("ТоварВПути"    , "Товар в пути");
15. Роман Уничкин (unichkin) 303 12.12.16 19:35 Сейчас в теме
(13) Основной профит - в удобной структуре кода. Кроме того, автоматически получается оптимизация - в том смысле что коллекция параметров не будет рассчитываться по 10 раз подряд. Неоднократно видел как люди в цикле пишут что-то вроде сч70_1_1 = ПланыСчетов.Хозрасчетный.НайтиПоКоду("70.1.1").
В каких случаях использовать - я теперь только так работаю, если есть несколько строковых констант, даже не задаюсь вопросом "надо ли". Это похоже на рассуждение: "зачем оформлять код по правилам ИТС, для своей разовой доработки?" - т. е. человек не понимает зачем вообще его нужно оформлять, не видит в чем удобство. Я например даже для небольших работ все оформляю - это копейки времени, которые окупаются с лихвой если из разовой доработки понадобится ваять что-то серьезное, или передать кому-то на анализ, или вспомнить что делалось через полгода. Это на подкорке. Чтобы я забыл код оформить - никогда такого не было. Также и здесь. Но это конечно мое "имхо")
16. Николай Васильев (vasilev2015) 208 13.12.16 10:15 Сейчас в теме
Может, лучше использовать соответствие ?
Синтаксис похожий, плюшек больше.
Подходит для больших списков.
the1; vvirus; +2 Ответить
17. Сан Саныч (herfis) 54 13.12.16 10:20 Сейчас в теме
(15) "Основной профит - в удобной структуре кода". Не согласен. "Структура кода" удобнее не становится. Я не про счета и кэширование (это уже несколько про другое), а про саму идею программных перечислений. В плане удобства - получаем сомнительный аргумент "красивенько" против дополнительного времени на реализацию и въезжание постороннего программиста в этот код. Вот своевременное падение в рантайме для легкого поиска ошибки - это профит. Если бы во время компиляции ругалось - это вообще был бы всем профитам профит. А если бы еще и автокомплишн в конфигураторе - практически полноценные перечисления бы вышли.
18. Роман Уничкин (unichkin) 303 13.12.16 11:05 Сейчас в теме
(17) Именно в нем. "Тупой код с хорошей структурой, лучше чем тупая структура с гениальным кодом". Про время на реализацию - расхожее заблуждение. Дровосек рубит деревья, у него спрашивают - мужик, че ты мучаешься, у тебя ж топор тупой. Наточи топор. А он отвечает: "мне НЕКОГДА! мне надо РУБИТЬ". И все "рубят". Код должен читаться как книга.
По приоритету, для меня так:
- "въехать" в это можно достаточно быстро
- при этом можно быть уверенным что коллекция заполняется только в одном конкретном месте, благодаря использованию фиксированной структуры
19. Роман Уничкин (unichkin) 303 13.12.16 11:06 Сейчас в теме
(16) Используйте то, что вам удобнее) Но соответствие не выдаст исключения при получении отсутствующего значения, а вернет неопределено. У него несколько иное назначение, чем у структуры.
sulfur17; +1 Ответить
20. Александр Беляков (=Kollega=) 13.12.16 14:39 Сейчас в теме
Идея хорошая, но все же ИМХО лучше один раз вызвать функцию и вернуть в локальную переменную структуру и работать с ней, чем 10 раз вызывать и проверять, проиницилизирована ли нужная нам структура.
Но это так просто придирка, хотя когда подобных структур будет достаточно много (хотя я даже не представляю себе род такой задачи), поиск и копирование структур может стать достаточно ощутимым.
21. Сан Саныч (herfis) 54 13.12.16 16:19 Сейчас в теме
(20) Тут как раз все в порядке.
Во-первых, ленивая инициализация - это само по себе хорошо.
Во-вторых, явная инициализация на старте - это еще одна "точка привязки" в коде для реализации этой концепции. Абсолютно лишняя.
ЗЫ. Поиск в структуре по ключу не должен стать ощутимым, даже если ключей будет много. Если я правильно помню - это хэшированная структура данных. Ну, разве что свопить начнет :) А копирования тут нет.
22. Леонид Павлиенко (PLAstic) 60 13.12.16 18:08 Сейчас в теме
Не имею возможности изучить каменты. А автору уже намекнули на то, что надо вынести инфу в табличный макет и грузить соответствия из него?
23. Андрей Акулов (DrAku1a) 1188 14.12.16 09:40 Сейчас в теме
Мне кажется, что автор начиная со первого примера "СтруктураСтатусыЗаявок" забыл про своё-же замечание: (буква "О" <> "о").
корум; belchonokh; klinval; dimk@a; +4 Ответить 1
24. Николай Орлов (sulfur17) 14.12.16 11:44 Сейчас в теме
А можно функцию СтатусыЗаявок() разместить в глобальном общем модуле с повторным использованием возвращаемых значений на время сеанса?
Тогда и переменная мСтруктураКэшПрограммныхПеречислений не нужна и можно будет использовать СтатусыЗаявок() в других модулях.

Например если я хочу передать СтатусыЗаявок().Отказ в качестве параметра из другого модуля, то в другом модуле функцию СтатусыЗаявок() не видно. А если разместить ее в глобальном модуле, то будет видно.
unichkin, Что об этом думаете?
25. rjhev korum (корум) 297 14.12.16 11:55 Сейчас в теме
(0) Более другой вариант.
Заполнять такие перечисления в таблицы на форме, проводить программное сопоставление, окончательную корректировку оставлять пользователю.
Обработку данных производить с учетом полученных таблиц соответствий (количество значений в которых неопределено и разработчика не волнует - он работает со стандартным справочником/перечислением из соответствия)

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

обработаются одинаково корректно.
26. Роман Уничкин (unichkin) 303 14.12.16 13:10 Сейчас в теме
(23)
Мне кажется, что автор начиная со первого примера "СтруктураСтатусыЗаявок" забыл про своё-же замечание: (буква "О" <> "о").
- не вижу ошибки, ткните пальцем если не сложно.
(24) Я думаю, если дорабатываете конфу - то добавьте нормальное перечисление.
Этот способ хорош для константных значений, уникальных в каком-то определенном алгоритме (внешнем или внутреннем). Например - статусы заявок приходят к нам в виде текста. Но в конфигурации это наверняка перечисление. Здесь структура нужна только для того, чтобы удобно и качественно проверять все входящие значения статусов.
Еще пример с потолка (кривая методология, просто чтобы отразить суть вопроса): скажем в документе оператор заполняет строковое поле "Причина отказа". Причина может вводиться как из заранее определенного списка, так и произвольно - если установлен соотв. флаг. Так вот - если не добавлять в конфигурации нормальное перечисление (а лучше добавить, сделав "причину" составным полем), то да, наверное логично так сделать. Только модуль ПовтИсп хранит кэш 20 минут. Возможно лучше использовать какие-то существующие кэши конфигурации. И "мСтруктураКэшПрограммныхПеречислений" не будет нужна только для этого конкретного случая.
(25) Если рассуждать только с позиции загрузки заявок - то конечно, да, лучше дать на откуп пользователю. А еще лучше проговорить это все в ТЗ. Потом при формировании структуры перечисления собрать данные из таблицы формы - да, логично, почему нет. Но загрузка заявок - это ведь частный случай, я его использовал для примера. У меня например была задача, в которой я создавал программное перечисление для событий журнала регистрации. Т.е. было примерно так:
СтруктураСобытийЖурнала = Новый Структура();
СтруктураСобытийЖурнала.Вставить("НачалоСеанса", "_$Session$_.Start");
СтруктураСобытийЖурнала.Вставить("КонецСеанса", "_$Session$_.Finish");
СтруктураСобытийЖурнала.Вставить("Проведение", "_$Data$_.Post");
// ну и т. д.
...Показать Скрыть

Потом для фильтров использовал СобытияЖР().Проведение и т.п.
корум; sulfur17; +2 Ответить
27. Игорь Герман (German_Tagil) 4 15.12.16 07:58 Сейчас в теме
28. Владислав Мороз (vlad.frost) 168 15.12.16 09:35 Сейчас в теме
Если инвертировать проверку свойства в мСтруктураКэшПрограммныхПеречислений, то это позволит уменьшить уровни вложенности и код будет читаться легче. Сравните:

Функция СтатусыЗаявок()
	
	Если мСтруктураКэшПрограммныхПеречислений.Свойство("СтатусыЗаявок") Тогда		
		Возврат мСтруктураКэшПрограммныхПеречислений.СтатусыЗаявок;
	КонецЕсли;

	СтруктураСтатусыЗаявок = Новый Структура;
	СтруктураСтатусыЗаявок.Вставить("НаУтверждении", "НаУтверждении");
	СтруктураСтатусыЗаявок.Вставить("ТоварвПути", "ТоварВПути");
	СтруктураСтатусыЗаявок.Вставить("КОтгрузке", "КОтгрузке");
	СтруктураСтатусыЗаявок.Вставить("Отказ", "Отказ");
					
	мСтруктураКэшПрограммныхПеречислений.Вставить("СтатусыЗаявок", Новый ФиксированнаяСтруктура(СтруктураСтатусыЗаявок));
	
	Возврат мСтруктураКэшПрограммныхПеречислений.СтатусыЗаявок;
		
КонецФункции
...Показать Скрыть
29. Роман Уничкин (unichkin) 303 15.12.16 10:09 Сейчас в теме
(28) Я обычно стремлюсь к сокращению "Возвратов", если можно рассчитать значение внутри функции и вернуть результат в конце метода - так и делаю; приведенный вами код не кажется мне более читабельным решением, может дело вкуса. Делайте как вам удобнее) Я останусь при своем.
Кстати, сейчас подумал - что в функциях обычно минимизирую возвраты, а в процедурах как раз наоборот - если есть условие прерывания, стараюсь выполнить его в самом начале, чтобы не использовать лишних расчетов.
30. Владислав Мороз (vlad.frost) 168 15.12.16 13:54 Сейчас в теме
(29) Единая точка выхода, ага, нас тоже так в школе учили. Но если уж вы предлагаете способы, как улучшить читаемость кода, идите дальше. Согласен, в приведённом мной примере данное изменение не сильно улучшит читаемость, но примените его к вашей функции ИспользуемыеСчета(), и там такое улучшение будет уже более актуально. Матчасть: Замена вложенных условных операторов граничным оператором.
31. Роман Уничкин (unichkin) 303 15.12.16 16:41 Сейчас в теме
(30) Да нет в "ИспользуемыеСчета()" ветка условия всего одна, так что принцип тот же что и в (29). То, что описывает приведенная вами статья я стараюсь соблюдать, и это как-то всегда на уровне спинного мозга осознавал - что не стоит допускать дебрей Case-Of Если-Тогда. Однако за наводку и интерес к моей статье - спасибо)
Мне в данном конкретном случае кажется более логичным заполнять структуру именно внутри условия. Возможно потому, что основные цели этих методов (для вызова программного перечисления) - это заполнение соотв. кэша, и более логично в начале алгоритма видеть инициализацию коллекции по условию ее отсутствия. Тут с т.з. рефакторинга было бы неплохо вынести код по заполнению структуры счетов в внешний метод, но я не люблю перегружать программный интерфейс методами (пусть даже и служебный). Т.е. использоваться -то он будет все-равно только в одном месте. Вот если его глобальным сделать, тогда другое дело. Было бы нечто вроде такого:
Функция ИспользуемыеСчета()
	
	Если НЕ мСтруктураКэшПрограммныхПеречислений.Свойство("ИспользуемыеСчета") Тогда
		СтруктураИспользуемыеСчета = Новый Структура;
		
		// Чтобы добавить счет, добавьте сюда его код
		СтрокаКодовСчетов = "10, 10.3, 19, 60.1, 60.2, 62, 51, 51, 70, 70.1, 76.АВ, 90, 90.01, 90.02";
		СтруктураИспользуемыеСчета = ОбщегоНазначенияБП.СтруктураСчетовПоСтрокеКодов(СтрокаКодовСчетов );

		мСтруктураКэшПрограммныхПеречислений.Вставить("ИспользуемыеСчета", Новый ФиксированнаяСтруктура(СтруктураИспользуемыеСчета));
	КонецЕсли; 	
	
	Возврат мСтруктураКэшПрограммныхПеречислений.ИспользуемыеСчета;
	
КонецФункции
...Показать Скрыть
32. Кирилл Власов (neikist) 29.12.16 20:38 Сейчас в теме
Понимаю что поздновато отписываюсь, но как вам такой вариант?

#Область ПрограммноеПеречисление_СтатусыЗаявок

Функция _СтатусыЗаявок_НаУтверждении()	Возврат "НаУтверждении"	КонецФункции
Функция _СтатусыЗаявок_ТоварВПути()		Возврат	"ТоварВПути"		КонецФункции
Функция _СтатусыЗаявок_КОтгрузке()			Возврат	"КОтгрузке"		КонецФункции
Функция _СтатусыЗаявок_Отказ()			Возврат	"Отказ"			КонецФункции


#КонецОбласти

Функция ДанныеФайлаУспешноСчитаны() Экспорт
	
	//...
	СтатусЗаявки = СокрЛП(Excel.Cells(1, Сч).Text);

	Если СтатусЗаявки = _СтатусыЗаявок_НаУтверждении() Тогда
		//...		
	ИначеЕсли СтатусЗаявки = _СтатусыЗаявок_ТоварВПути() Тогда
		//...		
	ИначеЕсли СтатусЗаявки = _СтатусыЗаявок_КОтгрузке() Тогда	
		//...		
	КонецЕсли; 

	Возврат Истина; 		
	
КонецФункции
...Показать Скрыть



Плюсы:
1. Можно использовать в формах &НаСервере, вместо того чтобы каждый раз инициализировать переменную после клиента;
2. Есть автодополнение и контекстная подсказка;
3. Если даже набрать имя функции неправильно - ошибка всплывет на этапе синтаксической проверки (при отладке вашего способа не всегда может получится все ветки прогнать, и до ветки с ошибочно набранным значением можно не добраться)
4. По идее возвращаемое значение таких функций должно "инлайниться" в место использования, так что производительность должна быть такая же как при обычном сравнении со значением, а если и нет то что у меня, что у Вас накладные расходы на вызов функции так или иначе идут.

Минусов с ходу могу назвать только два:
1. Засорение контекстной подсказки, для чего и добавил в начало _;
2. Такое "перечисление" не передашь в другой модуль, разве что вместе со всем текущим контекстом (ЭтотОбъект придется передавать из общего модуля или формы) и делать данные функции экспортными.
33. Роман Уничкин (unichkin) 303 29.12.16 23:51 Сейчас в теме
(32)
1. Объявляете реквизит формы "СтруктураКэшПрограммныхПеречислений", с произвольным типом реквизита... А остальное все то-же) Это если для формы. Вообще правильнее все-же к форме относить то, что касается *формы* - интерактив, все расчеты лучше отправлять на сервер, т.е. в модуль объекта. Ну тут можно много рассуждать и говорить - по всякому можно. Если говорим о внешней обработке можно сделать реквизит обработки произвольного типа - он будет доступен и с сервера и с клиента. Если о объекте конфигурации - сделайте реквизит формы. Или - вызов из модуля ПовтИсп.
2. Если учесть что различие только в префиксе - имхо, не очень удобно для набора, когда много коллекций.
С моей точки зрения, когда перечисление обосабливается в свой метод - это и нагляднее и удобнее. Ну да, синтакс контроль не заругается. Пишите аккуратнее) Каждому свое конечно, используйте то что вам больше подходит. Но мне с таким кодом было бы работать тяжеловато. Подчеркивание в начале метода - это нарушение правил образования имен переменных. Ну и плюшки с ленивой инициализацией теряются.
34. Andrey Erastov (tailer2) 20.01.17 18:31 Сейчас в теме
>через предопределенный список элементов плана счетов, т.е. туда надо провалиться, найти код счета, скопировать имя... - долго

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