views:

791

answers:

2

I've now written a few applications using scala actors and I'm interested in how people have approached or dealt with some of the problems I've encountered.

A plethora of Message classes or !?

I have an actor which reacts to a user operation and must cause something to happen. Let's say it reacts to a message UserRequestsX(id). A continuing problem I have is that, because I want to modularize my programs, a single actor on its own is unable to complete the action without involving other actors. For example, suppose I need to use the id parameter to retrieve a bunch of values and then these need to be deleted via some other actor. If I were writing a normal Java program, I might do something like:

public void reportTrades(Date date) {
    Set<Trade> trades = persistence.lookup(date);
    reportService.report(trades);
}

Which is simple enough. However, using actors this becomes a bit of a pain because I want to avoid using !?. One actor reacts to the ReportTrades(date) message but it must ask a PersistenceActor for the trades and then a ReportActor to report them. The only way I've found of doing this is to do:

react {
    case ReportTrades(date) =>
       persistenceActor ! GetTradesAndReport(date)
}

So that in my PersistenceActor I have a react block:

react {
    case GetTradesAndReport(date) =>
       val ts = trades.get(date) //from persietent store
       reportActor ! ReportTrades(ts)
}

But now I have 2 problems:

  1. I have to create extra message classes to represent the same request (i.e. "report trades"). In fact I have three in this scenario but I may have many more - it becomes a problem keeping track of these
  2. What should I call the first and third message ReportTrades? It's confusing to call them both ReportTrades (or if I do, I must put them in separate packages). Essentially there is no such thing as overloading a class by val type.

Is there something I'm missing? Can I avoid this? Should I just give up and use !? Do people use some organizational structure to clarify what is going on?

+1  A: 

To me, your ReportTrades message is mixing two different concepts. One is a Request, the order is a Response. They might be named GetTradesReport(Date) and SendTradesReport(List[Trade]), for example. Or, maybe, ReportTradesByDate(Date) and GenerateTradesReport(List[Trade]).

Daniel
But my point still stands; I have all these classes used for nothing other than passing data around. Yesterday I wrote some code whereby I needed to "decorate" a request with information from 4 separate actors. Even allowing for sensible naming, it is a lot of confusing classes!
oxbow_lakes
Well, such classes are never used just to convey information. They are used to convey information from one place to another for a purpose. If you name them accordingly, you improve the overall legibility of the code.
Daniel
A: 

Are there some objections to using reply? Or passing trades around? If not, your code would probably look like

react {
  case ReportTrades(date) => persistenceActor ! GetTrades(date)
  case Trades(ts) => // do smth with trades
}

and

react {
  case GetTrades(date) => reply(Trades(trades.get(date)))
}

respectively.

Alexander Azarov
I guess my point is that I can't just pass a `Trades` object back to my coordinator as *how would it know which original command was being invoked?* For example, I may have several things I need to do: *DeleteTrades*, *ReportTrades*, *LoadTrades* etc. The coordinator is going to need to get a response like `SomeTradesToReport`, `SomeTradesToDelete` or `SomeTradesToLoad` (assuming I am avoiding `!?`)
oxbow_lakes