I've been using Akka and Scala for about a month and I'm somewhat bothered by replacing explicit interfaces with messages. Consider the following simple Akka Actor:
case class DoMyHomework()
class Parent extends Actor {
def receive = {
case d: DoMyHomework => // do nothing
}
}
Actor or non-actor code that sends this actor a DoMyHomework message like this:
ActorRef parent = ...
parent.ask(DoMyHomework)
Has no idea what the outcome will be. What's the type of the answer? Will I ever get an answer? Can I get an exception? And so on.
The fix seems to be to document the case class... but what if some other actor also receives that same case class. Then the documentation should for receiving that message should be in the actor itself.
In an effort to clean this up a little I thought of doing the following:
trait SomeoneSmarter {
def wouldYouDoMyHomework: Future[Boolean]
}
class Parent extends Actor with SomeoneSmarter {
case class DoMyHomework()
def wouldYouDoMyHomework = {
(self ? DoMyHomework()).mapTo(Boolean)
}
def receive = {
case d: DoMyHomework =>
// TODO: If I'm busy schedule a false "No way" reply for a few seconds from now.
// Just to keep their hopes up for a while. Otherwise, say sure right away.
}
}
So, I chatted with colleagues about this and one of the reactions was "you're not being true to the actor model."
First, I would really appreciate some guidance from folks that have been using Actors for a longer time. Do all the messages become unwieldy? Do you end up hiding message-passing behind interfaces?
The actors I'm proposing still have the option of sending messages among themselves, subscribing to event streams, all the stuff you expect from Akka. And the interface gives you a time-tested way of knowing what you're talking to. And it helps when coding in IDEs, and so on. And why should the user of an actor need to know it's an actor (unless it's also an actor and is very tightly coupled with it)?
The other reaction I got was "it looks like you want a TypedActor". But after reading about TypedActor I'm not convinced. Certainly TypedActor saves me the trouble of creating those internal messages. But, at least from the code sample at http://doc.akka.io/docs/akka/snapshot/scala/typed-actors.html I get the impression that the TypedActor is meant only to work as a proxy around a block of code you want to encapsulate, or make thread-safe, or simply not call directly from your current thread. And what you code is just the implementation and interface. You don't mess with the actor itself (the proxy) - e.g. if you want your implementation to do periodic work or subscribe to an event stream, or do anything else unrelated to the interface.
I've also read http://letitcrash.com/post/19074284309/when-to-use-typedactors and didn't find that example more illuminating. I'm probably just not grokking TypedActor (not that I claim to have really understood Actors yet).
thanks in advance for help.
Pino