キュウリをビジネスルールエンジンとして使用する

この記事では、 キュウリをビジネスルールエンジンとして使用するというアイデアと、そのようなルールをチェックする方法について説明します。







例では、さまざまなパラメーターに応じてクライアントをグループに分散する問題を解決するアプリケーションを参照します。 アプリケーションの要件は次のとおりです。









クライアントは、国、識別子、言語などのパラメーターに固有のものである場合があります。







Cucumberは、振る舞い駆動開発(BDD)をサポートするツールです。これは、ソフトウェアの品質を高め、メンテナンスコストを削減することを目的としたソフトウェア開発プロセスです。

Gherkinはビジネス向けの読み取り可能なドメイン固有言語であり、ソフトウェアの動作を実装方法を詳しく説明することなく記述することができます。





理由



この問題に対処するように私たちを促した理由を以下に示し、そのうちの3つがあることを示すために番号を付けました。







理由1



私が参加する多くのプロジェクトはよだれを使います。 ルールは単体テストで厳密にカバーされており、一部の場所ではBDD(Behavior Driven Development)テストでさえキュウリで使用されています。 これらのプロジェクトの1つで、奇妙なことに気付きました。BDDテストのコードは、よだれルールのコードに非常に似ています。

例を挙げましょう。 droolsのコードは次のようになります。







rule "For client from country ENG group will be England" when Client(country == "ENG") then insert(new Group("England")); end
      
      





BDDテストの機能( gherkinの キュウリ機能 )の説明は次のようになります。







  Scenario: For client from country ENG group will be England When client's country is "ENG" Then group will be "England"
      
      





構文を無視する場合-1対1! この例はほとんど合成ですが、それでも正直です-実際のプロジェクトではすべてがそのようになりました。 実際、私たちの期待は2つの場所で2つの異なる方法で説明されており、2番目(ガーキン)は明らかに人間が読みやすいようです。 それで、なぜそれだけで書いていないのですか?







理由2



顧客に提供する必要があります(この場合、「顧客」は、アプリケーションの要件を作成し、必要に応じてクライアントと連携する彼のエコシステムで使用します)。ビジネスルールを使用して機能の意図/要件を記述して適用できるシンプルで理解可能なツールそれらをリアルタイムで。 すなわち この例の一部として、顧客はグループにクライアントを配布するためのルールを変更したいのですが、プログラマーは今それを行っています-顧客の要件をルールの形で実装し、テストとテスターユニットでテストし(この問題をすべて尊重して)、一部として配信しますアプリケーションの新しいバージョン。







上で述べたように、私たちはよだれを使い、それを愛します(これはおそらく同じロマンチックな感情ではなく、ただの習慣です)、そしてよだれエコシステムの有声の問題を解決するために、ツールがあります-豊富な(そして最も重要なことには)機能を備えたdrools workbench 。 しかし、このツールを「現状のまま」顧客に提供し、彼が好きなようにルールを書いてもらうことは、非常に楽観的な考えだと思います。 よだれは複雑なものであり、それを可能にするには少なくとも特別な訓練を受ける必要があるためです。 同時に、テストでよだれルールをカバーすることは厳密に必要です-これはもちろん私の意見ですが、私はそれをすべての人に課しています。

droolsワークベンチでの作業を簡素化するには、次を使用できます。









さらに、テーブルは抽象化のレベルが異なり、ビジネスルールによる実装とは異なります。

Drools dslを使用すると、代わりに







 when Client(country == "ENG") then insert(new Group("England")); end
      
      





あなたはこのように書くことができます







 when client's country is "ENG" then group will be "England" end
      
      





Dslは正しい方法であり、キュウリとガーキンがすでに放牧されている草原にあります。







理由3



この理由はテストの問題に関連しています。顧客が自分の手で書かれたルールをどのようにテストするかは明確ではありません。 テストを書くことは理想的ですが、私はそれがお客様がよだれを書くよりもさらに少ないと信じています。 この場合、プログラマに行う必要がある最低限のことは、基本的なロジックの一般的なテストを提供することです。 たとえば、アプリケーションの要件は次のとおりです。







  • 確立された配布ルールに従って、クライアントのグループを選択する必要があります
  • 各クライアントに対して1つのグループのみを選択する必要があります


また、顧客がどの配布ルールを作成する場合でも、これらの要件は常に満たされている必要があります。 そして、次のように確認できます。









実装



ucumberは 、テスト環境外での使用のために投獄されたのでなく、説得と脅威によってテスト環境を機能させることができました。 概念実証の例は、 https://github.com/avvero/croolsにあります 。 実際、キュウリをビジネスルールエンジンとして使用できます。 それはすべての人々です!







テスト中



このアプリケーションでは、次をテストする必要があります。







  1. 確立された配布ルールに従って、クライアントのグループを選択する必要があります
  2. 各クライアントに対して1つのグループのみを選択する必要があります
  3. パラメーターセットAの場合、グループBが選択されます


同時に、パラグラフ1と2は一般的な要件であり、顧客が実装/実装した特定の配布ルールに依存しないため、テストを準備して実装を事前に検証し、配布ルールを変更するときに実行できます。 これを行うには、データセット(パラメーターの可能なオプションのすべての組み合わせのセット)を作成することをお勧めします。 それは直感的に構築され、キュウリの現在の実装のおかげで非常に簡単です。 なぜ直感的ですか? 例を挙げましょう。







条件を取得する場合:







 client's country is 'RUS'
      
      





、それから私はそのような国の値の単体テストを書くでしょう:









あなたが条件を取る場合:







 client's country is 'RUS' client's country is 'CHL'
      
      





、それから私はそのような国の値の単体テストを書くでしょう:









条件を取得する場合:







 client's payment > '1000'
      
      





、その後、私はそのような値の単体テストを書くでしょう:









したがって、パラメーターに必要なすべてのオプションは、ルール自体から取得できます! そして、オプションの組み合わせは、混合するだけで取得できます。







キュウリに慣れていない方へ

機能ファイル(ガーキン言語)に記述されているルールは、定義ファイルでサポートされている必要があります(Java実装を使用しています)。 この場合のサポートは、フィーチャファイルのレコードを定義ファイルのメソッドに(定期的に)関連付ける機能です。そうしないと、レコードは理解されず、処理されません(エラーまたはルール全体の無視)。 たとえば、







  Scenario: For client from country ENG group will be England When client's country is "ENG" Then group will be "England"
      
      





メソッドを説明する必要があります







  private Set<String> groups = new HashSet<>(); @When("^client country is \"([^\"]*)\"$") public void clientCountryIs(String code) throws Throwable { Assert.isTrue(code.equals(client.getCountry())); } @Then("^group will be \"([^\"]*)\"$") public void groupWillBe(String code) throws Throwable { groups.add(code); }
      
      





定義ファイルには、スクリプトを記述するために使用できるすべての可能な式が記述されていることがわかります。







パラメータのオプションを取得するには、この方法でメソッドを実装した追加の定義ファイルを記述することで実装できます。







  @When("^client's country is \"([^\"]*)\"$") public void clientCountryIs(String code) throws Throwable { factDictionary.getCountries().add(null); factDictionary.getCountries().add(code); factDictionary.getCountries().add(UNDEFINED); }
      
      





すなわち 開発者は、スクリプトを記述するための機能を形成するメイン定義ファイルに加えて、データセットを抽出できる追加のファイルも提供します。







そのようなテストのいくつかの例を見てみましょう(デモhttp://avvero.pw/crools/を使用して自分で行うことができます)







例1



 Feature: Select group Scenario: England When client country is "ENG" Then group will be "England"
      
      





チェック結果







 Some entries have not been distributed: #0 {"client":{},"deposit":{}} #1 {"client":{"country":"any"},"deposit":{}}
      
      





したがって、もう1つのルールを追加する必要があります







 Feature: Select group Scenario: England When client country is "ENG" Then group will be "England" Scenario: Default When client country is not "ENG" Then group will be "Default"
      
      





例2



 Feature: Select group Scenario: England When client country is "ENG" Then group will be "England" Scenario: Russia When client country is "RUS" Then group will be "Russia" Scenario: RichRussia When client country is "RUS" And deposit >= 1000 Then group will be "RichRussia"
      
      





チェック結果







 Some entries have not been distributed #0 {"client":{"country":"any"},"deposit":{"amount":999}} #1 {"client":{},"deposit":{"amount":1001}} #2 {"client":{"country":"any"},"deposit":{"amount":1001}} ... Some entries have been distributed to more than one group {"client":{"country":"RUS"}, {"amount":1001}}: Russia, RichRussia
      
      





条件を追加して複数のグループに入る問題を修正し、 And deposit < 1000









  Scenario: Russia (no deposit) When client country is "RUS" And deposit is null Then group will be "Russia" Scenario: Russia When client country is "RUS" And deposit < 1000 Then group will be "Russia"
      
      





そして、そのようなルールのいくつかのバリアントのルールの欠如に関する問題







  Scenario: Default When client country not in |ENG| |RUS| Then group will be "Default"
      
      





「良い」ルールのセットは次のようになります







  Feature: Select group Scenario: England When client country is "ENG" Then group will be "England" Scenario: Russia (no deposit) When client country is "RUS" And deposit is null Then group will be "Russia" Scenario: Russia When client country is "RUS" And deposit < 1000 Then group will be "Russia" Scenario: RichRussia When client country is "RUS" And deposit >= 1000 Then group will be "RichRussia" Scenario: Default When client country not in |ENG| |RUS| Then group will be "Default"
      
      





このように形成されたデータセットにより、多数のパラメーター値とそれらの組み合わせがわかります。 それに基づいて、私たちはすでに分配ルールがどのように機能するかについて結論を導き出すことができます。 そして最も重要なことは、編集中にリアルタイムでGUIで顧客に見せることです。

残りのチェックは







パラメーターAのセットでは3、グループBが選択されます

、ここであなたはまだあなたの目で見なければなりません-必要なグループが正しいパラメータを持つクライアントで満たされているのは本当ですか? しかし、データセットのおかげで、これは簡単に行うことができ、チェックリストを確認してオプションをチェックする必要はありません。







要件やその他の条件(「顧客が使用するシナリオを想定できる」など)に応じて、データセットに基づいて他のチェックを追加できます。

「2000年の預金を持つロシアの顧客は、RichRussiaグループに確実にアクセスしますか?」 あなたはこれを行うことができます-(そのようなことのためのGUIを提供した後)どのクライアントがRichRussiaに入るか、またはロシアからのクライアントが1000以上の預金を持っている場所を参照してください。








All Articles