最佳实践- akka actor 中的辅助方法

Best practices- Helper methods in akka actor

我最近重构了我的 actor,并最终得到了很多作为 actor 一部分的辅助方法。这是正确的做法吗?所有的辅助方法都应该是它们自己的参与者吗?如何进行分离?

  public class MyActor extends UntypedActor {



        public MyActor () {

        }

        @Override
        public void onReceive(Object msg) throws Exception {


        if ( msg instanceof doSomethingComplex) {
                doSomethingComplex message = (doSomethingComplex) msg;
               doSimple(message.prop);
}

private void  doSimple(String prop){
doSimpler(prop);
....
}

private void  doSimpler(String prop){
...
....
}

}

辅助方法应该放在哪里?这些也应该是演员吗?

A helper method is a method that helps another method to perform it's task. These are typically used when a method has to perform a complicated task that is composed of several smaller tasks. The smaller tasks are often performed by helper methods.

辅助方法通常仅用于将较大的任务分成更小、更有条理的方法。辅助方法应该位于使用它们的 class 的层次结构中。

Should all helper methods be an actor of their own? How do I make the separation?

在解决这些问题时,思考什么是演员会很有帮助。 Derek Wyatt 在他的书 Akka Concurrency 中将演员与人进行了类比(以下摘自他的书的免费 fourth chapter):

Your day-to-day world is full of concurrency. You impose it on yourself as well as the people around you, and they impose it on you. The real-world equivalents of critical sections and locks as well as synchronized methods and data are all naturally handled by yourself and the people in your world. People manage this by literally doing only one thing at a time. We like to pretend that we can multi-task, but it’s simply not true. Anything meaningful that we do requires that we do just that one thing. We can pause that task and resume it later, switch it out for something else to work on and then return to it, but actually doing more than one thing at a time just isn’t in our wheelhouse.

So what if we want to do more than one thing at a time? The answer is pretty obvious: we just use more than one person. There’s not much in the world that we’ve benefited from that wasn’t created by a gaggle of talented people.

This is why actors make our application development more intuitive and our application designs easier to reason about: they’re modeled after our day-to-day lives.

随后在同一章中,他写道:

Actors only do one thing at a time; that’s the model of concurrency. If you want to have more than one thing happen simultaneously, then you need to create more than one actor to do that work. This makes pretty good sense, right? We’ve been saying all along that actor programming draws a lot on your day-to-day life experiences. If you want work done faster, put more people on the job.

在设计参与者系统时,将系统的主要部分分配给具有不同职责的参与者是一个很好的原则。例如,在 ETL 管道中,可能有:

  1. 订阅新数据队列的参与者。
  2. 解析原始数据的参与者。
  3. 为用户感兴趣的信息片段过滤解析数据的参与者。
  4. 将结果保存到数据库的 actor。
  5. 将结果发布到用户可以订阅的队列的参与者。

假设解析器 actor 使用辅助方法。这个方法是否应该封装在它自己的 actor 中取决于这个方法做什么。将任务分解为子任务是个好主意,但在某些时候你必须决定任务太小 "small"-- 太小而不能成为它自己的参与者。

回到人的类比,让我们将管道中的每个阶段想象成一个人。让我们假设解析器人员需要一支削尖的铅笔来完成他的工作,并且目前解析器自己拿到了铅笔。雇用一个低级实习生(借用怀亚特书中的另一个例子)唯一的工作就是削铅笔并在需要时交给解析器人员是否有意义?如果大量数据流入,不招实习生,多招几个parser就够了吗?为 10 个解析器配备 30 个削铅笔实习生可能效率不高。换句话说,我们可能不需要根据解析器的数量独立地缩放实习生的数量。如果我们确实需要这样做,那将表明实习生的工作足够重要,足以证明雇用实习生是合理的。

总结一下这个主观的深思:

  • 将您的系统分解为职责明确的部分。将每个部分分配给一个演员。
  • 如有必要,将每个部分分解为子任务。将每个子任务分配给一个参与者。帮助决定是否需要进一步分解的一个关键方法是确定独立扩展子任务是否有效。
  • 如果您愿意,可以将太小而不能作为自己的参与者的功能放在辅助方法中。

Where should the helper methods be?

几个想法:

  • 如果辅助方法仅与某个 actor 相关,请在执行操作时在 actor 内部声明它。
  • 如果可以在不同类型的 actor 中使用辅助方法,请在 actor 中的 utility class. Alternatively, declare it as a static method 中声明它。