 That belongs to me. That belongs in a museum. Thank you very much, especially to Sean and Caleb. Pungy Spike Guide number two. You don't want to know what happened to Pungy Spike Guide number one. So thank you very much for coming. We want to start out asking the question, why does Sprockets need saving? So for those of you who haven't been around since May of 2011, it is the premier feature of Rails 3.1. And Sprockets is the asset pipeline. Sprockets actually came first before it was ever kind of wrapped up in Rails. So, whew, sorry, I got to catch my breath. That adventuring, it's like, man, you want the perils I had to go through? So a little bit about me. People call me shneems. And by people I mean me. I kind of made that my own name. It sounds a lot like schnapps. And as of today, I am not only a pretend hero, I am also a Ruby hero. Thank you. Thank you very much. What? Oh, air quotes, hero. There we go. I work for Heroku. And I do, before we want to get too carried away, I do want to say all likenesses to Disney-owned property, 100% coincidental. And it's parody, a.k.a. Don't sue me, or if you are a lawyer in the audience, ignore what I said previously. You can call me by my real name, which is DHH. Send all complaints to professional race car driver care of DHHs. So also another thing I wanted to mention before we get too carried away is that you don't need to look like Indiana Jones in order to maintain open source. It just so happens that he is my sprockets spirit animal. Hey, it's OK. So from 2011 to 2016, sprockets has had 51 million downloads. And I'd like to put that in perspective. Rails has had 65 million downloads. So sprockets is pretty close. And of that entire library, one developer is responsible for 2027 commits, which happens to be about 68% of sprockets. That's one person. Compare in contrast to another Ruby hero, Rafael Franca, has 5,000 commits on Rails, which accounts for about 0.9% of Rails. Yeah, so 51 million downloads, one developer. And just one day, Josh is like, I'm cutting it. I'm out. I'm gone. So when something like this happens, what should we do? Should we, as a community, turn around? Should we abandon sprockets? There's a lot of people who said, I don't like sprockets. It's got problems. So that might say, well, hey, what are the problems? Do you know what they are? Because we can't fix what we can't define. And if we want to attempt a rewrite, then a rewrite would assume that we know better. We still have the same need to do things with assets. So we don't really know better. So yeah, I think we should stick with it. Assets are really the easy part of sprockets. There's a whole bunch of edge cases. Also, sprockets has a really well-defined and established API. So a quick show of hands. How many of you maintain code? How many of you have written code or seen code? Use any kind of code? OK, good, good. Now, how many of you want to maintain it forever? I'm glad that the number one contributor to Rails still is raising his hand. That's a good sign. That's a good sign. So I'm sorry, but losing maintainers is inevitable. And it's not always expected in this case. For those of you who don't know, this is Jim Wyrick. Jim Wyrick was the creator of a amazing library that we've all used called Rake. And in 2014, Jim passed away very suddenly. It wasn't like anybody saw this coming. He wasn't working with someone to pass on the software to for a long period of time. It was just, wow, it hit like a ton of bricks. And so whether somebody just walks away or they pass away, it hurts losing a maintainer. And we, as consumers of that, have to cope with it. And there's a lot of different ways that we do that. We might go through a period of denial and say something like, hey, they're gonna come back. We are gonna get this person back into our lives. You might be angry and say, hey, leaving is selfish. Or that was such a jerk thing to do. You might also say, hey, there's tons of seats over on this side of the room. And you can totally go over there and sit down. I call that bargaining. So you might say something along the lines of maybe if we hire them, they'll work on it full time and we can get them to come back. And eventually, acceptance, hey, okay, they're not gonna come and who's gonna take this over? So the number one rule, my number one rule, because I'm on stage, I gotta make the rules, is that a maintainer does not owe you anything and not even an explanation. So if you're gonna leave a project or someone is leaving a project, it's a very personal decision. I actually reached out to Josh and said, hey man, let's talk about this. I'm giving a talk at RailsConf. I need some content, gotta help me out. And Josh didn't wanna talk about it. And I wanna respect that wish and I also wanna respect what he's done, which brings me onto the number two rule, which is that you do owe a maintainer respect. Some people will say things like, oh, but I really hate this thing. It is possible to critique a software without demonizing the creator. And as a matter of fact, I'm gonna critique the crap out of sprockets. And notice one word choice was intentional here is that I'm critiquing and I'm not criticizing. I aim to be productive with the words that I'm using. I want to find what is bad and then make it better. Originally, when sprockets kinda sort of fell into my lap and somebody said, hey, do you wanna be on sprockets core? I was like, sprockets. Why did that have to be sprockets? But you know what, you are not your khakis and you are not your software. You are also not your khakis. And Josh gave years of his life to this, no matter what you think of the project or you think of how it was maintained, as well as hundreds of issues closed. So please, I wanna give a thank you to Josh. All right, so I'm gonna need a lot less audience participation because I still have like 300 more slides to go through, which bring me to rule number three. Words without actions are empty. So I want you to be actionable and think about this. For example, we have a hacker news comment which says, unless they add blah, blah, blah, blah, I see this as ugly and barely usable to a Node.js release. You know, that's not really helpful. And when I read that, I'm like, boo, boo, boo, like that's not gonna make me wanna go out and help them. Instead, they easily could have said, hey, this is great, this is amazing, I love it. It looks like they don't have this thing I need. And as a matter of fact, because they don't have it, I can't use it because of this and that's actionable feedback. You can critique without criticizing. So I want you to ask yourself, is this comment adding anything? Hyperbole is like funny for like fake internet points, but it doesn't help. I want you to be honest with your critiques. I want you to be productive. Here is the Babel.js creator tweeted out the screenshot, again, coincidentally from hacker news. And it reads, Babel sucks. I never thought I could hate something so strongly. Like, wow, that's really gonna encourage that guy to go out and fix all of your problems. You might disagree and you might have very strong opinions and those opinions might be very negative, but this software is in your life for a reason. And if you can figure out why those things, why you're having those opinions and those feelings, then it helps. Complaining by itself accomplishes nothing. So originally, I wanted to talk about how do we keep a maintainer longer? Or really, how do we wanna stay as a maintainer? If you are maintaining a product, how do you stay longer? But before that, I wanna talk about what do maintainers want? And do we really even want them to stay? Do we want them to stick around? We can either have a maintainer that just like mic drops and you like never see him again, or we can have somebody who's like passing the torch and graceful handoff. And while I'm working on sprockets, there's so many times that I'm just like, this is absolutely batshit insane. Like, this makes no sense. I'm gonna rip this all out. I'm gonna completely redo all of this and then six hours later, I'm like, wow, that was genius. And it's just, I didn't have that context. So maintainers are really historians and these maintainers, they help bring context. We try to focus on good commit messages and good pull requests. Change log entries, please, keep a change log. But none of that compares to having someone who's actually there. A story is worth 1,000 commit messages. For example, you can't exactly ask a commit message a question like, hey, did you consider trying to, and the commit message is like, I'm a commit message? Like, it's like, it doesn't store the context about the conversations around that. So maintainers are historians and we can keep those maintainers longer by giving them what do they want. Maintainers want respect, they also want help. And I know all of you are thinking, oh, this is the part where he's gonna be like, asking me to help and I really don't wanna do that. Or maybe you already are helping. Maybe you're saying like, I don't have enough time or like, ah, just fix all of the things for me. But I'm here to say that if you have five minutes to snap the face to force to gram, I had to practice that a lot. Then you have five minutes to help. You can contribute to docs. You can read the guides. You can fix typos. Maybe you found a really surprising behavior. Well, was that behavior documented? Then go ahead and add it to the guide. If you have five minutes to help, then you can submit a bug report. Like seriously, the maintainers have no clue that things are broken. You might be like, oh, there's thousands of people using Rails and all of them have reported this thing. No, like the question of like, why is Sprocket's bad? I don't know. Nobody actually gives me actionable bug reports. So if you have five minutes to help, then please let us know what your problems are in a productive way. Critique over criticism. Another thing you can do to help is sign up for a service that I wrote and maintain called Codetriage. You can go there at codetriage.com. And it will send you an issue in your inbox once a day. It's a very actionable way to get started. You can ask common questions like, oh, what version were you running on? Was this working previously? And so ask yourself the question, would you rather another maintainer spent the time either fixing bugs, or would you rather they spent the time asking for like insanely small minutiae on like GitHub issues? So if you give a minute, it might seem really small, but you were actually saving a minute of a maintainer's time. So a little bit of help can go a long way. And if you don't, then who will? It also has the benefit of exposing you to different parts of projects, which helps you grow as a developer. That's pretty good. If you have 10 minutes to help, include an example app to reproduce a problem. Example apps are amazing. I get all these bug reports that are like, well, first I run Rails new, and then I'm like, I try it, and then I'm like, couldn't reproduce. And then they're like, oh yeah, I forgot to add this other thing. And then I try it and couldn't reproduce. And then they're like, oh yeah, and can you try this other thing? And I try it and reproduce. And I waste hours of my life, you waste hours of your life, nobody's happy. Instead you can ask and say, well you can say, here's an application that is going to reproduce my problem. Like I just went Rails new and here's an exact micro example of the thing that I'm experiencing. Put it on github.com, slash your name, your username, slash example app if you don't have that yet. You can even choose example app one or example app two. I'm not picky. So if you give a minute, then you're gonna save a minute. And I personally challenge you if you haven't already and you're not involved with an open source project, please try and make one example app this year. It is so helpful. If you have 30 minutes to help, you can try fixing a bug, anybody's bug or your bug. It's not as hard as it sounds, just time box it. Even if you don't fix it, then you're guaranteed to learn something. You're guaranteed to learn some other people's code. You're gonna be navigating and debugging other people's code, which happen to be highly marketable skills, coincidentally. And with all of this, I know you're like, okay, I don't wanna do that every time. And that brings me back to club soda. So I drink club soda at home and I don't like putting the whole thing in my refrigerator. So instead what I do is I put three or four in to get cold and then I pull one out and then I put one back in. And sometimes I run out of club soda. I'm like, how did this happen? Is somebody stealing my club soda? Is my dog drinking my club soda? You know, I'm one out, one in, pretty simple. And so what I found is that if I put two in every single time that I want to, that I actually remember, oh, I should put a club soda back in the refrigerator, I always have club soda. You got it? It all makes sense. So what I'm saying is you don't always have to contribute, you don't always have to make an example app, but just every once in a while, you have to, or please go the extra mile. So these are all different ways that we can help a maintainer, that we can make their job a little bit easier. Well, how do we transition from one maintainer to another maintainer? Like, that's a question that happened. Well, what is a maintainer? We talked about this. A maintainer is somebody who knows the stories. A maintainer is someone who's gonna take five minutes out of their day. They are going to take 10 minutes out of their day, 30 minutes out of their day. A maintainer is somebody who helps. And by the act of helping, we are preserving history. So maybe you see where I'm going with this. The act of helping is the answer to keeping a maintainer. Also the act of helping is also the key to creating maintainers. So whenever you actually go through that handoff process, people aren't just starting from zero. They have people who are involved with the project. So then the next question we have is, how can we foster a culture for helping? How can we get more people to help? If you are a maintainer, you want people in your project. Like if you're using that project, you want more people helping and contributing because that makes it better. So how do we foster that culture for helping? We talked about what the maintainers want, but we never really talked about what the helpers want. Well, helpers want documentation. They want sane code. They want what regular users want. Good user experience, non-magical code, backwards compatibility, good deprecation, reliable test. These are all things that are interesting to them. So let's look at one and compare it on the sprockets chart. So documentation. Sprockets has 73% documented methods. 73% of all methods are documented. That's a lot. I don't know, that's like really high. That's like really up there. On a side note, I think that method documents are kind of like unit tests. They are very focused on one part and don't necessarily tell the whole story. So it is possible for those comments to get a little bit out of sync with reality. Yes, we've all seen code comments like this. So I also highly recommend keeping a read me. And a read me, I see as something more like an integration test. It's gonna tell a little bit more of the whole story. And if we look at sprockets, well, sprockets has about 2,500 words. That's a pretty long blog post. That's a pretty substantial read me. That's a pretty long story. So I'm here, I'm telling you that helpers love docs and I'm telling you that sprockets has docs. Why doesn't sprockets have anybody helping? So I put on my design research hat. I went to design research school and I learned about user stories. So we are gonna actually consider the people using our product. I want to introduce you to Pedro. This is Pedro. Pedro enjoys long walks on the beach, favorite food is bagel bites, and is building the next Uber for goldfish. Pedro is a Rails user. And Pedro cares about the Rails interface. This is gonna be, hey, how do I get one file to require another one? I wanna know what I actually have to type in my project to get it to work. Now, I don't care about all that other stuff. I just want the things I need now. So that was Pedro. We also have Pat. Pat is addicted to ES6. I know, it's tragic. Pat loves to fly fish and Pat is a plugin developer for sprockets. By the way, did you know that sprockets has plugins? Okay, well they're not called plugins. They're called processors and transformers and compressors and like 20 other things. But it does have a plugin system. And Pat cares about the processor interface. They maintain one. It looks a little bit something like this. And they wanna know that whenever we pass that hash of things to them, what is gonna be in it? And what can I do with it? What should I do with it? Pat wants this documented when Pat is working on their plugin. Conversely, Diana has a dog named Exception and hates mustard. Both of these are highly relevant to Diana's job as a Rails developer. I.e., somebody actually developing Rails. Somebody actually building Asset Pipeline or another Asset Pipeline. Diana cares about the low level interface. What does that mean? Diana cares about what are the classes I can use? What are the methods on those classes? Like all of them. I wanna be able to disable Gzip. Oh, here you go. So these are all different people with very different needs who need different documentation. Don't make them hunt down the documentation that they need. One of the things that I did when I first started Sprockets is I said, I basically kind of know nothing about the behavior. Somebody be like, is this expected? And I'm like, I don't know. You tell me, was it happening before? And through doing that research, I put together some guides. And I said, yes, this is expected behavior, but the only way I could make that fluid and make those guides make sense is if I split them out. And so we now have guides. We have a guide for building an Asset Processing Framework. So if you're building the next Rails Asset Pipeline or end user asset generation, if you are a Rails user, or extending Sprockets, if you wanna make one of those plugins. It's all right there. It's kind of right at your fingertips. And you only look at the documentation that you need when you need it. So we made it easier for developers to find what they need. Also, I mean, I was super useful for me as well. One thing I love about this is that it lives in the source and not in a wiki, because documentation is really only valid from one point in time. Like, otherwise you end up in the wiki. It's like, if you're using this version, do this. If you're using this version, do this. And it's like 20 versions and you're, it's no good. So helpers love contributing to docs. So you know what? We can make more docs. We can make our docs better. Those docs are gonna be the gateway drug to code contribution. So the next thing I wanna talk about is, is same code in real talk. Sprockets was designed to solve problems. And sometimes when it's putting out a fire, it kind of feels like it's maybe making additional problems that you didn't see before. And you don't know why it fails. And the reason you don't know why is because Sprockets isn't talking to you. Well, you know, how does code talk? So code can speak to you through errors. And I'm not talking about like, oh, something broke. No method error on nil. I'm talking about, here we have no route matches. I want my error to say this broke. I want my error to say ID key is missing. This is the thing you were missing. Hey, look here. This is the thing you should care about. Good errors are instructive. And Sprockets will have better errors. It doesn't yet. I do care about this. I am the owner of a gem called, wait for it. Sprockets better errors. That was merged into Sprockets Rails. But yes, I have some good ideas for better errors in Sprockets itself. The other way that we can speak is through deprecation. Now, deprecating something in a code comment is not enough. Right now, Sprockets is doing this. They have a little code comment and they're like, by the way, this method is now deprecated. We will just delete it and it won't be available and you never knew that because, A, no one is casually reading the method documentation. I mean, B, if they were, like who has the time? It's like every single time you upgrade every version of Sprockets, like are you gonna do that? No, and you cannot just sit there and break your API, asterisk, especially when you've got 51 million downloads. Like, that is kind of unacceptable. So your code knows when somebody's using a deprecated interface, well, guess what? We can yell at them. We have these things called deprecations. So Sprockets3.x will have deprecations before we go to Sprockets4.x. We have a branch, we've started on this. If you've not implemented deprecations in your own project, it's super simple. You're like, hey, the thing you're using is deprecated. Use this other thing that's not deprecated and here's where you were using it. It's kind of like a three-step process. So deprecations are gonna nudge people into the right behavior. They're gonna help get people to upgrade and they also help with API design. Because if you can't write a good deprecation, then guess what? The interface probably wasn't the best. For example, what if you just randomly changed a hash key? Well, it's like, oh, this hash key sounds better than this other hash key. Well, that's something that Sprockets did. Between two versions of Sprockets, and I don't even actually know which versions of Sprockets, these two things change. So now if you want to support both versions, you have to use both keys. And there was no warning. It's just like, oh, I quit, I'm starting to get a nil. You would just have to wait until your stuff broke and then maybe you would kind of figure out what was going on. Okay, this is my favorite section coming up. I hope you're paying attention. So Sprockets suffers from something that I like to call the God object problem. It has this one main class that has all of these concerns mixed in with it. It's one object with 105 methods. Like, it's using a lot of them. And you ask yourself like, where did that method come from? And then you look into the source code and you're like, oh, well, maybe it came from Sprockets base or environment. Dependencies, digest utils, HTTP utils, MIME, server, resolve, loader, Bower, path utils, path dependency utils, path digest utils, digest utils, source map utils, URI utils. This is my personal favorite. Sprockets utils is mixed into Sprockets compressing, which is then mixed into Sprockets configuration, which is then included in Sprockets base, which is inherited by Sprockets environment, which is then wrapped and cached by Sprockets cached environment. So yeah, that's all I have to say about that. It's impossible to just glance at something and know how things are interacting. Like, you change this one method that you thought was only being used in this one part of the project and it's not true. For more information about how Sprockets work, I highly recommend you go to Raphael's talk, which was yesterday. So you can catch it on Confreaks. What is the solution to God Objects? Well, we can move logic over to helper classes. This is an example of a class that I introduced while I was adding new functionality. It takes a absolute path and trims it down to a relative path, or it can take a relative path and make it an absolute path. We need this for storing things in the cache. The beautiful thing about this is it has a couple of extra methods that make it a little bit cleaner that are not actually exposed to that God Object API. We can expose only the things we need. So it's gonna minimize that God Object API and it also hopefully produces small, easy to read files. You can look at that file and say, oh, you're ITAR, like, I vaguely understand a TAR can expand or compress a file. Like maybe it's related to that, for URIs. Ideally, this produces readable code and readable code also attracts helpers who read code, believe it or not. As a side note, I will say that Ruby is object oriented if you're not super comfortable with objects and classes. Please spend a little bit of time there. It's totally worth checking out. Sandy Metz has a book that I have totally not read, but she's given a ton of conference talks, which I have seen and you should watch the talks and I am sure the book is amazing as well. As well as Katrina Owen has done a ton of refactoring talks. If you wanna see, oh, how can we make this better? How can we make this more readable? As well as exorcism.io is an actual place where you can go and try out your skills. You actually refactor things there. It's pretty cool. So helping takes commitment and we do need to respect that. How are different ways that we can respect that commitment? Well, when somebody gives a pull request, even if it's not the best pull request, we as maintainers can say, hey, thanks for submitting this. You know, that person cared enough and you can help them to help you. You can say, well, explain the reasons why you're not merging it or help them to get to a place where you can merge it. You can also say, oh, you're working on this thing. I don't really care about that thing. How about you look at this other thing, which I really care about. And it's a way to get them on board. Don't, I mean, if you just like close and dismiss and like lock, that is not how you attract people to help you. So what else do people want? Maybe people want recognition. Rails has this great leaderboard. That's actually the reason why I gave, I had my first commit onto Rails is I was like, I wanna just be on the board, period. And maybe you don't have a leaderboard, but you can still give recognition. Maybe your helpers want pizza. There's a fun story where when I introduced a test, or I introduced a feature, I actually broke windows on a minor release of sprockets and I had a developer come to me and be like, hey, you broke windows and I'm like, yeah? How do I do fix this? And he said, well, here's the problem. We worked through it. We pushed out a release and I said, okay, obviously you care about sprockets. You care about windows. You have a windows machine. Can you help me get the windows tests, or the sprockets tests running on windows? And he was like, I don't know. It sounds really hard. And I'm like, I would be so appreciative. I would buy you a pizza if you did this. I will send you a pizza. I'm not joking. That's not like hyperbole. Like I will actually get like order delivery for you for a pizza to your home. And I was like, well, a couple of weeks later, he did it. He did not happen to, in those couple of weeks, reach out to me and been like, hey, by the way, I live in Germany, but he did. And if you wanna ask me questions later about sending a pizza to Germany and explaining to your credit card what open source is, I'm happy to do that. So I would also say, we mentioned acknowledgement. Well, thank you. Thank you, Daniel, for this. And sprockets is now tested on windows CI. So it's good. So those are kind of ideals and things that you might want in your project and can make helpers a little bit more comfortable. What happens when you actually have this scenario? Where are you inherited that project? Where the previous maintainer might not have done all of these things. They just might drop. What are you gonna do? Well, you can start by finding something that needs fixing. I call this bug driven development. And really the only way, I keep on talking about example apps because the only way to get started is with an example app where you can reproduce the problem. And if I didn't mention example apps are amazing and you should probably make it a goal to make one this year. So reproduce the problem and then repeat. Every single bug that you fix you're gonna learn a little bit something more about the code base. And eventually you're gonna start seeing non-bug problems. Eventually you're gonna be a lot more comfortable. Well, okay, what happens when you get a bug report? So source maps in Sprockets 4 is a thing and it was half finished when Josh stepped away. And when I got this project I was like, hey, what's a source map? And somebody would report a bug. I would try and fix that bug and it made the test break and I'm like, okay, well, are the tests that are there even reliable? I've got no clue. So where do we start? I put on my archeologist hat which was totally the inspiration for this talk. And I started research. So I looked at the Mozilla RFC. I got out a Evernote and I started taking notes. And I learned a whole lot about source maps. I eventually was able to take those notes and actually turn them into guides. So I took all that information. I said, I don't know this so other people probably don't know this. Let's not make them work. I made that as a guide and I put it in Sprocket's source tree. So even if you're interested in, it's totally rough but it works. And I can use it as a future reference. So if you wanna know what a source map is then I can tell you, go read my guide. Seriously. In this process I ended up having to borrow from some other projects where I actually used other projects from the technology, which shall not be named. So I use Uglify.js to verify my encoding and make sure that my encoding tests were valid. I use a source map to verify that my decoding was testwork correct and then I got the test to a place where they could pass. So is it finished? No. I need more bug reports and I need more actionable bug reports. So with all of that, all that being said, where do we go? Because maintainers won't be around forever. I won't be around forever. Raphael apparently will be around forever. I actually have a sneaking suspicion that Raphael is actually secretly like 100 robots. Think about it, have you seen 100 robots and Raphael in the room at the same time? It's proof right there. So I need help. And I need help maintaining the history of sprockets. I don't necessarily need you to know everything. I don't necessarily need you to go out there and fix all of the problems. You know what, sometimes I might just need you to help not say bad things about me. If somebody's like, hey, trash talking, it's like, listen, listen. Let's critique. So we can preserve these stories by getting involved. And if you don't get involved, then who will? It's open source. You can say, well, maybe somebody else will. Guess what? That somebody else is you. And we all need to step up. We can take five minutes. We can just read those guides. We can write some docs. We can open some issues. We can create example apps, which I've totally not mentioned before. Only five minutes. So I please invite you to join me and together. We can become maintainers. We can become helpers. And together we can save sprockets.