Комментарии 20
У меня небольшой вопрос к автору: Вы знаете, что фраза «окончательное решение вопроса» несёт в себе некоторый культурный подтекст, и обычно используется только в связи с этим контекстом?
я пишу это потому, что кое кого за такую формулировку уже заминусовали…
буквоедство - болезнь мозга, которой часто подвержены программисты в силу профессиональной деформации с синтаксис-контролем.
я хоть и программист, но много общался с женщинами, это хорошее противоядие. Рекомендую.
Эта "пластинка" про буквоедство - очень удобное оправдание неспособности корректно формулировать мысли.
Значит, корректировка типовых шаблонов у вас слетит при обновлении. А замена типовых шаблонов на ваш Основной не слетит.
иногда буквоедство это признак граммар-наци.
я предлагаю метод, а как вы будете его использовать - совместно с типовыми ролями или вместо типовых ролей, дело хозяйское.
главное, у программистов по RLS на чтение теперь появился выбор. Раньше его, все 10 лет существования RLS не было. В этом ценность.
Я предлагаю на чтение делать одну роль.
На изменения, конечно, контроль в модулях.
Так будет законченная и логичная система прав в отличии от типовой галочной стыдобы в 1С.
Влияет ли на производительность шаблон с большим количеством #Если?
нет, все компилируется на этапе сохранения метаданных (компиляции), т.е. это не run-time вычисления.
Скорее это аналог макросов в Си, где просто подставляются параметры в результирующий код.
Кстати, так не хватает макросов в Cи Шарп...
C# содержит директивы препроцессора. Они не настолько развиты как в Си, но с другой стороны, что они там и не нужны
я про макросы #Define, это мощная штука.
В C# есть кодогенерация https://habr.com/en/articles/906778/ и сорсгенерация. Если не достаточно дженериков и экстеншенов, то не слабее штука.
ну вот пример.
В зависимости от типа устройства может быть возвращена структура A1, A2 или A3.
Мне надо с результатом вызвать процедуру Work и Bench.
Например:
R = GetValueFromDevice();
If R.code = 1 {
V = R.value as A1;
Work_A1(v);
Bench_A1(v);
}
elseIf R.code = 2 {
V = R.value as A2;
Work_A2(v);
Bench_A2(v);
}
elseIf R.code = 3 {
V = R.value as A3;
Work_A3(v);
Bench_A3(v);
}
Конечно, можно городить обертки над структурами, но это не так красиво, как макросы.
switch (code)
{
case 1: Test<A1>(value, Work_A1,Bench_A1); break;
case 2: Test<A1>(value, Work_A2, Bench_A2); break;
case 3: Test<A3>(value, Work_A3, Bench_A3); break;
}
static void Test<T>(object a, Action<T> work, Action<T> bench)
{
T t = (T)a;
work(t);
bench(t);
}
Если тип устройства, то, конечно, надо смотреть, что за структура -- может надо довести до CLR. Но пусть все просто будет.
Путь интерфейсов (он же про дженерики)
// можно и без него, но просто понимать что что-то есть внутри abstract class BaseA { public BaseA(string value) { Value = value; // какое-то создание } public string Value {get; init;} } // можно методы объеденить interface IA { void Work(); void Bench(); } // эти классы по ходу у тебя уже есть // им только добавить интерфейсы class A1: BaseA, IA { public A1(string value): base(value) {} public void Work() { // логика для Work_A1(this.Value) } public void Bench() { // логика для и Bench_A1(this.Value) } } class A2: BaseA, IA { public A2(string value): base(value) {} public void Work() { // логика для Work_A1(this.Value) } public void Bench() { // логика для и Bench_A2(this.Value) } } class A3: BaseA, IA { public A3(string value): base(value) {} public void Work() { // логика для Work_A3(this.Value) } public void Bench() { // логика для и Bench_A3(this.Value) } } // конечный код var R = GetValueFromDevice(); var concrete_A = R.value () switch { 1 => new A1(R.value), 2 => new A2(R.value), 3 => new A3(R.value), _ => throw new Exception("неизвестное устройство") }; concrete_A.Work(); concrete_A.Bench(); // и даже можно будет так var deviceList = new List<IA> { new A1("a1"), new A2("a2"), new A2("a2-2")) }; foreach (var device in deviceList) { device.Work(); device.Bench(); }Путь экстеншенов
abstract class BaseA { public BaseA(string value) { Value = value; // какое-то создание } public string Value {get; init;} } class A1: BaseA { public A1(string value): base(value) {} } class A2: BaseA { public A2(string value): base(value) {} } class A3: BaseA { public A3(string value): base(value) {} } // если не интерфейсы, то вот // и для краткости объединяю методы целевые static class AExtensions { static void WorkAndBench(this A1 a) { // Work_A1(a.Value); // Bench_A1(a.Value); } static void WorkAndBench(this A2 a) { // Work_A2(a.Value); // Bench_A2(a.Value); } static void WorkAndBench(this A3 a) { // Work_A3(a.Value); // Bench_A3(a.Value); } } // конечный код var R = GetValueFromDevice(); var concrete_A = R.value () switch { 1 => new A1(R.value), 2 => new A2(R.value), 3 => new A3(R.value), _ => throw new Exception("неизвестное устройство") }; concrete_A.WorkAndBench(); // с колекцией тоже прокатитА так -- патерн chain of responsibility или какой-то другой пайплайн, если девайс один.
Но если вариантов десятки, то генерацию подключать.
А вообще кажется классы не нужны и можно так
var dict = new Dictionary<int, Action<string>> {
{1, value => {Work_A1(value); Bench_A1(value);)},
{2, value => {Work_A2(value); Bench_A2(value);)},
{3, value => {Work_A3(value); Bench_A3(value);)}
};
R = GetValueFromDevice();
dict[R](R.value);В производительном режиме типовых 1С (библиотека БСП) не требуется менять шаблоны RLS. Делается это иначе, например тут описано https://infostart.ru/1c/articles/1656341/
Вам придется этот шаблон скопировать во все роли, использующие RLS. Главное ничего не пропустить. Кроме того, т.к. шаблон хранить ВСЕ правила - это путь к коллизиям файлов при групповой разработке. Во всех ролях.
Ваши примеры не покрывают размещения пользователя в разных областях ограничений. Например, в типовых решениях пользователя можно поместить в группу доступа с ограничением склад "Север", а также в группу доступа с ограничением клиенты менеджера "Вася". В итоге он будет видеть документы по складу "Север" ИЛИ по менеджеру "Вася".
при чем тут производительный режим, у которого своя "тележка недостатков"
нет. мне достаточно иметь только одну роль с RLS, если одна роль расово неприемлема и хочется прям разделения по ролям, то во всех ролях, где доступен просмотр, пишите Где ЛОЖЬ, чтобы они не давали право на просмотр.
В статье этого нет, но я приводил вам пример тут https://infostart.ru/1c/articles/2622960/ (в сообщении номер 4), как это решается в "моём случае". Ничего не мешает использовать справочник групп доступа и в моем решении. Методу это не противоречит.
Какие недостатки типового производительного режима по сравнению с данным решением?
Роль ГДЕ ЛОЖЬ и Роль где отключено право чтения это совершенно разное поведение системы.
Вы меня с кем-то путаете.
Производительный режим - https://infostart.ru/1c/articles/1656341/, недостатки:
- нужно рассчитывать по-объектно и хранить эти доступы.
- тяжеловесность решения
- сложность добавления своих отборов, впрочем как и все, что взаимодействует с монструозной БСП.
Помню в Документообороте 2.0 права доступа по-объектно пересчитывались сутками на больших объемах.
Да, это очевидная попытка снизить сложность настройки RLS на чтение, которая была, пока я не предложил этот метод. Этот метод побивает производительный режим.в чем разница? роль с RLS одна, она как раз управляет доступностью объектов на просмотр. Мне достаточно одной роли, это полностью закрывает проблему с видимостью через RLS. Это удобно.
ну если это не вы писали, то почитайте, там пользователь задавал такой же вопрос как вы и я ему подробно ответил.
В производительном режиме делается иначе, то есть заведомо написали ложь. По поводу "тяжеловесности" и "монструозности" - это все слова, надо подкреплять фактами. Покажите свой продукт, сделайте сравнения
Вы действительно не знаете, чем отсутствие прав отличается от прав, где недоступны все записи? А если на этом принимается системой решение. Если забыть дать право на таблицу - в первом случае у вас выкинет исключение - это плохо конечно, во втором случае ошибок не будет, но будет получен неверный результат, который возможно обнаружат не сразу.
Исходя из написанного - "переобуваемся" на ходу, довешиваем новые данные и... вот уже тоже самое, только свой велосипед, родной )))
-- В производительном режиме делается иначе, то есть заведомо написали ложь.
что не так, напишите своими словами.
-- По поводу "тяжеловесности" и "монструозности" - это все слова, надо подкреплять фактами. Покажите свой продукт, сделайте сравнения
несомненно, но перспективы метода уже неплохи. Я давно искал такой. Жаль, раньше не знал, думаю и сейчас кто-то в поисках, им пригодится.
-- Вы действительно не знаете, чем отсутствие прав отличается от прав, где недоступны все записи? А если на этом принимается системой решение. Если забыть дать право на таблицу - в первом случае у вас выкинет исключение - это плохо конечно, во втором случае ошибок не будет, но будет получен неверный результат, который возможно обнаружат не сразу.
приведите пример, не понимаю о чем вы.
-- Исходя из написанного - "переобуваемся" на ходу, довешиваем новые данные и... вот уже тоже самое, только свой велосипед, родной )))
мастер класс обесценивания. но пока что убойных аргументов не увидел, а метод реально хорош.

Окончательное решение вопроса RLS на чтение