From: Austin Ziegler Date: 2005-08-25T07:16:17+09:00 Subject: Re: Extending Code Cleanly On 8/24/05, David Brady wrote: > Austin Ziegler wrote: >> Aye, so I'll start. If you're going to extend core or standard >> library classes, you should: >> 1. Do so only at the user's request. > I disagree. requiring a library should extend stuff in the standard > library if that is proper behavior for the library. E.g. require 'foo' > might well inject a parsing ctor into String as String#to_foo, if it > made sense to do so. I don't see any difference between a library and > a framework extending Fixnum with #day as per Rails. I agree strongly > with documenting it in a very loud tone of voice, however. I'm arguing that it's generally inappropriate for a random library to add #day to Fixnum or to require a library which does so. See, I *do* see a big difference between a library and an application framework. It is inappropriate for a random library (say, Diff::LCS) to add a new method to String and Array (#diff, as well as others). However, if one is programming a Rails or Nitro application, then one is dealing with Rails or Nitro and are, effectively, extending a *static* environment that you control. Adding #day to Fixnum when you're a library, on the other hand, is modifying an environment that you *don't* control (and shouldn't). Sometimes, as in #to_foo, it may be appropriate, but that should *probably* be done with: require 'foo' require 'foo/string' Alternatively, just use "require 'foo/string'" and 'foo/string' requires 'foo'. This is, IIRC, what Diff::LCS does. Like I said, I'm not as hard and fast on this, but as a general rule, one should avoid modifying those unless the user of the *library* requests it. > 1.1 Do not change existing behavior of external classes or modules. I would generally agree with this. > 1.1.1 If you reopen an external class and redefine an existing method, > should Ruby issue a warning? Is there a safe_level that will prevent a > library from touching external classes? Ruby does issue a warning, when run with -w. And AFAIK, there is no such $SAFE level that won't also restrict certain behaviours severely. > 1.1.2 Before adding a new method to a class or method, consider > testing with respond_to? to see if it really is a new method, and > raising a warning if it isn't. Maybe. > 4. In a library, never change existing behavior of code outside the > library. If I have a set of unit tests for a class, and I require your > library, all of the unit tests for my class must still pass. Agreed. > It would be really useful if there were an idiomatic way of testing > the Core, StdLib and any modules the library required. Then a sanity > test could be run against the library verifying that all is as it > should be. Ultimately, this should be the Rubicon. -austin -- Austin Ziegler * halostatue@gmail.com * Alternate: austin@halostatue.ca