Gleyzer両氏によって共同開発されました。2019で、同言語の発表を行いました。InfoQはPurdy氏に言語と、氏らが解決を目指した問題について聞きました。設計/アーキテクチャアジャイルマニュフェスト:ソフトウェアアーキテクトの視点ソフトウェアアーキテクトの役割と責任はアジャイルソフトウェア開発のためのマニフェストの価値と矛盾していると見えますが、優れたアーキテクトはアジャイル開発チームをサポートするテクニックを見つけています。Streamingは、ストリーミングデータのためのSQLライクなインターフェースを提供します。Streamsによって、Redisがストリーミングデータを複数のプロデューサとコンシューマの間で消費、保持、配信することができるようになります。ソフトウェア開発のマニフェストたゆまず息もつかずに市場に突進することで、会社を静かに消滅の崖っぷちへと追い込みます。それは設計してコードを書く方法を再考する時です。簡単さへの投資は、速さへの投資です。簡単さは知的財産の主鉱脈でもあります。競争上の優位性は、一度失ったら、もう一度手に入れることはほとんど不可能です。Buytaerts氏が過去10年間にわたって、企業がDevOps採用のハイプサイクルをくぐり抜け、変革に対する誤解を解消する過程を支援してきた経験について語ります。はじめにあなたは、フローに似たプロセスを実装する必要があるとします。できれば組み込みで、それが設定可能であり、管理や保守に対して拡張性があり、容易であるべきです。あなたが探している単純なフローのオーケストレーションに対して、重厚に思われる抽象化への道のりを進んでいるフルスケールのBPMエンジンを必要としますか?あるいは、フルスケールのBPMエンジンに委ねることなく利用することのできる軽量な代替手段を必要としますか?本稿では、アスペクト指向プログラミング(AOP)の技術を使用して、高度に設定可能で拡張性があり、さらに軽量な組み込みプロセスフローを構築し、オーケストレートするための方法を説明します。Jをベースにしていますが、他のAOPでも同様の結果を得ることができます。本題に入る前に、始めに実際の問題についてさらなる理解を得る必要があります。その後で、利用可能なパターン、ツール、技術のセットに対する私たちの理解を合わせ、私たちにフィットしたものを見つけることができるかどうかを確かめます。私たちの問題はプロセスそのものであるので、それに関するさらなる理解を得ることにしましょう。プロセスとは何でしょうか?プロセスは、定められたゴールの達成に至るための協調されたアクティビティの集まりです。アクティビティは、ある実行命令の一つであり、プロセスを構築するブロックです。それぞれのアクティビティは、そのプロセスのゴール全体の一部を満たすための共有データ(コンテキスト)の一部で動作します。達成されたプロセスのゴールの一部は、残りのアクティビティの実行を協調するのに利用される事象を得ます。これは、そのようなプロセスを定義しているアクティビティの実行を協調するための事象のセットで動作する規則のパターンでしかないとして、基本的にプロセスを再定義します。アクティビティの実行を協調するためのプロセスとして、以下の特性について知っている必要があります。関連スポンサーコンテンツ下記のダイアグラムは、プロセスの高レベルな構造を示しています。:ここで、私たちは以下の一連の要求の中でプロセスを形式化することができます。アーキテクチャとデザイン私たちは、先の4つの要求を解決することによってアーキテクチャの定義を始めようと思います。:アクティビティの集まりとしてプロセスを組み立てるためのメカニズムを定義します個別のアクティビティを定義します共有データに対するプレースホルダーを定義しますそのプロセスの範囲内で、それらのアクティビティの実行を協調するメカニズムを定義しますアクティビティはステートレスなワーカーで、いくつかのデータ(コンテキスト)を含んでいるトークンを受け取ります。このアクティビティによって定義されたビジネスロジックを実行している間、共有データからの読み込みや共有データへの書き込みにより、その共有データのトークンで動作します。共有データのトークンは、プロセスの実行状態を定義します。(POJO)として、私たちのアクティビティを定義することに異論はないでしょう。以下は、Activityインターフェースの定義です。obj)メソッドがあり、入力パラメータは共有データ(コンテキスト)のプレースホルダーです。data);}共有データのためのプレースホールダーは、構造化されたものか非構造化された(つまり、Map)オブジェクトです。それは、完全にあなた次第です。インターフェースにjava.lang.Objectを定義します。実際の環境では、そのプロセスに参加するすべてが知っている構造を示したある構造化オブジェクトの型としてあらわされることでしょう。プロセスプロセスがアクティビティの集まりであることから、それらの集まりを組み立て、実行するためのメカニズムを理解する必要があります。それを達成するための方法はたくさんあります。それらの一つは、ある順序づけられたコレクションの型にすべてのアクティビティを閉じこめ、事前定義された順序の中でそれぞれのアクティビティを繰り返し呼び出すことです。このアプローチの設定可能性と拡張性は、プロセスの制御と実行のすべての側面がハードコードされるという事実から、確実に劣っているでしょう。私たちは、多少型破りや方法でそのプロセスを見ることができ、それは、プロセスが具体的な実装の無い、ビヘイビアレス(振る舞いのない)な抽象概念であると言えます。この一連のアクティビティによる抽象概念をフィルターすることで、そのプロセスの特性、状態、振る舞いを定義します。process(..)メソッドが定義されているGenericProcessクラスがあると仮定します。}}process(..)メソッドは役に立たず、コンテキストの状態が変化しないので、私たちがインプットとなるオブジェクトを渡してprocess(..)メソッドを直接呼び出しても、ほぼ何も起きないでしょう。私たちがprocess(..)メソッドを呼び出す前に、何らかの方法でアクティビティを導入するための方法を見つけ、インプットのオブジェクトを変更するアクティビティがあるときは、process(..)メソッドは不変のままにも関わらず、インプットのオブジェクトがアクティビティによって事前に処理されているので、プロセスの内容全体の結果は変化するでしょう。Filterパターンとして十分に裏付けられているもので、今日のエンタープライズアプリケーションで広く利用されています。典型的な例としてサーブレットフィルターがあります。Filterパターンは、リクエストの受信やレスポンスの転送をインターセプトするフィルターで、既存のアプリケーションリソースをラップします。filterは、アプリケーションリクエストの事前処理やリダイレクトをおこなったり、アプリケーションレスポンスの内容の事後処理や置換をおこなうことができます。filterは、ソースコードを変更することなく既存のリソースに対し、一連の分離した、宣言的でデプロイ可能なサービスを加えるために、順に重ねて積み上げることも可能です。(リンク)歴史的に、このアーキテクチャはセキュリティやトランザクションなどといった非機能的な関心事を解決するために利用されてきました。filterからプロセスに似た構造を組み立てることで、同じアプローチがアプリケーションの機能的な特性の解決に対して容易に適用することができるということです。下図は、プロセスへの呼び出しがフィルターチェーンによってインターセプトされる方法を示しています。それらはそれぞれのフィルターがそのプロセスに関する個々のアクティビティに関連していて、何もすることが無い状態で実際の対象プロセスコンポーネントをおき、それを空っぽの再利用可能な対象オブジェクトとしています。フィルターチェーンを切り替えることで、あなたは異なるプロセスを持つことができます。おこなうべきただ一つのことは、エレガントな方法でこういったものの組み立てを支援してくれる外部フレームワークが存在するかを探すことです。AOPは、単純な構造と最も重要な実行メカニズムを提供していることから、うってつけのものとなりそうです。filterの順序づけられた集まりを定義することができます。Filterで実行される振る舞いで処理を形成しているこれらのフィルターによって代理されます。これで、残りの要求は一つだけとなります。:トランジッションルールと実行の決定メカニズムを定義し、それは、アクティビティによって登録された事象をベースとしたトランジッションルールを強制します。プロキシベースのフィルタの美しさは、トランジッションメカニズムそのものです。filterがプロキシメカニズムによって次々と呼ばれます。これは制限のない自由なもので、一つ一つのアクティビティが常に呼び出されなければならない状況下で変わることなく機能します。実際にはいつもそうであるとは限りません。私たちがあげた先の問題提起の説明の一つは、「達成されたプロセスのゴールの一部は、残りのアクティビティの実行を協調するのに利用される達成された事象を示している。それは、一つのアクティビティの完了が、必ずしももう一つのアクティビティへの遷移を許可する必要があるわけではないということを意味しています。実世界のプロセスでは、トランジッションは前のアクティビティにより達成された/されなかった事象に正確に基づいているべきです。これらの事象は、共有データのプレースフォルダーと共に登録されなければならないので、それらを問い合わせて取り出すことができます。filter内でIF文を入れるのと同じくらい単純です。}}しかし、それはいくつかの問題を生じさせます。私たちがそれに入る前に、一つのことをはっきりとさせましょう。filterは、対応するPOJOアクティビティと密結合であり、それは当然のことです。filterそれ自身の中に全てのアクティビティロジックを保持することは容易にできます。しないようにするための唯一のことは、POJOとして私たちのアクティビティを保持したいと願うことです。filterのコードをアクティビティのコールバックに委譲することを意味しています。これは、私たちがアクティビティの中にトランジッションの評価ロジックを置く場合、私たちは本質的に二つの関心事(アクティビティのトランジッションロジックとアクティビティのビジネスロジック)を結合することができるということを意味しています。それは関心事の分離という基本的なアーキテクチャの原則に違反し、関心事/コードの結合をもたらします。filterにわたって同じトランジッションロジックの繰り返しが発生します。私たちはそれを関心事/コードの分散と呼んでいます。filterをクロスカットします。あなたがAOPを推測したように、技術の選択として、再度、脳裏に浮かびます。adviceを書くことです。インプットを評価し、実行する対象メソッドを許可するかしないのかのどちらかによって、トランジッションの判断をします。filterとなることです。したがって、基本的にはインターセプターをインターセプトするようにしてください。AOPがプロキシベースであるという理由から、それをサポートすることはできません。filterは、既にプロキシの基盤の一部となっているので、私たちは単純にプロキシをプロキシとすることができないのです。AOPで最高の特徴の一つは、それがいくつかの異なる趣向や実装で提供されているということです(つまり、プロキシベースやバイトコードのウィービングなど)。filterを扱うでしょう。それ故、トランジッションとビジネスロジックの分離が保たれるのです。これは、AspectJのようなフレームワークを使用することで容易に達成することができます。することで、私たちは自身のアーキテクチャの中に第二のAOP層を導入します。それは非常に興味深い関係を持つでしょう。下記の図は二つのAOP層で示されたプロセスフローの最終的な構造を表しています。filterからプロセスを組み立てることに責任を持ちます。非機能的なAOP層は、トランジッションの統治の問題に対処します。ここで、このアーキテクチャを示すために、私たちはサンプルのユースケースを実装したいと思います。それは、単純なプロセスフローを定義する購入品目です。4.ユースケース(購入品目)あなたがオンラインショッピングをしていると想像してください。あなたは品目を選び、それをショッピングカートへ入れ、確認画面へ進みます。あなたのクレジットカード情報を入力し、最後に、購入品リクエストを送信します。システムは購入品目プロセスを起動します。含むデータを受信しなければなりません。クレジットの認可を取得する3.出荷の処理をするこのプロセスは、下図で示されるように、現時点で3つのアクティビティを定義しています。:この図では、統治されていないアクティビティのトランジッションも示しています。実際、品目が利用できない場合に何が起こるのでしょうか?「クレジットの認可を取得する」のアクティビティ実行でしょうか?それとも、「出荷の処理をする」が次に実行されるのでしょうか?もう一つの興味深い警告として、クレジットの認可は自動で処理することができない(認可ネットワークはダウンしている)という条件を前提としています。あなたか顧客サービスの代表者は、認可番号を得るためにクレジット会社に直接電話する必要があります。その認可番号を取得して、システムに入力したら、どのポイントでこのプロセスが再開、あるいは継続するのでしょうか?開始、あるいは直接出荷に進むのでしょうか?私は出荷に進むと言いますが、それはどのようにすれば良いのでしょう?私たちが多くの実行制御を維持、管理していない状態で途中からプロセスを再開するにはどうしたら良いのでしょうか?興味深いことに、AOPを用いることで、私たちは実行制御の維持やプロセスの指示の維持をおこなう必要がないということです。filterアクティビティを通したリクエストをプロキシするので、それはフレームワーク自身によっておこなわれます。私たちが必要なことのすべては、登録された事象に基づいた実行のために、個々のフィルターを許可するかどうかのメカニズムを用意することです。「品目の有効性を確認する」では、品目が有効であるという事象を登録します。その事象は、「クレジットの認可を取得する」のために事前に必要なものとして機能する必要があります。同様に、クレジットが認可の事象を登録すると、その事象は、「出荷の処理をする」のアクティビティのために事前に必要なものとして機能する必要があります。ある事象が存在するかどうかは、ある特定のアクティビティを実行しないときの判断として利用されることもあるでしょう。「手動でのクレジット照合」のシナリオに戻り、途中からプロセスを再開する方法について考えます。次のより良い疑問についてです。プロセスの途中で、既に実行されたアクティビティを繰り返すことなく、そのプロセスを再開するにはどうしたら良いのか?共有データのトークン(コンテキスト)が、プロセスの状態も表していたことを思い出してください。その状態は、プロセスと共に登録されたすべての事象を含んでいます。これらの事象は、トランジッションの判断をするために評価されます。したがって、私たちの「手動でのクレジット照合」のシナリオでは、私たちがまさに最初から全体としてプロセスを再送信した場合の、トランジッションメカニズムはこうです。最初のアクティビティである「品目の有効性を確認する」に直面します。そこで、品目の有効性の事象は既に登録済で、アクティビティを繰り返す必要はないことをすぐに知ります。次のアクティビティ「クレジットの認可」へとスキップします。クレジットの認可の事象も(何らかの手入力によって)登録されているので、次のアクティビティである「出荷の処理をする」へと再度スキップします。そのアクティビティだけがプロセスを実行し完了することができます。私たちが実際の例へ移る前に、まだ議論が必要なもう一つの重要な話題があります。それはアクティビティが定義される順序です。それについては最初に議論すべきと思うかもしれませんが、アクティビティの順序はこれらのアクティビティによって定義されるプロセスのトランジッションの決定において、何の役割も演じてないのです。プロセスのアクティビティの順序は、プロセスそのものの均衡を意味するだけです。t事象の見込みや可能性に基づいた戦略は、その存在によって、その実効を遂行するのか除外するのかに対して次のアクティビティのための理想的な環境を作ります。アクティビティの順序を変更することで、プロセス全体へ影響を及ぼしてはいけません。5);上記の公式に従ってプロセスが所定のProcessContextの中で始まるとき、最初のアクティビティはAです。それが呼び出される前に、それが存在するために事象1と2に依存しています。事実1と2がProcessContextの中に存在すると仮定すると、アクティビティAは実行され、事実3を生じます。次のアクティビティは、事象1と3に依存するBです。私たちのプロセスを知ることで、私たちはアクティビティAの前に起こっている事象3の見込みと可能性がとても低いと判断しました。アクティビティAが呼ばれた後で存在する事象3の見込みと可能性は非常に高く、それゆえに、Aに続くアクティビティBという順序となります。5);ほとんど変わりません。プロセスが呼び出されるとき、事象のレジストリを維持するProcessContextは、アクティビティBの呼び出しを許可するために登録されるべき事象が足りていないということをすぐに判断します。次のアクティビティのAもスキップされるでしょう。事象1と2が存在すると仮定すると、アクティビティAの呼び出しを許可するために登録されるべき十分な事象が存在するので、その事象の評価を判断することができます。アクティビティBを生成するための必要条件を失ったことで、同様に、アクティビティCもスキップされます。プロセスが同じProcessContextで再送信された場合、先のプロセス呼び出しのアクティビティAは、事前条件を満足させるためのアクティビティBによって要求された事象を登録したので、アクティビティBが呼ばれます。ProcesContextがアクティビティAがその作業を完了したことを知っているので、アクティビティAはスキップされます。同様に、アクティビティBは、アクティビティCの事前条件を満足させるのに十分な事象を登録したので、アクティビティCも呼ばれます。アクティビティの変更がプロセスの振る舞いに変更を与えないことを見てきましたが、それはプロセス自動化の特性に影響を与える可能性があります。例この例は、以下のアーティファクトからなります。Processの実行。これは、以下に見るように意味のあるコードを含んでいません。実際に意味のあるコードを含めてはいけません。filterチェーンを適用するための対象クラスとして機能することです。対応するSpring定義は、以下の通りです。:購入品目プロセスの残りの構成は、3つの部分から成ります。Pointとして定義しているポイントカットから構成される組み立てのAOP設定を処理します。私たちがどのbeanをインターセプトしているのかを知るために、bean(purchseItem)ポイントカットのexpressionを使用していることを見ることができます。異なるフィルターチェーンを適用している異なるbean名称で、別のGenericProcessImplインスタンスを生成することにより、複数の処理を定義することができます。interceptorとして実装されたアクティビティフィルタへの参照も含んでいます。デフォルトでは、フィルターはほぼ上から下まで連鎖していますが、より明確に言うと、私たちはorder属性も使用しています。ActivityFilterInterceptorの3つのインスタンスを定義することで、アクティビティインターセプターを構成します。それぞれのインスタンスには、facts属性だけでなく、後で定義された対応するPOJOアクティビティのbeanがインジェクトされます。facts属性は、単純なルールのメカニズムを定義し、それは、基底となるアクティビティの実行を許可するかどうかに基づいた単純な状態を特定できます。「品目を確認する」という事象のルールを定義し、それはVALIDATED_ITEMの事象が事象のレジストリ内に登録されていなければ、アクティビティを呼び出すと解釈されるでしょう。この事象は、validatItemActivityが実行されるとすぐに、事象のレジストリに登録されます。事象がまだ登録されていない場合は、このアクティビティは実行可能となり、同じ実行コンテキストに事象が既に登録されている状態でプロセスが再送信された場合は、このアクティビティが再度実行されないようにします。私たちのプロセスに対し、3つのPOJOアクティビティを設定します。これがおこなうすべてのことは、基底にあるPOJOアクティビティを呼び出し、このアクティビティ(53行目)によって返された事象を登録します。POJOアクティビティによって、事象のレジストリやこのプロセスのその他すべての基盤となるコンポーネントを見せないようにすることができます(下図参照)。私たちが後で見るように、このインターセプター自身の呼び出しは、それぞれのインターセプターの設定で指定された事象のルールに基づいたAspectJのアドバイス(第2のAOP層)によって制御されます。このようにして、ここのアクティビティの実行を制御しています。個々のPOJOアクティビティは、所有しているインターセプター(上記参照)によって事象のレジストリに登録されているもので、登録したいと思っている全ての事象をStringのArrayで返します。コンポーネントで、個々のアクティビティを表すSpringのAOPインターセプターそれぞれの呼び出しをインターセプトします。それは、Aroundアドバイスを使用しておこなわれ、事象のルールと現在の事象のレジストリを評価します。interceptorの呼び出しを実行するのか、スキップするのかについての決定を下します。proxyMethodInvocation)のproceed(..)メソッドを呼び出すかのいずれかによっておこなわれます。META-INF/aop.xml(下記参照)で構成を規定する必要があります。私たちはロードタイムのAOPを使うので、Springの設定にウィーバーを登録する必要があります。contextの名前空間を用いてそれをおこないます。:この時点で、私たちはテストの準備が整っています。お分かりのように、テストについては大したことはありません。以下のステップとなります。:ApplicationContextを取得しますGenericProcessオブジェクトを取得します事象のレジストリリストを生成します実行コンテキストだけでなく、入力データを表すオブジェクト(私たちのケースではMapです)を生成しますプロセスメソッドを呼び出します私たちはAspectJのロードタイムウィービングを利用しているので、VM引数として-javaagentオプションが必要になります。is:-javaagent:lib/spring-agent.jar既に、libディレクトリ内にspring-agient.jarが存在します。実行後は、以下のような出力となるでしょう。:テストで見たように、事象の初期リストは空です。既存の事象とともにそれを投入するのであれば、プロセスフローは変わるでしょう。レジストリに事業を追加する行をコメントアウトしてみましょう。あなたのテストの次の行をコメントアウトしてください。factRegistry.add("VALIDATED_ITEM");そして、アウトプットが変わるはずです。今回のアプローチでは、プロセスフローを組み立て、協調し、制御するためにAOPの2つの層を使用する方法を実演しました。filterとしてプロセスを組み立てます。第2の層は、AspectJを使用して実装され、プロセスの協調とフロー制御を提供します。filterによるプロセスをプロキシすることで、プロセスの方向を定義・維持することができます。メカニズムをプロキシすることで、BPMのような分離したエンジンを必要とせずに実行環境を提供することもできます。AOP)を使用することでそれをおこないました。そのアプローチは軽量で組み込まれたものです。既存のSpring基盤を使用し、プロセスが協調されたアクティビティの集まりであることを前提として構築しています。それぞれのアクティビティはPOJOで、それを管理しているすべての基盤/制御のコンポーネントについては、全く知りません。これにより、いくつかのメリットが与えられます。...)となることを可能にしていることなどがあります。テストでは別の利点があります。アクティビティがPOJOであるので、適用されたプロセスを除いたPOJOとしてのテストが可能です。それらには非常に良く定義された入力/出力の規約(必要とするデータと出力を期待しているデータ)があります。あなたはそれぞれのアクティビティのテストを分離しておこなうことができます。filter)を分離することで、テストのトランジッション制御ロジックが、基底のアクティビティによって実装されたビジネスロジックに作用されないことをテストするだけでなく、事象のルールを処理するためのより洗練されたルールのファサードのプラグインを可能とします。アクティビティは構築したブロックから独立していて、ある別のプロセスの一部として再利用することができます。「クレジット確認」のアクティビティは、クレジットの確認を必要としている別のプロセスを組み立てるときに、容易に再利用することができます。本稿のサンプルソースコードは、ここ(ZIP)からダウンロード可能です。現在、SpringSourceでシニアコンサルタントとして働いているITプロフェッショナルです。ソフトウェアアーキテクチャ、設計、コンサルティング、ビジネス分析、アプリケーション開発を含む複数の分野で、ソフトウェアエンジニアとして14年上の経験があります。90年代前半にCOBOLとCICSの世界で彼の職歴が始まったのを皮切りに、1999年以降は、専門のJavaとJavaEE開発に注力していました。2004年以降、Olegはいくつかのオープンソース技術とプラットホーム(特にSpring)を使うことにかなり熱中していました。Telecommunication、Banking、法Enforcement、米国国防総省など、数多くの仕事に取り組んでいます。毎週火曜日に前週のまとめコンテンツがお送りいたします。25万人ものシニアデベロッパーのコミュニティーにぜひご参加ください。サンプルを見るあなたのメールアドレスはこちら国を選んでください。プライバシーポリシーに従って私の個人情報を扱うことに同意します。登録するとさまざまなことができます。アカウント登録をしてInfoQをお楽しみください。あなたの意見をお聞かせください。毎週火曜日に前週のまとめコンテンツがお送りいたします。25万人ものシニアデベロッパーのコミュニティーにぜひご参加ください。サンプルを見る様々なイノベーターとアーリーアダプターがお送りするテクノロジーの概要を見る。自分がまだ知らないことに気づいていないと知るあなたが興味のあるトピックスをいつでも最新な情報に。あなたのメールアドレスはこちら国を選んでください。プライバシーポリシーに従って私の個人情報を扱うことに同意します。よい世界へ私たちが暮らす世界を大切に思い、よりよいものにしたいと考えています。人のためのソフトウェア開発を加速し私たちのミッションを実現することで、この思いを成し遂げようとしています。私たちは利益の1%をさまざまな慈善団体に寄付しています。会社として、また従業員として、そうしたことの価値を強く信じているからです。with.プライバシーBTあなたのプロファイルは最新ですか?プロフィールを確認してアップデートしてください。アドレス*Eメールを変更すると確認のメールが配信されます。会社名:現在の会社名をご入力ください。Other組織規模:現在の組織規模をご入力ください。2,501+国:現在の国を設定してください。Zimbabwe都道府県:現在の都道府県に設定してください。次の都道府県にアップデートする:ニュースレターを購読しますか?インダストリーメールを購読しますか?本Eメールに登録すると、以前より関心のあったトピックの関連情報をお送りする場合がございます。詳細はこちらのプライバシーポリシーをご覧ください。newsletter?新しいメールアドレスに確認用のメールを送信します。このポップアップ画面は自動的に閉じられます。