00:00:09.360
Well, thanks a lot, guys. It's very nice to be here. I'm talking today about the state of Ruby, the state that things are in.
00:00:15.519
So, let's get cracking. This is Ruby; we've all seen a few in our time, right? They're in a pretty good state, I think. There's been a lot happening recently.
00:00:26.640
Today, I want to divide things into two areas and then get stuck in. Firstly, I want to talk about some tech, because there's lots of good new tech happening in Ruby these days.
00:00:32.079
There's a heap of stuff happening. We just heard and saw that so much progress is happening in all of the interpreters, particularly in JRubyland.
00:00:39.120
I want to talk about some tech and feelings as well because feelings are important, and the state of Ruby has left me with a lot of feelings.
00:00:52.079
But first, let's get into tech because we all know tech, right? So, Ruby. This is the date when Ruby first began; this is when Mats started working on it back in '93 on the 24th of February.
00:01:05.280
Since then, so much has happened. Like I said, MRI isn't the only one nowadays. There's JRuby, Rubinius, MagLev, and many others. There's so much going on.
00:01:19.119
As I mentioned, there's been a lot happening, and pretty soon there's an interesting date coming up which is 20 years later—in fact, in two days' time, on Sunday.
00:01:29.759
We're hopefully going to see a really big change, which is Ruby 2.0. I'm really excited about 2.0. It's going to be a really interesting release, and to me, the thing that characterizes this release is convention.
00:01:42.240
This release is focused on formalizing useful conventions that we've all developed as Ruby developers and finding new solutions for bad conventions that we've all sort of found ourselves using.
00:01:53.600
So, what's actually changed in 2.0? I want to discuss three quick changes and then delve into three more things in more detail.
00:02:03.759
Firstly, copy-on-write. This is going to be a great change. As most of us know in Unix land, copy-on-write happens when a process is forked.
00:02:10.879
Forking a process is a really cheap operation because the new process gets to share its memory with the old one. As soon as any of that data changes, the kernel will copy into the new process's memory space and they'll start using their own separate areas of memory.
00:02:28.319
However, this doesn't work so well with Ruby because its garbage collector touches every object when it does its mark-and-sweep. Thus, copy-on-write essentially duplicates the memory footprint of every Ruby process.
00:02:40.640
But the garbage collector in 2.0 has vastly improved. Instead of the mark phase of the mark-and-sweep being stored on the object, as of 2.0, it will be stored separately in a central list. This means that the objects themselves won't change during the mark-and-sweep.
00:03:14.080
Therefore, the resident size of all the services you run will stay the same, but the shared size will really increase. That means that the overall footprint is a lot less because there's a lot less duplication.
00:03:38.560
I was hoping to have some numbers to show you for this, but I can't actually get my application running on 2.0 yet because there's an exception somewhere down inside Rails.
00:03:56.400
So, suffice it to say, it's going to be less effective. Secondly, Unicode strings—is a good one! As we know, Ruby 1.9 introduced Unicode by introducing encoding on strings.
00:04:07.200
Before that, in Ruby 1.8, strings were just raw bytes. This simple scenario was straightforward, but when we moved to Ruby 1.9, everything gained encoding by default, using ASCII.
00:04:19.600
This was fine for us English speakers, but in other languages with different character sets, especially Japanese, if you wanted to say 'hello,' it became necessary to annotate your files with encoding statements.
00:04:43.120
In 2.0, encoding is going to be UTF-8 by default for literal strings, which is a really nice change. It's important to note, this only affects literal strings; if you read from a file, it might not automatically be Unicode. But for literals, it's now Unicode all the time.
00:05:01.360
Thirdly, keyword arguments. I'm very excited about this change. This is what I mean when I say that 2.0 is a release about convention. Keyword arguments are essentially a formalization of how we pass optional named arguments.
00:05:18.000
Initially, the commentary around named arguments was negative, with some believing these weren't real named arguments like Python's, as you couldn't pass any argument by name.
00:05:32.560
However, that seems a bit unfair, as they're intended to be a specific formalization of how we pass those default arguments. Here's an example: we have a little renderer class and want to pass in some options at the end.
00:05:50.880
We would attach a hash as the last argument, merging it with some defaults. It works well, but it's not ideal. In 2.0, things will look much better, as the defaults will move up into the definition.
00:06:07.679
You can refer to them as arguments rather than just looking something up in a hash. They can coexist with existing default arguments, and as a result, you can call that method in multiple valid ways.
00:06:29.120
Next up, refinements. This is a big change and one that has been discussed a lot, with a fair amount of uncertainty around it. What’s the deal with refinements? Well, monkey patching is something we all know and, in some cases, love.
00:06:44.480
But it's not great; it doesn't work very well, and although it seems convenient at the time, it causes issues later on. Back in one of the talks Mats discussed during RubyKaigi in 2010 or 11, he addressed his plans for 2.0.
00:07:03.520
He introduced class boxing, which was meant as a non-global way of monkey patching. Class boxing has since evolved into refinements. The way it's structured is that if you take a method like 'collapse,' which I think is a fantastic addition.
00:07:23.360
The idea is that you can filter a list and then remove the one you've filtered by in one step. In 2.0, instead of patching directly onto a class, you encapsulate it into a module, which refines the class.
00:07:41.600
Refinement is not a keyword; it's a method call that takes a block, allowing your functionality to be neatly wrapped up. Originally, it was going to be a statement that would be used for a class, but as of the second release candidate, it only works at the top level of a file.
00:08:02.559
This example demonstrates that you can refine method functionality and keep everything tidy. It's nice that this allows you to pull refinements from anywhere. Although refinements are still experimental, they hold great potential.
00:08:29.919
For example, if my phone has gone off because someone tweeted me, that’s a reminder that my presenter is still in front of me.
00:08:44.960
Again, back to the concept of local rebinding. This was a feature that was originally intended to be part of refinements but got cut. Local rebinding refers to how refinements are active and how they can affect code in different contexts.
00:09:03.680
The tricky part was that if you allow rebinding, it could break the localization of refinements. Thus, by only applying refinements to the static context of code, we can ensure that they are really scoped and not dangerously global.
00:09:23.840
I think this limitation is a positive step away from monkey patching practices. When reflecting on my dictionary class and subclassing a refined class, it became apparent that refinements are indeed working as intended.
00:09:41.919
At least as of the current state, it seems that refinements will be strictly scoped, meaning only the code that statically defines a context with the usage statement will affect refinement.
00:09:56.480
This is a solid decision because it preserves the use-case of refinements without allowing unintentioned side effects.
00:10:13.920
Next, I want to talk about 'Module Prepend', which is an exciting feature. It falls into the same vein as keyword arguments; it's another formalization of Ruby that many developers will appreciate.
00:10:44.880
We've all heard of alias method chain. It's a strategy used in frameworks like Rails that patches functionality by adding methods around existing implementations.
00:11:04.240
However, prepend is a different way of thinking about it. If you prepend a module, it allows you to override methods effectively. Let’s think through an example.
00:11:29.040
With prepend, you can create a profiling module that sits in front of the methods you want to track. By doing this, you can easily capture the performance of any method calls while maintaining the original method functionality below it.
00:11:57.360
This elegance helps simplify the previous boilerplate of calling methods within a context. It seamlessly allows for method overlay, where you don't lose any original functionality; it integrates smoothly.
00:12:19.440
What we see here is that it's a much cleaner solution to a problem many developers have faced before. In summary, this wraps up some exciting things coming with Ruby 2.0.
00:12:34.080
Now I want to talk about feelings, which is a more abstract area of conversation. This may seem less concrete, but introspection in our community is valuable. We've been through a lot together, and Ruby has been an interesting language to work with in recent times.
00:12:56.480
When reflecting on our progress, I think it’s essential to consider the vibe within the Ruby community. We've experienced significant growth, and often the cultural shift catches people off guard.
00:13:17.040
Yesterday, Mats mentioned ‘nice’ during various discussions, and it resonated with me. That idea of maintaining kindness and empathy is something we need to carry with us.
00:13:35.760
I remember getting immersed in Ruby because of pivotal resources, such as the 'Poignant Guide.' That guide guided me toward Ruby's ideals, and I think it speaks to why we fell in love with Ruby in the first place.
00:13:50.560
As I started crafting this part of my talk, I felt a bit ambivalent, possibly pondering if Ruby is different now compared to what it was before. Has the Ruby community changed those relationships?
00:14:05.760
Or do we feel the priorities are slightly out of sync at this moment? I felt the need for some introspection but also looked outward.
00:14:25.920
This led me to the idea of reputation. The Ruby community has gained a reputation—some think it's cavalier, focusing on style over substance.
00:14:34.160
Whether this reputation is warranted or not is up for debate, but it's worth examining how our priorities might distill down to different views of value in programming.
00:14:45.920
Reputation and perception matter as they shape how we address problems and both technical and personal interactions.
00:15:01.680
This brings to mind a thought-provoking post by Reganwald entitled “Optimism.” it's worth diving into, as it discusses the importance of empathy in programming.
00:15:17.680
I want us to understand that sometimes, what's perceived as conflict is a question of priorities, and recognizing that can help direct our paths.
00:15:32.960
The Ruby community, like any other, has its differences, but this doesn’t have to equate to opposition. I truly believe that often, we’re more aligned on fundamentals than we realize.
00:15:49.840
And while there's sometimes heated discussion about libraries, frameworks, and approaches, underneath it all, there's common ground.
00:16:02.080
We respect security, performance, and the needs of our clients; it's just how we prioritize these values that differ. We all seek elegance in our solutions.
00:16:17.680
If I may close simply: it's all about empathy. When we encounter code we find difficult, it might be easy to dismiss and criticize.
00:16:39.760
But by practicing understanding, we can enhance our communication and foster a collaborative environment. Let's keep empathy at the forefront of our discussions.
00:16:59.760
Thank you very much.