[Facets] Looking for Feedback: Using Core Mixins

3 views
Skip to first unread message

Trans

unread,
Apr 1, 2010, 9:35:59 AM4/1/10
to facets-u...@rubyforge.org
Hi--

I would like to get some feedback on an idea for the next major
release of Facets. I am thinking about using mixins modules for core
extensions, much in the same way that ActiveSupport does. There are a
few reasons:

1) While functionally it will make no difference, it is considered the
way to "play nice" with other extensions. I am not sure why this idea
has emerged for core extensions --perhaps just to avoid warnings about
redefined methods. I think it makes more sense for other types of
libs, but none these less ...

2) Since ActiveSupport uses mixin modules, the only way to allow
ActiveSupport to take precedence when extensions conflict (or any
other library that does the same for that matter) is to create if
method_defined? or if defined?(ActiveSupport) exceptions in Facets.
This smacks of hacks. Going around and putting such conditions on
every method is also rather egregious.

3) Documentation would improve. As it stands documentation is very
messy when Facets is documented as a whole, which is why I include
docs that separate Core from More libraries. It still won't be
prefect, but it would at least be reasonably readable thanks to these
mixin modules.

Does anyone see any other issues/benefits? Also, if I do this would
it be prudent to move the Kernel extensions to Object?

To use this new design with Rails, would simply mean requiring Facets
extensions in config/preinitializer.rb in order to ensure
ActiveSupport's methods to take precedence over Facets.
_______________________________________________
facets-universal mailing list
facets-u...@rubyforge.org
http://rubyforge.org/mailman/listinfo/facets-universal

Calamitas

unread,
Apr 1, 2010, 2:22:55 PM4/1/10
to Facets
Hi Tom,

According to Gregory Brown's book (Ruby Best Practices) an important
reason to use modules like this is that you can easily find out where
a method comes from. The method objects have in their inspect string
the class or module that actually defines the method, so you can
figure out that way what library defined the method. Also, if you have
multiple libraries providing the same method, you can easily find out
which ends up being used.

irb(main):001:0> String.instance_method(:puts)
=> #<UnboundMethod: String(Kernel)#puts>

Peter

Trans

unread,
Apr 2, 2010, 4:03:08 PM4/2/10
to facets-u...@rubyforge.org

On Apr 1, 2:22 pm, Calamitas <calamita...@gmail.com> wrote:
> According to Gregory Brown's book (Ruby Best Practices) an important
> reason to use modules like this is that you can easily find out where
> a method comes from. The method objects have in their inspect string
> the class or module that actually defines the method, so you can
> figure out that way what library defined the method. Also, if you have
> multiple libraries providing the same method, you can easily find out
> which ends up being used.
>
> irb(main):001:0> String.instance_method(:puts)
> => #<UnboundMethod: String(Kernel)#puts>

Another good reason. And as far as I can tell the only downside is the
taking the time to do it.

I'm going to move forward with this for 3.0 release.

Thanks.

Trans

unread,
Apr 11, 2010, 7:23:56 AM4/11/10
to facets-u...@rubyforge.org

On Apr 1, 2:22 pm, Calamitas <calamita...@gmail.com> wrote:

> According to Gregory Brown's book (Ruby Best Practices) an important
> reason to use modules like this is that you can easily find out where
> a method comes from. The method objects have in their inspect string
> the class or module that actually defines the method, so you can
> figure out that way what library defined the method. Also, if you have
> multiple libraries providing the same method, you can easily find out
> which ends up being used.
>
> irb(main):001:0> String.instance_method(:puts)
> => #<UnboundMethod: String(Kernel)#puts>

Unfortunately I just ran into an ugly snag --our old friend, the
Double Inclusion Problem.

module Facets
module Enumerble
def foo; 'foo'; end
end
end

module ::Enumerable
include Facets::Enumerable
end

[1,2,3].foo => NoMethodError

The only work around that I know is to use ObjectSpace to loop through
all classes/modules that include Enumerable and re-include it. But
that's an intensive operation. And all Facets' methods are cherry
pickable, so this would have to be done over and over for every single
method, which I am pretty sure is not practical.

Did this whole "good idea" just get thrown out a window?

Trans

unread,
Apr 11, 2010, 8:20:58 AM4/11/10
to facets-u...@rubyforge.org
On Apr 11, 7:23 am, Trans <transf...@gmail.com> wrote:
> Unfortunately I just ran into an ugly snag --our old friend, the
> Double Inclusion Problem.
>
>   module Facets
>     module Enumerble
>       def foo; 'foo'; end
>     end
>   end
>
>   module ::Enumerable
>     include Facets::Enumerable
>   end
>
>   [1,2,3].foo  => NoMethodError
>
> The only work around that I know is to use ObjectSpace to loop through
> all classes/modules that include Enumerable and re-include it. But
> that's an intensive operation. And all Facets' methods are cherry
> pickable, so this would have to be done over and over for every single
> method, which I am pretty sure is not practical.
>
> Did this whole "good idea" just get thrown out a window?

Ha ha. To top is all off, I just looked at ActiveSupport, just to see
how they might be handling the issue, only to discover that as of 3.0
they totally ditched using mixin modules and are now injecting the
methods directly. How ironic. The no. 1 reason I was finally going to
make the switch to using modules was to make it possible to use Facets
and ActiveSupport together without conflict. I have long been of the
opinion that, outside some documenting niceties, just inserting them
directly is whole lot less problematic, and that ActiveSupport would
be better to do that same. Now they have! So then forget the mixin
thing. Another problem solved :-)

Calamitas

unread,
Apr 11, 2010, 9:01:30 PM4/11/10
to Facets
On Sun, Apr 11, 2010 at 2:20 PM, Trans <tran...@gmail.com> wrote:
> Ha ha. To top is all off, I just looked at ActiveSupport, just to see
> how they might be handling the issue, only to discover that as of 3.0
> they totally ditched using mixin modules and are now injecting the
> methods directly. How ironic. The no. 1 reason I was finally going to
> make the switch to using modules was to make it possible to use Facets
> and ActiveSupport together without conflict. I have long been of the
> opinion that, outside some documenting niceties, just inserting them
> directly is whole lot less problematic, and that ActiveSupport would
> be better to do that same. Now they have! So then forget the mixin
> thing. Another problem solved :-)

Curious that they did that. Of course, having a somewhat exemplary
function, if they are allowed to do it this way, anyone is. Maybe they
did it because they hit the same snag you did.

Peter

Trans

unread,
Apr 25, 2010, 9:52:03 AM4/25/10
to facets-u...@rubyforge.org
On Apr 11, 9:01 pm, Calamitas <calamita...@gmail.com> wrote:

> Curious that they did that. Of course, having a somewhat exemplary
> function, if they are allowed to do it this way, anyone is. Maybe they
> did it because they hit the same snag you did.

Probably. I read in a blog post that they wanted to make it more
cherry-pickable, so in doing that they would face the same problems.

Ultimately I think using mixin modules is probably the better
approach, but, ironically perhaps, Ruby's mixin system is inadequate.
Two issue's make it so: 1) the double inclusion problem and 2) module
meta-methods don't mix. The first is a difficulty in implementation.
The later however is an idealogical issue b/c Matz thinks it amounts
to supporting multiple-inheritance (which is silly IMO b/c people do
it anyway with ClassMethods trick).
_______________________________________________
facets-universal mailing list
facets-u...@rubyforge.org
http://rubyforge.org/mailman/listinfo/facets-universal

--
You received this message because you are subscribed to the Google Groups "Ruby Facets" group.
To post to this group, send email to facets-u...@googlegroups.com.
To unsubscribe from this group, send email to facets-univers...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/facets-universal?hl=en.

Reply all
Reply to author
Forward
0 new messages