 The first thing I notice here is that I misspelled Rahm Emanuel, so I apologize for that for all the Americans and the others. How many people actually know who Rahm Emanuel is here? Okay, for those of you who don't know, he's Barack Obama's former White House chief of staff who was infamously kind of crucified for using the term fucking retarded in public. And considering this statement, the last presentation that I gave in public, I got threatened with a lawsuit for defamation by using the term fucking retarded in my presentation. So if anyone's going to be offended by me cussing like a sailor up here or some of the things that you may see on these slides may project images that could be considered offensive, you may want to go to another talk. I will give you permission to leave now and I will not harass you. Okay, so we're good. When I first submitted a proposal for this talk, I wanted it to be kind of like a rant on open source in the Ruby community. Things change over time and I think I've rewritten this talk three times now. So what I want to discuss today is pretty much open source in the Ruby world and from two sides of the story as a author or a maintainer of an open source project, what you should and what you should not be doing to make our lives in the Ruby community easier and also from a contributor and a user standpoint things that you should be doing with respect to open source to make the world a better place. So let's start off with a little bit of a statistic there. That's 160 million, I believe Ruby gems is like 162 million now, but it's over 160 million downloads of gems from rubygems.org. That's 22,000 versions of gems cut and over 1500 total gems, that's a fuck ton. The Ruby open source community is ridiculous in the amount of projects that they push out and it's exponentially growing and because of this growth is I want to try and like get everyone on a common ground here and hopefully set some standards. I'm going to throw some opinions out there. I'm a highly opinionated person and we can agree or we can disagree and at least we're going to have a fun time with this. Let's first start as a maintainer of an open source project. I've got expectations when I want to contribute to your open source project and as an author of an open source project of certain basic things that need to be happening in order to make people's lives easier to contribute to the project. So there's some things that I consider understood which not all projects do, but all projects should do. First of all you should be using Git and this is like a thank you captain obvious moment. If you're not using Git, I know Mercurial is kind of a play toy but you should be using Git and you should be posting your project on GitHub. I know there's Bitbucket, there is unfuddle, there's various other sites, but GitHub has pretty much taken over the community, the social coding aspect of GitHub has made contributions to open source just incredible. They've revolutionized the industry and everyone I think needs to embrace it and I know this is kind of like sucking on the mother teeth of GitHub right now, but just do it. RVM, I've gotten a lot of complaints over the last year about RVM, it's not that hard to use, you should be using RVM in your project, you should be committing your RVM RC. Some people will tell you not to do this, I'm telling you to do this. The last thing that I ever want when forking and cloning your repo is to switch into the directory and having my global gem set polluted with dependencies for a specific gem. So definitely use RVM and commit your RVM RC, you should be using Bundler at this point. It's pretty much bug free now, there's a few issues here and there, but what I want to do when I want to contribute to your project is I want to clone the repo, I want to change into that directory, I want to do gem install Bundler, I want to do a bundle install and then I want to run rake and I want it to all work fine and there's really no excuse for that not to work. If there's specific dependencies of your open source library to databases or other frameworks that should be documented in an obvious fashion in order to ease people's setup of your project. Continuous integration for open source, don't do it. Simply put, given this statement, there's no real point when it comes to CI for your open source project to ever have to do it. You have a small amount of contributors to your repository, people who have commit access, they should be trusted, they should know exactly what their Git workflow should be, they know, you know, you run your tests, everything passes, you're going to do a Git commit, everything's kosher, you're going to do a Git pull rebase for any other changes that someone else may have committed and then you're going to run your tests again and they're all going to pass and you're going to push. It's pretty simple, there's really no need for CI whatsoever and I don't know why open source projects do it and I kind of want that to stop. When I call documentation imperialism. Documentation is a thing that seems to be lacking in the open source community right now. I think there's a very small number of open source frameworks in the Ruby community that really do a good job of documentation. Rails is one of them, DataMapper is one of them, Plug, Mongo is one of them. What I'd like to say is for documentation imperialism is you should shoot for as many lines of documentation that America has troops overseas, that's a lot. But documentation can come in several different forms. The first thing that you can do as an author for documentation is a well-written readme and especially if you're using GitHub, that readme is showing up on your project homepage and this is the best first point of entry to your project on letting people know how to use it. You can use GitHub Wiki for your documentation, let people contribute to it, that's a really easy way as well. Examples, a lot of people like to go to the root of examples in their projects as long as you make it quite obvious that your documentation is an examples directory, code speaks very loud. That's another form of documentation, API doc, this is a small pet peeve of mine for people who write libraries who don't provide API documentation. It's not that difficult, you know, you're probably in the mode of test, implement your methods there, everything's good, write the documentation to that method right at that point. It is lazy for someone not to provide API documentation on any public method in an open source project. People rely on these things to understand what's going on in your framework. Well written test suite, I can't emphasize enough how important testing is in frameworks and I'm going to cover testing in detail here but testing is also documentation and well written test suite is essential to allowing users of your framework to know what's going on and how to use it. For larger frameworks, probably a website for documentation is needed, you know, like I mentioned Rails and DataMapper before, they have very good websites telling you exactly how to use the framework, code examples are really good and any extra resource that you can provide to your users in order for them to use your framework easier is always a good thing. And the last thing on the documentation front which I think is probably the most important thing that you can do as far as documentation goes is mailing list and why I think mailing lists are important is that mailing lists provide context. If I'm searching for a specific issue on whatever framework I'm using, whatever library I'm using and I go to Google and I search for a specific issue and I can get a mailing list thread then not only do I have documentation on how to solve my problem, I've got context around this and I've got context around the decisions that were made around the implementation of that feature, I've got decisions that were made around why maybe something was not implemented and the conversations that happen on mailing lists are far more important than any static documentation can give you. So if you are writing an open source project, I recommend highly that you have a mailing list. More on the testing front. We've gotten into a big thing lately over the past year or two years of the concept of outside in testing and this happens at the application level and usually with cucumber and for application code, this is a great tool. We've got whatever the language you speak, human readable tests that the business can understand that are easy for potentially testers to write but at the same time for library code, this is kind of a waste of our time and I know there are a lot of big cucumber fans out there but I want to tell everyone please do not use cucumber for testing library code. As a developer, I am your user of library code. I don't want to look through cucumber scenarios and then have to go to your step definitions in order to find out the exact code that I need to write in order to use your library. It's an extra step for me that is unnecessary. It's a layer of abstraction in a test suite that should never, ever have to happen for a user who is a developer and if you are one of those crazy psycho developers who loves to go nuts with your regex, my grep becomes useless when trying to find what your feature is actually testing. I'm going to say there's one exception to this rule and that is RSpec and how many people here have looked at the RSpec features. So we can maybe say that David Sholensky is walking the fine line between genius and insanity with those things but if you look at the RSpec features and I'm not showing any code up here for the main reason because usually my talks are code heavy and image heavy and have audio and I'm going bare bones today. If you go to the RSpec features, he's actually testing that a file gets generated with specific code in it in order for you to see the API and if you look at relishapp.com where all the RSpec documentation is, he's using the features as the documentation and to me that's acceptable but it's really excessive on the testing front from a maintainer's point of view in order to do that so anyways. On the topic of outside in testing continuing, we've all drank Jager at some point and I want to introduce a testing technique that I've used for over a year now on library code which I called the Jager Meister technique and we all know that Jager comes in and then Jager eventually comes out. So we're going to call this an inside out testing technique. So what goes in and it works and then eventually the crap exits because your body rejects it. So this is what I want to talk about as far as outside in to inside out testing is that when you're doing outside in testing and we're going to say you should be using RSpec here and nothing else, I don't think there's any compelling reason to use any other test framework for library code other than RSpec. You've written your functional tests in RSpec and you've executed everything from a user standpoint entry points to your API but what outside in testing doesn't give you is control over the implementation of your code. So you can have working code and it can be a shit design. You can go crazy going outside in and what I like to do is you do outside in to make sure your framework works from a user facing standpoint and then you come back and you unit test using mocks inside out and for any of you who are mock heavy testing people, you know that if you've got a poor class design, poor OO design and you're mocking, it is excruciating to mock. So the idea behind this is that you would write your functional tests first, get everything to work and come back around and use your unit tests to flush out the actual OO design of your classes. Another good side to this is that once you've got all your mocks in place and everything is tested and passing for someone to come in to your framework and contribute some code that could be, you know, shady, dodgy. It's going to be a nightmare for them to implement. So you've got control over your design at a level beyond anything else by mocking and doing functional testing. Like Jägermeister, this approach is painful. You feel like and you are doubling your test coverage. For instance, if any of you are familiar with Mongoette and you've looked at the test suite, there's something like 5,000 specs in that test suite. It could be halved if you did just one or the other, but there's a reason for it in that you want to make sure that you can maintain good design and allow contributors to adhere to that design at the same time without, you know, supplying crazy, 100 line method code. We like to talk about code quality versus time to market in kind of all aspects of software. I think I'm being pretty blunt with this slide on what I think about code quality versus time to market and open source. Time to market and open source should not matter whatsoever. It's not a competition. There's no business driving this behind it. You don't have to worry about losing competitive advantages. There's no money involved here. You shouldn't have to feel the pressure to push something to market faster and sacrifice code quality for it as far as open source goes. The Ruby community when it comes to open source is constantly looking for better frameworks, better ways to do things. Always searching for gems. If you write a better gem a year later than someone else did a year before, it will be used. There's no reason to feel forced to push something out earlier. The gem that gets released first does not become the de facto, and if you can't contribute to it, that's not really a big deal. I mean, obviously first you should try to contribute before writing your own, but there's no reason to feel any pressure, and people are going to constantly pressure you into releasing something as quickly as possible, but it's definitely not necessary. That's pretty much all about that. So with accepting patches into open source, you should provide a single way to contribute to your project in just one way, and that should become the standard of contributing to your project. Rails has a thing of doing patches on Lighthouse. I don't necessarily like it, but at least it's one particular way of doing things. I would say if you're embracing GitHub, you go with pull request, for pull request, accept the pull request in. Pull requests are nice on GitHub because they create their own issues, so you've got a code and you've got an issue associated with it, and you've got the project management aspect of it in GitHub. You can have discussions around them, which is great. Everyone can submit a pull request, and anyone who's looking at the project can have a conversation around that pull request. They can say what they like about it, they can say what they don't like about it. You've got more context, and this also leads back into more documentation, because on GitHub, your pull requests, your issues are there forever, and people can search for it. The other nice thing about doing a pull request system on GitHub is that as a maintainer of a project, your commits are parsed by GitHub, and I don't have to go back to the web UI and say, oh, I closed this issue because of such and such. My commit message is automatically put into the pull request and closes the issue, and we're done. Find a dandy. From a user standpoint, and this is something I think a lot of people don't necessarily think about, when you're including a gem in your application, it is part of your application. Any bug, any performance issue in that gem is a bug and a performance issue in your application. It is an extension of your app. As we are open source, the first thing I advise anyone to do on any open source project before you use it is go look at the source code. This is key. If you're going to look at the source code for a framework that you're going to use, and, well, it's shit code, ask yourself, do you want shit code in your application? Because essentially by including that gem, you're putting shit code in your application. I think a lot of people take, oh, this gem is used for this all the time, and it's very popular, and we'll just use it and not think about it. That's wrong. You should definitely look at the source code of your applications. That's what open source is for. A prime example of this is, I'm a heavy Rails user, but when it comes to relational databases on Rails frameworks, I use Datamapper, and I don't use ActiveRecord, and that's because Datamapper's code, source code, is far better factored than ActiveRecord says, and I trust it. I see too many shady things in ActiveRecord that I don't trust it. Another thing to look for when you're going to use a gem is, besides looking at the source code, make sure it's got tests. Why would you ever use a gem in your application that wasn't tested itself when you yourself, all of us are testing people, right, we're all Ruby guys, we love testing. So just make sure that the gem has tests, and make sure the code is good. Another thing from a user's perspective, and a maintainer's perspective, sometimes you run into an issue with an open source project, and you've gone through the code base and you don't know the best way to fix something. Maybe it's not quite apparent to you, you're new to the project. The absolute best thing you can do, and this is like a ponies and rainbows situation for an open source author, is if you provide a pull request with a failing test. It's almost like I come in my pants when I see this. Pull request, failing test, yes, I pull it in immediately. If you can't navigate the framework or the test suite that well to provide the failing test, the next best thing you can do is, you know, gist. Give some sort of reproducible steps that the maintainer of the project can, you know, start a new Rails project, new Sinatra project, and easily recreate it, and then they can write their own failing test for it. Failing issues for projects without anything is just kind of unacceptable, and it's a waste of people's time. Sometimes people will say, oh, this just doesn't work. Okay. A little bit of context would be good here. Does please provide at least something, but failing test first will bring joy to all of your OSS maintainers' hearts. Twitter. Twitter has kind of gotten out of hand, in my opinion, and by far is it not first line tech support. If you're a maintainer of a gem or an author of a gem, you should document all the channels that people need to go through in order to maintain support for your gem. This can be mailing lists first. This can be GitHub issues. This could be Pivotal Tracker, you know, some other sort of tracking tool, but Twitter is definitely not it, and I think most of us follow hundreds of people and have hundreds or maybe thousands, maybe tens of thousands, I don't know, and Nicholas has got like a million followers. The tweets are going to get lost. We can't keep up with them, so if you're going to tweet for tech support, expect it not to be answered. It's just not the way to do it. Further on the Twitter front. And this is actually my biggest pet peeve with open source, sorry. I know it creates an image that, you know, all eight arms. It's got to fucking hurt. At least maybe once a day, twice a day, maybe once a week, depending on the gem, depending on the framework. I see tweets coming out that go something like blah, blah, blah. I'm not going to use this technology because this insert my gem name here sucks. That's just absolute shit. It's unacceptable for people to do non-constructive criticism like that in the open source community, and doing it over Twitter makes it even worse, and it just pisses people off, it pisses me off. And I want to say, like, people work really hard in their free time to write open source software for you, and to do something like this just degrades the whole thing. The least you can show is a little bit of respect for people who are working on these things in your free time and provide constructive criticism. So instead of my your library sucks tweet, I propose this. I disagree with your API because dot, dot, dot. Or there is an issue with this. And here's a gist to show you an example to potentially fix it. On this case, as a maintainer, I would say if you get tweets of this nature, it's okay to call an asshole an asshole when they're being an asshole. By all means, if you want to call them out on Twitter and say get fisted by the octokat, by all means do so, I will applaud you for that. The other thing, even though I'm kind of ruthless here and saying that is what I usually do, is kill them with kindness. And for most tweets that I've gotten over the past year or two on this front, I usually respond back saying, I'm so sorry that the framework did not do what you expected it to do. Could you provide me with a gist if you have the time and I will get to that issue as soon as possible and hopefully you will be able to use it again. And usually that works far better than telling them to get fisted because people feel bad at that point and then they provide you with a gist and then they become users at the end. But I'm not saying that you can't tell them to be fisted. And wow, I went through that fast. Okay, so that's my story and I'm sticking to it. Yes. Does anyone have any questions? I went 15 minutes too fast. That's if you pull it in, a pull request with just a failing test. That's if you pull it in through the GitHub UI. So that's fine for your fork to have a failing test on it. In my opinion, that's fine. Use the topic branch and you've got a failing test on your fork. No worries. Your suite may be failing, but mine's still passing. Mine's the one that matters, right? Okay. I can't really think of an example where time to market matters. I mean the first one, the first one's going to be the early adopter. But over time, the better one is always or whatever other options you have, they're going to eventually take over. And I see this with Ruby more than any other language that I've worked in in the community is that it seems like every day Rubyists are, I want to know what the next hot thing is. I want to know what new gem was released. I want to use it immediately. Is it better than what I'm already using? And I think that's like a daily thing for people. We're constantly looking at the blogs. We're constantly looking at our GitHub streams. And if something better comes out a year later after we've been using something else, it's going to be adopted. I don't necessarily think, I mean, if you want early adoption, then time to market maybe matters. But eventually, if it's not a superior framework, it's going to be, you know, it's going to be faded out. Closing deal. I mean, so there's a business aspect tied to it, yeah, then that's a different story. What I'm referring to is like pure open source, no business tied to it whatsoever. Yeah. Let's get away from this slide. I was told live coding is like dangerous. Okay. So you've just seen that I've gone into the directory and I've got my, oh, sorry. Can we see this? Okay. Yeah. So it's a basic RVMRC. We say whenever I enter the directory, if that gem set's not already created, just automatically create it. And then in this case, I'm using Ruby 192 and the gem set name is Mongoid. Check that in. If someone doesn't have 192 installed, they will tell them and it's, you know, RVM install 192. What I don't like is like having my global gem set polluted with like all sorts of crap. There should be like only two or three gems in my global gem set. So if I want to start deleting projects out of my directory, I don't want like an excessive amount of gems like sitting in my global gem set for things to have to be scanned through. We've got cash, we've got specifications, then we've got all the gems sitting in three different directories. That's not very optimal the way that gems work, but I like things to be fast. I've gotten numerous amounts of emails over the past two years of people telling me to not check in my RVMRC. They're worried about, usually, I think they're not using RVM properly. And for a while, I was like, okay, I'm going to be the nice guy and be like, I won't check in my RVMRC and then I got tired of like going to new machines and then having to create a new RVMRC every time. So I just, I started checking it in and I said, fuck it. Yes. In my perfect world, we're all using Bundler and you're pointing directly at the master branch and telling it what commit you want or pointing at a tag. The one thing that I am guilty of is horrible versioning. And I love to change public APIs and patch releases and, you know, so I don't think you should be listening to me on this subject. But in the ideal world, you know, I don't know, there's, we're all using stuff that's not even 1.0 in production apps. So what does 1.0 mean anymore? What does any version number mean to us anymore? I think it's most of the time in our production apps that we use at my current employer, we point at the repos themselves. And if we do a bundle update and something breaks from one of the repos, then we point a specific commit on that repo. But we want the latest and greatest of everything all the time. It doesn't seem like the version numbers in Ruby open source in particular really mean that much. Maybe with the exception of Rails, they're pretty strict on the way that they version things, but every other project is, it seems like a free-for-all. I could be using something in production for two years that's at 0.5. But it works fine. That I'm not really sure about. I think that given, given the way that we treat open source now, especially with respect to GitHub, I think versions are going to fade out. I think they're going to be a thing of the past. And I think maybe tagging, tagging a branch or a specific point in time in your code base will become the new thing. And you may tag it with a name, something instead of a number, something that's more usable to people. Like, oh, what's 1.36 do for me? That doesn't do much. But oh, we just added so-and-so feature here is much more meaningful to me as a developer. So I mean, maybe I'd like to see pointing at specific tags instead of releasing versions at all. I'd miss that one. So he said everyone is using test unit and too complex. Oh, wow. So do we want to tweet this one here? So DHH is a douchebag for saying that. Tweets. Get your phones out. I don't understand at this point in time why anyone, I mean, I understand why Rails, I think I understand why Rails is still using test unit because you've got a massive framework, this framework that's been there before RSpec existed. And the entire migration of test unit to RSpec on the Rails code base would be a fucking nightmare. But I mean, let's leave by example. Okay. Can I shrink this a little bit? Can we still read it? Is that readable? Can you write something like this as readable as this in test unit and have the output of it instead of bullshit dots running across your screen actually be readable output? In order to do this in test unit, I've got to write 100 character method names. I don't, it's just the organization of it is so much better when you throw in filtering and focus from RSpec. It's such a more powerful framework, for example, and we're sitting on Mongoide right now for things like this. I can do in my setup, if you've got a certain number of databases set up on your local machine, and if they are set up or they're not set up, I'm going to give you warning messages on what you need to do to set them up or not, but I'm not going to fail your test suite because of it. I'm just going to filter them out. So I can do a filter run excluding in RSpec, and then I can say, oh, well, if any of these things are not configured, we're just going to skip them. And then when I go to my tests, you can see here, I do a config slaves on that one that says, oh, well, if the slaves aren't configured, I'm just going to skip this and print that message out. It comes back to the contributing factor in making people's lives painless. Someone who wants to contribute a feature to your open source project that may have nothing to do with slave databases, in my case here, doesn't need to have slave databases running. So we just filter it out if they're not running. That would be, but if I'm hoping in the context of it that if someone's contributing and they know that they're going to affect a slave database right in this fact that they should be running them. I don't think it's that much magic. I mean, for example, and I'll show you this and how we make it a current. So the first thing you're going to get here is because I don't have databases running slave, oh, let's see live coding. There we go, okay. So you can see the because the slave databases are running, the first thing I do is print out a warning message telling you exactly what to do. And that kind of covers my filtering aspect there. I mean, if you don't do something like that, then it can be kind of confusing if you broke anything, but I would say a good pattern is if you're filtering something out and something doesn't adhere to that filter, then you need to be doing something like this. Okay, so we're trying to get an internet connection. Fun. Any other questions? Well, I'm of the opinion that CI, it's not just open source. Open source generally, your core contribution team is not that many people, usually five, six people, maybe 10 tops depending on how big your project is. And I think on any development team, that small CI is actually unnecessary. The only time I've actually found CI necessary was when you have humongous development teams, which shouldn't be happening in any of the Ruby community. This is kind of like a Java.net thing where you've got guys in India, you've got guys in the States, guys in Europe. Usually, you're all disciplined enough to know that you're not going to commit anything that breaks anything. And I feel like CI is more of a finger pointing app than actually providing any real value. This is also CI in its current incarnation and that it's not really continuous integration. It's continuous build, continuous run the specs. It's not integrating with anything. True CI, I think, is worthwhile. We've built something and we've deployed it somewhere in order for our users to continue to use it and be on the most recent versions of the software. But I think most people use CI as a build tool and in Ruby it's not building anything, it's just running specs. So I don't really see it deployment. All right.