(1) "ТОЛЬКО В КРАЙНИХ СЛУЧАЯХ ИСПОЛЬЗУЙТЕ В ЗАПРОСАХ ВЛОЖЕННЫЕ ЗАПРОСЫ." Не согласен. На Курсы-1с.рф можно купить курс по запросам, там очень хорошо разжевывают почему иногда выигрыш вложенного запроса имеет место.
"ОБЩИЕ МОДУЛИ НЕ ДОЛЖНЫ БЫТЬ ГЛОБАЛЬНЫМИ" А зачем тогда флаг "глобальный"? Слишком уж запрещено.
"НЕ ИСПОЛЬЗОВАТЬ МНОГОВАРИАНТНЫХ УСЛОВНЫХ ОПЕРАТОРОВ – НЕСКОЛЬКО ВЫРАЖЕНИЙ ИНАЧЕЕСЛИ В ПОЛЕ ВЫБОРА" Иногда только так и можно сделать.
Пример (вижу только доп переменную РасчетВыполнен):
Если Значение > 100 Тогда РасчетКатегорииА()
ИначеЕсли Значение > 50 Тогда РасчетКатегорииB()
Иначе РасчетКатегорииC()
КонецЕсли;
Пример 2 (зачем проверять заявку и, возможно, десяток других типов если у нас на входе приходная):
Если ТипЗнчДокумента = Тип("Приходная") Тогда РасчетПН()
ИначеЕсли ТипЗнчДокумента = Тип("Заявка") Тогда РасчетЗаявки();
КонецЕсли;
(4) Я бы разбил к примеру так: ГлобальныйОбщийМодуль, ГлобальныйОтчеты, ГлобальныйНапоминания.
Да, можно в один объединить, но как-то... ну не знаю... По имени модуля должно быть понятно что там :) А глобальный или нет то это такое :)
За тем что глобальный модуль должен быть только один.
Это откуда следует? Да и не может быть таких ограничений.
Даже если взять чисто БСП, то там глобальных модулей много. По тематике так сказать.
Другое дело, что в итоге они будут скомпилированы в один глобальный контекст на уровне платформы. Но для нас это не важно. Для нас это разные модули.
(11) Это специфика БСП, т.к. каждая из подсистем предполагает возможность автономного использования.
Если самописка, то расфасовывать глобальный контекст по разным модулям - это быть ССЗБ.
Никто не мешает функционально все разбить по общим модулям, но вынести в глобальный модуль нужный функционал проксирующими функциями.
(13) конечно плодить кучу глобальных модулей не стоит. Но и все в одном модуле держать тоже не обязательно.
Даже самописки в большинстве случаев делаются на основе БСП (в последнее время). Не будем же в такой самописке выносить все глобальные методы в один общий. И для своего функционала скорее всего создадим свой отдельный глобальный модуль. Это нормальная практика.
"Не рекомендуется использовать в запросе получение значения через точку от поля составного ссылочного типа"
" частности, не рекомендуется обращаться к реквизитам регистратора регистра (например, ТоварыНаСкладах.Регистратор.Дата) и т.п. "
Я никак не "доеду", это в типовых то как? Да и в нетиповых - каждый док нужно расширить реквизитом и сделать базу чуточку жирней)
(2) по теме (рефракторинг пытается все выделить в отдельные процедуры функции по 15-20 строк кода)
Функции рефакторинга
Функции рефакторинга позволяют сделать код более понятным и удобным для восприятия. Например, вы можете оформить часть кода в виде отдельной процедуры или функции (команда Выделить фрагмент):
первый раз на конфигурации, которую видишь первый раз - ОЧЕНЬ тяжело скакать по всем процедурам и функциям, чтобы понять что делается в основной процедуре
(50) Для этого есть комбинация "Ctrl"+"-". И уж совершенно точно анализировать такой код в одной сплошной процедуре никак не проще. Можно, конечно, набыдлокодить и так, что и процедуры с функциями только создают путаницу. Но при нормальном подходе анализ сверху вниз упрощает сопровождение.
Ну и вообще по сути правильно в статье написано. Должны быть ОЧЕНЬ веские основания и какие-то особые случаи для засорения глобального пространства имен. Общие неглобальные модуля - это отдельные пространства имен и в 99.99% случаев это именно то, что требуется.
Через исключение ты в ЖР получишь запись с описанием ошибки.
А если будет возврат кода ошибки или неопределено то тебе придётся с отладчиком разбираться.
когда логика функции не является бинарной.
Пример:
То есть есть функция, которая проверяет является ли контрагент юридическим или физическим лицом (вроде как результат да или нет). Но в фунцию может быть передана пустая ссылка или ссылка на группу справочника. И что согласно рекомендации автора произойдет? - Отработка исключеня. А с чего Вы уверены что Вам всегда в подобном случае нужно вызывать исключение?
(20) А что, если это - нормальное выполнение? Если контрагент - группа то выполнение идет одним путем, если физлицо - добавляется еще что-то, если юрлицо - еще чтото?
(18) в данном случае это не штатная ситуация. Что-то пошло не так. Лучше выбросить исключение. Так будет понятно откуда смотреть.
Если же возвращать что-то другое. Что можно в данном случае вернуть? Неопределено? Допустим. Т.е. есть много разных мест откуда вызывается процедура. И вот в один из вызывов пришли не корректные данные:
Если ЭтоЮрЛицо(Ссылка) Тогда
...
Возвращаем Неопределено и получаем тоже исключение, только в другом месте, но самое главное с непонятным описанием ошибки.
Но самое опасное, что ошибка может вскрыться не сразу, а через кучу процедур. Или вообще не вылезти и в базу будут записываться неверные данные.
(24) эта проблема уйдет, когда Вы осознаете что результат возврата функции всегда нужно инициализировать значением по умолчанию. Таким образом всегда при вызове функции нужно ожидать возврата значения по умолчанию.
Функция ЧтотамПроверить(Хрень)
Резвозврата = неопределено; // инициализация возрата
Если Хрень.Собачья>10 тогда
Резвозврата = истина
конецеесли
возврат резвозврата
конецфункции
(26) так какое значение по-умолчанию нужно возвращать из функции ЭтоЮрЛицо(Ссылка) ?
Может Вы наконец осознаете, что не всегда возможно приемлемое значение по-умолчанию. И пихать туда Неопределено бывает вредно. Потом это нужно в 100500 разных участках проверять, а вдруг там Неопределено, которое по нормальной логике там быть не должно. А потом, через полгода, другой программист решит использовать эту функцию и не проверит на Неопределено? Ваше решение это тихий ужас.
А юзать функции не глядя что внутри и как оно там - это, видимо, нормальная практика.
В программировании вроде как считается нормальной практикой скрывать реализацию и работать с функцией как с чёрным ящиком получающим на вход параметры и возвращающим результат. Нет?
(44) попробуйте в типовых выполнить глобальный поиск по "ВызватьИсключение". Удивитесь обилию. Наверно тоже не понимают, что нужно использовать значения по-умолчанию.
(51) это видно было сразу, что слушаете только себя.
Наверно и "Совершенный код" Макконнелл приводить нет смысла?
Вот выдержка (на всякий случай):
Используйте исключения для оповещения других частей программы об ошибках, которые нельзя игнорировать.
Основное преимущество исключений состоит в их способности сигнализировать об ошибке так, что ее нельзя проигнорировать.
При других подходах к обработке ошибок есть вероятность, что сбойная ситуация останется незамеченной. Исключения устраняют такую возможность.
(56) мне не интересно Ваше сообщение (21). Оно не информативно. Я отвечал на (18). Читайте (24).
Никто не говорит, что всегда нужно выбрасывать исключения. Но если в функцию передается заведомо неверное значение, которое функция обработать никак не может, и по логике вызова этой функции рассчитывают получить конкретные значения, то это ошибочная ситуация вызванная ошибкой в коде, и в этом случае лучше выбросить исключение.
Да, кстати. Выброс исключения не означает, что это будет обязательно закрытие программы. Исключения можно (а иногда и нужно) обрабатывать самому (в смысле перехватывать в коде).
И не все исключения приводят к краху программы.
Насчет "магических чисел". Да, тоже стараюсь их примерно так избегать, как написано.
Но иногда (вернее, 50/50) делаю по-своему.
Например, объявляю переменные модуля типа:
/////////////////////////////////////
// Условно-константы, для избавления от "магических" значений
Перем ВИД_ПРИБОРА_УЧЕТА_ОДПУ;
Перем ВИД_ПРИБОРА_УЧЕТА_ИПУ;
Возвраты из середины функции уж очень сильно путают логику кода.
Практически как goto.
Нормальные люди такую практику не используют.
В функции должна быть единая точка возврата.
"ВМЕСТО БЛОКА ЕСЛИ … ТОГДА В РЕЗУЛЬТАТЕ ФУНКЦИИ, ВОЗВРАЩАЮЩЕЙ БУЛЕВО ЗНАЧЕНИЕ, РЕКОМЕНДУЕТСЯ ИСПОЛЬЗОВАТЬ УСЛОВНОЕ ВЫРАЖЕНИЕ"
Код становится менее читаемым и сложнее сопровождаемым
Вызывать исключения вместо кода возврата - тоже не самый лучший стиль.
Насчёт магических чисел. Давайте сделаем функцию, которая будет возвращать 24*60*60.
Или функцию КоличествоМинутВЧасе().
Обработка ошибок - слишком обширная тема для продвигания единственно верного решения. Ситуации очень разные бывают.
Но в общем случае конечно же логично падать как можно раньше по внятному эксепшну, что позволит максимально быстро локализовать проблему, буде таковая возникнет. Тут возразить нечего.
"НЕ РЕКОМЕНДУЕТСЯ ИСПОЛЬЗОВАТЬ В ЗАПРОСЕ ПОЛУЧЕНИЕ ЗНАЧЕНИЯ ЧЕРЕЗ ТОЧКУ ОТ ПОЛЯ СОСТАВНОГО ССЫЛОЧНОГО ТИПА"
В частности, не рекомендуется обращаться к реквизитам регистратора регистра (например, ТоварыНаСкладах.Регистратор.Дата) и т.п.
Это увеличивает время запроса или влияет на что-то другое?
Если у меня в Справочнике есть табличная часть и нужно получать данные как из таблицы, так и реквизиты справочника, то в запросе "выносить" лучше табличную часть и по Ссылке получать реквизиты справочника или "выносить" целиком справочник и обращаться к табличной части?
ВЫБРАТЬ
Номенклатура.Ссылка,
Номенклатура.Код,
Номенклатура.Наименование,
Номенклатура.КомпонентныйСостав.(
Ссылка,
Компонента,
Количество
)
ИЗ
Показать
ИЛИ так
ВЫБРАТЬ
НоменклатураКомпонентныйСостав.Ссылка.Ссылка,
НоменклатураКомпонентныйСостав.Ссылка.Код,
НоменклатураКомпонентныйСостав.Ссылка.Наименование,
НоменклатураКомпонентныйСостав.Компонента,
НоменклатураКомпонентныйСостав.Количество
ИЗ
Напишите ваше сообщение
(29) в запросе это связано с тем что будет неявное соединение по полю "регистратор" со всеми документами что могут этот регистр двигать, это может быть причиной как низкой производительности так и возникновения ошибки выполнения
ЗАПРЕЩЕНО ИСПОЛЬЗОВАТЬ В КОДЕ КОНФИГУРАЦИИ МЕТОДЫ НАЙТИПОНАИМЕНОВАНИЮ(), НАЙТИПОКОДУ() И ИМ ПОДОБНЫЕ
не помню, была статья о минимилизации поиска по конкретному коду или наименованию для полной универсализации - и было пару решений: через справочник, через регистр сведений, через свойства
(30) Это сильно снижает гибкость кода и ведет возникновению ошибок. По сути - это хардкод или разновидность быдлокода (присваивать переменным, входящим или конфигурационным данным значение внутри самого программного кода, вместо того чтобы получать их значения из внешних источников, выбора пользователя, настроечных файлов и т.п. Типа как:
В статье есть как полезные и правильные рекомендации, так и ошибочные/вредные. К сожалению, большинство таких публикаций страдают плохим разъяснением принципов и смысла тех или иных советов, отсюда их непринятие или неверное использование на практике.
(33) "Не использовать многовариантных условных операторов – несколько выражений ИначеЕсли в поле выбора"
Эта рекомендация и пример с возвратами в ней - нарушение принципа структурного программирования и очень плохой паттерн. Несмотря на популярность "возвратов" и распространенность даже в типовых, такой код является источником проблем и ошибок при сопровождении, особенно при использовании в функциях. Простой пример, возьмем, согласно вышеприведенного совета, следующий код:
Если Условие1 тогда
Возврат Знач1;
КонецЕсли;
Если Условие2 тогда
Возврат Знач2
КонецЕсли;
Возврат Знач3;
Показать
И предположим, что нужно доработать расчет возвращаемого значения. В этом случае доработку придется делать в каждом месте, где стоит Возврат. А если эти возвраты ещё и разбросаны по телу функции, то нужно быть очень внимательным что бы ничего не пропустить.
В то же время код вида:
Перем Знач=Знач3;
Если Условие1 тогда
Знач=Знач1;
ИначеЕсли Условие2 тогда
Знач=Знач2;
КонецЕсли;
Возврат Знач;
Показать
Полностью лишен этих проблем и позволяет легко выполнить нужную доработку. И это не единственная проблема подхода с возвратами. Следующие грабли возникают при доработке сложных условий.
Если функция/процедура очень проста и содержит всего несколько строк, то иногда ещё можно натыкать в неё возвратов. Хотя часто бывает так, что изначально простую функцию приходится в скором времени развивать и усложнять и тут уже возвраты создают указанные проблемы. Поэтому сейчас этот паттерн практически никогда не использую.
Моё мнение (если оно кому-то интересно).
Исключения
а) приводят в оверхеду в производительности
б) затрудняют разбор логики.
Поясню..
а) Для раскрутки стека вызовов для исключений требуются большие накладные расходы (может, в 1с это и не так, но в общем случае...)
б) Я вызываю процедуру ОбщийМодульФирмыНе1с.ВыполнитьЗаполнениеДанныхПоФазамЛуны(). И программа вываливается в исключение именно на этой строчке. Как я должен реагировать? В каком месте мне искать проблему?
(66)
а) раскрутка в общем не больше той, которая была бы при нормальном выполнении кода. А как правило меньше, так как не будут дополнительно выполняться другие вызовы в модулях по цепочке. Процедура/модуль будут принудительно завершены вверх по стеку, пока не будет встречена обработка ошибки.
б) Если информирования об ошибке не достаточно, то делается "остановка по ошибке" и проверяется стек вызовов. Все достаточно наглядно.
Но это не значит, что исключения нужно пихать везде. Они нужны в ситуациях, когда возникла нештатная ситуация. И силами метода обработать невозможно. И/или получено заведомо неправильное значение, которое может навредить дальнейшее его использование.
(66) Откуда возьмется оверхед, если исключения используются по прямому назначению - для обработки ИСКЛЮЧИТЕЛЬНЫХ ситуаций?
Почему именно затрудняется разбор логики? Наглядным будет пример с исключением и без.