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] metaclass.livejournal.com 2009-11-18 03:39 pm (UTC)(link)
Не совсем понял, причем тут файл? Речь о том, как хранить и обрабатывать правила сопоставления операций и статей выходного отчета.

[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] mudasobwa.livejournal.com 2009-11-18 03:47 pm (UTC)(link)
Текстовые файлы поддаются правке без требования перекомпиляции. Поэтому для хранения — отличный вариант. Хотя можно хоть в ту же базу запихнуть.

Большинство выходных данных отчета, насколько я понял, тащится из базы без особых правил, просто поле из таблицы (но это тоже не так важно).

Правила я предлагаю записывать на языке SQL, который для этого уже придуман — тогда не придется писать свой язык.

[identity profile] mudasobwa.livejournal.com 2009-11-18 03:50 pm (UTC)(link)
Только хранить их лучше в лежащем рядом текстовом файле, чтобы для апдейта правил не нужно было в саму базу лезть (а если база далеко — то файл проще переслать почтой).

[identity profile] metaclass.livejournal.com 2009-11-18 03:59 pm (UTC)(link)
А причем тут хранимые процедуры? Как средство реализации в принципе подходят (но опять же - либо они будут правила из таблиц брать и паттерн-матчинг имитировать) либо прямо в них жестко вшивать код бизнес-логики и делать на каждую вариацию правил по хранимой процедуре и еще одну общую процедуру-диспетчер.

[identity profile] metaclass.livejournal.com 2009-11-18 04:01 pm (UTC)(link)
Да, хорошая идея.

[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)
Ребе, я бы добавил в систему какой нить скриптоязык (я бы взял схему) и хранил бы такую хрень где нить во внешних файликах.

(Anonymous) 2009-11-18 04:17 pm (UTC)(link)
SQL is not really suitable as a business rules language. People are inventing Prolog clones like DRools, and those are smart people, like from IBM Labs et al. They cross unification construct of logical programming with functional approach and practical library. Also they made lot of infrastructure -- GUI, unit testing, versions/namespaces/baseline, inter-language interface etc.

SQL is a smart hack but not maintainable at all for a big ruleset.
I'd suggest using SQL for getting the result of classification (SQL is an output of the reporting, not a processing engine.) And PL/SQL (T-SQL) is even worse than SQL. Real maintainance nightmare.

OTOH metaclass should have been started from reporting tools, not from classification phase. It all depends on the requirements of course (I just wonder if he knows about MDX for example).

(Anonymous) 2009-11-18 04:18 pm (UTC)(link)
+1

(Anonymous) 2009-11-18 04:19 pm (UTC)(link)
rrright

[identity profile] oldmann.livejournal.com 2009-11-18 04:23 pm (UTC)(link)
жестко вшивать бизнес-логику, процедуры заменять при апдейте по причине изменения бизнес-логики, механизм существует.

[identity profile] mudasobwa.livejournal.com 2009-11-18 04:30 pm (UTC)(link)
I have just answered the question, I had no purpose to teach or to share a knowledge.

As far as I understood the problem, MDX is overkill for it. We have an amount of fields and some restrictions (to say, queries) applied on resultsets. There is no multidimensional data at all and using such tools as DRolls will dramatically slow the development down.

And, increase the cost, as far.

[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] metaclass.livejournal.com 2009-11-18 05:03 pm (UTC)(link)
У меня была идея генерить SQL (или там заполнение таблиц правил) из правил на другом языке, но как известно, собственные языки изобретать запрещено, т.е. вернее не запрещено, но это считается грехом, особо присущим русским программистам, которые не могут самореализоваться, не сделав хотя бы парочку собственных языков :))

[identity profile] metaclass.livejournal.com 2009-11-18 05:04 pm (UTC)(link)
А вот смех в том, что операции не ложаться в одну статью, и не все попадают на выход.
Для проверки нужно делать другой набор правил, например брать главную книгу или еще какой-нибудь бухгалтерский отчет(или несколько отчетов) и сравнивать результаты между несколькими отчетами.

[identity profile] metaclass.livejournal.com 2009-11-18 05:06 pm (UTC)(link)
Ну в общем-то хранение правил в отдельной таблице в БД, тем более с версионностью по датам изменения правил и есть оный DSL.

[identity profile] metaclass.livejournal.com 2009-11-18 05:19 pm (UTC)(link)
Reporting tools used in our current projects support only SQL query results. So if I will be implementing this report with current tools then it will be ruleset in table (one record - rule+time span of rule activity) and selectable stored procedure for report generation. Stored procedure and rule table may be autogenerated to avoid manual coding of facts table processing.

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

[identity profile] metaclass.livejournal.com 2009-11-18 05:23 pm (UTC)(link)
Логика версионная. Мы должны уметь посмотреть старый отчет(за 2008 год к примеру) в том виде, в котором он был тогда. А новые - по новому.
Так что даже с файликами - придется привязывать правила к дате операции или дате в параметрах фильтра. Еще печальнее - это если отчет за период пересекающий дату изменения, в таком случае, вообще хорошо бы показывать два отчета.

Page 1 of 3