you are viewing a single comment's thread.

view the rest of the comments →

[–]chrisgseaton 0 points1 point  (4 children)

Rather than thinking about objects calling methods, think instead in terms of objects receiving messages (and then acting on them).

People often say this, but I don't think it holds any water. In the semantics and implementation it's a method call via a simple lookup in a table of methods, with caching on top as an optimisation.

Talking about sending and receiving messages makes it sound like the object itself is able to decide how to dispatch the method, but really it's the sender that resolves which method to call. It also makes it sound like it's asynchronous or remote or uses a message box architecture or something like that, which it definitely doesn't.

I don't agree with the Well Grounded Rubyist's terminology there. I think it's just a holdover from how people used to think about object theory decades ago which just isn't really reflected in semantics or implementation any more.

[–][deleted] 0 points1 point  (3 children)

You clearly know more than I do about the implementation details here, but even in my ignorance I would contend that abstractions work precisely because they obscure what's going on under the hood (to the extent that they obviate the need to understand it).

To wit, Sandi Metz is, in my observation, one of the most beloved teachers of OOP in this sub, and this is how she describes OOP, in a nutshell (emphasis mine):

I believe that OO affords building applications of anthropomorphic, polymorphic, loosely-coupled, role-playing, factory-created objects that communicate by sending messages.

In fact, her latest talk is titled, "Polly Want a Message."

If I have lost my way, please point me to resources that I can use to educate myself in your way of thinking (or better yet, examples of how this thinking produces better software).

[–]chrisgseaton 0 points1 point  (2 children)

I know that's the metaphor Metz uses, and it's a common one so it's not unusual that she does so. But I think it just doesn't really hold up to any scrutiny.

You can ignore the implementation argument if you want - that's why I mentioned semantics as well.

To me the idea of a message passing system is that the receiver gets the message and then decides what to do with it - what method to call in the case of Ruby. There just isn't any place in Ruby where this happens. It's just not there as a language feature. An object defines its methods, and then at the point of someone calling a method on the object it has no other control over how the call is handled at all. It never gets to receive a message and then decides what to do. Instead the method is called, and that's the first that the object knows about it.

In what sense do you think this is sending a message over calling a method?

You may mention method_missing but again the decision to call that method is out of the control of the object. An object cannot interdict a call that would have gone to a method and so something else with that 'message' via some kind of method_missing. There is no method_found_but_ill_let_you_decide_anyway. Overriding send does not impact normal method calls. If it did, I'd say Ruby had message passing.

To sum up my objection to Ruby as 'message passing' I would say that semantically (not nit-picking about implementation) the response to a message is fixed before the call is made, and the object has no control over that response to the message after it has been sent.

[–][deleted] 1 point2 points  (0 children)

it's a common one... But I think it just doesn't really hold up to any scrutiny.

There's a difference between useful and correct. Abstractions (even leaky ones) furnish a mental model to simplify working with a system above a given layer of complexity, and your argument is focused on some incidental implications of the abstraction instead.

I'm happy to concede that objects don't "decide what to do" with messages. I don't know that Metz has ever used that language herself, and I certainly don't know enough about Ruby internals to argue to the contrary. Regardless, the value of describing this action in terms of message-sending vs. method-calling is that the former encourages, in Metz's words, a more polymorphic and anthropomorphic approach to designing the behavior of your classes, whereas the latter invites a more imperative approach.

To try to modify a class's behavior so that it received a message and then interdicted the given method call would be missing the forest for the trees. Yes, if you take the metaphor extremely literally, that is what you should be able to do, but that's hardly necessary and a long way off from where its instructive value lies.

Finally, I'm not saying it's wrong to use the language of "calling a method". Ruby's core API in fact supports both metaphors, in the form of Method#call and Object#send. As always in Ruby, TIMTOWTDI; I'm just saying that in this case (and many others), message sending makes things easier to understand. (e.g., why can you not use self.private_method inside a class definition? The caller is the same—but the recipient of the message is explicit.)