FP fanboys will laugh so hard at this. The proper way to deal with duplication, as described in this article, is of course to use functors. With a general method_missing(), your compiler will not even catch spelling errors anymore.
> With a general method_missing(), your compiler will not even catch spelling errors anymore.
Ruby isn't compiled. Whether or not it catches typos is up to your logic. All of my method_missing calls eventually hand off to the parent class's implementation when they can't match anything.
> The proper way to deal with duplication, as described in this article, is of course to use functors.
Except this is ruby. Ruby has modules to deal with duplication between classes and code blocks (closures, which can be bound to variables) for general use. It also allows for a rather clean implementation of the proxy design pattern via method_missing. Anything dealing with classes assumes OOP, not FP.
I only have begun to figure out that I don't know anything about FP but your comment seems rather absurd in this context.
There's actually a fairly safe way to use method_missing. Just remember to call super if none of your conditions are met, that way you'll still get errors when commands are misspelled. You really shouldn't ever use method_missing without that.
He probably also should be checking if @desk actually has a method with the provided name (with @desk.respond_to?(method_name)) before attempting to call it.
When using method_missing in a proxy why bother checking? Just call the method and let wrapped object handle the errors. The stack trace will show you where to look for the error. The only reason I can see to check before calling is if you have different failure mode than the wrapped object. Otherwise you are duplicating logic.
It's a small thing, I admit, but I like getting a slightly cleaner stack trace since the exception happens in the wrapper module (where the error is) instead of getting all the way to @desk.
After I've spent the last 2~3 years reading funky rails stacktraces something like that doesn't bother me a bit. (I get more worried about older versions of jruby deciding to puke on internal ruby<->java mismatches at work) :)
He should also define respond_to? on the DoNotDisturb class. Relying on method_missing to pass calls to respond_to? to the proxied class will not work, as it is defined in Object. Responding to a method when respond_to? returns false breaks the class contract.
From the OP: I agree with you guys (or gals) on both calling super and redefining respond_to?(). Those are two of the "caveats" I mentioned at the end of the original post. I considered mentioning them explicitly, but the post is long enough already.
I prefer to use define_method over method_missing when "metaprogramming". It allows you to explicitly define your "metamethods" up-front.
Using his example of the DoNotDisturb wrapper around InformationDesk, you could easily do something like:
[:emergency, :flights, :local_transports, :hotels].each do |name|
define_method(name) do
check_lunch_break unless name == :emergency
@desk.send(name)
end
end
Now you don't get the side effect of screwing up your exception handling and having to walk on eggshells with the rest of your coding in that class.
The other thing I like about this method is that it gets evaluated once, and then those methods exist. With method_missing, every single time you call one of those methods, it has to go all the way up the chain to find that method until it finally hits method_missing.
EDIT: Oh, and if nothing else, you can at least put the define_method inside the method_missing (I had a project that required method_missing once, so this is what I did). That way, it only has to crawl all the way up the inheritance chain once, then that method gets defined on your class, so subsequent calls to that method don't have to go all the way up the chain again.
Might not be much performance gain in Ruby, but when programming a rails app (where you're likely working on a class that inherits from ActiveRecord and 10 other classes), it helps.
Your approach of defining, even within method_missing is better. Defined methods instead of method_missing is also how Rails 3 got some of it's major speed boosts.
Oh, and another option would be to pull the common methods out into a module that you can include in each class with one line. I like this option, because then it’s trivial to go create another class called OutForVacation, in which you could include this module, and now you have another wrapper with all the same functionality.
That makes a ton of sense. It would also aid significantly in debugging, as you can see every method you created, rather than only being able to infer what they might be.
While I know this is a rubyist thread, I want to chime in as a Javascript developer. You can almost do the same thing there - joy! Probably not the best way to do it, but it's 3AM and I'm writing off the top of my head. And it's a little bit messy. And it gets rid of that pesky emergency case.
Within the object constructor:
// assuming the desk object was inherited and accessible. There are several ways to do this.
var thisContext = this; // unless you want to do some weird stuff with calling a function that returns a function that calls a function
["flights", "local_transports", "hotels"].forEach(function(fn) {
thisContext[fn] = function() {
check_lunch_break && desk[fn](arguments);
};
});
Granted, this doesn't get your methods on the prototype, and will incur a cost every time you create one of these objects. If you properly inherited from the desk class, it will overwrite them. And the emergency function will work just fine, if defined on desk.
Nitpickery indeed, but that won't work as expected. `fn` can be reused within the loop, depending on the runtime, so all methods will end up calling the same `desk[fn]`.
From the OP: I used dynamic proxies in both Java and C#. For example, I wrote the annotations introspector for Hibernate Annotations, and a memcached wrapper for a C# project. Both are proxy-based.
However, using dynamic proxies in Java feels like going against the grain of the language: strong typing and dynamic calls don't really like each other. As a result, you usually resort to Java/C# dynamic proxies only when you have no other option. I've yet to see anyone using a dynamic proxy just to remove duplication in a Java class.
C# dynamics might make dynamic proxies less clumsy in that language. Will try. Do you have experience with them already?
I haven't seen them used much in any of the open source Java projects I'm familiar with, I agree. We used them fairly extensively at my previous job, though, for implementing a mix-in pattern for boilerplate-free service endpoints, and they worked nicely. Outside of that, I use them al the time during development to add quick-and-dirty method call tracing when I'm trying to debug something.
I personally think that they're very much underused, and having based an interview question on them for a while, not well-known at all.
"I use method_missing()to remove duplication ... On the other hand, I usually think twice about using method_missing() for cosmetic reasons, like getting cool method names such as find_by_name_and_address()."
That seems backwards to me. I use magic methods to define methods that can only be defined at run time, like his example of creating methods based on schema introspection.
Using magic methods breaks a lot of tools: IDE code completion, reflection, documentation generation so I always explicitly define methods unless it's not possible.
For me method_missing looks more like an anti-pattern because it's easy to miss, it's hard to debug, it's impossible to scan visually, it messes up code lookup if you use IDE, it messes up search if you don't.
A better analogy to magic methods would be dynamite. There are a few situations where you should use it, but not many, and generally it's when there's no other option.
His example violates the principle that objects should represent things. (What is a DoNotDisturb?) Back to OOP school, metaprogrammer!
From the OP: I considered changing the names because I had the same concern, but in the end I figured that the current name was good enough for a toy example. In hindsight, you're probably right I should have used other names (although your sneering tone is not really necessary).
method_missing / AUTOLOAD is a great way to break any tools that rely on being able to introspect your classes.
For something as simple as this, just add the methods to the class in a loop. Then you class works just like every other class; no introspection is broken. It's also faster at runtime.
The most sited example is ActiveRecord where finders can be auto-generated. For example `find_by_name_and_address` will be defined on the fly the first time it is used in code. Another common usage is a wrapper class that provides a unified interface to a set of underlying objects. If many of these objects have almost the same interface `def method_missing(method,args); @object.send(method, args);end` can save a lot of redundant definitions.
First off, I feel using mechanisms like method_missing should be used carefully. The Perl community abused things like AUTOLOAD & monkey-patching some years ago and learnt hard lessons and have now established good practises for their use. I feel Ruby/Rails world is going through the same growing pains but it does look like they are now maturing (eg. Rails 3).
Now IMHO I see a builder as a good case for a method_missing mechanism (I think there were a few others mentioned in thread/post). No magic, just a simple one-to-one relationship between code and what it does (result):
b.name "Jim" => <name>Jim</name>
However I feel something like find_by_name_and_address in ActiveRecord is cute (both in nice and ugly sense!). There is so much more going on underneath an ORM that I'd be wary of the extra layers of complexity upon what is already an (acceptable) impedance mismatch.
Bottom line, an ORM is important to me and I don't want any loose cogs lying around! I'd prefer to be explicit here:
# using DBIx::Class
my $p = $schema->resultset('Addresses')->find({ name => '...', address => '...' });
So while find_by_name_and_address is a pretty nice aesthetic its feels more plastic cosmetics compared the elegant cosmetics that Builder solutions provide.
Disclaimer: I haven't touched Rails for about 4 years now. I don't actually know for certain that something like find_by_name_and_address did or still uses method_missing. It could actually build methods like these straight from schema introspection. I would guess method_missing was used to avoid a performance hit on building all these at startup? If so then this could be a good argument for using method_missing here!
As of now, it uses method_missing to catch the first call to find_by_name_and_address, then defines the method inline, so future calls are handled by an actual method.
Right, which is what I'm trying to understand: what does this allow you to do that is not just a cute way to call a method?
I think the ActiveRecord example below is the answer I'm looking for, since it creates a method at runtime based on information that did not exist until runtime. But I need to read up on it to understand it.
I also find aesthetics important, but I don't find this more aesthetically pleasing; it pings the "something's wrong" feeling. Being succinct is a goal, but it's not the only goal.
Yes its subjective. There will always be a difference in view between what is cute and what is not cute (and also what I think is cute today may also not hold true tomorrow!).
I've found that the only good time to use method_missing is when I'm wrapping an object and need to send all but a couple methods through to it untouched. I've really never used it for anything else.
50 comments
[ 3.7 ms ] story [ 70.0 ms ] threadRuby isn't compiled. Whether or not it catches typos is up to your logic. All of my method_missing calls eventually hand off to the parent class's implementation when they can't match anything.
> The proper way to deal with duplication, as described in this article, is of course to use functors.
Except this is ruby. Ruby has modules to deal with duplication between classes and code blocks (closures, which can be bound to variables) for general use. It also allows for a rather clean implementation of the proxy design pattern via method_missing. Anything dealing with classes assumes OOP, not FP.
I only have begun to figure out that I don't know anything about FP but your comment seems rather absurd in this context.
He probably also should be checking if @desk actually has a method with the provided name (with @desk.respond_to?(method_name)) before attempting to call it.
Using his example of the DoNotDisturb wrapper around InformationDesk, you could easily do something like:
Now you don't get the side effect of screwing up your exception handling and having to walk on eggshells with the rest of your coding in that class.The other thing I like about this method is that it gets evaluated once, and then those methods exist. With method_missing, every single time you call one of those methods, it has to go all the way up the chain to find that method until it finally hits method_missing.
EDIT: Oh, and if nothing else, you can at least put the define_method inside the method_missing (I had a project that required method_missing once, so this is what I did). That way, it only has to crawl all the way up the inheritance chain once, then that method gets defined on your class, so subsequent calls to that method don't have to go all the way up the chain again.
Might not be much performance gain in Ruby, but when programming a rails app (where you're likely working on a class that inherits from ActiveRecord and 10 other classes), it helps.
Within the object constructor:
Granted, this doesn't get your methods on the prototype, and will incur a cost every time you create one of these objects. If you properly inherited from the desk class, it will overwrite them. And the emergency function will work just fine, if defined on desk.Each `fn` is bound exactly once, `forEach` is not a loop.
Java has had dynamic proxies since 1.4. As long as you're working with interfaces, you can do the exact same thing as the example given in this post.
However, using dynamic proxies in Java feels like going against the grain of the language: strong typing and dynamic calls don't really like each other. As a result, you usually resort to Java/C# dynamic proxies only when you have no other option. I've yet to see anyone using a dynamic proxy just to remove duplication in a Java class.
C# dynamics might make dynamic proxies less clumsy in that language. Will try. Do you have experience with them already?
I personally think that they're very much underused, and having based an interview question on them for a while, not well-known at all.
That seems backwards to me. I use magic methods to define methods that can only be defined at run time, like his example of creating methods based on schema introspection.
Using magic methods breaks a lot of tools: IDE code completion, reflection, documentation generation so I always explicitly define methods unless it's not possible.
His example violates the principle that objects should represent things. (What is a DoNotDisturb?) Back to OOP school, metaprogrammer!
For something as simple as this, just add the methods to the class in a loop. Then you class works just like every other class; no introspection is broken. It's also faster at runtime.
ref: http://perldoc.perl.org/perlsub.html#Autoloading
Conversely though I find that using it in ActiveRecord is cute (ie. a bad thing!).
Now IMHO I see a builder as a good case for a method_missing mechanism (I think there were a few others mentioned in thread/post). No magic, just a simple one-to-one relationship between code and what it does (result):
However I feel something like find_by_name_and_address in ActiveRecord is cute (both in nice and ugly sense!). There is so much more going on underneath an ORM that I'd be wary of the extra layers of complexity upon what is already an (acceptable) impedance mismatch.Bottom line, an ORM is important to me and I don't want any loose cogs lying around! I'd prefer to be explicit here:
So while find_by_name_and_address is a pretty nice aesthetic its feels more plastic cosmetics compared the elegant cosmetics that Builder solutions provide.Disclaimer: I haven't touched Rails for about 4 years now. I don't actually know for certain that something like find_by_name_and_address did or still uses method_missing. It could actually build methods like these straight from schema introspection. I would guess method_missing was used to avoid a performance hit on building all these at startup? If so then this could be a good argument for using method_missing here!
Instead of:
You could write it like this:I think the ActiveRecord example below is the answer I'm looking for, since it creates a method at runtime based on information that did not exist until runtime. But I need to read up on it to understand it.
So I don't view it has cute but more it being succinct.