Книга знаний

Инф. технологии / Приемы программирования / Встроенный язык

Признаки плохого программирования и проектирования

Рассмотрены признаки плохого программированияАвтор статьи: Гений 1С | Редакторы: Волшебник, Fynjy, Лёвыч, EmK, Stillcat, Asmody
Последняя редакция №21 от 26.12.08 | История
URL: http://kb.mista.ru/article.php?id=273

Ключевые слова: программирование, стиль, оформление


Функции с большим числом параметров


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

Пример плохого стиля:
ПеретаскиваниеВНовуюОбластьДанных(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Колонка, ПраваДоступаПользователей, МодифицированностьФормы)


Использование в коде программы конкретных данных


Пример плохого стиля:
Если ИмяПользователя="Иванов_С" Тогда ... КонецЕсли

Представьте потом, что если пользователь уволится, нужно будет найти все случаи, где встречается Иванов_С и сделать замену на нового сотрудника.
Пример плохого стиля:
Если Справочник.Код=17 Тогда ... КонецЕсли

Конфигурация должна быть написана так, чтобы можно было наложить ее на пустую базу и она была работоспособна. А в данном случае, если в базе нет элемента с кодом 17, или нужный элемент будет под другим кодом, программа будет работать неверно.

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


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

Дублирование кода


Весь дублирующийся функционал нужно выносить в процедуры и функции:
Сравните:
А=Макс(Х,-Х);
Б=Мин(Y,-Y);

Против:
А=Модуль(Х);
Б=-Модуль(Y);


Замена индекса массива кодом


В коде начинающих программистов часто встречаются конструкции вида:
А1=0;
А2=0;
А3=0;
А4=0;
А5=0;

Против:
Для Каждого Эл из А Цикл
    Эл=0;
КонецЦикла;

На самом деле примеры бывают ужаснее (по 100, 200 элементов), просто нет под рукой ссылок.

Длинное "тело" процедуры или функции


Если длина процедуры становится больше трех экранов, прочитать и понять, что же она делает становится очень сложно (очень сильно грешат этим разработчики 1С). Разумнее выделить из процедуры отдельные логические части и оформить в виде отдельных процедур или функций.


Имена переменных, процедур и функций

Система именования переменных



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

Из-за этого код становиться сложно читаемым.
Правильно
Без локализации.
Счетчик, СправочникКонтрагенты

С локализацией.
//гл - глобальная, ф - форма, м - общая модуль, л - локальная процедура/функция, сз - список значений и т.д. 
лСчетчик, мСправочникКонтрагенты, лсзСправочникТМЦ

Более детально можно почитать в любой книге по программированию + на ИТС достаточно подробно описаны данные правила (дайте пожалуйста название темы на ИТС, не нашли - ИТС - > 1C:Система стандартов и методик разработки конфигураций - общие правила построения метаданных - Оформление модулей).

Еще можно почитать здесь: Книга знаний: Kazakh Notation (Казахская нотация) В программировании это называется "венгерская нотация".

Похожие имена


Следует избегать в названиях переменных, ролей и т.п. сходных идентификаторов.
У меня был случай, когда программисты завели две роли РуководительФилиала и ФилиалРуководитель, которые означали совершенно разный доступ.

Мат


Не рекомендуется использовать в комментариях, названиях переменных и т.п. мат.
Особенно не рекомендуется использовать его в процессе отладки.
Был случай, когда программист в отладочной базе отлаживался под пользователем "Пиздюков Фома Ильич", но он не знал, что извещения о проведении документов в некоторых случаях отсылаются на рабочие e-mail руководителей. В результате был неприятный скандал.

Явное объявление локальных переменных


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

Использование текущей даты в функциях


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

Прочее


Напишите здесь ваши мысли.

// + {{ Лёвыч

Использование методов Сообщить(), Предупреждение(), Вопрос() и прочих модальных окон


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

  • Всегда указывайте не нулевой таймаут при вызове функций типа Вопрос() и Предупреждение(), чтобы порождаемые ими модальные окна закрывались самостоятельно в случае, если пользователь куда-нибудь отошел от компьютера
  • Глобальные процедуры и функции не должны ни чего сообщать, спрашивать или о чем-то предупреждать. Всевозможные описания ошибок следует передавать в специальный необязательный параметр. Например:
    Процедура глСканерШК_ЗагрузитьДрайвер() Экспорт
    
       Если ЗагрузитьВнешнююКомпоненту("ScanOPOS.DLL")<>0 Тогда            
         Scan = СоздатьОбъект("AddIn.Scanner");   
       Иначе   
          Предупреждение("Ошибка загрузки драйверов сканера: ScanOPOS.DLL!");
       КонецЕсли;
    
    КонецПроцедуры

    Это нельзя назвать адекватным программированием, поскольку, если эта процедура удет вызвана из ПриНачалеРаботыСистемы(), то в случае отсутствия Scanopos.dll в каталоге базы нельзя будет загрузить эту базу в режиме предприятия программно. Например для обмена по ОЛЕ или с целью реализации какого-то автопроцесса. Куда логичнее изменить эту процедуру таким образом:
    Функция глСканерШК_ЗагрузитьДрайвер(сОписаниеОшибки = "") Экспорт
       
       Если ЗагрузитьВнешнююКомпоненту("ScanOPOS.DLL")<>0 Тогда            
         Scan = СоздатьОбъект("AddIn.Scanner");   
       Иначе   
          сОписаниеОшибки = "Ошибка загрузки драйверов сканера: ScanOPOS.DLL !";
          Возврат 0;
       КонецЕсли;
       
       Возврат 1;
    
    КонецФункции

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

  • Для оживлния долгоиграющих процесов предпочтительнее использовать процедуру Состояние(), нежели Сообщить() иначе, опять-таки, пользователи перестанут обращать внимание на все сообщения, в том числе и на критичные


//+Emk

Тем более, бесконечные сообщить() в цикле приводят к значительному замедлению процесса.
//-Emk

Некорректность и неоднозначность именования процедур и функций


Процедура/функция должна делать именно то, что написано в ее названии. Напрмер, пусть у нас есть некая база данных, в которой реализоаны статусы документов для целей контроля жизненного цикла документов. Вот такой код нельзя назвать адекватным:
Процедура ДокументРасходная_УстановитьСостояние(докРасходная, СостояниеДокумента)
   
   // блок, устанавливающий состояние расходной

   // а вот тут совершенно неожиданный блок, устанавливающий
   // состояния некоторых (не всех) подчиненных данной
   // расходой документов
   
КонецПроцедуры

Тут проблема в том, что понимать код или/и корректировать, написаный подобным образом, крайне трудно, а порой и не возможно - легче все переписать заново.
// }} Лёвыч


Использование в логике программы пометки удаления


Очень часто встречаю, что пометка удаления используется, как некий аналитический признак учета. Это очень плохой стиль программирования, лучше заводить статус активность/не активность.

Использование ограниченного набора вместо списка


Иногда встречаешь несколько реквизитов там, где нужно использовать подчиненный справочник или табличную часть.
Например, есть реквизиты Сумма1, Сумма2, ..., Сумма5. Вместо них можно было бы использовать гораздо эффективнее табличную часть, тем более что ограничение на 5 реквизитов - искусственное.


Хранение в базе данных одинаковых наименований или кодов


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

Использование наименования элементов справочников для поиска и сравнения


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

Примеры плохого кода:
1:
Докум.ВыбратьСтроки();
Пока Докум.ПолучитьСтроку()=1 Цикл
Если Докум.Номенклатура.Наименование=НужныйТовар.Наименование Тогда
Сумма=Докум.Сумма
КонецЕсли
КонецЦикла

2:
СпрНоменклатура=СоздатьОбъект("Справочник.Номенклатура");
СпрНоменклатура.НайтиПоНаименованию(НужныйТовар.Наименование);

Описание | Рубрикатор | Поиск | ТелепатБот | Захваченные статьи | Установки | Форум
© Станислав Митичкин (Волшебник), 2005-2024 | Mista.ru

Яндекс.Метрика