How to Start Learning Actor-Based Programming
Discovering and appreciating differences between Akka.NET actors and traditional Object-Oriented Programming
One of the most frequent pieces of feedback we get from developers who are new to Akka.NET is that the “learning curve” is high. I want to explore that today and why I think this isn’t actually true, but what developers are saying is that working with actors is unfamiliar, not difficult.
I’d also argue that really, really bad pre-existing habits many software developers have, such as frameworkism, become a hundred-fold more destructive when you introduce unfamiliar paradigms, such as stateful programming with actors, to the mix. You could substitute “stateful programming with actors” with “using NoSQL” or “going cloud native” and that sentence would be equally true.
Let’s assume you’ve already decided that learning actors is worth your time and now you want to know: “how can I begin to learn how to work with actors for my own purposes?” That’s what this post is about.
If you’re still not sure about using the actor model and Akka.NET, two suggestions:
- Go see our “Cool Projects” Playlist on YouTube for some inspiration and subscribe to
@Petabridge
there.- Join the Akka.NET Discord and see what real users are building with it.
Begin by Discovering and Appreciating Differences Between Actors and Traditional OOP
Actor syntax is simple, the behavior is intuitive (i.e. read messages one at a time), and it offers superior handling of matters such as fault tolerance and thread-safety by generalizing those issues.
Actors are still classes, so they’re not a total departure from OOP, but they do have some pronounced differences for reasons that are intentional, not arbitrary.
“Start with the basics” is an obvious thing to say to someone beginning to learn - so here’s a twist: begin by discovering how actors are appreciably different from other OOP / .NET constructs and why that is for your benefit.
A really basic example of this - we interact with actors by sending them messages, rather than invoking methods on them:
ActorSystem system = ActorSystem.Create("MySys");
Props helloUntypedActorProps = Props.Create(() => new HelloUntypedActor());
IActorRef helloUntypedActor = system.ActorOf(helloUntypedActorProps, "hello-untyped-actor");
helloUntypedActor.Tell("process-me"); // asynchronously send this actor a message
One example of where .NET developers mistake “unfamiliar” for “complex” / “difficult to learn” is the IActorRef.Tell
method: it’s a void
method, thus it doesn’t return anything, but it’s asynchronous!
I wrote just a few days ago on “Why IActorRef.Tell
Doesn’t Return a Task
” with a fairly deep explanation for the behavior, philisophic, fault tolerance, and performance-centric motivations for this design. Some developers will see that lengthy explanation and say “see, Akka.NET is complicated if developers have to know all of that in order to use Akka.NET effectively.”
If I was teaching high school students how variable assignment works in Python, including an explanation of how things like memory registers work and what’s happening to them when variables are being assigned, no one would bat an eye and call Python variable assignment “complex” as a result.
You don’t have to understand how memory registers work in order to start using Python, but your ability to write effective software and your output will improve with that knowledge.
The same goes for learning the basics of Akka.NET: “you send a message to an actor via IActorRef.Tell
and the actor will process it later” is all you really need to know in order to start using Akka.NET. But understanding what’s happening behind the scenes will absolutely make you a more effective programmer. If you want to learn how to do something, you can just grok the syntax.
If you want to learn why it’s implemented that way and what value does that add - that’s always going to be a more detailed answer.
Appreciate, Not Attack, Differences
This is actually a bigger challenge for experienced developers than it is for beginners: beginners know they’re in a blank state and are ready to tolerate the discomfort learning new paradigms requires.
Experienced developers are:
- Often in a rush - “we have to get to production yesterday, don’t bother me with this theoretical garbage, just let me code” and
- Much, much faster to reflexively make right / wrong dismissals when things are simply “different” - this is both the result of trusting their own experience (good, usually) and having strong opinions on how things “should” be done (a mixed bag.)
These are both bad habits - I once had a senior developer propose an entire Kafka-based application design solely off of what he could discern from Kafka API auto-completions in Visual Studio Intellisense. Didn’t read any of the conceptual documentation and thus missed the forest for the trees. This was a week of wasted time; we had to throw the entire design out and start over. Discovering APIs this way works fine for things that are small and easy to reason about (i.e. how the new range operators work in C#) but not a great method for learning or understanding systems with moving parts. Conceptual documentation is designed to bridge the gap between what you can see in the IDE vs. what’s moving around when you invoke your functions - read it!
Appreciating differences means giving new technologies and paradigms the benefit of the doubt: assume there’s good intentions for differences, i.e. substantive reasons and not arbitrary ones. On the flip side: not every tool’s style or philosophy will suit every developer.
Key Differences to Learn and Where to Learn Them
Akka.NET Bootcamp is still a great place to learn Akka.NET-by-doing, nearly 10 years later, and while it does need some updating in key parts the lessons it teaches are still valuable.
However, if you’re pressed for time and want a breakdown of the most important concepts to learn - here they are:
- How Actors Process Messages
- Switchable Behaviors
- How Actors Restart
async
/await
vs.PipeTo
- How Actors Integrate withTask
- Everything You Wanted to Know about Dependency Injection and Akka.NET
- Using Akka.NET and ASP.NET Core Together
- Akka.NET Application Design: Don’t Create Bespoke Frameworks; Use Repeatable Patterns
- How to Test Akka.NET Applications Pt 1: How to Make Actors Easily Testable and How to Test Akka.NET Applications Pt 2: Writing Akka.NET Unit & Integration Tests with Akka.TestKit
That’s probably 4-5 hours worth of videos - and they all touch on the most important, fundamental concepts + key differences between Akka.NET and everything else. Start there and then give Akka.NET Bootcamp a try or check out some of our cool projects like DrawTogther.NET or Cluster.WebCrawler for some inspiration.
If you liked this post, you can share it with your followers or follow us on Twitter!
- Read more about:
- Akka.NET
- Case Studies
- Videos
Observe and Monitor Your Akka.NET Applications with Phobos
Did you know that Phobos can automatically instrument your Akka.NET applications with OpenTelemetry?
Click here to learn more.