gifts2017

TestIB8x - 0003 - Безопасный код - Option Explicit - первая реализация

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

Был момент, когда захотелось задвинуть этот тест подальше, т.к. в Платформе 8.х защита от небрежного кодирования проработана хорошо. Достаточно перестать использовать экспортные переменные уровня приложения, внешнего соединения и переменные уровня модуля. После этого можно "клепать" код, даже не вымыв перед этим руки и не промыв мозги Ж-).
Спасибо, комментариям на прошлое обсуждение и нескольким письмам на мыло - сподвигли на завершение начатого.
Тест получился большой - более 900 строк на JScript, но кое-какие моменты все-таки остались ...

Предисловие к описанию реализации

Тест входит в состав TestIB8x v. 1.0.1 (выложен на основном сайте brix8x.stavr.ru, сюда буду выкладывать более крупные версии) Также поднят баг-трекер (bts.stavr.ru), есть возможность оставить свои замечания и пожелания.

В ходе реализации возникла одна проблема, решить которую сам пока не могу.

Средствами платформы не получается получить полный список реквизитов формы!

Таким образом, при проверке события ПриОткрытии() формы элемента, например, нет возможности оценить код типа "формаДата = ТекущаяДата()" как корректный или нет, есть вероятность, что формаДата - реквизит формы элемента.

Можно, конечно, выдвинуть идею о том, что если реквизит есть, то он должен быть на форме, после чего, создав OLE соединение получить форму (ПолучитьФорму()) и проанализировать все ЭлементыФормы на значение свойства Элемент.Данные; Но уж очень это некрасиво.

Можно, конечно, дописать в стандарт требование присваивать значения реквизитам формы через конструкцию ЭтаФорма.формаДата, т.к. нам все равно нужен красивый способ, глядя на код, понимать о чём это присваивание. Но задав это требование, мы не можем обеспечить проверку на его выполнение, а пустые слова никому не нужны.

Таким образом, я пока вижу один выход: Найти способ получать информацию о реквизитах форм из файла .cf.
На данный момент как это делается не знаю.
Никаких исходников в помощь нет. Желающих написать ActiveX наподобие старого доброго Rainbow тоже.
Буду рад любой помощи - ссылки на исходники, создание компоненты, другой способ получения реквизитов форм (есть ведь еще интерфейсные тесты).

А пока "ложные" срабатывания теста можно подавить, дополняя файл настроек теста.

0003 - Безопасный код – Option Explicit


Категория: Безопасный код
Название: Option Explicit
GUID: 5c11d53e-1dda-4ccb-9ce2-4ea01a9a142c
Версия: 2 от 15.01.08

Введение

Рассмотрим ситуацию с функцией, претендующей на роль универсальной, объявленной с ключевым параметром Экспорт, или еще нет, но тем не менее делающую нечто очень полезное.

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

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

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

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

Но вот код, указанный ниже потенциально небезопасен.

Пример:
Перем Ном;
Функция Универсальная() Экспорт

Ном = 1;

Возврат «»;

КонецФункции
Функция ИспользуетУниверсальную()

Перем Ном;

Ном = 6;
Сообщить(Ном); // Ном = 6

Рез =Универсальная();

Сообщить(Ном);
// Ном = 1, а ожидаем 6
Возврат «»;
КонецФункции

 

Возможно, так и задумано и переменная уровня модуля должна получить своё новое значение именно таким образом. Но с точки зрения сопровождения такая функция является функцией с «побочными» эффектами.

То же самое произойдет, если переменная Ном объявлена как экспортная в модуле приложения или внешнего соединения.

И это – плохой стиль программирования.

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

Реализация

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

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

Особняком стоит объем проверяемых функций – Все или только экспортные, а также Проверять ли общие модули.

Выбор максималистов скорее всего Все, выбор минималистов – только экспортные, выбор пофигистов – тоже очевиден …

Тестирование

Объекты тестирования:
• Модуль приложения (AppModule)
• Модуль внешнего соединения (ComModule)
• Модуль сеанса [для 8.1] (SessionModule)
• Общие модули (CommonModules)
• Модули менеджера значений константы (ConstantModules)
• Модули объектов (ObjectModules)
• Модули форм (FormModules)
Параметры проверки объекта (список без учета специфики):
• Запрет экспортных переменных (disableExportVars)
• Запрет переменных модуля (disableModuleVars)
• Запрет необъявленных локальных переменных в локальных функциях (disableLocalVarsInExportFunc)
• Запрет необъявленных локальных переменных в экспортных функциях (disableLocalVarsInLocalFunc)

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

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

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

Существует два решения данной проблемы:
1. Через конструкцию ЭтаФорма.Реквизит, тем более, что нам все равно нужно визуально отличать реквизиты форм от просто переменных.
2. Через занесение имени реквизита формы в файл исключений.

Ситуация может кардинально измениться, когда тест сможет оперировать метаданными непосредственно из файла .cf.

Шаг 1 Проверка каждого объекта проверки по четырем показателям


1. Проверить объявления экспортных переменных
2. Проверить объявления переменных уровня модуля
3. Проверить качество экспортных функций
4. Проверить качество локальных функций

Для пункта 4 и 5, в модуле объектов переменные в операциях присваивания проверяются дополнительно на наличие в списке реквизитов объекта метаданного.

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Hromov (hromov) 21.01.08 10:11
На счет реквизитов формы.
Я выкручивался так. Посмотри что дает метод "ЗначениеВСтрокуВнутр" для объекта "форма", вот по этому тексту как раз можно понять какие реквизиты есть у формы, но правда текст долго анализируется, хотя.. может если его регулярными выражениями попытать....
2. brix8x (brix8x) 22.01.08 10:02
Спасибо огромное! Этого вполне достаточно. Один минутс - нужно получать через OLE, через COM нельзя.
Но самое классное, что те же самые данные можно получать в будущем из .cf.
Поэтому пока оставлю .cf в покое и научусь парсить полученные данные Ж-)
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа