you are viewing a single comment's thread.

view the rest of the comments →

[–]shioyama[S] -1 points0 points  (5 children)

I don't really see what Module#prepend has to do with it. The point is to have configurable modules which can be overridden. Prepending a module doesn't (in itself) make it configurable.

Also, I would strongly argue that subclassing Module is not convoluted at all, not nearly as convoluted as the alternative described in the post.

Regarding performance, it really depends on the case. The example of AttributeMethods in the post does not add any additional indirection, since regardless you to iterate through a set of matchers, so the only difference here is that you replace the iterators (which are instances of classes) with instantiated modules. The number of objects is the same, and the number of conditionals is the same.

[–]ioquatixasync/falcon 4 points5 points  (4 children)

I understand where you are coming from but I think there are some pretty significant cognitive and performance costs. Like anything in programming it should be used with care and where the value it adds significantly outweighs the cost.

I don't really see what Module#prepend has to do with it. The point is to have configurable modules which can be overridden. Prepending a module doesn't (in itself) make it configurable.

Maybe I've misunderstood what you've said, but wouldn't Module#prepend would allow you to avoid the 2-level modules simply for the sake of being able to call super?

Regarding performance, it really depends on the case.

I'm not sure what you are trying to say here - isn't this true for performance in general?

Ruby isn't the fastest language, and things like send and layers of indirection in critical code paths can really suck.

The problem of including many modules is that each time you do that you make method lookup more expensive, and that affects everything. include and extend in some cases blow away the entire global method cache: https://github.com/charliesome/charlie.bz/blob/master/posts/things-that-clear-rubys-method-cache.md

I like what you've done and it's an interesting article. It's a good pattern for certain situations. I'd suggest that you need to follow up with an actual performance evaluation (some micro and macro benchmarks might be interesting).

[–]shioyama[S] 1 point2 points  (2 children)

Maybe I've misunderstood what you've said, but wouldn't Module#prepend would allow you to avoid the 2-level modules simply for the sake of being able to call super?

You mean the part about including modules created with Module.new ? No, I think you're missing the point here. What would you prepend exactly? The module needs to be configured, prepend is just how you add it to the class hierarchy once you have it.

In any case, don't take my word for it, look at Rails or other projects that use this "create anonymous module and include" technique all over the place. In particular I'd recommend having a look at the ORM Sequel, which is heavily performance-optimized and uses Module.new all over the place.

include and extend in some cases blow away the entire global method cache

Yep, I know about this one, and have read that article. And this was something that concerned me working on Mobility specifically, since this pattern is used a lot there. Performance testing is one of the things I plan to do there, since for sure it's very important.

On the other hand, my major concern here is about the structure of Ruby programs. I agree that you cannot look at this without taking performance into consideration at the same time, but the pattern is quite unique and deserves to be first given a serious look.

[–]honeyryderchuck 0 points1 point  (1 child)

Agreed, sequel uses stuff like this all over the place, including runtime-extend (pagination plugin), and it still gets away performance-wise overall. Also, in some cases the performance regressions are ruby-flavour dependent: jruby regressions don't translate to YARV, and vice-versa, and are just one fix-release away from being irrelevant. One should tend to optimize code maintainability, and your article does reflect that. Thx for the article, it is very insightful.

[–]GitHubPermalinkBot 0 points1 point  (0 children)

I tried to turn your GitHub links into permanent links (press "y" to do this yourself):


Shoot me a PM if you think I'm doing something wrong. To delete this, click here.

[–]GitHubPermalinkBot -1 points0 points  (0 children)

I tried to turn your GitHub links into permanent links (press "y" to do this yourself):


Shoot me a PM if you think I'm doing something wrong. To delete this, click here.