From: Avdi Grimm Date: 2006-03-14T04:01:12+09:00 Subject: Re: abstract method in Ruby On 3/13/06, ara.t.howard@noaa.gov wrote: > i disagree strongly here. check out these two snippets that i am working on > as we speak: > > def will_process_holding *a, &b > raise NotImplementedError > end > def process_holding *a, &b > raise NotImplementedError > end > def will_process_incoming(*a, &b) > raise NotImplementedError > end > def process_incoming(*a, &b) > raise NotImplementedError > end > > vs > > abstract_method "will_process_holding" > abstract_method "process_holding" > abstract_method "will_process_incoming" > abstract_method "process_incoming" The question is, why use either of those methods? Why not just note in your documentation that those four functions must be defined? The user is going to have to read the documentation anyway, in order to understand what those four abstract methods are for. A "NoMethodError" conveys the same information as a "NotImplementedError", in this case. And this is arguably an abuse of NotImplementedError. The usual semantics of NotImplementedError are to indicate that the method is either a) not yet implemented by a library; or b) is not supported on the current platform. Whereas in the example above it is being used to indicate that a precondition was not met. I see that you're trying to make your code more declarative and more explicit about it's semantics. But seeing 'abstract_method :will_process_holding' doesn't tell me anything more than getting a "NoMethodError: will_process_holding". Both of them just tell me I'm going to have to go look at the documentation to learn what the heck #will_process_holding is supposed to do. If you really want to add useful semantic information, then put in more specific error information where the "abstract" method is *called*. E.g.: def frobnicate(duck) duck.quack() rescue NoMethodError raise("Ducks must quack in order to be frobnicated. See documentation.") end If you want to get fancy and declarative and proactive about it, you could make a #precondition method: def frobnicate(duck) precondition("Ducks must quack in order to be frobnicated"){ duck.respond_to? :quack} ... end I believe there are some libraries out there that assist in doing this kind of "strict duck typing". As a bonus, you are keeping your preconditions close to the code that actually depends on them, which reduces the chances that they will get out of sync with your code, and give the user false information. ~Avdi