Pin*_*ino 28 scala actor akka typedactor
我一直在使用Akka和Scala大约一个月,我有点担心用消息替换显式接口.考虑以下简单的Akka Actor:
case class DoMyHomework()
class Parent extends Actor {
def receive = {
case d: DoMyHomework => // do nothing
}
}
Run Code Online (Sandbox Code Playgroud)
演员或非演员代码,发送此演员DoMyHomework消息,如下所示:
ActorRef parent = ...
parent.ask(DoMyHomework)
Run Code Online (Sandbox Code Playgroud)
不知道结果会是什么.答案的类型是什么?我能得到答案吗?我能得到例外吗?等等.
修复似乎是记录案例类...但如果其他一些actor也接收相同的案例类该怎么办.然后文档应该接收该消息应该在actor本身.
为了清理这一点,我想到了以下几点:
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.
}
}
Run Code Online (Sandbox Code Playgroud)
所以,我和同事聊起这个,其中一个反应是"你不是真的对演员模特."
首先,我非常感谢那些长时间使用Actors的人的一些指导.所有的消息都变得笨拙吗?你最后隐藏了接口后面的消息传递吗?
我提议的演员仍然可以选择在他们之间发送消息,订阅事件流,以及你对Akka期望的所有东西.界面为您提供了一种经过时间考验的方式来了解您正在与之交谈的内容.在IDE中进行编码时,它会有所帮助,等等.为什么一个演员的用户需要知道它是一个演员(除非它也是一个演员而且与它紧密结合)?
我得到的另一个反应是"看起来你想要一个TypedActor".但在阅读了有关TypedActor之后,我并不相信.当然TypedActor可以省去创建这些内部消息的麻烦.但是,至少从http://doc.akka.io/docs/akka/snapshot/scala/typed-actors.html上的代码示例中 我得到的印象是,TypedActor仅用作围绕块的代理您想要封装的代码,或者是线程安全的,或者根本不直接从当前线程调用.你编码的只是实现和接口.你不要搞砸演员本身(代理) - 例如,如果你希望你的实现做定期工作或订阅事件流,或做任何与接口无关的事情.
我还阅读了http://letitcrash.com/post/19074284309/when-to-use-typedactors,并没有发现这个例子更具启发性.我可能只是不喜欢TypedActor(不是我声称已经真正理解Actors).
在此先感谢您的帮助.
皮诺
Rol*_*uhn 11
让我首先回答我认为非常重要的一点.你说:
为什么一个演员的用户需要知道它是一个演员(除非它也是一个演员而且与它紧密结合)?
Actor是与传统OO完全不同的编程范式,主要区别在于一切都是异步的,因此永远不会有真正的"返回值".这意味着隐藏它是一个actor的事实通常是一个坏主意,因为异常请参考我的TypedActors博客文章.关于actor的最好的事情是它们完全封装在Akka后面ActorRef- 与OO语言的弱封装相对立.为了充分利用它,ActorRef尽可能公开s,这使客户端代码有机会以最合适的方式使用它们(可能正在使用tell或ask取决于上下文).
在编写一个actor时,你应该将这个actor的所有内容放在一个地方,包括接口契约描述.它看起来有点像这样:
object Parent {
/**
* Send this message to make your parent do your homework … yeah, right ;-)
*/
case object DoHomework
}
/**
* This actor will do your homework if asked to.
*
* ==Actor Contract==
*
* ===Inbound Messages===
* - '''DoHomework''' will ask to do the homework
*
* ===Outbound Messages===
* - '''HomeworkResult''' is sent as reply to the '''DoHomework''' request
*
* ===Failure Modes===
* - '''BusinessTripException''' if the parent was not home
* - '''GrumpyException''' if the parent thinks you should do your own homework
*/
class Parent extends Actor {
…
}
Run Code Online (Sandbox Code Playgroud)
使用普通的无类型actor可以让你充分利用actor模型的全部功能,包括动态改变行为,而不是想把自己装入"同步"调用的超时保护笼子里(简而言之,TypedActors最有用)使用幕后演员实现传统的同步界面).我同意IDE对消息类型的支持会很好,但这是一个工具问题(我一直在与ScalaIDE团队谈论添加一些魔法,但是必须等到它可以获得优先级).在一个地方定义关于actor的所有属性是重要的部分.
免责声明:我不是Akka /演员专家.我已经和Actors和Akka一起工作了大约18个月,我仍然试图围绕某些概念,尤其是在不使用Akka时.
对于您想知道Akka未来的返回类型的特定和狭义情况,是的,您应该使用TypedActor.我曾几次使用TypedActors,它们被用来为不属于Actor系统的模块提供API.也就是说,我在Akka之上构建了一个系统,它在Akka网络中完成了大部分工作,但在Akka网络之外有一个或两个模块需要访问Akka网络提供的功能.最引人注目的是Scalatra前端调用了Akka网络并在响应其客户端之前对Akka网络返回的值进行了一些工作.然而,TypedActor实际上只是Akka网络的前端.我将使用TypedActor作为外部(在Akka网络外部)模块的API前端作为另一个关注点分离.
一般来说,我同意那些告诉你"你不是真的对演员模型"的人试图强迫其回归类型的观点.在最纯粹的形式和我取得最大成功的方式中,Actor模型是使用fire和forget语义实现的.这些消息并不笨拙,在许多情况下,它们帮助组织我的代码并定义工作边界.它确实有助于将它们放入自己的包装中.
如果我要实现您所描述的功能,它将如下所示:
trait SomeoneSmarter {
def wouldYouDoMyHomework : Boolean
}
class Response()
case class NoWay() extends Response
case class Sure() extends Response
class ActorNetworkFrontEnd extends Actor {
def receive = {
case d: DoMyHomework =>
busy match {
case true => sender ! NoWay()
case false => sender ! Sure()
}
}
}
case class SomeoneSmarter(actorNetworkFrontEnd:ActorRef) extends SomeoneSmarter {
def wouldYouDoMyHomework : Boolean = {
val future = actorNetworkFrontEnd ? DoMyHomework()
val response = Await.result(future, timeout.duration).asInstanceOf[Response]
response match {
case NoWay() => false
case Sure() => true
}
}
}
Run Code Online (Sandbox Code Playgroud)
记住我写的那种方式你会做我的家庭作业,它会在等待答案时阻止.然而,有一些聪明的方法可以异步地执行此操作.有关更多信息,请参见http://doc.akka.io/docs/akka/2.0.3/scala/futures.html.
此外,请记住,一旦您的消息在Akka网络内,您就可以执行所有很酷的扩展和远程处理,并且TypedActor API的用户永远不必知道.
这样做确实会增加大型项目的复杂性,但是如果你认为它分离了为外部模块提供API的责任,甚至可能将责任转移到另一个包,那么它很容易管理.
好问题.我迫不及待地想听听更有经验的Akka开发人员的答案.
| 归档时间: |
|
| 查看次数: |
3808 次 |
| 最近记录: |