 So the reason I need to do this microphone instead of the other one is that this is a live coding talk. I have never done a live coding talk before. In fact, I usually hate them. I think David's earlier today was the best one I've ever seen in my life. That was amazing. But normally I really dislike them. I feel like sometimes I don't add a lot to the topic that we're discussing. So I decided to try and do one just to see if I could make one that I liked. We'll see if I succeed. I'm really happy to be here. I tried to come last year, but unfortunately last year this conference and Golden Gate Ruby Conference were on the same weekend. And I helped organize the Golden Gate Ruby Conference so I was sort of obligated to that. I'm really glad that this year we found different weekends to do our conferences so that I can be here. I'm really excited. I'm also excited because it's raining outside. I don't know if you've heard, but in California we haven't had rain for like a year. So I went outside and I was just like, wow, this is cool. I would love to. If you can arrange it, I will do that. I have a slight confession to make though, and that is that I don't really know why I am here. I don't really know why it is that people invite me to come speak at their conferences, to be perfectly honest. I have some qualifications that I have put on a slide to show you, like all speakers do. I will show you my qualifications. I work with some really awesome people. I've worked with other awesome people over the years. I am a director of Ruby Central, which means that I help run the program for RubyConf and RailsConf. So if you have submitted a talk to either of those conferences in the last couple of years, I have rated it. I also started RailsBridge back in the day in like 2009. I know it's hard to think back that far. So those are my qualifications. I do a lot of speaking. I teach with Sandy Metz, she's pretty awesome. She and I are writing a book. All that sounds great, right? But then, then there's this. This is my GitHub profile. The part at the bottom is the interesting part. Let's zoom in on that a little bit. This is a contribution graph. And how this works, everyone on GitHub has one. And how this works is that every time you make a contribution to an open source project, one of these little dots gets filled in. And the more stuff you do on an individual day, the darker the dot gets. So I had one really good day in the last year. And then like a scattering of like kind of not great days. And a lot of empty. This thing looks a lot to me like bathroom tile, like a strip of bathroom tile. In fact, this is my friend Ben Lovell's shower. And he likes to say that his shower is a more prolific open source contributor than he is. But my contribution graph, on the other hand, kind of looks like it's been bleached. I never really got into contributing open source code, contributing gems, releasing gems. And it looks particularly unimpressive next to all of the other speakers that you're hearing from at this conference. For example, here's David Padilla's contribution graph. For if you are doing a lot of open source work, it starts to look like you're growing mold cultures. So the more green it is, the better, healthier it is, something like that. Best arrangement of dots definitely goes to Carrie Miller. I like the little dots. She's got a nice sort of pattern of light and dark dots, very nice. In fact, the only other speaker whose contribution graph looks as sanitary as mine is the guy who works at GitHub. So clearly he has mastered GitHub in other ways. We can forgive him for that. And it's not just speakers, right? Other people say that GitHub's your resume, right? Here's Eric Michaels-Ober. He contributes a lot to various gems. It's got nice mold culture growing there. It looks like here's Katrina Owen, looking pretty good there. Here's Nobu, who's on Ruby Core from Ruby Core. And it's not just famous people, right? Here's my friend Travis. He and I used to work together at Pivotal Labs. He's got a nice little street going of 580 days right there. Very nice. I happen to know he's getting married in a couple weeks though, so we'll see how that goes. And then there's mine. So why haven't I done that? Every developer seems to have something they feel insecure about. Sometimes for some developers, it's their educational background. Maybe they feel like they didn't get the right degree or they didn't go to college or something along those lines or they haven't worked for the right companies. For me, it's my, this is my insecurity. The fact that I don't contribute to open source. And so I could give you some excuses. In fact, I'll try some right now. I'm a consultant. It's like gonna work, it's totally gonna work. This is my most amazing gift ever. But I'm a consultant, which means all the code I write belongs to somebody else. It just keeps going, man. This is definitely what I do all day. But the real reason that I haven't ever really gotten into doing open source is that I am intimidated. I am intimidated by gems. I write a lot of Rails applications. And in the course of writing applications, of course, sometimes I have to go in and look at the insides of gems. But every time I do, it's like opening a door and finding myself in a different world. Clearly, libraries have a different set of constraints because the code looks very different. It looks like a foreign language. So it doesn't look like Ruby to me even in many cases. And we'll see an example of that later on. And so you might say, you might legitimately ask, well, if the gem code is unfamiliar, why don't you just contribute to an open source Rails app? Because either one gets the square filled in on your bingo card, right? I mean, your contribution graph, whatever you wanna call it. And that's a legitimate point. However, most Ruby open source work that is available is on gems, just to throw some numbers at it. There are 90, almost 90,000 individual gems on rubygems.org. But my research turned up less than 150 open source Rails apps. Now, both of these numbers could be off in significant ways, right? So first off, the number of individual non-forked gem code bases could be significantly lower than the total number of gems, right? And second, since there's no central repository for open source Rails apps, like there is for gems, the number of open source Rails apps could be significantly higher. So let's be conservative and say that one third of the rubygems are original works. And let's say that my research was off by two orders of magnitude. So for every one Rails app I found, there were 99 I missed. Even then, there are still twice as many opportunities to contribute to open source gems than there are to contribute to open source Rails apps. Now, the number of repositories isn't everything that's important, of course. But it backs up my intuition and my anecdotes, if you will. That most Ruby developers who contribute to open source are contributing gems. But the code inside of gems is so different to me. It almost feels like the Ruby community, as we think of ourselves as two personalities. This is the application developers, and then there's the gem developers. And I don't think that we acknowledge very often how different these things are. And I was thinking about this, and it reminded me, it made me think back to when I used to read things back in the day. This is some poetry from Walt Whitman. I actually read Walt Whitman in high school, totally did not get it. Went back and read it a couple of years ago again and got a lot more out of it. So I recommend if you were forced to read it in high school, go back and try again. It's pretty amazing. So this is from a poem called Song of Myself. And he says, do I contradict myself? Very well then? I contradict myself. I am large. I contain multitudes. What I love about this is it's a very succinct way of expressing a pretty complicated idea which is the idea of the multiple nature of our inner selves. And I know we'll come back to code in a minute, I promise. So we think of our self, our person, our interior being as a single fairly consistent representation that we project out into the world, but that's actually not how it works at all. And poets have always known this. This was written in 1855. You can see this idea in Shakespeare. You can see it in much earlier stuff as well. But interestingly enough, in the last 40 years, science has finally caught up with poetry. And now we have some theories about how this works. So psychologists talk about this concept in many ways, but one of them is in terms of something called personas. And this was originally an idea that Carl Jung put forth in the 50s. It's been expanded and changed a lot since then. But the essential idea is that even in people who are mentally normative, meaning people who are not crazy, which apparently doesn't really include anyone, what we think of as our self is not consistent. Instead, we have a constantly shifting set of personas, some of whom are quite different from each other, that we bring out to use with different people at different times in different situations. We don't have a fixed set of personas. We add to it, we remove from it. We merge personas. Sometimes we separate them. It's a complicated set of mental transformations that we all do. And most of the time, we aren't really aware that we're doing it. From our internal perspective, all of these personas are us. Even though in some cases, they may hold mutually contradictory opinions. And I've started thinking about the Ruby community in much the same way. Our sense of ourselves is that we are all Rubyists. This is, we even have a word for it that we've coined. And we have a set of behaviors and assumptions that we've attached to this label. For instance, we talk about the concept of idiomatic Ruby, which is a set of conventions that in theory, we all agree on. And that tells us what Ruby is supposed to look like when we write it. But the Ruby community is large and our multitudes maybe look like Lego people, but they are there. So I wanna make this a little more concrete. I wanna show you what I mean when I say that the interior of Gems ends up looking much more different than the exterior inside of an app. So we're gonna look at RSpec. RSpec, very popular testing library for Ruby code. Anyone used RSpec before? Yay, hooray. All right, so here's the Ruby toolbox page for unit testing frameworks. This is a bar graph that shows their estimate of popularity. Bigger numbers mean more popular. RSpec gets a 16. Mini test gets a 10. And the nearest competitor after that gets a one. So most people who are writing tests in Ruby are apparently using RSpec. So this is gonna look real familiar. Which is good, because I'm not sure how well it's gonna show up on the screen. Here's a very basic RSpec example. We all know how American movies work. I did this talk the first time I gave it in France, so this was definitely something they appreciated. American movies have explosions, that's what they're about. The good ones, I guess. So here's an RSpec file that tests an imaginary Ruby class called American movies. It's got a few basic concepts to notice. First is the describe. The describe groups individual tests. And then inside of a group it has two sections, a before and it's, which are generally called examples. But I like to think of them as it's. The before runs as you might expect before each of the examples. And so in this describe we instantiate a, or rather in the before, we instantiate a new American movie object and we assign it to the instance variable movie. So this is functionally equivalent to this, which instantiates it at the beginning of each test. So that's what the before is. So using RSpec is pretty straightforward. It is a different skill from actually writing applications. So, and people tend to learn them together, but it's something that a lot of application developers do. We write these RSpec files for our models, we write them for our controllers. And although it is a different set of things to learn, as I said, beyond the mechanics of Rails, after a while it becomes kind of second nature. We understand how it's organized, we understand how things are groups, or are groups together, and it starts to seem pretty straightforward. And then one day, one day we decide we need some custom behavior. Yeah, I'm going to old school, I'm doing cats and not ponies. I think that's cause we're over our pony quota for the day. I had a client once who wanted a custom version of before. He wanted something like this. So, he wanted a custom before like block that ran before all the other befores, right? Okay, here it's called before seeds. Now you might legitimately wonder why you would want such a thing. And so a little more context. He wanted this because he had set up a global before here that ran automatically before every example, and it loaded seed data, and occasionally he had something slightly, slightly maybe out of the norm, let's call it, that he wanted to do before that seed data was loaded. So when he had an example that needed that slightly weird thing, he would add the before seeds, which is what he wanted to write. That would run first, and then this would run second, and then any other things after that would run after that. So this is not an unreasonable request, and there are sanctioned ways to do this sort of thing in our spec. This was a few years ago before a lot of that had shaken out, so I thought, okay, how hard could this be? Let's do it. Let's go find out where before happens in our spec. We'll start out by searching for def before in the RSpec code and see what we find. So here's our first abstraction. This is actually, you know, it's not bad. This is our first abstraction, though, that isn't represented in the external API that we use of RSpec, and that's hooks. RSpec has this idea of hooks that are things like before, after, and around. So, all right, fine. Let's go look at register hook. Okay, getting slightly more complicated. Not entirely sure what line 213 is doing. Something about scope. Let's go look at that hooks method that it's calling. Oh, okay. All right, so now we have some collections of hooks. Here's another abstraction we don't have on the external interface. And then down on line 151, we're like extending the Singleton class with something global. I don't really know what's going on there. So it gets even more complicated from there. I'm not gonna show you all of it. It turns out that in order to understand how before works in RSpec, you need to take in an entire file that's about 300 lines. Here it is in four point font. And just keeps going. There we go, that whole thing. So you don't have to get that far into RSpec to find abstractions that seem very unfamiliar. If all you know is it's public API. And so if you're just a user of RSpec, even a long time user, even a power user, going in and looking at its internals feels like opening a door that you expected to go into your living room and like finding yourself here where you don't speak the language and you don't really know what's going on. So I wanted to see what would happen. Like did it have to be this way? How much of this is required by the code that we're writing? And how much of it is people just being too clever? RSpec is often accused of using too much metaprogramming and being too clever and being too abstract and hard to understand. So I thought, well, how much of this is required? Now when I was less experienced and I looked inside of something like RSpec and I found things that I didn't understand, I thought the answer to the question of why it was that way was object-oriented design. I thought clearly I did not have enough experience to understand the sophisticated object-oriented design that these people had put into it. People writing libraries are doing real object-oriented software where I'm just messing around in rails, right? So let's see if we can write RSpec without these abstractions. Can we write a version of RSpec that is as easy to understand on the inside as it is on the outside? And this is where we do live coding. Are you excited? Are you ready? All right. First we have to do exciting visual things where I switch all of my inputs. Let's see here. This is why they gave me 45 minutes because I knew I'm gonna spend 15 minutes doing this stuff. All right, now we're seeing the same things in theory. I'm gonna get rid of that. So we're gonna build a gem. As Brandi mentioned before this morning, building a gem is ridiculously easy these days. So when I was doing this talk the first time, one of the things I looked for was a logo for RSpec. At the time, RSpec did not have a logo. So when I searched for RSpec with a Google image search, I found things like R-Spec, which is some kind of spectroscopy analysis tool. And I thought, hmm, all right, so that gave me a name for my gem. We're gonna call it spectroscopy. Now the problem with that is that it's really kind of difficult to spell. Ah, sorry, what I wanted was bundled gem. Let's see what happens. So it creates you a bunch of stuff. Look at that, very exciting. I'm just gonna tap complete that thing because I have no idea. All right, so let's look at what's in here. And here's the place where those of you who like to use Emacs or Vim can laugh at me for a few minutes while we wait for RubyMind to start up. I actually really love RubyMind, but that's because I learned it by pairing with other people who loved it, so I learned all the keyboard shortcuts. All right, so let's look at what we got in here. So this is super amazing, right? It gives you everything you need, the skeleton for an entire gem, and then there's a nice little helpful comment here. I don't know if you can read that from the back. It says, your code goes here, dot, dot, dot. The first time I gave this talk in, at Lecompe in Paris, André Arco was in the audience and he was like, you're welcome. And I was like, what? He's like, I did that. I was like, oh yeah, right, you wrote must a bundler. Great, that's not awkward. So yeah, so thanks, André. That's amazing, I like that comment. So we want to write, I'm gonna take this out for a moment so we don't need it. What we want to do is we want to create a testing library that does something like this. Let's not do it before right now. So let's start with something easy. How about equality? We'll do something like, we expect one, two, equal, equal, one, seems reasonable, right? Okay, let's run that. So, undefined method describe for main object. We will let our test tell us what we need to do. And I can fix that one. Are you ready? Oh, wrong number, right, it takes a block, doesn't it? Oh no, it doesn't take a block. It takes a thingy, what do you call this? Parameter, a description. A thing being described, let's call it that. And also a block. Okay, well, okay, nothing happened. We should probably call the block. Okay, next error, undefined method it for object. How do you think we should fix that one? If you answered define a method, then you win. And this one also takes an argument, and a block. And just like we did before, we're probably just gonna wanna do block.call. It's totally gonna be awesome. Okay, undefined method expect for object. I think you know where we're going with this one. What does expect take? Takes a thing, let's call it a thing. Undefined method two equal for nilcloth, that's different, undefined method two equal for nil. How do we get that? That's different. And that is because expect returns nil, doesn't return anything, right? Of course not. So like we do with all DSLs, we'll just return self. All right, now we get undefined method two equal for object. Once again, this is gonna be great. All right, two equal other thing. All right, no more errors. Okay, so all right, fine. So we probably wanted to actually fail if it's supposed to fail, right? So if we said expect one to equal two, I think at the moment, this is still gonna work, right? Yeah, it prints out a nice dot for you either way. So we can do something like unless, and then oh wait, we don't have that thing. Here's our thing. We gotta keep our thing from that thing. Thing equals other thing. Oh no, no, no, no, that's not what we want. That's not gonna work. We wanna do this at the end. Here we go. And then we wanna say raise, all right? So our regular one still works, but if we change this to two, now it's gonna fail. Oops, oh look at that, unhandled exception. That's a great error message, I love that. We can do something a little bit better. Expected thing two equal other thing. But it didn't, expected one to equal two, but it didn't. Well that's unfortunate. So now if we put it back to one equals one, we get our dot back. See, all right, that's all it takes, right? Now we're done with R. So there's one more thing we need. There is one other thing we need. And that is to be able to implement a before block. We wanna do something like, if we set an instance variable up here, then we wanna be able to access it down here. So we wanna be able to say something like, that we expect var two equal, oops, 42. What's that gonna do? Looks like we're missing another method on object. All right, here we go. Before, what does that before take? It takes a block, and we'll just do block.call like we did before. All right, we have two, two passing tests. And if we change this to 43, we're gonna start failing, right? Great, I expected 43 to be 42. But my secretive universe has went off. So, there's some problems with this code. There's actually some functional problems with this code. Let me be more clear. There are many problems with this code. It actually does not work the way you would expect. And that is because it has some test pollution problems. So, if I put something in here that says it pollutes a test, and I say var equals 15, and then I put the same expect down here that I have up there, that's not gonna work. And that is not gonna work, because I'm only calling this before block once. I'm not calling it before each instance, each it block. I'm calling it once at the beginning. So, at this point, we expected 15 to equal 42, and that's because we changed it to 15 here, and we didn't change it back to 42 before we ran this test. So, we can fix that. It's not a problem. Instead of calling block.call right here inside of the before, we'll just save this block and we'll call it later. So, we'll make another instance variable inside of object, which is gonna be a great thing to do. We'll make an array, and then we'll put our block onto the end of that array and not call it right now. And then, inside of it, we'll just call each of our before blocks. Whoops, call. There we go. Okay. And our test pollution problems are solved. So, let's look at some of the other problems with this code. We fixed all the functional problems with it. And I apologize, the font is so big that it's very difficult to see all of this at once. It's much easier if you can see the whole thing at once. So, the most obvious problem I think of this code is that we're putting a whole bunch of stuff on object. And here's how I see a lot of people fix this type of problem in many Rails apps. I'm gonna take something like this. We'll just take this out of here because we don't want it in object. And we'll put it where this comment is. Okay. And now, inside of object, we'll just include this module. If I can't spell it, I can't, yeah, there we go. All right. Ah, tests are still green. Great. All right, so now, this looks great, right? We've tidied everything up. So, I see that people do this a lot, right? Especially with active record models. Active record model gets too big. Let's just put some stuff in a module and include it into the active record model. And all you've done is hide the mess at that point. It's still messy. It's just messy in different places and you can't see all the mess at once. And so, it's actually even more messy than it used to be. It just looks slightly less messy when you look at the file. So, this is probably not actually what we wanna do. So, instead, we can start trying to find some objects in here and try and move some of this stuff out of being included directly in object and instead make it its own thing. So, if we sort of eyeball this set of methods that we have now included onto object, there's a couple of conceptual things that are trying to get out here. One of them is probably a described block, right? So, let's make a class called describe block. And a describe block takes, what does it take? It takes a thing being described, okay? And so then, I don't know how this works. So, we have a described block that takes, and so what we wanna actually do here is call this block when we create it. So, we can do this and we can move all of these other things in there. Okay, so now, what we've got in this module is one class and a method called describe. And so, what we do in our describe is we make a new describe block object and we call instance eval, which is mysterious. We'll do it anyway. Instance eval block. And so, now what we've done is we've taken everything off object except for the describe method. I've put it all into a describe block object. No implicit proof, okay, this is one thing I always forget. When do I need this stupid ampersand and when do I not need it? I can never remember when I'm supposed to use it when I'm not. So, I think that what this is telling us is that I need that ampersand right there. I don't know why it is that I can't. See, there we go. Okay, tests are still green. Look at that, everything still works. We've moved a whole bunch of stuff around and done some very mysterious things here. If we wanted to, there are ways that we could get the describe method off of object also, but it involves some really serious weirdness that has to do with like eval-ing a file. And yeah, so DSLs are weird. I think it's what you should take away from this. We're not gonna do that refactoring right now. However, we can look inside a describe block and there's still a bunch of stuff in here that doesn't really feel like it fits in a describe block. Like two equal, what is two equal doing is an instance method on a describe block, right? So, one of the other things that we have in here is probably an it block. Let's make a new class for it block. And this will take a description. And so then we can move everything out of describe that's not it and put it up here. And to find method before, we do have one thing. So what this is telling us is that before actually does belong in the describe. That before is attached to a particular describe. It's not attached to a particular example, a particular it. So before actually should be back here in describe. So we have an it block class, a describe block class. Uh-oh. And to find method expect for describe block. Hmm. That's because in our it now, we need to do, instead of just doing block.call, we need to do it block.new, pass it the description and then we'll instance eval the block with the ampersand this time. Aha. Expected, hmm, to equal 42. There's actually nothing there. Expected blank to equal 42. But it didn't. That's interesting. Why doesn't blank equal 42, you guys? And so the reason is in our before blocks, we are evaluating the before block in the context of the describe, but we're evaluating the it block in its own context. So the before needs to happen in the describe block, but be evaluated in the context of the it block. Stay with me here. I know this is weird. So what we need here is we need an it block variable. We need this guy and take that from there. We're gonna put it over here. And then we're gonna say it block that instance eval, whoops, instance no, instance eval, and we're gonna give it our block. And I don't know if I need the parent, I don't know if I need that or not, we'll find out. And then we just do this. So we're evaluating all these things in the context of the example. And everything still works. Look at that. So who's confused about scope here? Who's confused about what's being evaluated where? I am. This is JavaScript or something. What are we doing here? So you can kinda start to see how this is shaking out. And what's happening here is that we have a different set of constraints when we're writing this code than when we're writing our normal application code. And part of that is because we want to provide this really nice external interface to people who are using our spec. We just wanna be able to have them do stuff like this. Describe some stuff, do some stuff, before some stuff. And in order to provide that readable and understandable DSL, which stands for domain-specific language, which is a fancy way of saying you don't have to call this on any particular object, because we do all of that for you. We figure out what object it needs to be called on up here and we call it on the right object. And it is sort of JavaScript-y, right? We're passing around blocks and we're calling stuff in different places, in different contexts. And it's no wonder to me, anyway, that this set of constraints, which is so unusual in the realm of Rails development, leads to a different set of code structures. For example, it block is an awkward name for this thing and I keep wanting to call it example instead, because it's not really an it block. There are other things it could, anyway. So you can see how the naming would evolve over time towards things that don't necessarily match up to the external interface of our spec as we are using it. And this concludes the live coding portion of this talk. Thank you very much. Gonna go back to slides here for a minute. I'm not quite done. Sorry to disappoint you. Where's the other one? There we go. That's what I wanted. Thank you. Unmirror. Keynote, where'd keynote go? As fast as I've ever done that transition. All right. So neither of these ways of writing code are wrong. They're different types of Ruby that evolve out of different constraints, different things we're trying to do. And I was talking about this with Sandy when I was at a conference, probably six or eight months ago. And she told me a really interesting story that she told me, she gave me permission to share. You guys know who Sandy Mets is, right? She wrote this book. It's a pretty awesome book. I recommend reading it if you haven't. And the story she told me, she said that she spoke at ancient city Ruby last year. Did anyone here go to ancient city Ruby? I guess it was down in Florida. And, or I guess it was the year before. Yeah, the year before. And she gave a talk about objury design as she does. And she made an offhand comment during her talk in which she said that she thought people should always use adder readers in their code rather than talking to instance variables directly. Okay, so I'll show you what that means. What that means is that instead of directly accessing the instance variables of a class, oops, instance variables of a class, like you see on the left side where you have at bar equals bar on line three and then on line seven, you're directly accessing that instance variable. Rather than doing that, what she was saying is that you should instead use an adder reader like you see on the right. Left and right, very difficult for me. And what that means is that you initialize it using the instance variable on line five and then after that you access it by sending a message like you do on line nine rather than by accessing it directly. And her reasoning for that was that you want to, is that putting that message send in between you and the data allows you to have that as a seam if you want to change something later. And so she said after her talk, Jim Wyrick came up to talk to her. I don't know if you guys know who Jim Wyrick is, but he was a founding member of the English language Ruby community back in the 90s. And if you've ever typed either of these commands, then you have used his work. He did some really fantastic work. He passed away earlier suddenly this year and it's been very sad, but that ancient city Ruby after Sandy's talk, he came up to her and he said I completely disagree with your advice about Adder readers. Now I thought this was a fascinating situation because here we have two people who are both really, really smart, really, really experienced who fundamentally disagree about the use of a basic Ruby language construct. And when Sandy told me this story, she said I had no idea why Jim would say that because he's a very smart guy. He knows a lot about design. So I figure he must want something different than what I want. So she talked to him about it and what he said was, I use instance variables because adding an Adder reader to the class makes data manipulation public. And when it's public, then I have to support it forever because people will use it. And Sandy told me well, I had never really thought about it that way because I don't write gems. Sandy is an application developer as am I. She builds a lot of Rails apps. And inside of a Rails app, the interfaces of individual classes don't matter as much. However, when you are writing a gem, if you have a public interface, people are gonna use it. And once they use it, if you shut it off, they get very upset. Whereas in a Rails application, your external interface is the markup or the JSON or whatever it is that you're sending out to the world. That's the scene you have to worry about pissing people off at. But when you're writing gem code, that scene is much closer. It's the actual interfaces of the classes that you provide. And the nice thing about writing application code is that the abstractions can move slightly more freely around the code base. And I think of that side of things, of that spectrum as being the sandy side. And I think of the other side as being the gem side. And these are not right and wrong. These are different ways of writing code, excuse me, different constraints that lead to structurally different code styles. And let's see here. Right, so anytime, when you're in the gem side of things, anytime you do something that changes an interface, you have to do a major version upgrade. You have to, if you're doing semantic versioning, you have to change the major version every time you do something that's not backwards compatible. So that means every time you remove a public parameter, you have to go from version three to version four. And people get upset when you do that. So people who write gems have developed a system where they have a very minimal interface with a very rich set of internal abstractions that they can use while providing this very minimal external interface. So these are just two different approaches to programming. And what we're starting to see here is like there is a spectrum of Rubyists and there's a spectrum of projects. People will write different code on different points of the spectrum at different times and what the spectrum is measuring is sort of the surface area of our interface. And it seems like a fairly simple distinction but it does produce a huge difference in code structure. And what it means is that sometimes someone who's good at one side of this spectrum will not automatically be good at the other side right away. These are the personas of Ruby, you might say. They're like, why does this matter? Why do we care, right? And the main reason is that having these endpoints helps us define what else there is. For example, there's a middle here. And that middle is suddenly quite obvious actually. And that's external APIs on Rails apps. Many of us, many of Rails apps now need some kind of programmatic rather interface that is versioned and minimal because once it's out there and it's got users, you're stuck supporting it forever. So defining these personas actually helps us find other places on the spectrum. And the reason that external APIs for Rails apps that people struggle with this sometimes is that it is partially application development and it is partially gem style development and there aren't very many people that are good at both. And just like our psychological personas don't have well-defined edges, these personas don't have well-defined edges either, right? So they shift and blur and merge and sometimes you need more library style development inside of a Rails app because you've got a large team or multiple teams. You need to make explicit seams and make sure things don't pass between them. And sometimes you need more application style development in libraries, particularly if you're writing something that interfaces directly with Rails, something like Devise, for example. In other words, these are not sides or camps where you choose one, sometimes you'll be more often in one than the other, but we all move between them in different situations. And I think that this helps explain, to a certain extent, why it is that there are barriers to entry to people who want to start, who are application developers, professional programmers working in Rails apps and they don't really know how to get started with open source. Because when you are an application developer and I was in this camp for a long time and you're looking over the fence into gem development and you're wondering, how can I get started? How can I start working on open source because everyone tells me GitHub is my resume? Which if it's true, I'm just screwed. And you know, it's really, there's a lot of people for whom they are sitting at this fence and they're looking at the other side and they're like, I have no idea what's going on over there. Seems so simple to us who have been on both sides, but it's really not obvious to people who are coming in. And it's not because they're dumb, it's just because they haven't done that type of development before. And but it can be learned, right? You can move between personas. There was a time when we didn't know how to write any Ruby at all. So you can learn how to write libraries in Ruby's, write library code in Ruby. But you have to know that A, that it's a different skill and B, that you need to be intentional about learning it as intentional as you were when you were learning Rails. And it's important because we need people who can move between the ends of the spectrum. If we stop getting contributors from the application end in our gems and libraries, then our gems and libraries start losing touch with how they're actually being used. And I want to tell a story about my first pull request to close out. When I was just getting started with Ruby, this was probably, gosh, this was probably like 2006. I had a couple of Rails projects going where I had added a feature that I thought was useful to a testing gem, not our spec. So I decided I would send my first pull request. This was actually before there were pull requests on GitHub, pull request in theory, let's say. So I forked the gem, I added my little feature, and I emailed the mailing list with my patch because that's how you did it back then. And I was scared, it was really scary. I didn't know the guy that was running the project. I only knew Rails at that point at a fairly surface level and I had just asked a stranger to judge my code. And this is basically how I felt about it. I went back and looked at the mailing list a couple of times a day just to see if anyone had said anything about it, sort of peeking around the corner to see if anyone was there. And a couple weeks after I sent it in, he just rolled it in with like, thanks. And I was just like, okay, all right, sure. But now, the project was actually on my radar. And I started looking at it, I started looking at the code repo and noticing changes and commits, and I watched over the next couple of weeks after I did this pull request as the maintainer basically rewrote the entire feature throughout all the code that I had written and wrote it his way. And I thought, wow, am I that bad at Ruby? I stuck, that stuck with me for a really long time. And then a years later, after I'd done a bunch of conference talks, I actually met this guy at a bar in a conference party and we were a couple drinks in. So I was like, hey, do you remember? Like years and years and years ago and I emailed you that patch about that thing. And to my surprise, he was like, yeah. Totally remember that. And I was like, yeah, it was pretty shitty code, wasn't it? And he was like, yeah. And I was like, I thought to myself, like, you didn't have to agree that quickly. But then he went on and he said, but it was awesome. It was kind of awesome because I didn't know anyone was using the gem that way. So it was a great idea. So I rolled it in, but it wasn't implemented the way that I would need it to be for the gem. And I was like, yeah. But like, so why'd you bother rolling it in? Like, why didn't you just re-run? He was like, well, you know, I wanted to make you feel good about it. And he was like, and he said the rewriting part was easy. It's getting the ideas from the outside that is hard. And that is why it's important for us to have Rails people on the Ruby core team. And it is important for us to have application developers on the Rails core team. And that's the amazing thing about open source, but the normal product, you know, you can ask users what they like, you can collect their data. If you're lucky, maybe you can watch them use it. Both open source, you don't have to just listen to them. You can actually like recruit them, invite them to dive in and let them give you a fresh perspective on how your stuff is actually being used. And that is my formula for success of the Ruby community moving forward. Victory, if you will. And so if you're an application developer and you've been mystified by this idea of contributing to open source, you should know that we understand and we need you. We need you, we need your ideas. No matter how much experience we have, your input is valuable, not just to your company, not just to you for your career, not just so you can fill in a few little dots in your bingo card, but like to the community at large. And that's all I got. Thank you very much. I wanna say thanks to Sandy for letting me tell that story. We're writing a book together called Practical Rails about applying her object-oriented stuff directly to Rails. So if you're interested, this is our early access program you can sign up for. And that's all I got. Thank you. Thank you, Sarah. That was awesome. Let's hear it again for Sarah.