Rubyisms: reopening classes

Written on 2:26:00 PM by S. Potter

Ever wished you could write code in a very expressive way like the following examples?

  • expiration_date = 3.years.from_now
  • birth_date = 32.years.ago
Now you can, in Ruby at least. Two years ago I was a huge Python head that thought no other language could compete with Python for developer productivity. My Python indoctrination occurred after 7 solid years of proclaiming Java was the ultimate language that would reign supreme. Prior to my Java phase I was a C++ and Perl coder. It was also two years ago that I got my first glimpse at Ruby. I read articles, blogs and forums between Python and Ruby heads discussing finer points of each language and how one is far more superior than the other, because....bla bla bla. It was at this time that Ruby's concept of reopening classes came to my attention. As a hearty Python developer at the time I came to the conclusion that Python had to be superior on this point because Python allowed class reopening through metaclasses, so the original author of the code could be explicit to allow class reopening or not. In Ruby, however, anyone could reopen your classes, write malicious code and redploy without others knowing. Over the past two years I have realized that while Python is a beautiful programming language (not just scripting language) in its own right, my views on this point have changed considerably. To show class reopening I will be using an example of code that is very similar to some Ruby standard library extensions found in Active Support included in Rails (Disclaimer: This is not necessarily the same underlying code - I have not checked to be honest). Let us start up an irb shell session and write the following:
  irb> 3.class
  => Fixnum
  irb> class Fixnum
  irb>   def years
  irb>     return self*365*24*60*60
  irb>   end
  irb> end
  => nil
  irb> 3.years
  => 94608000
  irb> 3.years.class
  => Fixnum
  irb> class Fixnum
  irb>   def ago
  irb>     return Time.now() - self
  irb>   end
  irb>   def from_now
  irb>     return Time.now() + self
  irb>   end
  irb> end
  => nil
  irb> 3.years.from_now
  => Sun Aug 09 14:23:10 CDT 2009
  irb> 3.years.ago
  => Mon Aug 11 14:23:19 CDT 2003
Did you follow what I just did? I wanted to show what 3's class is in Ruby. To those not very familiar with Ruby, this was important to show, since newbies might expect 3.class to be Integer, but in fact it is of type Fixnum. Next we reopened the Fixnum class for new definition. If we had reopened it and inserted a method called floor or ceil we would have overwritten the original Ruby standard library implementation of these methods. Instead we defined a method called years, which wasn't previously defined in Fixnum. Then we closed the class and found that 3.years returns 94608000, which is the number of seconds in a year. Is that useful? Not yet, so next we reopened Fixnum again and insert two methods: ago and from_now. After reclosing the class again, we can write partial sentences in Ruby and provide an extremely expressive API for an application that deals a lot with dates and converting numbers to dates. This couldn't be done in Python with the same ease using metaclasses, because the builtin int type cannot be reopened unless you redefined the int type from scratch in Python including the addition of your special purpose methods in the mix. Anyway, this might not convince all readers of the significant utility of the class reopening feature of Ruby, but I have began to love this feature, arguably too much (some may say). I have found it has significantly improved readability and condensed the code necessary to do many tasks. After converting to Java a number of years ago from Perl and C++, I vowed not to take the Perlist's attitude toward trusting clients of your code not to bastardize it. However, I find myself accepting that if a client of my code knowingly decides to take this risk, it is on their own head they fall. I should not be bothered by this professionally or personally. I should also bring to reader's attention that this feature of Ruby is a stepping stone to promote the development of true domain specific languages (DSL), which is difficult at best to do in many other languages.

Rubyisms: naming conventions

Written on 12:43:00 PM by S. Potter

Today I wanted to show the implicit and explicit naming conventions in Ruby for newbies. It isn't particularly consistent with another language's conventions, so could cause confusion when reading the Ruby Standard Library (RSL). Where appropriate I also discuss how some of the naming conventions really aid code readability and developer productivity.

ClassName and ModuleName [implicit]

Naming classes is very similar to most common conventions following in C++, Java, Python and C#. e.g. DataMigration, CorporateConvertibleBond, Controller etc. I am unaware of a class name in the (RSL) that violates this rule. RSL examples of convention usage are Fixnum, Rational, DateTime, Module, NameError, NotImplementedError, NilClass. I realize Fixnum is a little controversial, but I think there is a case for it's naming as above.

variable_name and regular_method_name [implicit]

For variable names and methods that do something that isn't dangerous and/or return a non-boolean to the caller, the common underscoring convention is used to name them. This is consistent with Perl and PHP variable naming conventions. RSL examples include: String#strip, Object#instance_eval, Array#sort_by. Please note this is the one convention listed here that is violated in the RSL the most.

method_asking_a_question? [implicit]

Suffixing a method that asks a question with a '?' is a great way to tell clients of your code it returns a boolean value to be used in conditional expressions. My favorite RSL example is Object#nil?. This is one of the most important methods, in my mind, that exist in Ruby in conjunction with making Ruby's None, null, NULL equivalent, nil and object of type NilClass. RSL exaples include: Object#is_a?, Hash#has_key?, Object#frozen?. This naming approach is my joint favorite with the following convention that significantly increases readability of code and implicitly improves developer productivity as a side effect.

slightly_dangerous_method! [implicit]

For methods that change the internal state of the object in a way that may not be apparent, a '!' is suffixed to the method name to follow this convention. As an example in the RSL, you would probably expect the method "a string".upcase to return a copy of the original string in upper case, but the method "a string".upcase! would probably warn you that it would change the original object's internal state. This is an important distinction to know as a developer writing client code to the String class. This naming convention will keep you out of trouble. If a team mate decides to try out some of your APIs, then you can feel safe knowing you have warned him/her of potential danger spots.

@instance_variable [explicit]

Instance variables are explicitly prefixed with the '@' sign. Some may thing this is a Perlism that crept over, but in Perl '@' prefixed variables referred to arrays, if I remember correctly, so the usage is quite different. It should be noted that the '@' prefix is only used when referring to instance variables internally within the class. Using the '@' prefix does provide a convenient visual que that I am using an instance method which definitely improves readability of code.

$global_variable [explicit]

To refer to global variables prefix the name with '$'. This is an explicit naming convention in Ruby, much like the '@' prefix for instance variables above. This gives a quick visual note that we are knowingly using globals. For me it also provides a psychological check, where I start to question my motives whenever using a global variable and usually end up refactoring code to avoid using globals.

SOME_CONSTANT or OtherConstant [kind of explicit:)]

Much like in Java and Python, Ruby's constant naming convention is not commonly consistent. Often developers use the capilized naming approach, while just as many use the camel case convention used for class and module names in Ruby. Personally, if the constant is accessible from the module or class, I default to using the former approach unless the project has a different preference. For internally accessible constants, it is probably a moot point. All in all I find using these or very close naming conventions to those listed here, help me become more productive as a Ruby developer. I also find it useful to notice the Ruby mindset of being as expressive as possible without being verbose implicitly defined in the naming rules above.