By the way you could always make a message that takes a customer as an 
argument and pass 'this' to the message apply method if you don't want to 
look it up the way I did.

On Tuesday, August 25, 2015 at 1:59:53 PM UTC-5, kraythe wrote:
>
> No I dont mean they close over the state at all. I mean they are nested. I 
> fail to see how it is any more than an organizational strategy and why it 
> would be considered bad. Nor do I see how it is a single threaded executor. 
> Messages are still being sent. You are just taking advantage of the fact 
> that any nested class has access to the members of its enclosing class. 
>
> class Customer extends Actor {
>   val log = Logging(context.system, this)
>   private var id : Int = 0
>   private var name : String = null;
>
>   override def receive: Receive = {
>     case msg : CustomerMessage => msg match {
>       case f : Function0[_] =>
>         sender ! f.apply()
>     }
>     case msg =>
>       val data = ToStringBuilder.reflectionToString(msg)
>       log.error(s"received unknown message of type ${msg.getClass} with data 
> $data")
>       unhandled(msg)
>   }
>
>   sealed trait CustomerMessage
>
>   case class ChangeName(customerId: Int, newName : String) extends 
> CustomerMessage with Function0[Unit] {
>     override def apply(): Unit = {
>       Customer.findCustomerById(customerId).name = newName
>     }
>   }
> }
>
> object Customer {
>   def findCustomerById(id: Int) : Customer = {
>     // in reality we would look in cache for this.
>     new Customer()
>   }
> }
>
>
> How would you qualify that as a single threaded executor. Everything is 
> quite well encapsulated and protected and no mutable state has been closed 
> over. 
>
>
> On Tuesday, August 25, 2015 at 1:18:35 PM UTC-5, rkuhn wrote:
>
> Hi Robert,
>
> 25 aug 2015 kl. 19:51 skrev kraythe <kra...@gmail.com>:
>
> 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. 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>:
>
> 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>:
>
> 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>:
>
> 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>:
>
> 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/
> >>>>>>>>>>      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 akka-user+...@googlegroups.com.
> To post to this group, send email to akka...@googlegroups.com.
> Visit this group at http://groups.google.com/group/akka-user.
> For more options, visit https://groups.google.com/d/optout.
>
> -- 
> /Patrik
>
> -- 
> >>>>>>>>>> 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 akka-user+...@googlegroups.com.
> To post to this group, send email to akka...@googlegroups.com.
> Visit this group at http://groups.google.com/group/akka-user.
> For more options, visit https://groups.google.com/d/optout.
>
>
> -- 
> >>>>>>>>>> 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 akka-user+...@googlegroups.com.
> To post to this group, send email to akka...@googlegroups.com.
> Visit this group at http://groups.google.com/group/akka-user.
> For more options, visit 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 akka-user+...@googlegroups.com.
> To post to this group, send email to akka...@googlegroups.com.
> Visit this group at http://groups.google.com/group/akka-user.
> For more options, visit https://groups.google.com/d/optout.
>
>
> ...

-- 
>>>>>>>>>>      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 akka-user+unsubscr...@googlegroups.com.
To post to this group, send email to akka-user@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Reply via email to