Должны ли сообщения акторов распространять общую черту?

В большинстве примеров правильного использования рамок актера scala (и akka) люди склонны выводить каждое сообщение из одного признака. Например:

trait Message
object Ping extends Message
object Pong extends Message

Однако, как в scala, так и в Akka, прием сообщений вообще не вводится. Есть ли причина для реализации общей черты?

Ответ 1

Это действительно зависит от того, чего вы пытаетесь достичь. Например, недавно я создал небольшое приложение с участием актеров, у которых было несколько типов участников, и управляющего актера, который действовал более или менее как маршрутизатор. Теперь действующие участники могут получать множество сообщений, например Foo, Bar и Baz. Без супертипа, в управляющем актере я должен был бы написать что-то вроде этого:

react {
    case x:Foo | x:Bar | x:Baz => worker ! x
}

Это, очевидно, излишне подробный. Поэтому в этом случае супертип WorkerMessage будет иметь большой смысл, потому что он упрощает ваш код:

react {
    case x:WorkerMessage => worker ! x
}

С другой стороны, это делает сообщения Foo, Bar и Baz довольно непригодными для каких-либо других целей, чем использование вашим WorkerActors. Если у вас есть сообщение Stop или Init, например, это, вероятно, будет плохо, потому что вам нужно будет переопределить его по всему месту.

Итак, если вы знаете, что у вас будут только актеры, которые не передают сообщения (т.е. сами обрабатывают их), тогда я думаю, вы будете в порядке, если не будет супертипа для них.

Я предполагаю, что причина, по которой люди делают это более или менее по умолчанию, состоит в том, что, если вы позже измените свой код, вам не нужно будет потом создавать черту, потому что вы уже делали это в начале.

Лично я всегда стараюсь избегать лишних накладных расходов, поэтому я бы, вероятно, не определял супертип, если я действительно не нуждаюсь в нем. Кроме того, я действительно не знаю, влияет ли создание супертипа на производительность вообще, но мне было бы интересно узнать.

Ответ 2

  • Оба с scala.actors (через InputChannel[T] или Reactor[T]) и Akka (TypedActor) вы можете установить ограничения типов для входящих сообщений;

  • В большинстве примеров сообщения расширяют sealed trait. Это сделано по двум причинам:

    • если обработчик сообщения (частичная функция) вашего актора не охватывает все сообщения, расширяющие этот признак, компилятор генерирует предупреждение;

    • sealed trait может быть расширен только в исходном файле, где определен признак, и, таким образом, клиент не может определить его собственные сообщения, которые расширяют признак;

Ответ 3

Это не обязательно, но это материал дизайна OO. Лучше иметь абстрактный тип для сообщений домена приложения. Таким образом, вы можете иметь преимущества полиморфизма при работе с сообщениями в нашем коде приложения.

  
trait Message

object Ping extends Message
objet Pong extends Message

object Stop
  

Например, если где-то в вашем приложении вам приходится иметь дело с кучей сообщений независимо от их конкретных типов (Ping или Pong), вы будете рассматривать их как объекты типа Message. Это имеет смысл? Нет?