/ / Où définir les classes de cas lorsqu’on utilise Actors - scala, actor

Où définir des classes de cas en utilisant des acteurs - scala, acteur

Je fais mes premiers pas avec scala.

J'ai créé un PhotosLoaderActor cela se chargera de télécharger une image et de l'enregistrer dans un cache. Pour ce faire, je vais avoir un CacheActor et un DownloadActor.

ma PhotosLoaderActor a ceci:

override def act() {
loop {
react {
case (caller : Actor, photoToLoad:String) => { // bla bla }

Je viens d'apprendre que je pourrais utiliser case classes utiliser quelque chose comme ceci:

case class LoadImage(caller: Actor, photoToLoad: String)
override def act() {
loop {
react {
case LoadImage(caller, photoToLoad) => { // bla bla }

Ma question est:

Où devrais-je définir le case classes? Si j'appelle le PhotosLoaderActor à partir d'un package différent, importer l'acteur importerait également le case classes? Quelle est la meilleure pratique?

Réponses:

10 pour la réponse № 1

J’ai essayé différentes approches et décidé de mettre tous les messages associés dans un objet, généralement nommé quelque chose comme XyzProtocol.

Par exemple:

object PhotoProtocol {
case class LoadImage(caller: Actor, photoToLoad: String)
case class UpdateCache(photoToLoad: String, photo: Photo)
case object ClearCache
}

J'aime cette approche pour plusieurs raisons:

  1. L'analyse du package contenant, dans un IDE ou dans ScalaDoc, n'affiche que 1 ou quelques objets XyzProtocol au lieu d'être encombrée de dizaines de messages.

  2. Si le nombre d'acteurs requis pour traiter un message change avec le temps (par exemple, l'introduction d'un pool d'acteurs ou l'indirection vers un autre sous-arbre d'acteurs), les messages ne sont pas affectés.

  3. Il n'y a pas de capture accidentelle de l'acteurexemple, comme lors de la définition des classes de cas dans la classe d’acteur. Cette capture accidentelle est une raison suffisante pour que je ne définisse jamais les classes de cas à l'intérieur de la classe d'acteur.

Remarque: si le message est purement un détail d'implémentation interne d'un acteur (par exemple, un signal interne qui lui est envoyé par lui-même), je définis le message dans l'objet compagnon de la classe d'acteur.

PS. Je suggère également de passer à Akka des acteurs de la bibliothèque standard. Akka sera ajouté à la distribution Scala 2.10.


1 pour la réponse № 2

Si l'acteur est un objet singleton, je le placerais probablement dans l'objet même.


1 pour la réponse № 3

Je les définis souvent au-dessus de l'acteur qui les utilise. Ou dans un fichier dédié uniquement à ces classes de cas si plusieurs acteurs correspondent sur les mêmes cas

package org.numbers
import akka.actor.Actor

sealed trait Numbers
case class Even(n: Int) extends Numbers
case class Odd(n: Int) extends Numbers

class NumberActor extends Actor {
def receive = {
case Even(n) => doEven(n)
case Odd(n) => doOdd(n)
}

def doEven = ...
def doOdd = ...
}

Utilise akka au lieu d'acteurs de scala, mais dans les deux cas. De cette manière, l'importation du package contenant l'acteur importera également les messages pouvant être envoyés à cet acteur. Si les classes de cas sont définies "à l'intérieur" de l'acteur, elles ne seront pas disponibles pour les autres classes souhaitant envoyer des messages à cet acteur.