RECENT POSTS
Ruby and the freedom to use sharp knives
October 17, 2024 | Written by Lucas Gordon | 184 views
I had the opportunity to attend Rails World 2024 last month in Toronto, the annual conference for the Ruby on Rails community. Shopify was one of the sponsors, and I was lucky to snag a ticket.
My favorite session from the conference was a panel discussion with Tobi (Shopify), Matz (creator of Ruby), and DHH (creator of Rails). During this discussion, one line grabbed my interest enough for me to lose concentration for a few minutes to reflect on the statement.
DHH mentioned that Ruby gives programmers the freedom to use "sharp knives." In other words, Ruby trusts developers to use the language's powerful features responsibly. DHH contrasted this with a language like Java, described as having "baby edges," implying that it is designed to be safer and more restrictive, with features that prevent developers from making mistakes.
Rails World 2024, DHH explaining Rails 8 release
Having used Ruby every day for the last year at work, and having spent much of my second and third years of university using Java, I first questioned why this was the case.
The Java approach can be seen as patronizing, as it assumes developers need protection from themselves.
Ruby is designed to prioritize developer happiness and productivity, offering flexibility and expressiveness. One can express themselves however they wish—within reason, of course. It allows developers to modify and extend the language, trusting them to use these capabilities wisely. If a developer chooses to be too careless, that’s on them. Maybe the program works, but bugs will surely follow. This approach encourages creativity (and fun) but requires careful handling.
Java, on the other hand, emphasizes safety and robustness, often at the cost of flexibility. It includes features that prevent developers from making certain types of errors, which can make it feel more restrictive. This design choice aims to reduce bugs, obviously, but it can limit the ability to experiment and innovate.
Let’s consider an example.
Let’s say I want to create a rule in Ruby and Java that if I print the phrase “holy cow,” it will instead format the phrase for me on its own, without the need for an additional method, and print “HOLY COW!”
In Ruby, I can do this easily by extending the String class with a new method called “yell.”
So, if I have:
phrase = "holy cow"
phrase.yell
The output will be “HOLY COW!”
Here’s what this looks like in Ruby:
class String
def yell
self.upcase + "!!!"
end
end
puts "holy cow".yell # Outputs: HOLY COW!!!
Pretty simple and clean.
But here’s the risk. Adding too many of these methods on the fly will surely result in bugs that will cause my program to crash or not behave as intended for other developers when looking at my code.
As a silly example, consider overriding the addition operator +
to actually subtract numbers instead of add:
class Integer
def +(other)
self - other
end
end
puts 5 + 3 # Outputs: 2
If someone was looking at this arithmetic elsewhere in my codebase without seeing the override, they would go nuts.
Now, how can we do this in Java? In Java, you would typically create a utility class or method to achieve similar functionality, rather than modifying the existing class.
public class Main {
public static void main(String[] args) {
String text = "hello";
// Java does not allow adding methods to the String class directly.
System.out.println(text.toUpperCase() + "!");
}
}