49 votes

Acteurs Scala - les pires pratiques ?

Je ne suis pas très sûr de l'utilisation des acteurs en Scala. J'ai lu de la documentation sur la façon de faire des choses, mais je pense que j'aurais également besoin de quelques règles à ne pas faire pour me sentir libre de les utiliser. Je pense que j'ai peur de les utiliser d'une mauvaise manière, sans même m'en rendre compte.

Pouvez-vous penser à quelque chose qui, s'il était appliqué, entraînerait une rupture des avantages apportés par les acteurs Scala, voire des résultats erronés ?

55voto

oxbow_lakes Points 70013
  • Évitez !? dans la mesure du possible. Vous sera Obtenez un système verrouillé !

  • Toujours envoyer un message à partir d'un fil de discussion Acteur-sous-système. Si cela signifie créer un Acteur transitoire via la fonction Actor.actor méthode, alors qu'il en soit ainsi :

    case ButtonClicked(src) => Actor.actor { controller ! SaveTrade(trdFld.text) }

  • Ajouter un "tout autre message" aux réactions de votre acteur. Sinon, il est impossible de savoir si vous envoyez un message au mauvais acteur :

    case other => log.warning(this + " has received unexpected message " + other

  • N'utilisez pas Actor.actor pour vos acteurs primaires, sublcass Actor à la place. La raison en est que ce n'est qu'en sous-classant que l'on peut fournir un modèle de toString méthode. Encore une fois, le débogage des acteurs est très difficile si vos journaux sont jonchés de déclarations du type :

    12:03 [INFO] Sending RequestTrades(2009-10-12) to scala.actors.Actor$anonfun$1

  • Documentez les acteurs de votre système, en indiquant explicitement les messages qu'ils recevront et la manière précise dont ils doivent calculer la réponse. L'utilisation des acteurs entraîne la conversion d'une procédure standard (normalement encapsulée dans une méthode) en une logique répartie sur plusieurs réactions d'acteurs. Il est facile de se perdre sans une bonne documentation.

  • Assurez-vous toujours que vous pouvez communiquer avec votre acteur en dehors de ses react pour trouver son état. Par exemple, je déclare toujours une méthode à invoquer via un fichier MBean qui ressemble à l'extrait de code suivant. Sinon, il peut être très difficile de savoir si votre acteur est en cours d'exécution, s'il s'est arrêté, s'il a une grande file d'attente de messages, etc.

.

def reportState = {
  val _this = this
  synchronized {
    val msg = "%s Received request to report state with %d items in mailbox".format(
                   _this, mailboxSize) 
    log.info(msg)
  }
  Actor.actor { _this ! ReportState }
}
  • Reliez vos acteurs entre eux et utilisez trapExit = true - Dans le cas contraire, ils peuvent échouer silencieusement, ce qui signifie que votre programme ne fait pas ce que vous pensez qu'il fait et qu'il manquera probablement de mémoire car les messages resteront dans la boîte aux lettres de l'acteur.

  • Je pense que d'autres choix intéressants concernant les décisions de conception à prendre en utilisant des acteurs ont été mis en évidence. ici et ici

0 votes

Tous vos autres points sont immédiatement logiques, mais je suis curieux de votre deuxième point, qui consiste à toujours envoyer des messages à partir d'un fil de discussion Acteur. Quelle est la motivation première ici, performance/clarté/autre chose ? Je ne comprends pas bien.

0 votes

Je vois que vous avez beaucoup souffert en écrivant du code Actor en Scala ! :-)

2 votes

@Michael - si vous ne déclarez pas explicitement un Acteur vous-même, un sera créé pour vous et lié à l'objet Thread en tant que ThreadLocal . Il n'est pas du tout clair pour moi que cette approche soit logiquement sûre ou exempte de fuites de mémoire. Il est beaucoup plus simple de déclarer explicitement un

12voto

DigitalRoss Points 80400

Je sais que cela ne répond pas vraiment à la question, mais vous devriez au moins vous réjouir du fait que la concurrence basée sur les messages est beaucoup moins sujette à des erreurs bizarres que la concurrence basée sur la mémoire partagée et les threads.

Je présume que vous avez vu les directives pour les acteurs en Programmation en Scala mais pour mémoire :

  • Les acteurs ne devraient pas bloquer pendant le traitement d'un message. Si vous voulez bloquer, essayez de vous arranger pour recevoir un message plus tard à la place.
  • Utilisez react {} plutôt que receive {} lorsque cela est possible.
  • Communiquez avec les acteurs uniquement par messages.
  • Préférez les messages immuables.
  • Faites en sorte que les messages soient autonomes.

0 votes

Bonjour, merci pour votre réponse rapide - elle apporte des éléments très utiles. Je pensais aussi que le "partage d'état" est quelque chose à ne pas faire mais je ne sais pas exactement ce que cela signifie au niveau du code - peut-être, - avoir comme message une classe C avec un champ privé F et avec un getter classique pour ce champ (getF) - d'un acteur, envoyer une instance de C - de l'acteur acteur, recevoir C et appeler getF ? Cela pourrait-il signifier "partager l'état" ? Merci !

0 votes

Un état partagé est un état auquel on accède par plus d'un thread. Ce n'est pas aussi mauvais qu'un état mutable partagé, mais cela nécessite un raisonnement sur la cohérence, à moins qu'il ne soit partagé qu'après la construction et donc immuable. Ainsi, envoyer une référence à soi-même dans un message ne serait pas la meilleure solution, bien qu'une référence à un objet mutable soit pire qu'une référence à un objet immuable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X