レポートを作成するために特定のデータに基づいて機能するいくつかのビジネスロジックルールを記述したいと考えています。それらをデータベースMySQLに保存するのに最適な方法がわからない。
上記のように、ルールのチェーンと結果のステートメントを含めることができます。
レポートを作成するために、ビジネスロジックを任意のプログラミング言語に変換できます。また、データベースデータを使用してレポートを生成します。
データベースに格納されたビジネスロジックの対抗策
私は表現力に高い価値を置いており、SQLスペースがそれほど表現力があるとは思えません。最も適切なタスクには、手持ちの最良のツールを使用してください。ロジックと高次の概念をいじるのは、最高レベルで行うのが最善です。その結果、ストレージと大容量データの操作はサーバーレベルで、おそらくストアドプロシージャで行うのが最適です。
しかし、それは場合によります。 1つのストレージメカニズムと相互作用する複数のアプリケーションがあり、アプリケーションがその整合性とワークフローを維持することを確認したい場合は、すべてのロジックをデータベースサーバーにオフロードする必要があります。または、複数のアプリケーションでの同時開発を管理する準備をしてください。
ソース: ストアドプロシージャのビジネスロジックに対する/に対する引数
以下も参照してください。
次のような「ソフトコーディング」ビジネスロジックに対する反対論: http://thedailywtf.com/Articles/Soft_Coding.aspx
「私たちがソフトコーディングを見つけた理由は、変更を恐れているからです。通常の変更の恐れではなく、ビジネスルールの変更の結果として、私たちが作成したコードを変更する必要があるという恐怖です。 。ソフトウェア(つまり「ソフト」)の要点は、ソフトウェアが変化することを変えることができるということです。ソフトウェアをビジネスルールの変更から隔離する唯一の方法は、まだすべてのビジネスルールを欠いている完全に汎用的なプログラムを構築することです。ルールを実装します。ああ、彼らはすでにそのツールをビルドしています。C++、Java、C#、Basicと呼ばれています。そして、あえてCOBOLと言います。」
CREATE TABLE businessRule (
id INT NOT NULL ,
name VARCHAR(32) NOT NULL ,
description VARCHAR(255) NULL ,
statement VARCHAR(255) NOT NULL ,
PRIMARY KEY (id) )
ENGINE = InnoDB;
CREATE TABLE leftOperand (
id INT NOT NULL ,
value VARCHAR(255) NOT NULL ,
PRIMARY KEY (id) )
ENGINE = InnoDB;
CREATE TABLE ruleItem (
id INT NOT NULL ,
businessRuleId INT NOT NULL ,
operator ENUM('if','and','or','not') NOT NULL ,
loperand INT NOT NULL ,
comparator ENUM('<','=','>') NOT NULL ,
roperand VARCHAR(255) NOT NULL ,
roperand_ispercentage TINYINT(1) NOT NULL ,
PRIMARY KEY (id) ,
INDEX businessRule_FK (businessRuleId ASC) ,
INDEX leftOperand_FK (loperand ASC) ,
CONSTRAINT businessRule_FK
FOREIGN KEY (businessRuleId )
REFERENCES mydb.businessRule (id )
ON DELETE CASCADE
ON UPDATE RESTRICT,
CONSTRAINT leftOperand_FK
FOREIGN KEY (loperand )
REFERENCES mydb.leftOperand (id )
ON DELETE RESTRICT
ON UPDATE RESTRICT)
ENGINE = InnoDB;
私があなたに与えることができるのは、この問題を解決する方法であり、答えそのものではありません。
このような複雑なデータを格納するデータベースを設計する一般的な方法は、それらをオブジェクトとしてメモリに保持し、それに応じてデータベースを設計する方法です。結局のところ、プログラミング言語でルールを評価することになります。手順は次のとおりです。最初にクラス図
次に、それをERDに変換します。
オブジェクトを格納/再ロードするデータベース構造ができたら、クラスを作成して、各オブジェクトがそれ自体をロード/格納するようにすることができます。
[更新]
たとえば、ステートメントa + b * -c
をデータベースに保存する場合、次の挿入として変換できます。
-- c
INSERT INTO statement (statement_id) VALUES (1);
INSERT INTO operand (statement_id, type) VALUES (1, 'double');
-- - (minus)
INSERT INTO statement (statement_id) VALUES (2);
INSERT INTO operator (statement_id, type) VALUES (2, 'minus');
-- -c
INSERT INTO binary (operator_statement_id, operand_statement_id) VALUES (2, 1);
-- b
INSERT INTO statement (statement_id) VALUES (3);
INSERT INTO operand (statement_id, type) VALUES (3, 'double');
-- * (multiply)
INSERT INTO statement (statement_id) VALUES (4);
INSERT INTO operator (statement_id, type) VALUES (4, 'multiply');
-- b * -c
INSERT INTO unary (operator_statement_id, operand_statement_id1, operand_statement_id2) VALUES (4, 3, 2);
-- a
INSERT INTO statement (statement_id) VALUES (5);
INSERT INTO operand (statement_id, type) VALUES (5, 'double');
-- + (plus)
INSERT INTO statement (statement_id) VALUES (6);
INSERT INTO operator (statement_id, type) VALUES (6, 'sum');
-- a + b * -c
INSERT INTO unary (operator_statement_id, operand_statement_id1, operand_statement_id2) VALUES (6, 5, 4);
最初に行う必要があるのは、データベースにルールを配置する必要があるかどうかということです。
データベースは強引な解決策であり、多くの場合、単に必要とされません。
データベース駆動型を含むさまざまな形式のルールエンジンを扱ってきたので、非常に苛立たしく、非生産的で、非常に速くなる可能性があります。私が目にした大きな間違いの1つは、独自のアドホックルール言語を記述しようとして、それを使用してデータベースを介して条件付きロジックを駆動することです。少なくとも、すでに証明されている言語(Python、javscriptなど)を使用して、そこに埋め込みます。
さらに良いことに、ルールが十分に複雑であれば、私は個人的にはExcelスプレッドシートを使用することを好みます。これを自動化に使用し(発効日などに基づいて変数ロジックを処理するため)、次の製品を使用して、Webサービスを介してインターフェイスされるPerlスクリプトにかなり複雑な保険評価ロジックをコンパイルします http:// decisionresearch。 com/products/rating.html 。
ロジックをデータベースに保存する場合と、たとえばExcelスプレッドシートと比較すると、
もちろん、ご想像のとおり、Webサービス主導のExcelルールエンジンがすべての状況に適合するわけではありません。そして、それがここで可能な唯一の解決策ではありません。
しかし、私が得ているのは、ユーザビリティー/表現力/テスト容易性/パフォーマンスの観点から、適切なトレードオフを行っていることを確認することです。私が作業している場所では、実行速度が速いことよりも正しいこと、生産的であることのほうが重要なので、Excel/Webサービスを使用します。
そして、slavik262のコメントを拡張すると、最終的にルールエンジンで達成したいのは、最終的には抽象化と一般化であり、可動部品を最小限に抑え、信頼性、テスト容易性、および理解しやすさを向上させます私の経験では、データベースルールエンジンは、Javaベースのルールなど)を作成するだけの場合と比較しても、最適ではありません。サンドボックス化されていて、適切に整理され、一般化された一貫性のあるインターフェースの背後に隠れるので、問題なく機能します。
私の会社では、それはルールの規模と、ルールの変更頻度によって異なります。保険の評価-Excel、それについての質問はありません。いくつかの状態固有のロジック?インターフェースJavaルールファイルで十分です。
したがって、私が正しく理解している場合、フロントエンドを使用して、クエリに適用されるロジックを動的に作成できるようにすることを検討しています(使用されているルールに基づいて、実行時にwhere句が動的に構築されます)?
その場合は、ルールで選択できる条件についてかなり具体的に指定する必要があります(どの値(列)を変更して、レポート元のデータセットに存在する列に対してのみ条件付きルールを持つことができるようにします)。
私があなたの質問を正しく理解している場合、条件を選択できるようにしたいテーブル/列をマッピングすることから始めます。これは、ルールを設計するためのWebページのコントロールになります。
ただし、ルールがデータベースで選択された後の格納方法を尋ねるだけの場合は、以下を含む単一のテーブルに格納することをお勧めします。
ID | RuleSetName | Table | Column | Comparison | Value | Percentage | Notes | CreatedDate | Created By
1 | 'VisitorAnalytics' | Visitors | SUM(Views) | > | null | 10 | n/a | 1/1/2012 | JohnDoe
次に、これらのレコードを作成したら、テーブルをfrom句に挿入し、列を動的SQLのwhere句に挿入することによって、それらを使用します。
これは混乱するように聞こえるかもしれませんが、あなたが求めているのはかなり複雑な解決策です。ただし、最終的には、SQLを動的に構築してからSQLを実行してレポートを生成できる1つの場所にルールをまとめて格納したいだけです。うまくいけば、これはあなたを正しい方向に向けます。
ルールの目的は、既存のデータベーステーブルからの計算フィールドに名前を付けることだと思います。それ以外の場合は、単なるレポート目的で、データをExcelにダンプし、ユーザーがExcel関数とピボットテーブルを使用できるようにすることができます。
重要な問題は、ルールをどのようにアクションに変換するかです。ビジネスルールを格納することだけが目的であり、ビジネスルールのレポートを作成できる場合は、SQLの単純なデータ構造で十分です。
ただし、ルールをコードに変換する場合は、コードが実行される場所を検討する必要があります。データがSQLに格納されている場合、いくつかのオプションがあります。
私はこれらの最初のものに偏っています。主な理由は、ツールがSQLに限定されているためです。
あなたのルールが何をしているかはわかりません。重要なのは、「ステートメント」コンポーネントが行うことです。これは定数または計算可能なデータの式であると仮定します。その場合、ルールはcaseステートメントのように見え始めます。注意点の1つは、ステートメントがデータテーブルの複数の行を調べる必要がある場合があることです(時間の経過に伴う変化を処理するため)。
これらのルールをデータベースに保存することをお勧めします。このストレージにより、SQLコーディングを使用して一連のビジネスルールからクエリを構築できます。 Mysqlは動的SQLを許可します(現在)。基礎となるテーブルとルールについてもう少し理解していなければ、より多くの情報を提供することは困難です。
シナリオ分析に使用するはるかに複雑なシステムを設計したと言えます。シナリオ自体は、スプレッドシート、一連のテーブル、定数など、ビジネスルールと同様に保存されました。システムは、SQL(および一部のExcel)を使用して、シナリオのスプレッドシート表現を(巨大な)クエリに変換しました。次に、クエリを実行して、関連するレポートを生成します。このシステムは、柔軟性があり、パフォーマンスが高く、強力であることが証明されています。
ルールのコンポーネントに基づいて検索を実行する必要がない場合は、データベースの2つのフィールドにルールを保存できます。ステートメントが実行される条件と、別のステートメントが実行される条件。
id, name, description, condition, statement
ルールは、JSONまたは同様の形式を使用して保存できます。
使用するいくつかの用語を定義する必要があります。 アトミック用語、ユーザーが入力した値と比較して真/偽に評価されるシステム値、および複雑な用語、論理演算子を使用して結合された用語があります。
アトミック用語の場合、varは、システムが提供する値を示します(訪問者数やユニーク訪問者数など)。 比較varが値に対してどのように評価されるかを決定します。 valueは、ユーザーが生成する数値または文字列です。 varとvalueが両方とも数値の場合、比較は "<"、 "<="、 "="、 "> ="、または ">"になります。 varとvalueが両方とも文字列の場合、比較は「等しい」、「で始まる」、「で終わる」、または「含む」のいずれかになります。アトミック用語は次のように保存できます。
{ var: varName, comp: comparison, value: numberOrString }
次の形式を使用して、論理積、論理和、否定(および/または否定)で構成される複雑な用語を保存できます。
// Conjunction
{ op: "and", terms: [ term, ..., term ] }
// Disjunction
{ op: "or", terms: [ term, ..., term ] }
// Negation
{ op: "not", term: term }
次に、これらのメソッドを使用してtrue/falseに評価されるステートメントを作成できます。次に例を示します。
{ op: "and", terms: [
{op "or", terms: [
{ field: "numVisitors", comp: ">", value: 1000 },
{ field: "numUniqueVisitors", comp: ">=" 100 }
]},
{ op: "not", term: {
{ field: "numVisitors", comp: "<", value: 500 }
}}
]}
上記の例は、訪問者数が1000を超えるか、ユニーク訪問者数が100以上で、訪問者数が500以上の場合にtrueに相当します。
次に、ルールがtrueと評価されたときに、「ステートメント」と呼ぶものを実行できます。
これを行う簡単な方法の1つは、OODBMSを使用することです。そこでは、メソッドはスロットでオブジェクトにカプセル化され、データベース内で(トリガーのように)実行することもできます。
SQLデータベースを主張する場合、できることは、動的プログラミング言語を使用して、おそらく他のテーブルや行に関連付けられたコードを格納するテーブルを用意することです。
数年前、私はアルジェリア政府の税制の入札を見ました。彼らはビジネスルール(税法)をRDBMSのVisual Basicコードとして保存することを計画していました。
アプリケーションにインタープリターを簡単に組み込むことができる任意の言語を選択できます(Common LISP http://ecls.sourceforge.net ;または http://common-LISP.net/project/armedbear / アプリケーションをJavaで作成する場合)、Lua、Javascript、Schemeなど。
これらの言語を使用すると、ビジネスルール用のDSLを簡単に作成できるため、Common LISPまたはSchemeを好む傾向があります。
与えられた例は次のようなシンボリック式として書くことができます:
(rule :name "RuleName"
:description "Some description"
:body (if (and (< (change-in total-visitor) (percent 10))
(> (change-in unique-visitors) (percent 2)))
(do-something)))
lISPでは、このような記号式はPRINTまたはPRINT-TO-STRING演算子を使用して読みやすく出力できるため、この式をSQLデータベースに挿入できます。
insert into rules (id,expression) values (42,"(rule :name \"RuleName\"
:description \"Some description\"
:body (if (and (< (change-in total-visitor) (percent 10))
(> (change-in unique-visitors) (percent 2)))
(do-something)))");
そして、SQLからそれを取得し、LISPのREADまたはREAD-FROM-STRING演算子を使用してシンボリック式として再度読み取ることができます。次に、適切なDSLを使用して、LISP EVAL演算子を使用して評価できます。
;; with the right DSL written:
(eval (read-from-string (sql-select (expression) :where (= id 42))))
ストアドプロシージャを使用することの唯一の可能な利点は、PythonやJavaなどの異なるテクノロジーを使用するアプリケーションからデータベースにアクセスできることです。
既存のビジネスロジックルールと要件がすでに文書化されていると思いますか。私はこれを質屋管理アプリケーションのために行いました。アプリケーションの機能は完全にテーブル駆動です。これには、管理者がシステムの動作方法を変更するために有効なパラメータを変更できるコントロールテーブルがあります。構造化プログラミング手法と組み合わせると、プログラミングコードの変更量が最小限になります。銀行業務アプリケーションも、複雑なビジネスルールを持つ良い例です。