Extending ruby classes - Against new methods?

Hi,

Recently I added
def strip!
to class Array. I found that I needed it, and some of my arrays were
collection of strings having whitespace. It was trivial, and I thought
this could be part of standard ruby. But I remember that there was some
issue, i.e. matz not wanting to have too many methods or similar. We
also have the facets library (but I found it to be too big, or,
depending on the viewpoint one has, should rather be part of the
language itself)

Anyway, my question is - is it true that new methods are rarely added to
ruby?

The String class is really rather big compared to the Array class, and i
figured that people will work with string objects most of the time
(compared to Array objects or Hash objects) - they are useful, but I
think all through rubyland (think all virtual ruby objects), there would
be more string objects than array objects etc…

Marc H. wrote:

Anyway, my question is - is it true that new methods are rarely
added to ruby?

I don’t know; but, after reading your post I sure hope it’s true. I
wouldn’t want your strip! added to Ruby.

I can think of at least four very different things to expect an
Array#strip! to do. Why add foggy methods to Ruby?

The String class is really rather big compared to the Array class

So?

It isn’t wastful to have classes with very few methods. If computers had
a “5$ for the first 20 methods; Any method above 20 is free” rule then
indeed it’d be wasteful to have little classes. But it isn’t the case.

On 23.04.2009 23:30, Marc H. wrote:

Recently I added
def strip!
to class Array. I found that I needed it, and some of my arrays were
collection of strings having whitespace.

Why didn’t you choose to add this to module Enumerable? Restricting
this to Arrays does not seem to make much sense.

It was trivial, and I thought
this could be part of standard ruby.

The reason to include something in standard Ruby is not the ease of
implementation but rather the usefulness for a wide audience and many
uses of the class. Since your case of stripping all strings in a
collection seems to be a rather esoteric case. Remember that there can
be any type of object in such a collection! When deciding on adding
something to a core class you should look at the outside.

Anyway, my question is - is it true that new methods are rarely added to
ruby?

Do you mean by the core team or ad hoc by application programmers?
Modification of core classes is done cautiously (seldom) while
application programmers seem to often augment core classes with
additional methods.

The String class is really rather big compared to the Array class, and i
figured that people will work with string objects most of the time

This totally depends on the application case. Side note: my impression
is that people tend to create too few classes (common example: methods
are added to Hash instead of creating a class whose instances contain a
Hash instance and use it appropriately).

(compared to Array objects or Hash objects) - they are useful, but I
think all through rubyland (think all virtual ruby objects), there would
be more string objects than array objects etc…

I am not sure I get your point. The sole fact that there are more
instances of class X vs. class Y does not tell me anything about what
methods should be added to X or Y.

Kind regards

robert

2009/4/24 Marc H. [email protected]:

This is no problem if everyone works alone, but when you do extend
core classes a lot and rely on solutions which you think are shorter and
more elegant, people are quick to shout “monkey patching” or refuse to
adopt another style. The more projects involved, the more different
styles involved, the higher the chances of conflict. For instance, I do
not like code parts involving @@, $ or lambdas.

The context is important: as long as you do it for a simply script or
a small project only, then criteria for change of core classes can be
far less restricted than for example if you write a library that you
intend to make public.

I can think of at least four very different things to expect an
Array#strip! to do. Why add foggy methods to Ruby?

Quite obviously .strip! on Array simply applies what .strip! does on
Strings.

This is by far not obvious because even Array instances with no
Strings in them (but other objects) will have it.

The semantics of strip! in a core class should not rely on features of
potential collection members. Your Array#strip! will fail as soon as
there is a single instance in the Array which does not respond to
strip!. That way you have introduced a bad dependency.

Why didn’t you choose to add this to module Enumerable? Restricting
this to Arrays does not seem to make much sense.

Quite frankly, I didn’t need it outside of Strings or Arrays so far.
Maybe it should be part of Enumerable, but I really have needed it
outside there yet. It seems easier to add it only where it is needed.

There is no difference in effort between

class Array
def strip!
each {|s| s.strip!}
end
end

module Enumerable
def strip!
each {|s| s.strip!}
end
end

Granted, “Enumerable” has a few more characters to type than “Array”…

As
written above the only problem is when I release projects and use my own
style here which extends ruby classes. How do other people solve this?
Not extend ruby core classes?

This would be the logical solution for me, but it quite makes the
flexibility of ruby less usable if everyone restricts oneself to what is
inside the language only, because they would have to make sure that
their code works with all their “personal extensions” as well (and add
that to projects).

You can still have personal extensions with the same functionality.
You just need to put it into a function.

def strip!(enum)
enum.each {|s| s.strip!}
end

Now you do not clutter the namespace of core classes.

The reason to include something in standard Ruby is not the ease of
implementation but rather the usefulness for a wide audience and many
uses of the class.

But how is this usefulness measured?

The fact that your strip method works only for collections that solely
contains String instances (or more precisely, instances which respond
to strip! is a killer criterion). The method simply lacks
universality.

Take the facets library for
example, how many people will use it? I mean in theory it sounds like a
great idea, but on the other hand if noone would use it it would make
the project quite … useless. http://facets.rubyforge.org/

Facets is a library you can consciously use - or not. If your
suggestion to place this method in the core lib would be followed
everybody would have to live with it.

This totally depends on the application case.

True. But for the perhaps 5000 .rb files I wrote so far, most objects
dealt
with strings, even if they are stored inside hashes or arrays.

This tells me that you either work in a very specific domain or that
you overuse String. :slight_smile:

I can’t really say how it is for other projects, but I dare claim now
that strings are the core everywhere. Bold statements catch attention :slight_smile:

Frankly, I do not understand what this has to do with your suggested
change of class Array (or module Enumerable).

The sole fact that there are more instances of class X vs. class Y
does not tell me anything about what methods should be added to X or Y.

I guess I tried to make a point that different classes in ruby are more
useful than others. Does this influence decisions to add or remove
methods at all?
I still think the String class is really the core of ruby as far as
everyday useage is concerned, and thus more important than let’s say
Array.

So you say, we can more easily introduce inconsistencies in Array
because it is less used? (If it is less used, I doubt it.)

I am actually interested in the complete useage patterns for all kind of
ruby objects, and whether people rather subclass and extend, or directly
extend core classes to solve a given problem at hand.

As I said, I guess if I never want to work on projects which other
people can use too, I have no problem at all, because my code is fine
already no matter what style I use (after all, I know my own code). But
if 1000 people have 1000 projects, it seems as if the netto result is a
huge spaghetti design, where others have partially called it monkey
patching or worse.

That’s the exact reason why you should be careful with changing core
classes if your code is targeted at a wider audience.

It seems to me that people are happier to not have a
dependency on something, if they can avoid it.

That’s a general rule because more dependencies create complexer code
and more potential for bugs.

Cheers

robert

Hmm, replying to two in one message now :wink:

I wouldn’t want your strip! added to Ruby.

See, exactly that is the dilemma and is one reason why facets is a
part of outside Ruby. The same could be reasoned for 1000 different use
cases as well, and the netto result will be that everyone has its own
share of coding style.

This is no problem if everyone works alone, but when you do extend
core classes a lot and rely on solutions which you think are shorter and
more elegant, people are quick to shout “monkey patching” or refuse to
adopt another style. The more projects involved, the more different
styles involved, the higher the chances of conflict. For instance, I do
not like code parts involving @@, $ or lambdas.

Let me put it another way. A ruby project I know of - which is somewhat
successful - is happy for patches contributed by other people. This will
lead to different styles, for instance one author used .kind_of? whereas
pretty much everyone else preferred .is_a?

I can think of at least four very different things to expect an
Array#strip! to do. Why add foggy methods to Ruby?

Quite obviously .strip! on Array simply applies what .strip! does on
Strings.

It isn’t wastful to have classes with very few methods.

The point is that I regard the String class as more central to ruby than
Array class as far as everyday usage is concerned. This is not about
being wasteful or not.

Why didn’t you choose to add this to module Enumerable? Restricting
this to Arrays does not seem to make much sense.

Quite frankly, I didn’t need it outside of Strings or Arrays so far.
Maybe it should be part of Enumerable, but I really have needed it
outside there yet. It seems easier to add it only where it is needed. As
written above the only problem is when I release projects and use my own
style here which extends ruby classes. How do other people solve this?
Not extend ruby core classes?

This would be the logical solution for me, but it quite makes the
flexibility of ruby less usable if everyone restricts oneself to what is
inside the language only, because they would have to make sure that
their code works with all their “personal extensions” as well (and add
that to projects).

The reason to include something in standard Ruby is not the ease of
implementation but rather the usefulness for a wide audience and many
uses of the class.

But how is this usefulness measured? Take the facets library for
example, how many people will use it? I mean in theory it sounds like a
great idea, but on the other hand if noone would use it it would make
the project quite … useless. http://facets.rubyforge.org/

Do you mean by the core team or ad hoc by application programmers?

Core team of course. The application programmers created facets, after
all … :wink:

Modification of core classes is done cautiously (seldom) while
application programmers seem to often augment core classes with
additional methods.

Does anyone know how Rails is doing this? Do they extend core classes
heavily?

This totally depends on the application case.

True. But for the perhaps 5000 .rb files I wrote so far, most objects
dealt
with strings, even if they are stored inside hashes or arrays.
I can’t really say how it is for other projects, but I dare claim now
that strings are the core everywhere. Bold statements catch attention :slight_smile:

my impression is that people tend to create too few classes
(common example: methods are added to Hash instead of
creating a class whose instances contain a Hash instance
and use it appropriately).

I would instantly believe you. I myself used to create huge classes
years ago until I realized that classes in itself are quite good at
simplifying problems by divide&conquer. If it becomes smaller, it
seems easier to manage.

The sole fact that there are more instances of class X vs. class Y
does not tell me anything about what methods should be added to X or Y.

I guess I tried to make a point that different classes in ruby are more
useful than others. Does this influence decisions to add or remove
methods at all?
I still think the String class is really the core of ruby as far as
everyday useage is concerned, and thus more important than let’s say
Array.
But on the other hand, how many people subclass String objects, and how
many people subclass Array or Hashes?

I am actually interested in the complete useage patterns for all kind of
ruby objects, and whether people rather subclass and extend, or directly
extend core classes to solve a given problem at hand.

As I said, I guess if I never want to work on projects which other
people can use too, I have no problem at all, because my code is fine
already no matter what style I use (after all, I know my own code). But
if 1000 people have 1000 projects, it seems as if the netto result is a
huge spaghetti design, where others have partially called it monkey
patching or worse.

Regards,
Marc

PS: To be honest, I can not think of any project that did
require ‘facets’
so far. It seems to me that people are happier to not have a
dependency on something, if they can avoid it. If anyone knows projects
that use or require facets, let me know people - the bigger the project,
the better for me to have a look. :slight_smile: