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)
Не совсем понял, причем тут файл? Речь о том, как хранить и обрабатывать правила сопоставления операций и статей выходного отчета.

(no subject)

[identity profile] mudasobwa.livejournal.com - 2009-11-18 15:47 (UTC) - Expand

(no subject)

[identity profile] metaclass.livejournal.com - 2009-11-18 16:01 (UTC) - Expand

(no subject)

(Anonymous) - 2009-11-18 16:17 (UTC) - Expand

(no subject)

[identity profile] mudasobwa.livejournal.com - 2009-11-18 16:30 (UTC) - Expand

(no subject)

[identity profile] metaclass.livejournal.com - 2009-11-18 17:19 (UTC) - Expand

(no subject)

(Anonymous) - 2009-11-18 19:00 (UTC) - Expand

(no subject)

[identity profile] metaclass.livejournal.com - 2009-11-18 19:07 (UTC) - Expand

(no subject)

[identity profile] theiced.livejournal.com - 2009-11-19 00:50 (UTC) - Expand

(no subject)

(Anonymous) - 2009-11-19 14:52 (UTC) - Expand

[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:50 pm (UTC)(link)
Только хранить их лучше в лежащем рядом текстовом файле, чтобы для апдейта правил не нужно было в саму базу лезть (а если база далеко — то файл проще переслать почтой).

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

(no subject)

[identity profile] oldmann.livejournal.com - 2009-11-18 16:23 (UTC) - Expand

(no subject)

[identity profile] theiced.livejournal.com - 2009-11-18 21:52 (UTC) - Expand

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

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

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

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

[identity profile] alexey-rom.livejournal.com 2009-11-18 09:22 pm (UTC)(link)
Именно, он для таких задач идеален. Или rule engine.

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

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

(no subject)

[identity profile] metaclass.livejournal.com - 2009-11-18 17:23 (UTC) - Expand

(no subject)

[identity profile] graynm.livejournal.com - 2009-11-18 18:15 (UTC) - Expand

(no subject)

[identity profile] theiced.livejournal.com - 2009-11-18 21:45 (UTC) - Expand

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

(no subject)

[identity profile] kosiakk.livejournal.com - 2009-11-18 17:36 (UTC) - Expand

(no subject)

[identity profile] metaclass.livejournal.com - 2009-11-18 17:39 (UTC) - Expand

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

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

(no subject)

[identity profile] gds.livejournal.com - 2009-11-18 17:35 (UTC) - Expand

(no subject)

[identity profile] metaclass.livejournal.com - 2009-11-18 17:37 (UTC) - Expand

(no subject)

[identity profile] gds.livejournal.com - 2009-11-18 17:46 (UTC) - Expand

(no subject)

[identity profile] theiced.livejournal.com - 2009-11-18 21:48 (UTC) - Expand

(no subject)

[identity profile] gds.livejournal.com - 2009-11-19 06:14 (UTC) - Expand

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

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

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

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

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

(no subject)

[identity profile] clayrat.livejournal.com - 2009-11-18 17:46 (UTC) - Expand

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

[identity profile] theiced.livejournal.com 2009-11-18 09:49 pm (UTC)(link)
гнусный овцеёб.

ну на кой хрен там xml и уродливо-ублюдочный xslt если есть кошерная схема например.

(no subject)

[identity profile] sergiej.livejournal.com - 2009-11-19 08:53 (UTC) - Expand

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

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

[identity profile] metaclass.livejournal.com 2009-11-18 09:00 pm (UTC)(link)
Звучит привлекательно, за исключением того, что я не совсем понял, "куды здесь лошадь запрягать".
Мы встраиваем хаскель себе? Как мы с ним будем взаимодействовать - т.е. передавать ему данные и получать результат?

(no subject)

[identity profile] permea-kra.livejournal.com - 2009-11-18 21:16 (UTC) - Expand

(no subject)

[identity profile] metaclass.livejournal.com - 2009-11-18 21:42 (UTC) - Expand

(no subject)

[identity profile] permea-kra.livejournal.com - 2009-11-18 21:50 (UTC) - Expand

(no subject)

[identity profile] permea-kra.livejournal.com - 2009-11-18 22:09 (UTC) - Expand

(no subject)

[identity profile] permea-kra.livejournal.com - 2009-11-18 22:20 (UTC) - Expand

(no subject)

[identity profile] tonal.myopenid.com - 2009-11-20 05:34 (UTC) - Expand

[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] vp.livejournal.com 2009-11-19 06:32 am (UTC)(link)
кстати да, мощнейшая штука.

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