metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2009-11-18 05:11 pm

Опердень и паттерн-матчинг.

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

И есть набор правил, согласно которым эта таблица раскладывается по статьям некоего выходного отчета который ложится на стол Президенту РБ, т.е. к примеру "все проводки с типом операции 126 относятся на статью затрат "Цех забоя и переработки свинины", за исключением проводок со счета 91, который относится на статью затрат "Цех забоя и переработки лошадей"". В таких правилах обычно проверяется где-то 5-10 условий на значения полей записи операции, самих правил может быть порядка сотни штук. И правила могут меняться, например в 2008 году переработка лошадей и свиней делилась на две статьи, а в 2009 министерство статистики решило, что достаточно одной статьи "забой любого скота", но обязательно детализированной по фазам луны.

И вот как бы вы такое решали?

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

PS: Здесь немного объяснено, что имеется в виду под "грехом собственного языка".

[identity profile] mudasobwa.livejournal.com 2009-11-18 03:36 pm (UTC)(link)
Я бы сделал обычный csv-like текстовый файл, в который складывал бы данные для отчета в форме

result ::= [db.table.field | sql]

— через запятую, например.

[identity profile] gds.livejournal.com 2009-11-18 03:42 pm (UTC)(link)
логика где-то быть просто обязана, будь то в данных или в коде. Если код достаточно высокоуровневый для обработки аналитики (а нужно именно так; на худой конец, эмбеддед хаксиль в руки), то любую разницу между кодом и данными следует скорее игнорировать, так как они выполняют задачу прилично, а трудности у них в разных местах. То есть, нет смысла делать умное решение "через данные" под такие вещи, если подобных программ/логик нужно менее нескольких штук.
А в generic-решениях "через данные" есть проблема: они постоянно оказываются недостаточно generic. Код править придётся по-любому, как минимум для дополнения, а скорее всего и для исправления багов в обработке данных, представляющих собой алгоритм матчинга.

Ещё один момент, не совсем в тему.
"все проводки с типом операции 126 относятся на статью затрат "Цех забоя и переработки свинины", за исключением проводок со счета 91, который относится на статью затрат "Цех забоя и переработки лошадей""

Если это просто пример, то забьём. Иначе же я бы обязательно вытащил "цех" в атрибуты первичного документа, и (определял бы | разрешал бы выбирать) бух.счёт на основании цеха.

[identity profile] oldmann.livejournal.com 2009-11-18 03:45 pm (UTC)(link)
ребе, а вы слышали про хранимые процедуры Oracle?

[identity profile] rssh.livejournal.com 2009-11-18 04:02 pm (UTC)(link)
В Джаве есть стандарт на rule-engine http://java-source.net/open-source/rule-engines
Наверняка для С# тоже что-то подобное есть

[identity profile] alexott.livejournal.com 2009-11-18 04:08 pm (UTC)(link)
DSL a-la prolog, и правила на нем?

[identity profile] theiced.livejournal.com 2009-11-18 04:16 pm (UTC)(link)
Ребе, я бы добавил в систему какой нить скриптоязык (я бы взял схему) и хранил бы такую хрень где нить во внешних файликах.

[identity profile] kosiakk.livejournal.com 2009-11-18 04:33 pm (UTC)(link)
metaclass, а про metaprogramming не помнишь =)

я бы сделал DSL для удобного написания правил, а потом бы по этим правилам генерил бы, например, SQL-скрипты.

DSL очень удобно делать в Jetbrains MPS, т.к. там шикарнейший редактор и правильная структура.

А за полсотни строк кода можно получить автокомплит нужной части структуры БД (даже с подсказкой-описанием), вытаскивая её по jdbc. Ну или просо руками захардкодить, если она часто не меняется.

А на выходе из правил получать что угодно. Хоть java-код, хоть sql, хоть низкоуровневый DSL для Drools, хоть код для кастомной системы отчётов и уже его выполнять.

[identity profile] nicka-startcev.livejournal.com 2009-11-18 04:56 pm (UTC)(link)
хехе. Встраивание make - это интересно, но ещё интереснее - это проверки правил на полноту и непротиворечивость, чтоб операция предсказуемо легла ровно в одну статью и чтоб в выходных статьях были представлены все операции.

[identity profile] dmzlj.livejournal.com 2009-11-18 05:01 pm (UTC)(link)
так может наколбасить какой-нить DSL, описывающий специфику забоя конины и свинятыны? и формулировать правила на нем?

где-нибудь внутри интерпретатора языка будет паттерн-матчинг...

[identity profile] clayrat.livejournal.com 2009-11-18 05:39 pm (UTC)(link)
действительно, а почему доменспецифик язык стал вдруг грехом? вся лисповая идеология проектирования на том построена.

[identity profile] sergiej.livejournal.com 2009-11-18 07:41 pm (UTC)(link)
Счас меня будут бить, возможно ногами, но я скажу эти слова XML+XSLT :)
А чтобы оптимально и на уровне базы то просто таблица правил выходного отчёта, в которой для каждой статьи выходного отчёта запись с источником и условиями, делов то :)

[identity profile] permea-kra.livejournal.com 2009-11-18 08:08 pm (UTC)(link)
Я бы взял ghc as lifrary, сваял бы модуль, точенный на нужные запросы и писал бы генератор отчёта на комбинаторах/функциях этого модуля. При этом есть библиотеки, парсящие хаскель, и оттуда можно проверить отсутствие левых импортов. А само приложение грузило бы и компилировало запрос в рантайме.

В вашем случае есть F#, который родственен окамлу и должен обеспечивать приемлимую степень изоляции и разумный набор правил.

[identity profile] yurri.livejournal.com 2009-11-18 08:20 pm (UTC)(link)
Реализовать обработку правил на WWF и редактировать потом только описательные XML-карты. Или вообще спихнуть это на MSSQL SSIS или даже BizTalk, если такой есть в инфраструктуре.

[identity profile] bigfrogg.livejournal.com 2009-11-18 08:38 pm (UTC)(link)
QtScript идеально ложится под эту задачу

[identity profile] molnij.livejournal.com 2009-11-19 04:26 am (UTC)(link)
у нас на уровне бухгалтерии, насколько знаю живет какой-то полускриптовый язык который создает sql-код для вычисления. код на языке ессно тоже живет в базе.
вообще говоря, это где-то рядом с грехом. но, чото, реальноприменимых альтернатив не видно.