 I dressed up today to make sure you guys take this seriously. Welcome! My name is Ryan Davis. I'm a member of CLRB. I'm Aaron Patterson, also a member of CLRB. We've both worked for our AT&T Interactive, but we've got some comments about that. So just to start, we're not here to trash anyone else's code. This is not the worst practices show and tell. This is about well engineered code, but really bad ideas. So we said that, blah blah blah, worrying. So please note, none of this presentation or software was supported sanctioned and endorsed or even tolerated by our employer. So AT&T Interactive, please don't mess with me. So we both had the opportunity to do each other's bio. So Aaron Patterson likes kittens, ponies and vim. He's totally in love with this mustache. And when you really think about it, he likes writing C, a lot more than he likes writing Ruby. But you know what? These slides are kind of low and I'm seeing a number of people goose-back. So we thought about pushing all of our text up like you did. But what would you rather have? Can everyone in the back row stand on their chairs? We need a gradient. Everyone in between just kind of kneel on their chairs and the front row stand up. They don't want to do it either, so I'm not going to do it. So if you think about it, he writes a lot more C than he does Ruby. He's no good Gary, Johnson, never say die, sight, booby, NFC, earworm, QR tools. And I'm sure more than he's even forgotten about all C. He doesn't like Ruby. Okay, this is Brian. Brian likes kittens, ponies and Emacs. He is totally in love with this pony tail. He wishes Sting never left the police. He fears nothing except mushrooms and asparagus. He really hates it when I say, and I do every day. And he wears the same colors every day. He also hates photos, so he's was redacted. All true. So what is a bad idea? Well in a sense, these slides are a bad idea. Not these slides, which we could have written, but these slides. So the first thing we needed to be able to do was figure out how to identify a bad idea. We came up with this field diet. First and foremost, it needs to be well engineered and tested. It needs to be useless-ish. It needs to follow pose law. And it needs to have a spiral nature. Or what we call, whoops. That's hard to read. Sorry about that. So well engineered and tested. Bad ideas are not bad code. That it really, you'd have to have a well engineered and written code to overcome the fact that the idea itself is terrible. So really in a sense, you need to be wary of the well tested project. That's a sign that someone might be trying to overcome the fact that they know it's a bad idea in the first place. These projects need to be useless-ish. Meaning they need to do something, but that something might just be something you don't want or need. They might be software looking for a solution. They might want to be a solution to a problem that doesn't exist. My favorite, pose law. How many people are familiar with pose law right now? Awesome. So basically the idea is that without a winking smiley or other blatant display of humor, it's impossible to create a parody of fundamentalism that someone won't mistake for the real thing. And the converse is true as well. It's impossible to have something serious about fundamentalism that someone won't take for a parody. So in the same sense, from a high level they sound perfectly reasonable. And when you start getting into the details, not so much. They are a solution looking for a problem. They're not going to solve any immediate problems at hand, but they will generate more. And everyone always ignores that guy in the corner going, really? Because what does he know? So bad ideas also need to be spiral in nature. And this can be something where maybe a bad idea will build on top of another one and hopefully have cyclic dependencies. Hopefully. So some hypothetical examples of this might be an XML multi-file format, a la Java's jar format. And really all these hypothetical ideas are just things we haven't necessarily written yet. DRB over RFID. Two laptops facing each other with webcams talking to each other over DRB with QR code or barcode. Assembly optimized webpages. I actually tried that, but it was hard. And an FFI. So Yoda. Yoda is an example that we picked because it shows that bad ideas can be very high level. Basically, test frameworks we've seen as being the new IRC bot. Yoda defines a spec language in the direction that we think that speckers think. Let's take a look at this. We have the canonical bowling example. So bowling.yoda starts the spec. Score is zero for gutter game. It will. Then we go through our setup code where we hit a zero on every single frame. Bowling.score is zero, it is. Bowling.score is 42, it is not. And here we're going to see that if we set up our initial score wrong that that fails with filming it in. I take it they get the point. So as far as our whoops identifier goes, how is it well engineered? Well, it's 65 lines of Jedi Master Ruby. It only has three conditionals and one loop. It flogs to 41.1 with an average of 4.1 per method. The international Ruby average is about 10 per. So really, how can you go wrong? It's so simple we wrote it on one bus right up and down town. So how is it useless? Well, the minimum a test framework needs is one assertion. We've got two. So that's twice as good. But it's not exactly very expressive, but it doesn't actually need to be. Pose got nothing on Yoda. Do we need another test framework? No, but we had a bus ride to go on. So it happened. And as far as its spiral nature goes, it is a test framework. So you could use it in every single project you've got. So Wilson, how many people are familiar with Wilson? So Ruby we all know and love is slow. And C is not. But why would you write in C when you can write in assembly? Really. So I picked this one because it's a good example that bad ideas can be very low level as well. Wilson generates x86 machine code via natural feeling Ruby DSL. And it was named after the very metal Wilson Milkovich partially because the metal gem name was already taken. So here's an example of some inline C for a method called C that counts from zero to n plus one and returns the result. Now this needs to be as fast as possible because there are a lot of web pages that have to do this type of counting. So we write this in C so that our web pages are fast. Now, as is obvious, we can see that this assembly code does the exact same thing. Oh, I knew that. I knew that place. Obvious. So really what we need to compare is the benchmarks. And as you can see here. Look at that. Wow. They're almost exactly the same coin. I'm blown away. So would you really want to go with something in C where you have to invoke GCC and compile and link and all that stuff? Or would you rather write in assembly code? Now as far as our whoops identifier goes, Wilson is whip smart. It generates machine code directly. It does not have any dependencies whatsoever. It does not use any external resources. No shell outs. No invocations. Nothing. It parses a 60-page x86 spec into instructions and their op codes and builds its entire DSL based on that. Smart. As far as the uses of this thing goes, it's really good at writing fast code and really good at crashing quickly. And I really, really truly hope that no one actually uses this in production. Truly. Somebody does. Anyone? No. Poeman's dispatch. So my original intent behind Wilson was to be able to use this to write an absolutely pure Ruby method dispatch for Rubinius or some implementation of Ruby. But it turns out that writing in assembly is really hard and I got laid off of Rubinius anyways and then I got distracted by other stuff. So whatever. And as far as the spiral nature goes, it was intended to be the method dispatcher so how much more spiral can you get? Oh, my turn. This project is called Wank. Wank produces human readable Marshall format. You might ask, why Wank? And this is the answer. Marshall data is too hard to read. So we Marshall and Neil and we get these bytes out, can't read it, therefore useless. YAML is also hard to read. Look at that. I don't even know what that says. Unreadable, therefore useless. Websites, readable. Exhibit A, perfect. So the field guide. I want to talk a little bit about how Wank is implemented so we're going to take a look at the guts. It has a few language dependencies. Ruby and YAML, of course, very obvious why. And XML or HTML. So the way that Wank works is the idea is that data is a tree. We have this data structure here in Ruby. If we were to graph this data out in memory, it might look like this is how it's represented. HTML is also represented as a tree, right? So all we really need to do is a little bit of translation. But the problem is that HTML data is a subset of Ruby, meaning that in HTML you can really only represent strings, lists, and maps. So we need a way to get the Ruby object graph into something that we can represent with those data types. And that's where YAML comes in. Now, the YAML representation is exactly that. It's just lists, maps, and strings. So if we take Ruby and turn it into a YAML AST, we have something like this, and we could say translate this AST into an HTML AST and produce an HTML document. And that is exactly what Wank does. So here's some sample use. All we do is we say take this data structure, HTML, Marshal, dump it. And we end up, obviously, very easy to read. This is our data structure, right here. And what's even better is in the browser, awesome, super obvious. And even better, we can wank in style. Apply a little style sheet to that and boom, look at that. Everything you want to know. So, and of course, Pose Law, it is... This explains it. We can completely round-trip over to HTML, and of course the HTML goes back into YAML, which then goes into Ruby. Even better, we can wank over DRB. So why use Marshal Format over DRB when we can serialize everything as HTML? So we can read it. Yeah. I know you're looking at all that network traffic, like, oh, what's this thing doing? Oh, see some HTML, and we can do it in one line. Literally, one line. That does it. Of course, we can do the usuals, wank on rack, wank on rails. Really, you can wank anywhere. Never say die. How many of you are using this in production? Everyone that's using Wilson is using this in production. I guarantee. Never say die is a library I wrote which helps you rescue from segfaults. It also helps you create segfaults. It's based on lib-sig-seg-v, which lets you do pageable virtual memory, memory mapped at the... But really, the idea behind it is that in Ruby, we're allowed to trap ints. We can trap these signals. So why can't we trap seg-v signals? So never say die lets us do that. We can begin, do some stuff. Uh-oh. Seg-v, rescue, fix the memory. We're done. It's safe. It's totally safe. Field guide time. Never say die is very well engineered. It is fully tested, which is why it ships with this method, the seg-v method, because of course we have to generate a seg-v in the test. How else would you test it? So let's take a look at a sample usage here. So we start this, never say die is seg-v, and we return the maverick. It's useless-ish-ish-ish. If you think you need this... You probably do. Sad but true. For example, our beautiful assembly language. Sometimes this dies. And if it does, we just fall right back onto the slow one. It's fine, you move on. No problems. Totally safe. We can even put never say die on rails, because you know, uptime, the next one is Poobie. Poobie is a PHP runtime embedded in Ruby. Why would we do this? Also you can, and the thing is PHP programmers are cheap. So like I said, Poobie is a PHP runtime embedded in Ruby. Oh, we gotta talk about the source of this. Ryan and I were on the bus, and Ryan said, hey, wouldn't it be awesome if we could run PHP in Ruby? And then I did it. That's a win by two, as far as I'm concerned, because I didn't have to implement it. So Poobie is well engineered, field guide time, and we're gonna talk about the internals of Poobie and how it works. Here is a diagram of, oh, okay. There we go. So here's an example of a Ruby variable moving into a PHP runtime. The middle here is a C proxy, which is the part I wrote. The Ruby variable moves into the C proxy. The C proxy knows how to communicate with the PHP runtime. So it puts that into a weak ref table. Is there any alcohol in the room? And it's into the PHP runtime. So we have a weak ref table, which stores the PHP object memory location as in the actual location memory as an int, and points to the value. Great idea, right? Luckily we have 6xb and never say die. So here's an example of a PHP calling Ruby. Ruby then communicates back to the same C proxy. It looks up the variable in the weak ref table and then knows which Ruby object to look up. Gives that back over to PHP. So PHP calling Ruby. Or excuse me, sorry, Ruby calling PHP. So Ruby can call methods on things defined in PHP. The way this happens is it asks the C proxy for a variable from the PHP runtime. Returns that to the C proxy. The C proxy then creates a new object proxy which knows how to communicate methods between the Ruby runtime and the PHP runtime. It's a little bit simplified, but high level. So here's some actual code. I want my blue back. We're going to look at some actual Poopy code. Yes, we did. I don't know if you guys noticed the gradient. It's actually a gradient. It took me hours to pick this. So here we start a new PHP runtime, evaluate some PHP, and then pull the value from the PHP runtime back into Ruby. Here we actually pull out a PHP array. Oh, I forgot to mention this. I actually don't know any PHP. So I found out, during the course of this, I found out that apparently arrays in PHP are not actually arrays. So we have to have this little Poopy array proxy object. Because apparently their arrays are ordered maps. You're crazy. I don't know. Something. So an example of shoving a Ruby object over into the PHP runtime, we have this class fun, which has fun times. And we create a new instance of that, put it into the PHP runtime, and we're able to access methods on the Ruby object from the PHP runtime. It is built like this. You got your PHP in my runtimes. So the one on the right is PHP. Sorry. And it's brown. Yeah. So anyway, turns into this. Now just invert your... That's actually worse in a better way. Invert your eyes and the colors will be perfect. So it produces what I like to call the circle of terrible. This is pose law, by the way. So next up is the S part, our dependency trees here, whatever S is. Yes, yes. We're going to talk about web adapters. I've written a couple web adapters. One for Web Brick. Of course this PHP runtime isn't useful unless we can run, say, WordPress. Right? So we're going to show some code. We have to handle PHP events because PHP just sends events back into the host application. And we have a class to do that. Don't read this. You'll hurt yourselves. This just handles that. Just trust us, it works. It works, believe me. It handles the body. It handles the headers, whatever. And then here's the actual adapter code. Don't read this, hurt your head. It works. All this does is take environment information from Web Brick and put that into the PHP runtime such that we can do right things, I guess. We also have a rack adapter because rack is totally hip. We call it frack. It's 50 lines. It's totally hip. I was going to enter this in the contest thing but I figured I didn't want to make the other contestants feel bad. Here's the code for it. You don't need to read it again. It's the same thing. And what we're going to do now is we're going to do a Pooby Blarg. And DHH did this in 15 minutes but we can do it in two. So right now we're getting the latest WordPress from WordPress.org. Yeah, create our little database here. We're creating the MySQL database or our WordPress database. Unzipping WordPress. Then we go into the WordPress directory and I'm starting up frack here down at the bottom in case you can't read. That starts up Web Brick on port L-O-L-O-L. So we access that. Create our little configuration file. And whoops, we have a freaking blog. You sick bastards. So logging in, doing our thing here. And then we got a blog. Yeah, so it's like loading stuff. Hello, what did I put here? Hello, RubyConf. Hello, RubyConf. How are we for time? Okay, we got time, I think. Okay. So then we'll go visit the site and hello. Yeah, we totally have a blog. And then, I think, yep. So it totally works and then to prove it, I switch back here. This is our Web Brick log. So I believe me, I'm not lying to you. Yes, I think, so that is it for that. We'll now move on to Enterprise. Scaleless software at its finest. So Enterprise's guiding principles are. We all know this, we can all agree on this. Ruby does not scale. Everyone knows this. But XML scales like a boss. So I wish Tim was here for these models. If we could just convert Ruby into XML. Scale. Yeah, it would scale. And we can. The secret is in trees. This is another bus conversation, wasn't it? Yes. Oh, yes. So, Ryan and I are on the bus. The fail bus. The short fail bus. So, so Ryan says to me, oh boy, in Ruby, in Ruby parser, I sure wish I could search my ASTs using some sort of language for searching trees. And I said, oh, you mean expat? And he was like, no. And I was like, I was like, I can just take your AST and turn that into an expat document. And then you can use expat. And he got mad. So then I had to do it. I had to do it. So it is well engineered. We're going to talk about the engineering. Here's some Ruby code. I touched on this a little bit earlier. Ruby, the Ruby code can actually be thought of as a tree. So we have this 2 plus 10. It can turn into this particular parse tree. 2 plus 10 goes into the parse tree like that. XML is also represented in memory as a tree. So we have this root, you know, if there was just, so we use Nohugiri to turn that XML into a tree. If only there was some way we could translate one tree into another, then we would become enterprise. Right? Right? Absolutely. So, uses. We can do that. Enterprise does that. Uses. We have advanced metaprogramming techniques. Very, very advanced. Here's an example of the code. Down at the bottom here, we have this class foo, foo instance variable foo.hello. And what we're going to do is parse that, turn it into an XML tree. So enterprise, sexML, uses parse tree. Uses RubyParser and converts that into an XML document. And we can treat it like a normal Nohugiri XML document and actually traverse the tree using XPath and perform changes to the XML tree and then output that back to Ruby. So, just a very simple example of taking this code at the bottom and turning it into this. That's all I really wanted to be able to do. Right. Exactly. And it does it perfectly. Now, the problem is, the problem with this code, there's a problem. I don't know if you guys noticed what the problem is. I was thinking small. There's not enough, it's not enterprise enough. There's not enough XML. If only there was a way that we could take that XML document using another XML document and turn that into a third XML document. That's enterprise. We would be three times more enterprise. And in truth, we can. We can take an XSLT style sheet like this. Isn't that beautiful? You all know exactly what this is doing, right? It's like poetry. Right? Totally clear. In fact, you can tell. It's converting food to bar. That's what it's doing. You really didn't need to explain it to them. Ah, yeah. Sorry, sorry. So really we just take this normal XML document, get our XSLT, perform the transform and output back to Ruby does exactly the same thing as our previous Ruby code. XML sucka. We really wish Tim was here. Pose law. Code is XML. Really? The name, enterprise, everything about this project? Is it? I think it's your turn now. Isn't it? Oh yeah, it is. Spiral downward. This is the downward spiral. So I was thinking how best to take advantage of enterprise. We decided that Rails wasn't enterprise enough. I mean, yeah, it can serve up XML and everything, but there's no XML in it. So we fixed that. So here we have a regular Rails app. It's got some real tests that will fail if the model and the database aren't right. You can see that they all pass. And I've got an isolated vendor Gems directory. So let's look at the active record lib directory for all the RB files. We can see that there's plenty. If we count them, there's 51 of them. Now I'm going to call enterprise AR. We're going to enterprise all those. We're going to convert them to XML and then turn around and gzip all the RB files so they cannot be used. So we do a find again. We see that there's one file and that file was driving a bug we couldn't figure out and we think it's in lib.xml. And we can see that we have 50 XML files and 50 RBGZ files. We're going to run our tests again. I love this part. I love this part, too. It's exciting. Yeah, it's so good. So what's happening here is... There's a pony over there. Oh. Look, there's tests. I think they work. Will they work? I'm so excited. I'm so excited. Oh, by the way, this video is shot in real time. Absolutely real time. And the truth is the tests actually run in the same amount of time. They just don't necessarily load in the same amount of time. But pony! So there are some actual benefits of us working on enterprise rails and enterprise and all this failbook. Is that we did actually find some bugs in Ruby2Ruby and some bugs in NoFiguri and possibly a bug in lib.xml. And I could have found and fixed those bugs at any time, but I wasn't looking for them. So apparently, a bad idea is a good reason to work and fix things. So let's bring all this together. I get to do this. Do you want this? Yes! The correct pronunciation here is pooby on fails. So we're going to start up. This is a normal rails project. We go into the old rails project here and I'm popping into the Vim window, grabbing the config environment and the big environment thingy. And then we got to set this up with pooby, right? Because you got to require the jam. This is so wrong. Supposedly I don't have to do that, but I suck or something. I don't know. So we're going to generate... Oh, in rails everything's plural, so we generate the PHP's controller. The controller, right? I suppose I could have named that codes, but I don't know if you can consider it codes. So we opened up index PHP. So do the PHP info? I just learned that the other day. Totally serious. So port 3000, hit local host, port 3000, the PHP's controller, and we're running that. There's more. Open up the PHP's controller, the index method. We're going to set some IVAR in here that we want to display to the entire world. And we can actually access the controller through my magic at variable and get the message. So we have hello world there. And then to top that off, we're going to open up the application layout, but we're going to do this in ERB and set up our little HTML here. So we can mix PHP and ERB, because I don't know. I don't know PHP. We'll let all the future PHP programmers that I'm going to hire use that. And then I'll use the ERB and load that up. And then there we have mixing PHP and ERB. And you can see all the requests are being served up by Rails. This is not a joke. So we haven't done Enterprise Pivity of Rails yet. Sorry, fails. I just titled it. We haven't written it yet, but we figured it would only take about 30 more minutes. But really, we need to know, and maybe we should just ask you guys, how much should we charge for this? This is Enterprise. Each. Millions each. Each CPU core. So in conclusion, it's more than okay if your idea is bad. Just practice good engineering, it's fun. We made 2009 the worst year for Ruby ever. And together, we can make 2010 even worse. Even worse. Thank you. The question was, did you see if the PHP views are faster than the Rails ones? You know, I may have missed that. We have another selling point. Yeah, so fast. Enterprise and XSLT to write a refactoring browser. No, we have not considered using Enterprise and XSLT to write a refactoring browser you sick bastard. I think my brain just melted. I'm not even going to repeat that. The question was, have we ever considered buying a car instead of writing that damn bus? Yes. Yes, we have. You don't already have a car? There is a car, two scooters, a boat, a pet fish and something else. And none of them work. But it's software does. Anything else? Thank you very much. Thank you.