| 
    
        
     
     | 
    
  | 
Регистры правил или проклятие вариативности. | ☑ | ||
|---|---|---|---|---|
| 
    0
    
        Гений 1С    
     гуру 
    31.10.06 
            ✎
    18:59 
 | 
         
        Сформулируем проблему в общем виде.
  
        Допустим, есть некоторые параметры, например Подразделение, Вид подразделения, Уровень подразделения, Товар, Вид товара. И допустим для этих параметров нужно вычислять некоторые фунцкии, например Прибыль, Доход, Затраты, Маржа и т.п. Допустим эти функции считаются по разному для разных параметров. Например, прибыль в разных видах подразделений считается по разному. В итоге получается такой код: Если УровеньПодразделения=… Тогда Прибыль=...; Доход=…; Иначе Если Подразделение=... Тогда Прибыль=...; ИначеЕсли Подразделение=… И УровеньПодразделения=… Тогда Прибыль=...; ИначеЕсли Подразделение=… Тогда Прибыль=...; КонецЕсли; КонецЕсли; В общем случае получается офигенно длинный и запутанный код. Кто-нибудь применял в своей программистской практике альтернативу, или смирился с этим, как со злом? Я лично запарилси...  | 
|||
| 
    1
    
        Волшебник    
     31.10.06 
            ✎
    19:30 
 | 
         
        Могу порекомендовать психолога, он изменит твоё отношение к такому коду и ты будешь считать это добром. Следовательно, проблема будет решена.     
         | 
|||
| 
    2
    
        avmlvm    
     31.10.06 
            ✎
    19:33 
 | 
         
        (1) А почему "психолога"? чЁ "Волшебника" для этого не достаточно? :-)))     
         | 
|||
| 
    3
    
        nbIx    
     31.10.06 
            ✎
    19:36 
 | 
         
        (0) Про какую альтернативу ты говоришь?
  
        Можно конечно ингда уменьшить количество Если Тогда, но все зависит от конкретной задачи.  | 
|||
| 
    4
    
        avmlvm    
     31.10.06 
            ✎
    19:36 
 | 
         
        (0) Если функции считаются по разному для разных параметров - то это РАЗНЫЕ функции... Т.е. Задача сводится, что бы по типу подразделения вызвать ПРАВИЛЬНУЮ функцию... Ну и чЁ тут сложного? :-)     
         | 
|||
| 
    5
    
        Темный Эльф    
     31.10.06 
            ✎
    19:38 
 | 
         
        Можно сделать справочник формул, задавать в реквизитах параметры и способы расчета, а затем просто искать по справочнику. У меня был отчет, в котором каждый месяц какие-то графы переносились со страницы на страницу, графы добавлялись, менялась ширина и положение колонок - так через полгода задолбался переделывать и каждый раз исправлять свои глюки, а сделал справочником настройки и сказал бухгалтеру - "Приспичило? Берите и меняйте!"     
         | 
|||
| 
    6
    
        nbIx    
     31.10.06 
            ✎
    19:43 
 | 
         
        (5) Да. Чем больше универсальности, тем лучше.     
         | 
|||
| 
    7
    
        Гений 1С    
     гуру 
    31.10.06 
            ✎
    19:45 
 | 
         
        (4) окей, это будет туча разных функций, но от этого количество Если не уменьшится....
  
        Хотя на самом деле вот тебе контрпример. Функция Доступ(Пользователь, Объект, ВидДоступа), которая определяет имеет ли пользователь доступ к объекту. Функция одна, а вариантов - туева хуча!  | 
|||
| 
    8
    
        Гений 1С    
     гуру 
    31.10.06 
            ✎
    19:45 
 | 
         
        (5) не то, не то... алгоритмы известны, но настолько много вариантов, что все выходит из-под контроля!     
         | 
|||
| 
    9
    
        Темный Эльф    
     31.10.06 
            ✎
    19:53 
 | 
         
        (8)Насколько много? Можно Шаблон использовать, можно вообще текст модуля создавать, а потом по ЗагрузитьИзФайла вызывать.     
         | 
|||
| 
    10
    
        Вуглускр    
     01.11.06 
            ✎
    07:15 
 | 
         
        (0) Не знаю как это будет по-русски, по-английски то что тебе нужно называется     
         | 
|||
| 
    11
    
        Вуглускр    
     01.11.06 
            ✎
    07:32 
 | 
         
        опаньки, не ту кнопку нажал  
        Короче, Design Patterns. Классическая книга на эту тему написана GoF. Вот очень хорошая книга, причем бесплатно - "Thinkig in Patterns", www.bruceeckel.com  | 
|||
| 
    12
    
        Гений 1С    
     гуру 
    01.11.06 
            ✎
    10:05 
 | 
         
        Поясню на примере прав доступа, хотя у меня сейчас задача по бюджетированию, но по правам тоже заморочки бывают.
  
        Функция Доступ(Пользователь, Объект, ВидДоступа) Если НаборПрав="Админ" Тогда //1 Возврат Истина; КонецЕсли; //Пользователю запрещено редактировать дату //2 Если НаборПрав="Пользователь" И Объект.Тип="ПриходнаяНакладная" Тогда Возврат ложь; КонецЕсли; //Контроль даты //3 Если НаборПрав="Пользователь" ИЛИ Набор="Оператор" Тогда Если текущаяДата-Объект.Дата()>24*3600 Тогда Возврат ложь; КонецЕсли; КонецЕсли; ... КонецФункции т.е. как видим нужно правильно указывать последовательность, потому что если мы перепутаем местами 2 и 3, результат будет другой...  | 
|||
| 
    13
    
        Defender aka LINN    
     01.11.06 
            ✎
    10:18 
 | 
         
        (12) Ж8-[ ] Это у тебя и правда такое в конфе?
  
        Жесть...  | 
|||
| 
    14
    
        Гений 1С    
     гуру 
    01.11.06 
            ✎
    10:45 
 | 
         
        (13) да     
         | 
|||
| 
    15
    
        Гений 1С    
     гуру 
    01.11.06 
            ✎
    10:45 
 | 
         
        Примерно     
         | 
|||
| 
    16
    
        Господин ПЖ    
     01.11.06 
            ✎
    10:58 
 | 
         
        Акуеть просто...     
         | 
|||
| 
    17
    
        asssa    
     01.11.06 
            ✎
    11:03 
 | 
         
        А рекурсия не поможет?     
         | 
|||
| 
    18
    
        Neco    
     01.11.06 
            ✎
    12:15 
 | 
         
        Ты же сам идеи толкал как в 1Ске Exel сделать. Ну так вперед. Реализуй.     
         | 
|||
| 
    19
    
        Гений 1С    
     гуру 
    01.11.06 
            ✎
    12:44 
 | 
         
        (17) тут ваще все слишком сложно, рекурсия - не поможет...     
         | 
|||
| 
    20
    
        Гений 1С    
     гуру 
    01.11.06 
            ✎
    12:45 
 | 
         
        (18) а каким боком здесь эксель поможет...
  
        это фундаментальный вопрос  | 
|||
| 
    21
    
        Salvador Limones    
     01.11.06 
            ✎
    12:47 
 | 
         
        (20) Тебя это беспокоит? Хочешь поговорить об этом?     
         | 
|||
| 
    22
    
        Гений 1С    
     гуру 
    01.11.06 
            ✎
    12:50 
 | 
         
        обобщенно вопрос можно сформулировать так.
  
        Есть некая функция F(A1, A2, ..... AК). Эта функция принимает различные значения при различных наборах А1....АК. Значения могут повторяться. В случае функции Доступ таких значений вообще только 2 - истина или ложь. Возможна реализация следующим образом - составляется таблица различных значений А1.....АК и пишется для них значения. Но в общем случае таблица может быть офигенно большой. Как минимизировать таблицу, исходя из того, что мы знаем много частных случаев, когда принимаются те или иные значения при различных наборах параметров?  | 
|||
| 
    23
    
        Бриарей    
     01.11.06 
            ✎
    13:07 
 | 
         
        (22) Полиморфизм тебе поможет     
         | 
|||
| 
    24
    
        Гений 1С    
     гуру 
    01.11.06 
            ✎
    13:21 
 | 
         
        (23) я думаю, мне поможет регистр правил... ;-(     
         | 
|||
| 
    25
    
        Гений 1С    
     гуру 
    01.11.06 
            ✎
    13:21 
 | 
         
        еще бы сообразить, как его соорудить.     
         | 
|||
| 
    26
    
        Asmody    
     01.11.06 
            ✎
    13:25 
 | 
         
        (25) гугл, первая строчка в выдаче: http://www.kint.ru/k.pl?p=110     
         | 
|||
| 
    27
    
        Гений 1С    
     гуру 
    01.11.06 
            ✎
    13:26 
 | 
         
        (26) это я уже читал, только это не очень то применишь к моему случаю. ;-)     
         | 
|||
| 
    28
    
        Asmody    
     01.11.06 
            ✎
    13:28 
 | 
         
        (27) да ладно. если и умом и руками подойти, на регистрах сведений можно реализовать регистры правил...     
         | 
|||
| 
    29
    
        Гений 1С    
     гуру 
    01.11.06 
            ✎
    13:28 
 | 
         
        (28) я не про то, что реализовать нельзя, просто не очень поможет наличие регистров правил. ;-)     
         | 
|||
| 
    30
    
        Бриарей    
     01.11.06 
            ✎
    13:42 
 | 
         
        (29) РП предназначен для хранения детерминированных корней. В данной задаче корень (прибыль, доход и т.д.) не детерминирован.   
        Юзай полиморфизм.  | 
|||
| 
    31
    
        Scooter    
     01.11.06 
            ✎
    13:47 
 | 
         
        Смотри как в УПП бюджетирование сделано
  
        перенеси подсистему если нужно  | 
|||
| 
    32
    
        Wasya    
     01.11.06 
            ✎
    13:58 
 | 
         
        (0) Сам спрашиваешь и сам отвечаешь. Так делай регистр правил.     
         | 
|||
| 
    33
    
        Neco    
     01.11.06 
            ✎
    14:42 
 | 
         
        +(31) Система финансовых расчетов (Справочник финансовые расчеты + Отчеты)     
         | 
|||
| 
    34
    
        Гений 1С    
     гуру 
    01.11.06 
            ✎
    16:22 
 | 
         
        Я просто продемонстрирую код, чтобы вы поняли, как я извращаюсь.
  
        Итак функция Показатель(П) вызывается для каждой ячейки отчета. П.Строка - ссылка на строку отчета П.Колонка - ссылка на строку отчета. Каждая строка и колонка отчета имеют уникальный идентификатор. П.Строка.Схема и П.Колонка.Схема - структуры, заполняются из таблицы, где напротив каждого идентификатора стоит список параметров, таких как ВидИтога, ФормулаИтога, ФормулаПростая, ФормулаАгрегатная и т.п. Получается нехилый если - то... Функция Показатель(П) Перем Показатель, Р; Перем С; Если НЕ П.Дерево.Данные.Свойство("ПараметрыВычислений") Тогда ДанныеПараметрыВычислений(П); П.Дерево.Данные.Вставить("ПараметрыВычислений", истина); КонецЕсли; С=П.Дерево.Данные; // Агрегат - используется для указания, что отчет представляет собой агрегат подотчетов // ЛистыСуммированияФакта // ЛистыСуммированияПлана // ЛистыСуммированияБюджета //Смотрим, какой показатель мы расчитываем Показатель=П.Строка.Схема.Идентификатор; //Определяем колонку Колонка=П.Колонка.Схема.Идентификатор; //Если итог по колонке считается по другому, указать специфику здесь //Для Колонки итого Если Колонка="ИтогПоКолонке" Тогда Если П.Строка.Схема.ВидИтога="Сумма" Тогда Возврат фоСумма(П,"@КолонкаМесяца"); КонецЕсли; //Берется значение последнего месяца Если П.Строка.Схема.ВидИтога="Последний" Тогда Возврат фоЗнач(П, "@М12"); КонецЕсли; //Берется значение первого месяца Если П.Строка.Схема.ВидИтога="Первый" Тогда Возврат фоЗнач(П, "@М1"); КонецЕсли; //Берется среднее значение по месяцам Если П.Строка.Схема.ВидИтога="Среднее" Тогда Возврат фоОКДеление(фоСумма(П,"@КолонкаМесяца"), 12,2); КонецЕсли; //А может быть есть явная формула итога? Если П.Строка.Схема.ФормулаИтога<>Неопределено Тогда Возврат ВычислитьФормулу(П, П.Строка.Схема.ФормулаИтога); КонецЕсли; //Иначе колонка итого считается так же, как и помесячная колонка ИначеЕсли Колонка="ФактПрошлогоГода" ИЛИ Колонка="ПланПрошлогоГода" Тогда //Простое суммирование за прошлые месяцы //Если фоКатегория("УВР_Департамент;УВР_Управление", П.ОбщийВидОтчета) Тогда // Листы=ДанныеЛисты; //КонецЕсли; //Если нужно суммирование данных подотчетов Если С.Агрегат Тогда //Смотрим, определена ли формула для агрегатных отчетов Формула=П.Строка.Схема.ФормулаАгрегат; Если Формула<>Неопределено И Формула<>"Сумма" Тогда Возврат ВычислитьФормулу(П, Формула); КонецЕсли; //Если формула не определена, но этот показатель подвержен суммированию //то считаем как обычную сумму листов книги //Или если явно указано, что нужно суммировать //Тогда суммируем подотчеты Если Формула="Сумма" ИЛИ фоЭтоКатегория("Сумма;Последний;Первый", П.Строка.Схема.ВидИтога) Тогда //Определяем, какие листы книги суммировать Листы=?(Колонка="ФактПрошлогоГода", С.ЛистыСуммированияФакта, С.ЛистыСуммированияПлана); //Если значение не заполнено, то оно не будет и учитываться Возврат ДанныеСуммаЛистов(П, П.Строка.Идентификатор, П.Строка.Значение, , Листы); КонецЕсли; КонецЕсли; //Смотрим, есть ли формула для вычисления факта/плана, если есть, она и используется Формула=П.Строка.Схема[Колонка]; Если Формула<>Неопределено Тогда Возврат ВычислитьФормулу(П, Формула); КонецЕсли; //Иначе данные по факту/плану считаются по обычной схеме месяца, по обычной формуле для месяца КонецЕсли; //Частные случаи по месяцам описываются здесь //В противном случае колонка итого расчитывается так же, как и месячный показатель Формула=П.Строка.Схема.ФормулаПростая; Возврат ВычислитьФормулу(П, Формула); КонецФункции Функция ВычислитьФормулу(П, Формула, Р=Неопределено) Если Формула="-" Тогда Возврат Неопределено; КонецЕсли; Возврат обВыполнитьФормулуСПараметром(Формула, П, Р); Возврат Р; КонецФункции  | 
|||
| 
    35
    
        Гений 1С    
     гуру 
    01.11.06 
            ✎
    16:23 
 | 
         
        (33) слишком простая модель для нашей конторы     
         | 
|||
| 
    36
    
        ОбычныйЧеловек    
     01.11.06 
            ✎
    16:31 
 | 
         
        (Гений 1С) если тебе "регистр правил" не поможет то тебе уже ничего не поможет.     
         | 
|||
| 
    37
    
        France    
     01.11.06 
            ✎
    19:45 
 | 
         
        я бы пошел как в (30).. классический случай..     
         | 
| Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |