Hi Robert, > 25 aug 2015 kl. 19:51 skrev kraythe <[email protected]>: > > Roland, > > All good points but if you look at large systems there are a large set of > messages that have a relatively static implementation. For example, go fetch > X from all objects of type Y in the system. There is little to be interpreted > in that message. With the "book" based examples, we could have a receive > method with hundreds of these messages in a huge case statement. That is the > reality of real, vs Academic, examples. With a code base in the hundreds of > thousands, we have classes that do hundreds of things. To have to write a > dispatcher even to call those methods separately is a lot of code duplication > for not much gain. Further it seems that there are cases where such "mutable > behavior" reaction to a message can be coded into the callable. If the > message is defined inside the class, when its run it will have access to the > data of the class. > > Consider a Customer class with over 100 things to do to it. We can write > these 100 things into methods and then create 100 messages to encapsulate > these events and then have a receive with a pattern matching case on 100 > types of messages. Sounds nasty, verbose and error prone (especially for more > junior programmers). Now lets say I have a different paradigm. I define the > 95 of the 100 messages and wrap up their implementation in a callable. The 5 > remaining methods are special, they transition the actor to some state, > change the behavior or the actor via become() or something like that. These > special messages are largely just messages without implementation. For the > actor implementation, all of the code of the 95 methods is hidden from direct > invocation (which is a good thing) but since the messages are defined as > nested classes they can still do what needs to be done to the customer > object. As for the receive() method, I just need 6 cases. 1 to handle all 95 > possible messages (just calls the callable and sends the sender back the > result) and 5 for the special messages. Furthermore, if the customer needs to > convert one of the 95 messages or alter behavior, that is going to be a rare > circumstance and can be programmed directly into the message or actor class. > For example if an attempt is made to grant a gift card to a customer whose > account is suspended, the code can do that in the call. If some reason the > actor needs to interpret a message in a different manner, that can be coded > right into the receive method for that message or the message can be made to > implement Function1[State, Result] and have the condition passed to it. > > In fact this would make the customer actor MUCH easier to understand and > increase the performance dramatically. In high volume systems and O(n) > solution to anything should be called into question. I have a prototype > running and its working nicely with even a base class that other actors can > extend: > > class SmartMessageActor extends Actor { > val log = Logging(context.system, this) > > override def receive: Receive = { > case f: Function0[_] => > sender ! f.apply() > case f: Callable[_] => > sender ! f.call() > case f: Runnable => > // no reply to sender, just run the message. > f.run() > case msg => > val data = ToStringBuilder.reflectionToString(msg) > log.error(s"received unknown message of type ${msg.getClass} with data > $data") > unhandled(msg) > } > } > > Interesting concept ?
Yes, and a very old one: you just implemented a single-threaded Executor with quite a bit of overhead that you don’t use—an Actor is meant to encapsulate state and none of the functions you pass can access or modify that state. If you implied by “nested classes” that the messages close over the actual state of the Actor then that is obviously a big no-go, it completely breaks the encapsulation to share this object outside of the Actor itself (which would be needed to instantiate these nested classes in the first place). As I said, for a real Actor the behavior does not belong to the message; as long as you treat the code accordingly it does not matter where you place it (i.e. you could place it into the message type, but then you’ll have to pass in all required context so that the Actor itself decides what it exposes to the processing and when it does it—and it is strongly preferred to not modify the state from within the message but instead return the new state, in our collective experience this approach saves you lots of head scratching). Note how this is incompatible with just sending a raw Runnable/Callable/etc. to an Actor, you’ll still need to define a proper message (super) type with appropriate method signatures. Regards, Roland > > -- Robert > > > On Tuesday, August 25, 2015 at 9:07:34 AM UTC-5, rkuhn wrote: > Hi Robert, > > this proposal shares some commonality with another experiment of mine, see > https://github.com/akka/akka/pull/18147#discussion_r37143815 > <https://github.com/akka/akka/pull/18147#discussion_r37143815>. The biggest > conceptual issue here is that messages are deliberately separated from > behavior in the Actor Model: an Actor reacts to messages when it wants and in > whichever way it wants, this is key to achieve protocol compositionality > (e.g. forwarding, aggregating, caching, etc.). What you describe is no longer > an Actor, it is just a queue of functions to be run by an Executor. > > Another angle is that placing the implementation within the message type > means that this message is bound to a particular Actor type (and its internal > state representation). How would you handle this message within another Actor > that happens to speak (part of) the same language? The freedom to interpret > the message at the receiving end is precisely what achieves the loose > coupling in message-oriented systems. > > So, while it is certainly possible to place the code wherever you want, in > general—or conceptually—the behavior belongs to the processing entity, not to > the message. > > Regards, > > Roland > >> 23 aug 2015 kl. 16:39 skrev kraythe <kra...@ <>gmail.com >> <http://gmail.com/>>: >> >> Sure I could do all of that. If the whole codebase was Scala. Its not. Its a >> hybrid of scala and java. Even with just java I could do method delegation. >> However, that kind of misses the point. >> >> Say we have domain object with the name Customer. There are certain messages >> we send customer to debit their balance, change name, etc. But there are >> other messages that we send to generate JSON specific to a particular rest >> endpoint. It seems problematic at best to mix together the customer >> implementation with the implementation to get the JSON data for that >> particular endpoint. I would rather put the JSON creation in a callable and >> pass it to the CustomerActor and then inside there we extract the relevant >> fields for the JSON to return to the user. >> >> But even excluding this use case, consider a large domain object with 60 >> different methods that can be done with it. You can order supplies, change >> relevant information and so on. Now in order to implement this with an actor >> I would have to make one HUGE 60 case message switch. Now, other than the >> fact that it wouldnt be an efficient method (pattern matching 60 cases) it >> would be really super annoying to see this massive method just to call some >> other method. It would seem to be a lot clearer if the message is smart. So >> when user calls Customer.placeOrder(Integer, Order) it would generate a >> Smart message that has the implementation of the message processing in the >> code. >> >> Naturally you would have to watch out for closing over, mutable state and >> all the other potential pitfalls of messsaging systems. However, the >> implementation would be clean. Inside the method, the message is generated >> and dispatched. The user gets back a future if needed and the actor for that >> domain object realizes it is a smart message and simply runs the apply >> function inside the smart message. >> >> In that paradigm the actor receive method is smaller, the message >> implementation is isolated to the PlaceOrder method and we dont have a 60 >> case dispatch. >> >> -- Robert >> >> On Sunday, August 23, 2015 at 2:28:54 AM UTC-5, Martin Senne wrote: >> typo: "ctor" has the "a" missing. should be "actor" of course. >> >> Am 23.08.2015 09:26 schrieb "Martin Senne" <martin...@ <>googlemail.com >> <http://googlemail.com/>>: >> Hi kraythe, >> >> first, you can use method delegation to untangle the "large" receive method. >> >> Second, you can wrap all these methods including the relevant part of the >> receive method into a trait and mix that into your concrete ctor >> implementation. >> >> Cheers, Martin >> >> Am 23.08.2015 09:14 schrieb "Patrik Nordwall" <patrik....@ <>gmail.com >> <http://gmail.com/>>: >> How would it look like when the actor has state? How is the state updated? >> How do you handle the message differently depending on the state? >> >> Regards, >> Patrik >> sön 23 aug 2015 kl. 04:56 skrev kraythe <kra...@ <>gmail.com >> <http://gmail.com/>>: >> Actually I am not talking about that. It's a simple concept of putting the >> implementation of the message processor in the message itself. It's just a >> different way to organize the code. >> >> -- >> >>>>>>>>>> Read the docs: http://akka.io/docs/ <http://akka.io/docs/> >> >>>>>>>>>> Check the FAQ: >> >>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html >> >>>>>>>>>> <http://doc.akka.io/docs/akka/current/additional/faq.html> >> >>>>>>>>>> Search the archives: >> >>>>>>>>>> https://groups.google.com/group/akka-user >> >>>>>>>>>> <https://groups.google.com/group/akka-user> >> --- >> You received this message because you are subscribed to the Google Groups >> "Akka User List" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to akka-user+...@ <>googlegroups.com <http://googlegroups.com/>. >> To post to this group, send email to akka...@ <>googlegroups.com >> <http://googlegroups.com/>. >> Visit this group at http://groups.google.com/group/akka-user >> <http://groups.google.com/group/akka-user>. >> For more options, visit https://groups.google.com/d/optout >> <https://groups.google.com/d/optout>. >> -- >> /Patrik >> >> -- >> >>>>>>>>>> Read the docs: http://akka.io/docs/ <http://akka.io/docs/> >> >>>>>>>>>> Check the FAQ: >> >>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html >> >>>>>>>>>> <http://doc.akka.io/docs/akka/current/additional/faq.html> >> >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user >> >>>>>>>>>> <https://groups.google.com/group/akka-user> >> --- >> You received this message because you are subscribed to the Google Groups >> "Akka User List" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to akka-user+...@ <>googlegroups.com <http://googlegroups.com/>. >> To post to this group, send email to akka...@ <>googlegroups.com >> <http://googlegroups.com/>. >> Visit this group at http://groups.google.com/group/akka-user >> <http://groups.google.com/group/akka-user>. >> For more options, visit https://groups.google.com/d/optout >> <https://groups.google.com/d/optout>. >> >> -- >> >>>>>>>>>> Read the docs: http://akka.io/docs/ <http://akka.io/docs/> >> >>>>>>>>>> Check the FAQ: >> >>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html >> >>>>>>>>>> <http://doc.akka.io/docs/akka/current/additional/faq.html> >> >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user >> >>>>>>>>>> <https://groups.google.com/group/akka-user> >> --- >> You received this message because you are subscribed to the Google Groups >> "Akka User List" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to akka-user+...@ <>googlegroups.com <http://googlegroups.com/>. >> To post to this group, send email to akka...@ <>googlegroups.com >> <http://googlegroups.com/>. >> Visit this group at http://groups.google.com/group/akka-user >> <http://groups.google.com/group/akka-user>. >> For more options, visit https://groups.google.com/d/optout >> <https://groups.google.com/d/optout>. > > > > Dr. Roland Kuhn > Akka Tech Lead > Typesafe <http://typesafe.com/> – Reactive apps on the JVM. > twitter: @rolandkuhn > <http://twitter.com/#!/rolandkuhn> > > > -- > >>>>>>>>>> Read the docs: http://akka.io/docs/ <http://akka.io/docs/> > >>>>>>>>>> Check the FAQ: > >>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html > >>>>>>>>>> <http://doc.akka.io/docs/akka/current/additional/faq.html> > >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user > >>>>>>>>>> <https://groups.google.com/group/akka-user> > --- > You received this message because you are subscribed to the Google Groups > "Akka User List" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected] > <mailto:[email protected]>. > To post to this group, send email to [email protected] > <mailto:[email protected]>. > Visit this group at http://groups.google.com/group/akka-user > <http://groups.google.com/group/akka-user>. > For more options, visit https://groups.google.com/d/optout > <https://groups.google.com/d/optout>. Dr. Roland Kuhn Akka Tech Lead Typesafe <http://typesafe.com/> – Reactive apps on the JVM. twitter: @rolandkuhn <http://twitter.com/#!/rolandkuhn> -- >>>>>>>>>> Read the docs: http://akka.io/docs/ >>>>>>>>>> Check the FAQ: >>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user --- You received this message because you are subscribed to the Google Groups "Akka User List" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/akka-user. For more options, visit https://groups.google.com/d/optout.
