Is "extend self" an anti-pattern for utility modules? [closed] - ruby

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Steve Klabnik recently said in a pull request for a utility module:
[The code] obscures the fact that these are class methods, and we
want to use them that way. Plus, I think that extend self is generally
an anti-pattern, and shouldn't really be used except in some cases. I
thought about it, and I think this is one of those cases.
When creating a utility module (e.g., for math) what's the best way to declare the methods?
And when is the extend self idiom ever appropriate?

It's not exactly helpful that he doesn't say 1) why he thinks it is an anti-pattern (other than obscuring the fact that you are defining class methods) or 2) why, having thought about it, this is one of the cases he thinks it shouldn't be used, so it's hard to specifically counter any of his arguments.
However, I'm not convinced that extend self is an anti-pattern. A utility module seems like a good example of a use case for it. I've also used it as easy storage for test fixtures.
I think it's worth examining what extend self is, what possible problems there might be with it, and what alternatives there are.
At it's core, it is simply a way to avoid having to write self. before every method definition in a module that you never intend to mix into a class, and that will therefore never have an 'instance' of itself created, so can by definition only have 'class' methods (if you want to be able to call them, that is).
Does it disguise the fact that you intend the methods to be used as class methods? Well, yes, if you don't look at the top of the file to where it says extend self, that's possible. However, I would argue that if it's possible for you to make this confusion, your class is probably too complicated anyway.
It should be obvious from your class - from its name and from its contents - that it is intended as a collection of utility functions. Ideally it wouldn't be much more than a screen tall anyway, so extend self would almost never be out of sight. And as we'll see, the alternatives also suffer almost exactly the same problem.
One alternative would be to use class << self like this:
module Utility
class << self
def utility_function1
end
def utility_function2
end
end
end
I am not a fan of this, not least because it introduces an extra layer of indentation. It's also ugly (totally subjective, I know). It also suffers from exactly the same problem of 'obscuring' the fact that you're defining class methods.
You're also free, using this approach, to define instance methods outside the class << self block - which might lead to the temptation to do so (although I'd hope it wouldn't), so I'd argue that extend self is superior in this regard by removing the possibility of this muddying of the waters.
(The same is true, of course, of the 'long-hand' style of using def self.utility_function.)
Another approach could be to use a singleton object. I don't think this is a good idea at all, because a singleton object is an object for a reason - it's meant to hold state and do stuff, but also be the only one in existence. That simply doesn't make sense for a utility module, which should be a series of independent stateless functions. You don't want MathUtils.cos(90) to ever return a different value based on internal state of MathUtils, right? (I know that you can of course hold state in a module and do all these things, but it's more of a semantic division for me than a technical one).
It also leads to the same problem of arguably obscuring the fact that the methods are intended to be called as class methods (sort of). They are defined as instance methods, and you call them as instance methods, but by first getting the single instance of the class by calling the class method instance.
class MathSingleton
include Singleton
def cos x
end
end
MathSingleton.instance.cos x
This would be a terrible alternative to extend self for this purpose. But look, also, the only thing indicating that these methods are to be used as methods on the singleton instance is that one line just up at the top, just like extend self.
So what other possible downsides are there? I don't know of any, but I'd be interested to hear them if anyone else does.
I would argue that extend self leads to shorter code, that leaves out the extraneous self.s and allows you to concentrate on the names and therefore meanings of its methods.
It also has the nice property that, if you are writing another class that uses lots of your utility functions, for example, you can just mix it in and they will be available without having to use the module name each time. Much like static imports work in other languages.

Utility modules, as opposed to mixins, are containers that wrap constants and methods with some common concern. Mixins, such as this one,
module SingingCapability
def sing; puts "I'm singing!" end
end
Human = Class.new
Fred = Human.new.tap { |o| o.extend SingingCapability }
generally pose some requirements on their includers. That is, generally only certain objects are good candidates to include or extend a given mixin. Hypothetically, it is possible that a module is at the same time a utility module, and a mixin. And if the module itself belongs among eligible candidates to be extended by it, then go ahead and extend it.
In sum, I do think it's somewhat not a very good practice, but Ruby defies me on this one since we even have Module#module_function method to facilitate this malpractice:
module SingingBox
def sing; "Tralala!" end
module_function :sing
end
SingingBox.sing #=> "Tralala!"

Related

Is there a gem that provides support to detect changes to native ruby type instances?

Although I agree that extending native types and objects is a bad practice, inheriting from them should not be.
In a supposedly supporting gem (that I could not find), the way that the native types were to be used would be as follows:
require 'cool-unkown-light-gem'
class MyTypedArray < CoolArray # would love to directly < Array
def initialize(*args)
super(*args)
# some inits for DataArray
#caches_init = false
end
def name?(name)
init_caches unless !#caches_init
!!#cache_by_name[name]
end
def element(name)
init_caches unless !#caches_init
#cache_by_name[name]
end
private
# overrides the CoolArray method:
# CoolArray methods that modify self will call this method
def on_change
#caches_init = false
super
end
def init_caches
return #cache_by_name if #caches_init
#caches_init = true
#cache_by_name = self.map do |elem|
[elem.unique_name, elem]
end.to_h
end
end
Any method of the parent class not overridden by the child class that modifies self would call, let's say (in this case), the on_change function. Which would allow to do not have to re-define every single one of those methods to avoid losing track on changes.
Let's say the MyTypedArray would array Foo objects:
class Foo
attr_reader :unique_name
def initialize(name)
#unique_name = name
end
end
a short example of the expected behaviour of its usage:
my_array = MyTypedArray.new
my_array.push( Foo.new("bar") ).push( Foo.new("baz") )
my_array.element("bar").unique_name
# => "bar"
my_array.shift # a method that removes the first element from self
my_array.element("bar").unique_name
# => undefined method `unique_name' for nil:NilClass (NoMethodError)
my_array.name?("bar")
# => false
I understand that we should search for immutable classes, yet those native types support changes on the same object and we want a proper way to do an inheritance that is as brief and easy as possible.
Any thoughts, approaches, or recommendations are more than welcome, of course. I do not think I am the only one that have thought on this.
The reason why I am searching for a maintained gem is because different ruby versions may offer different supported methods or options for native types / classes.
[Edit]
The aim of the above is to figure out a pattern that works. I could just follow the rules and suggestions of other posts, yet would not get things work the way I am intended and when I see it proper (a coding language is made by and for humans, and not humans made for coding languages). I know everyone is proud of their achievements in learning, developing and making things shaped in a pattern that is well known in the community.
The target of the above is because all the methods of Array are more than welcome. I do not care if in the version 20 of Ruby they remove some methods of Array. By then my application will be obsolete or someone will achieve the same result in far less code.
Why Array?
Because the order matters.
Why an internal Hash?
Because for the usage I want to make of it, in overall, the cost of building the hash compensates the optimization it offers.
Why not just include Enumerable?
Because we just reduce the number of methods that change the object, but we do not actually have a pattern that allows to change #caches_init to false, so the Hash is rebuilt on next usage (so same problem as with Array)
Why not just whitelist and include target Array methods?
Because that does not get me where I want to be. What if I want anyone to still use pop, or shift but I do not want to redefine them, or even having to bother to manage my mixins and constantly having to use responds_to?? (perhaps that exercise is good to improve your skills in coding and read code from other people, but that is not what it should be)
Where I want to be?
I want to be in a position that I can re-use / inherit any, I repeat, any class (no matter if it is native or not). That is basic for an OOP language. And if we are not talking about an OOP language (but just some sugar at the top of it to make it appear as OOP), then let's keep ourselves open to analyse patterns that should work well (no matter if they are odd - for me is more odd that there are no intermediate levels; which is symptom of many conventional patterns, which in turn is symptom of poor support for certain features that are more widely required than what is accepted).
Why should a gem offer the above?
Well, let's humble it. The above is a very simple case (and even though not covered). You may gain in flexibility at some point by using what some people want to call the Ruby way. But at a cost when you move to bigger architectures. What if I want to create intermediate classes to inherit from? Enriched native classes that boost simple code, yet keeping it aligned with the language. It is easier to say this is not the Ruby way than trying to make the language closer to something that escalates well from the bottom.
I am not surprised that Rails and Ruby are almost "indistinctly" used by many. Because at some point, without some Rails support, what you have with Ruby is a lot of trouble. As, consequently, I am not surprised that Rails is so maintained.
Why should I redefine a pop, or a last, or first methods? For what? They are already implemented.
Why should I whitelist methods and create mixins? is that a object or method oriented programming?
Anyway... I do not expect anyone to share my view on this. I do see other patterns, and I will keep allowing my mind to find them. If anyone is open enough, please, feel free to share. Someone may criticize the approach and be right, but if you got there is because it worked.
To answer your question as it is written, no, there is no gem for this. This is not a possibility of the language, either in pure Ruby or in C which is used internally.
There is no mechanism in detect when self is changed, nor any way to detect if a method is pure (does not change self) or impure (does change self). It seems you want a way to "automatically" be able to know when a method is one or the other, and that, to put simply, is just not possible, nor is it in any language that I am aware of.
Internally (using your example) an Array is backed by a RArray structure in C. A struct is simple storage space: a way to look at an arbitrary block of memory. C does not care how you choose to look at memory, I could just as easily cast the pointer of this struct and say it is a now a pointer to an array of integers and change it that way, it will happily manipulate the memory as I tell it to, and there is nothing that can detect that I did so. Now add in the fact that anyone, any script, or any gem can do this and you have no control over it, and it just shows that this solution is fundamentally and objectively flawed.
This is why most (all?) languages that need to be notified when an object is changed use an observer pattern. You create a function that "notifies" when something changes, and you invoke that function manually when needed. If someone decides to subclass your class, they need only continue the pattern to raise that function if it changes the object state.
There is no such thing as an automatic way of doing this. As already explained, this is an "opt-in" or "whitelist" solution. If you want to subclass an existing object instead of using your own from scratch, then you need to modify its behavior accordingly.
That said, adding the functionality is not as daunting as you may think if you use some clever aliasing and meta-programming with module_eval, class_eval or the like.
# This is 100% untested and not even checked for syntax, just rough idea
def on_changed
# Do whatever you need here when object is changed
end
# Unpure methods like []=, <<, push, map!, etc, etc
unpure_methods.each do |name|
class_eval <<-EOS
alias #{name}_orig #{name}
def #{name}(*args, &block)
#{name}_orig(*args, &block)
on_changed
end
EOS
end

Why is using a class variable in Ruby considered a 'code smell'?

According to Reek, creating a class variable is considered a 'code smell'. What is the explanation behind this?
As you can find in their documentation on Class Variables:
Class variables form part of the global runtime state, and as such make it easy for one part of the system to accidentally or inadvertently depend on another part of the system. So the system becomes more prone to problems where changing something over here breaks something over there. In particular, class variables can make it hard to set up tests (because the context of the test includes all global state).
Essentially, it's a manifestation of global state, which is almost universally considered evil, because it makes tests more difficult and results in a much more fragile class/program structure.
This Stack Overflow question may also be worth reading, which shows the main problem with class variables: if any class inherits from your class and modifies the class variable, every instance of that variable changes, even from the parent! This understandably gives you a way to shoot yourself in the foot easily, so it may be best to avoid them unless you're very careful.
It's also worth comparing class variables with class instance variables. This question has a few good examples which illustrate the usage differences, but in essence class variables are shared, whereas class instance variables are not shared. Therefore, to avoid unwanted side effects, class instance variables are almost always what you want.
In brief, this:
class Shape
##sides = 0
def self.sides
##sides
end
end
class Pentagon < Shape
##sides = 5
end
puts Shape.sides # oops ... prints 5

Code placed outside of a method [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
In Java, every instruction executed is defined inside a method. In Ruby, you can do something like this:
class A
puts "Inside of A class" # [1]
end
and [1] will be executed when A is loaded. An example of this is the following code in Rails:
class Product < ActiveRecord::Base
validates :title, :presence => true, length: 1..19, :uniqueness => true
end
What sense does it have to write code outside of a method? How can it be used (how can it be invoked)?
I assume you want to know why you'd place code to execute "inside a class," when there's no way to have it execute more than once (when the class is first loaded.)
In Ruby, all classes are themselves objects - they are instance of the class Class. So what's happening under the hood when Ruby "reads" a class definition, is that Ruby is actually running methods on that instance of the class Class.
So a def inside the class definition of the class A is actually the same as A.send(:define_method, ...) - to understand what that means, you have to understand what senders and receivers are, and how they are implemented in Ruby. That SO post I linked to does a pretty good job of referring you to more material. The def syntax is just a convention to make the sending/receiving look like the syntax of other languages so that it's easier to "transition" to Ruby from other languages.
Ruby doesn't require that you should only call methods on the class itself when defining the class - so you can run any code you want. One use case is when you define a variable prefixed with an # inside the class definition:
class A
#class_var=123
def self.class_var
#class_var
end
def self.class_var=(inp)
#class_var=inp
end
end
a=A.new
b=A.new
b.class.class_var=5
puts a.class.class_var
# 5
Note the def self. notation that defines "class methods" - they can then access the "class variable" that you created by writing the code "inside the class."
This question comes up a lot for me, so I've written a more extensive blog post about it, to try and go into more detail about how Ruby implements these concepts. I have written them here in scare quotes, because they mean slightly different things in Java and C++, so don't apply their meanings very directly to try and understand what they mean in Ruby.
What sense has write code out of methods?
You've already seen it. Instead of changing the language itself (and the compiler) to add annotations to Ruby, the makers of Rails could make model validations easily (and lots of DSL for different things). Another example is att_accessor, a method that called in the context of a class will add accessor methods. And there are many many more.
Basically, you are adding that way lots of flexibility to the language.
How it can be used (how can it be invoked)?
You already did in your example. Just put the code there... and it is executed.
You can use and invoke it like such:
def putString
puts "Inside method outside of class"
end
class A
puts "Inside of A class" #[1]
putString
end
It gets invoked when you require the file.
Uses?
Meta-programming is one
['foo','bar'].each |m| do
def m
[m]
end
end
There's an even sneakier scenario where you can put code outside of the class, never mind the method, confused the heck out me when I first saw it.
Most of the answers here refer to code inside a class and outside its methods. I think the OP asked about code outside everything - forbidden in Java!
Java mimics the C languages' compilation cycle. In C, only certain kinds of lines can happen during compilation. Then, only the remaining kinds of lines can run during execution.
In Ruby, code evaluates from top to bottom. The commands class and def essentially mean "capture all these tokens, and evaluate them later." So, because the entire file evaluates at runtime, things outside classes can happen very early.
The most notorious example is:
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
require is (prepare for a shock) just a method, and File is (prepare for another one) always available. So a Ruby programmer can exchange zillions of boring, fragile lines of configuration files (in Java ANT or C MAKE) for just a few ugly - but bullet-proof - lines of raw Ruby, at the top of each file.

Gotchas for redefining methods in ruby

What are the things to be careful about while redefining methods in Ruby? Is redefining core library methods okay?
the problems IMHO are
You'll forget about the change.
You'll copy paste a snippet from the internet, which will trigger an error the altered behavior and you'll scratch your head until you get hairless patches.
Another developer will come after your and fight a bug for 3 months, until he finds it's in one of the monkey patches. He'll go to HR, get your address and and show you why not to do monkey patches.
Now, sometimes you need to monkey patch a class (even in the core library, why not). My suggestion is
Put all of your monkey-patches in ONE source folder.
The second thing you say to a new developer after "Hello my name is ..." is the location of that folder and a detailed explanation of what each monkey patch does.
I don't do much monkeypatching myself, but I've heard that rather than doing
class String
def improved_method
# teh codes
end
end
It's better to put the new method into a module, and then include the module
module ImprovedString
def improved_method
# teh codes
end
end
class String
include ImprovedString
end
it makes it easier to find where a method has been defined, and the old version still exists without having to do alias chaining.
I like the other answers. Though, I have to add that:
Sometimes you may only want to redefine methods only for certain instances. You can do this, and it makes it somehow more controlled than changing the functionality for all objects of a certain class - as long as a proper debugger is used for debugging:
class << object_instance
def method_redefinition
return "method_redefinition"
end
end
object_instance.method_redefinition => "method redefinition"
The metioned set of functionalities can also be encapsulated in a mix-in in order to avoid too much nesting and messy "code definition inside code execution":
module M
def method_redefinition
"method_redefinition"
end
end
object_instance.extend M
object_instance.method_redefinition => "method_redefinition"
You're talking about monkey patching and it's dangerous for the following reasons according to wikipedia
Carelessly written or poorly
documented monkey patches can lead to
problems:
They can lead to upgrade problems when the patch makes assumptions about
the patched object that are no longer
true; if the product you have changed
changes with a new release it may very
well break your patch. For this reason
monkey patches are often made
conditional, and only applied if
appropriate.
If two modules attempt to monkey-patch the same method, one of
them (whichever one runs last) "wins"
and the other patch has no effect,
unless monkeypatches are written with
pattern like alias_method_chain
They create a discrepancy between the original source code on disk and
the observed behaviour that can be
very confusing to anyone unaware of
the patches' existence.
Even if monkey patching isn't used,
some see a problem with the
availability of the feature, since the
ability to use monkey patching in a
programming language is incompatible
with enforcing strong encapsulation,
as required by the object-capability
model, between objects.
There's talk of a safer way of monkey
patching coming in ruby 2 called
refinements
This tiny gem might be useful if you're finding yourself running into monkey-patching issues: (https://github.com/gnovos/ctx). I originally wrote it to create more expressive DSLs by allowing alterations to the base objects without doing too much damage elsewhere, but it can probably be put to any number of uses. It gets around some of the monkey-patching issues by scoping method re-definition into arbitrary contexts that can be swapped out as needed.
If I want to redefine a method in some core class (for example, in String, etc), I use ctx_define instead of "def" and then later wrap the section of code that should use the new definition in a ctx block, like so:
class ::String
ctx_define :dsl, :+ do |other|
"#{self[0].upcase}#{self[1..-1]}#{other.capitalize}"
end
end
puts "this" + "is" + "normal" + "text" + "concatination"
# => thisisnormaltextconcatination
ctx(:dsl) { puts "this" + "is" + "special" + "text" + "concatination" }
# => ThisIsSpecialTextConcatination
I only threw it together in a few minutes, so I can't make any guarantees about how robust it is in any number of complicated situations, but it seems to work fine for simple needs. Give it a look if you're interested and see if it is of any help. :)

What does 'Monkey Patching' exactly Mean in Ruby?

According to Wikipedia, a monkey patch is:
a way to extend or modify the runtime
code of dynamic languages [...]
without altering the original source
code.
The following statement from the same entry confused me:
In Ruby, the term monkey patch was
misunderstood to mean any dynamic
modification to a class and is often
used as a synonym for dynamically
modifying any class at runtime.
I would like to know the exact meaning of monkey patching in Ruby. Is it doing something like the following, or is it something else?
class String
def foo
"foo"
end
end
The best explanation I heard for Monkey patching/Duck-punching is by Patrick Ewing in RailsConf 2007
...if it walks like a duck and talks like a duck, it’s a duck, right? So
if this duck is not giving you the noise that you want, you’ve got to
just punch that duck until it returns what you expect.
The short answer is that there is no "exact" meaning, because it's a novel term, and different folks use it differently. That much at least can be discerned from the Wikipedia article. There are some who insist that it only applies to "runtime" code (built-in classes, I suppose) while some would use it to refer to the run-time modification of any class.
Personally, I prefer the more inclusive definition. After all, if we were to use the term for modification of built-in classes only, how would we refer to the run-time modification of all the other classes? The important thing to me is that there's a difference between the source code and the actual running class.
In Ruby, the term monkey patch was
misunderstood to mean any dynamic
modification to a class and is often
used as a synonym for dynamically
modifying any class at runtime.
The above statement asserts that the Ruby usage is incorrect - but terms evolve, and that's not always a bad thing.
Monkey patching is when you replace methods of a class at runtime (not adding new methods as others have described).
In addition to being a very un-obvious and difficult to debug way to change code, it doesn't scale; as more and more modules start monkey patching methods, the likelihood of the changes stomping each other grow.
You are correct; it's when you modify or extend an existing class rather than subclass it.
This is monkey patching:
class Float
def self.times(&block)
self.to_i.times { |i| yield(i) }
remainder = self - self.to_i
yield(remainder) if remainder > 0.0
end
end
Now I imagine this might be useful sometimes, but imagine if you saw routine.
def my_method(my_special_number)
sum = 0
my_special_number.times { |num| sum << some_val ** num }
sum
end
And it breaks only occasionally when it gets called. To those paying attention you already know why, but imagine that you didn't know about the float type having a .times class-method and you automatically assumed that my_special_number is an integer. Every time the parameter is a whole number, integer or float, it would work fine (whole ints are passed back except when there is a floating-point remainder). But pass a number with anything in the decimal area in and it'll break for sure!
Just imagine how often this might happen with your gems, Rails plugins, and even by your own co-workers in your projects. If there's one or two little methods in there like this and it could take some time to find and correct.
If you wonder why it breaks, note that sum is an integer and a floating-point remainder could be passed back; in addition, the exponential sign only works when types are the same. So you might think it's fixed, because you converted bother numbers to floats ... only to find that the sum can't take the floating-point result.
In Python monkeypatching is referred to a lot as a sign of embarrassment: "I had to monkeypatch this class because..." (I encountered it first when dealing with Zope, which the article mentions). It's used to say that it was necessary to take hold of an upstream class and fix it at runtime instead of lobbying to have the unwanted behaviors fixed in the actual class or fixing them in a subclass. In my experience Ruby people don't talk about monkeypatching that much, because it's not considered especially bad or even noteworthy (hence "duck punching"). Obviously you have to be careful about changing the return values of a method that will be used in other dependencies, but adding methods to a class the way that active_support and facets do is perfectly safe.
Update 10 years later: I would amend the last sentence to say "is relatively safe". Extending a core library class with new methods can lead to problems if somebody else gets the same idea and adds the same method with a different implementation or method signature, or if people confuse extended methods for core language functionality. Both cases often happen in Ruby (especially regarding active_support methods).
Explanation of the concept without code:
It means you can "dynamically" modify code. Wanna add a method "dynamically" to a particular class known only at "runtime"? No problem. It's powerful, yes: but can be misused. The concept "dynamically" might be a little too esoteric to understand, so I have prepared an example below (no code, I promise):
How to monkey patch a car:
Normal Car Operations
How do you normally start a car? It’s simple: you turn the ignition, the car starts!
Great, but how can we "monkey patch" the car class?
This is what Fabrizzio did to poor Michael Corleone. Normally, if you want to change how a car operates, you would have to make those changes in the car manufacturing plant (i.e. at "compile" time, within the Car class ^**). Fabrizzio ain't got no time for that: he monkey patches cars by getting under the bonnet to surreptitiously and sneakily rewire things. In other words, he re-opens the Car class, makes the changes he wants, and he's done: he's just monkey patched a car. he done this "dynamically".
You have to really know what you are doing when you monkey patch otherwise the results could be quite explosive.
“Fabrizzio, where are you going?”
Boom!
Like Confucius Say:
"Keep your source code close, but your monkey patches closer."
It can be dangerous.
^** yes i know, dynamic languages.
Usually it is meant about ad-hoc changes, using Ruby open classes, frequently with low quality code.
Here's a good follow-up on the subject.

Resources