2009-08-21 10 views
4

私の最初の質問は長かったので、これを別の質問として頼んでいます。これは、俳優ベースのアプリケーションのアーキテクチャに関する別のものです。Scalaの俳優を使ったアプリケーションの実践II

アプリケーションを介してメッセージのパスを追跡する

のは、Javaコードの一部を見てみましょう:このコードで

public void deleteTrades(User user, Date date) { 
    PermissionSet ps = permissionService.findPermissions(user) 
    if (ps.hasPermission("delete")) { 
     Set<Trade> ts = peristence.findTrades(date); 
     reportService.sendCancelReports(ts); 
     positionService.updateWithDeletedTrades(ts); 
    } 
} 

私は4つの別々のコンポーネントや手順に必要なそれらの間の相互作用を持っていますdeleteTradesは明確に定義されています。メソッドdeleteTradesに完全に含まれています。

これをモデル化してActorを使用し、4つのコンポーネントを4つの別個のアクタに置き換えると、プロシージャの内容をどのように追跡できますか?私は!?演算子を使用して回避していた場合に特に、それは私がその後、などなどのコードをさらにメッセージを送るであろう私のPersistenceActorにメッセージGetTradesAndDeleteを送信される、私のPermissionActorにメッセージConditionalDeleteを送信するだろうと考えられます削除を処理するには、私のアプリケーションに散らばります。

これは、すべてのアクタが(メッセージを転送するために)他のすべてのアクタにハンドルを必要とすることも意味します。

私の前の質問と同様に、人々はこれをどのように処理しますか?あなたはこれをすべて追跡できる良いモデリングツールはありますか?人々は使用しますか!?あまりに多くの成分をActorに変換していますか?

答えて

6

あなたは間違いなく5つのコンポーネントを使用します。特定のタスクを扱う俳優もいますし、オーケストレーターもあります。

あなたが持っている必要がある質問は、もちろん、これをどのようにアシンクロナスに連鎖させるかです。実際はやや簡単ですが、コードが不明瞭になることがあります。基本的に、あなたはそれぞれの構成員にあなたが望む返信を送ります。

react { 
    case DeleteTrades(user,dates) => 
    PermissionService ! FindPermissions(user, DeleteTradesPermissions(dates) _) 
    case DeleteTradesPermissions(dates)(ps) => 
    if (ps hasPermission "delete") 
     Persistence ! FindTrades(date, DeleteTradesTradeSet _) 
    case DeleteTradesTradeSet(ts) => 
    ReportService ! SendCancelReports(ts) 
    PositionService ! UpdateWithDeletedTrades(ts) 
} 

ここでは、最初の返信で「日付」を渡すためにカリングを使用します。インタラクションに関連するパラメータがたくさんある場合、ローカルのHashSetにあるすべての進行中のトランザクションの情報を保持し、回答を受け取ったときにその情報を見つけるために使用するトークンを渡すほうが良いでしょう。

この1人のアクターは、複数の同時アクションを処理できます。この特定のケースでは、トランザクションを削除するだけですが、それを処理するためのアクションをいくつでも追加できます。 1つのアクションに必要なデータが準備できたら、そのアクションは続行されます。カリー化と機能上の

class Date 
class User 
class PermissionSet 

abstract class Message 
case class DeleteTradesPermission(date: Date)(ps: PermissionSet) extends Message 
case class FindPermissions(u: User, r: (PermissionSet) => Message) extends Message 

FindPermissions(new User, DeleteTradesPermission(new Date) _) 

数説明:

EDIT

はここで、これらのクラスを定義することができる方法の作業例です。 DeleteTradesPermissionクラスは、Dateを渡すことができるようにカレット化されており、他のいくつかの関数はPermissionSetで完了します。これは応答メッセージのパターンになります。

クラスFindPermissionsは、2番目のパラメータとして関数を受け取ります。このメッセージを受け取った俳優は戻り値をこの関数に渡し、答えとして返されるMessageを受け取ります。この例では、メッセージには、呼び出すアクタが送信したDateと応答するアクタが提供しているPermissionSetの両方があります。

DeleteTrades,SendCancelReportsおよびUpdateWithDeletedTradesのように応答が期待されない場合は、返信メッセージの関数を渡す必要はありません。

我々は答えを必要とするメッセージのパラメータとしてメッセージを返す関数を期待しているので、我々はこのような特性を定義することができます。

trait MessageResponse1[-T1] extends Function1[T1, Message] 
trait MessageResponse2[-T1, -T2] extends Function2[T1, T2, Message] 
... 
+0

Daniel - 「DeleteTradesPermissions」のクラス定義を教えてもらえますか?それはケースクラスですか(私はあなたがそれらをカレーすることができるか分からなかった)?あなた自身のエクストラクタを定義しましたか? –

+0

さて、このコードは実際には機能しません。それは例です。私は部分的な適用を強制するために欠けている "_"があることを知っています - 私はそれがカリングで必要ではないと思っていました。しかし、私はそれが少し仕事で済むことをかなり確信しています。ここで、私は何かをした、私はそれを投稿します。 –

1

アクターは配慮せずに、従来のサービス・コンポーネントを交換するために使用すべきではありません。

今日私たちが書いているサービスコンポーネントのほとんどは、訓練によってステートレスです。ステートレスなサービスコンポーネントは、アクターよりも管理しやすい(メッセージクラスなど)。しかし、アクターと比較して、欠けていることの1つは、非同期実行です。しかし、クライアントが結果を同期的に返すことを期待している場合、同期のステートレスサービスコンポーネントは、そのジョブに対してうまくいきます。

管理する内部状態がある場合、俳優は適しています。内部状態にアクセスし、競合状態を心配するために、「act()」内で同期を行う必要はありません。限り "!?" "act()"の内部で使用されない場合、デッドロックも最小限に抑える必要があります。

アクターは、メッセージを処理する際に行われたブロッキング処理に注意する必要があります。アクターはメッセージを順番に処理するので、act()内のI/Oを待つことがブロックされるたびに、メールボックス内の他のメッセージを処理することはできません。ここで使用するScalaイディオムは、実際のブロッキング操作を行う別のアドホックアクターを開始することです。この反パターンは、イベントベースの(アクター)アクターにも影響を与えます。なぜなら、イベントベースのアクターがピギーバックされるスレッドをブロックするからです。

私が収集できることから、サービスコンポーネントへの4回の呼び出しはすべてブロックされる可能性があるため、アクターに変換する際には、それらをスケールする必要があります。

+0

@walter;私はあなたが私の質問に答えているかどうか分からない。私は俳優の仕組みを完全によく知っています。典型的なJavaコードを非同期および非ブロックのアクターコードに変換する際の問題を記述しようとしていました。つまり、アプリケーション全体に分散されたプロシージャロジックをどうやって追跡しますか? –

関連する問題