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

#scala #actor #akka

#scala #актер #akka

Вопрос:

В большинстве примеров правильного использования фреймворков акторов 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:

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

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

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

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

Комментарии:

1. Хорошо, теперь я понимаю причину scala.actors. Однако для актеров, типизированных akka, вы не определяете сообщения, вы просто вызываете свои методы интерфейса и ждете, когда произойдет волшебство. Запечатанный признак полезен, но опять же, если я правильно помню, Akka receive является частичной функцией [Any, Unit], поэтому нет проверки на пропущенные случаи.

Ответ №3:

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

   
trait Message

object Ping extends Message
objet Pong extends Message

object Stop
    

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

Комментарии:

1. Если есть несколько черт для реализации, это может иметь смысл. Но ваш аргумент недействителен, если все сообщения реализуют одну и ту же родительскую черту.