В 2005 году руководством было решено прекратить поддержку самописного программного обеспечения и перейти на 1С версии 8.0 «Управление производственным предприятием». При этом было принято «политическое решение» минимизировать изменения в стандартной конфигурации, чтобы обеспечить дальнейшую совместимость с последующими обновлениями, выпускаемыми компанией 1С. А так как наша фирма довольно крупная (на тот момент мы были одними из первых в России, кто приобретал SQL версию на 100 лицензий), то было необходимо довольно большое число доработок и настроек конфигурации. Так и родилась концепция «неизменяемой конфигурации». При этом базовый функционал остается практически без изменений и обновление конфигурации занимает на порядок меньше времени. Конечно, везде есть плюсы /минусы, и данная концепция может вызывать споры и использоваться далеко не везде. Проблема в том, что зачастую программисты не до конца понимают все тонкости бизнес-процессов на фирме. И нет людей, которые «видят» всю систему целиком и понимают как та или иная модификация отражается на функционировании этой программной системы. Начальники подразделений тянут одеяло на себя и вносят изменения, необходимые на их взгляд. При этом учетная система расплывается, теряет стройность, обрастает «подпорами». А когда конфигурацию «изменять нельзя» появляется некая постоянная точка опоры. И бывает проще перестроить бизнес-процесс, чтобы можно было обойтись стандартными средствами конфигурации. В общем, в нашем случае концепция показала свою дееспособность на практике. И даже если ею не пользоваться в полном объеме, некоторые решения всё равно могут найти применение. Итак, о сути концепции.
Начнем с того, что как не старайся – изменения вносить все равно придется. Изменения в модули форм/объектов вносятся с помощью специализированной конфигурации «Автоапдейтер». Работе в ней посвящена отдельная статья. Реквизиты объектов, как и сами объекты, можно только добавлять - ни в коем случае не изменять/удалять/переименовывать. Причем каждое добавление тщательно продумывать – зачастую его можно тем или иным образом избежать.
Необходимо создать как минимум 2 общих модуля: клиент/серверный и модуль с полными правами. Кроме того необходимо хранить огромное множество разнообразных по формату настроек. Для этого были созданы две универсальные структуры : План видов характеристик «Категории метанастроек» и регистр сведений «Метанастройки».Формат их следующий :
рис.1 Категории метанастроек
рис.2 Регистр сведений "Метанастройки"
У ведущего объекта, объекта и значения настройки не обязательно сразу вешать тип – любая ссылка. Можно добавлять типы по мере необходимости.
С помощью данных структур можно хранить практически любые настройки .Регистр можно использовать, когда необходимо хранение большого числа однотипных настроек, во всех случаях лучше использовать КМ. Их при необходимости можно соединять в составные цепи – т.е. объектом у такой настройки является другая настройка и т.д. В модуль с полными правами нужно внести следующие
Функции получают/создают если нету нужные категории и группы метанастроек.
Весь необходимый функционал реализуется с помощью внешних обработок и дополнительных общих модулей. Сами обработки хранятся в базе, в справочнике «Внешние обработки». Для их структурирования используются категория метанастроек . А для иерархического отображения, и запуска - обработка «Дополнительное меню», которая в свою очередь стартует при нажатии на клавишу F12. Как показала практика , пользователи быстро к этому привыкают и у них это не вызывает особых неудобств такой способ использования расширенного функционала.
рис.3 Дополнительное меню
Список отображаемых элементов для каждого пользователя/группы пользователей можно сделать различным, отображая только нужные пункты. Назначение горячих клавиш, добавление и удаление пунктов меню производятся обработкой «Редактор дополнительного меню». В самом меню для полных прав действуют клавиши ctrl + F12 – обновить текущую обработку из файла, что позволяет оперативно вносить изменения.
Для интеграции дополнительного меню в общий модуль следует внести следующие
Процедура ДополнительноеМеню() Экспорт ДПФ=Справочники.ВнешниеОбработки.НайтиПоНаименованию("Дополнительное меню ТД СБС",Истина); Если ДПФ.Пустая() Тогда Возврат; КонецЕсли; Пересоздавать = Ложь; Попытка Обработка = ДПФ.ХранилищеВнешнейОбработки.Получить(); Попытка МоментВремени = Строка(Число(ДПФ.КомментарийКФайлуИсточнику)); Исключение Пересоздавать = Истина; МоментВремени = ""; КонецПопытки; ИмяФайла = КаталогВременныхФайлов()+ДПФ.УникальныйИдентификатор()+МоментВремени+".EPF"; Исключение Возврат ; КонецПопытки; Файл=Новый Файл(ИмяФайла); Если НЕ Файл.Существует() ИЛИ Пересоздавать Тогда Попытка ДвоичныеДанные = Обработка; ДвоичныеДанные.Записать(ИмяФайла); Исключение Сообщить("Ошибка получения формы обработки :"+ОписаниеОшибки()); Возврат ; КонецПопытки; КонецЕсли; Форма=ВнешниеОбработки.ПолучитьФорму(ИмяФайла); Форма.Открыть(); КонецПроцедуры // ДополнительноеМеню Функция ПолучитьФормуЗарегистрированнойВнешнейОбработки(ЭлементДПФ,КлючУникальности=Неопределено, ИмяФормы=Неопределено,Владелец=Неопределено,ВестиСтатистику = Ложь) Экспорт Если ТипЗнч(ЭлементДПФ) = Тип("Строка") Тогда ЭлементДПФ = Справочники.ВнешниеОбработки.НайтиПоНаименованию(ЭлементДПФ,Истина); Если ЭлементДПФ.Пустая() Тогда Возврат Неопределено; КонецЕсли; КонецЕсли; Пересоздавать = Ложь; Попытка Обработка = ЭлементДПФ.ХранилищеВнешнейОбработки.Получить(); Попытка МоментВремени = Строка(Число(ЭлементДПФ.КомментарийКФайлуИсточнику)); Исключение Пересоздавать = Истина; МоментВремени = ""; КонецПопытки; ИмяФайла = КаталогВременныхФайлов()+ЭлементДПФ.УникальныйИдентификатор()+МоментВремени+".EPF"; Исключение Возврат Неопределено; КонецПопытки; Файл=Новый Файл(ИмяФайла); Если НЕ Файл.Существует() ИЛИ Пересоздавать Тогда Попытка ДвоичныеДанные = Обработка; ДвоичныеДанные.Записать(ИмяФайла); Исключение Сообщить("Ошибка получения формы обработки :"+ОписаниеОшибки()); Возврат Неопределено; КонецПопытки; КонецЕсли; Если ЭлементДПФ.ВидОбработки = Перечисления.ВидыДополнительныхВнешнихОбработок.Отчет Тогда МенеджерОбработок = ВнешниеОтчеты; Иначе МенеджерОбработок = ВнешниеОбработки; КонецЕсли; Если ТипЗнч(КлючУникальности)=Тип("Булево") Тогда Если КлючУникальности Тогда Форма=МенеджерОбработок.ПолучитьФорму(ИмяФайла,ИмяФормы,Владелец,Новый УникальныйИдентификатор()); Иначе Форма=МенеджерОбработок.ПолучитьФорму(ИмяФайла,ИмяФормы,Владелец); КонецЕсли; Иначе Форма=МенеджерОбработок.ПолучитьФорму(ИмяФайла,ИмяФормы,Владелец,КлючУникальности); КонецЕсли; Если ВестиСтатистику Тогда ОбновитьСтатистикуЗапускаВнешнейОбработки(ЭлементДПФ); КонецЕсли; Возврат Форма; КонецФункции Процедура ЗапуститьЗарегистрированнуюВнешнююОбработку(ЭлементДПФ,КлючУникальности=Неопределено, ИмяФормы=Неопределено,Владелец=Неопределено,Модально=Ложь) Экспорт Форма=ПолучитьФормуЗарегистрированнойВнешнейОбработки(ЭлементДПФ,КлючУникальности,ИмяФормы,Владелец); Если Форма=Неопределено Тогда Возврат ; КонецЕсли; ОбновитьСтатистикуЗапускаВнешнейОбработки(ЭлементДПФ); Если Модально Тогда Форма.ОткрытьМодально(); Иначе Форма.Открыть(); КонецЕсли; КонецПроцедуры // ЗапуститьЗарегистрированнуюВнешнююОбработку
Кроме того, конфигурация должна содержать стандартный справочник "Внешние обработки", характерный для многих типовых конфигураций.
В конфигурации в общий для всех пользователей интерфейс нужно добавить новый пункт меню "Дополнительное меню" с горячей клавишей F12 и привязать к нему помещенную ранее в общий модуль одноименную процедуру "ДополнительноеМеню()".
С помощью этих средств обновление конфигурации до нового релиза ускоряется во много раз. Кроме того, все изменения хранятся в «запротоколированном» виде в автоапдейтере. Стандартная структура остается без изменений. Остается при этом проверить и при необходимости поправить логику работы добавленных обработок в новой конфигурации. Обновление в этом случае может легко выполнит другой человек, не тот который вносил изменения в базу.