WPF - Actor Model as a Model layer for MVVM

WPF Team Blog
04 September 2018

A little while ago, we received some very interesting feedback from one of our DevExpress MVPs, Mikhail Shubin, who had created an Actor-based implementation of a model layer with a WPF MVVM application. I have been interested in Actor models for a long time, so I thought this was pretty exciting. We decided to publish his demo as a knowledge base article, so others can benefit from it.

To give you some background, the Actor Model (follow the link for a detailed explanation on Wikipedia) is a pattern that helps create loosely coupled entities called Actors which execute concurrently and can be deployed in distributed systems. Actors use message passing to communicate, and actors as well as messages are very light-weight so that very large numbers of both can be handled by typical implementations. Actors usually form fault-tolerant logical systems where they are organized hierarchically, with parents being responsible for the supervision of their children. Erlang is a platform that became famous for its Actor Model support, and Scala also offers it as a standard API. For .NET there are several library based implementations and Mikhail chose Proto.Actor for his application.

Without further ado, here is the KB article that shows some technical examples and includes a demo application: KB Article T630656

8 comment(s)
Dom Sinclair
Dom Sinclair

Oliver, your last link to the knowledgebase article doesn't appear to work, at least not at the time of writing this.

4 September, 2018
Mikhail Shubin [DevExpress MVP]
Mikhail Shubin [DevExpress MVP]

Hi Dom,

You're right, the correct link to the KN article is below:

www.devexpress.com/.../actor-model-as-a-model-layer-in-the-wpf-mvvm-application

4 September, 2018
Dom Sinclair
Dom Sinclair

Interesting concept by the way Mikhail, I'm going to print it up and take it away for a little light holiday reading!  Now that I finally have an understanding of MVVM I stand a much better chance of understanding what's actually going on.

4 September, 2018
Cyril Leuba
Cyril Leuba

Do you see any benefit using an actor-oriented approach in a single-threaded environnement over an object-oriented approach ?

If immutability is achieved in the "model" with an object-oriented approach, does it bring value to use an actor-oriented framework instead ?

4 September, 2018
Mikhail Shubin [DevExpress MVP]
Mikhail Shubin [DevExpress MVP]

@Cyril

I think the immutability and concurrency are not the principal benefits of the actor model.

The actor-oriented approach is a high level abstraction over the object-oriented approach.

Actor is an object, which has state and behavior (similar to OO approach), but you don't have access to the actor properties and methods (and even don't need it).

As a result you have high focused and loose coupled code, which can be easily tested.

Actor model helps me to control the code complexity and code maintainability.

4 September, 2018
Cyril Leuba
Cyril Leuba

@Mikail Ok thank you for sharing your point of view. I was emphazing on concurrency because it was (and still is) the only benefit I see from using an actor-oriented approach over a "standard" object-oriented one.

I agree that it produces (very) loose-coupled code but at the price of a low cohesion, which I strive to avoid (see enterprisecraftsmanship.com/.../cohesion-coupling-difference for more details on this).

5 September, 2018
Mikhail Shubin [DevExpress MVP]
Mikhail Shubin [DevExpress MVP]

@Cyril Thanks for the link to this interesting post!

So the code cohesion is a subjective estimation of the code readability, right?

As for me - the readability of code with actors is not worse than in pure OO approach.

Simple example - master-detail grid with lazy loading of details:

   public class MainVM

   {

       private readonly PID _actor;

       public MainVM() { /*. . .*/ }

       public virtual IList<Item1> MasterItems { get; set; }

       public virtual Item1 MasterItem { get; set; }

       public virtual IList<Item2> DetailItems { get; set; }

       protected async void OnMasterItemChanged() =>

           DetailItems = await _actor.RequestAsync<IList<Item2>>(new ItemChanged(MasterItem.Id));

   }

Message class:

   public class ItemChanged

   {

       public int ItemId { get; }

       public ItemChanged(int itemId) => ItemId = itemId;

   }

We've moved DetailItems population method to an actor and I would say that readability has become even better... This actor is responsible for the detail items population only and has a single dependence on the Repository<Item2>.

6 September, 2018
Cyril Leuba
Cyril Leuba

@Mikhail I still think that using something like that:

   DetailsItems = await _items2.GetAsync(MasterItem.Id);

makes the code clearer because _items2 is a kind of strongly typed repository for Item2 and it does not add an extra layer (actor) in between. When reading the code with the actor-oriented approach, the intent is less clear because the VM's direct colaborator is now of type "PID" which has no semantic.

In resumé, I think I would use the new layer of indirection provided by an actor-oriented approach only if it allows me to be abstracted from something I don't want to manage by myself: for example concurrency. But never to make my code more decoupled than what it is by using an object-oriented approach.

Anyway, I think that if we want to continue this discussion, we need to find another channel, since this may not be the appropriate one for such debate.

6 September, 2018

Please login or register to post comments.