 So I gave a talk at Ruby Fringe and Ruby Nation, which was about living on the edge and some cool stuff that's happening on the edge. And when I gave this talk the second time, I added a very short lightning talk size chunk about what we can learn from the sorts of things that are happening on the edge, the non-rails, but still projects that people are still using heavily and what people are thinking outside of the monolithic rails world. So I just basically gonna give that five or 10-ish minute talk. I think it's more like five minutes. The first part of the talk is just that it's possible to build Ruby that works for the enterprise. I know there's a lot of stigma about that, but there's no reason why we should say, if you are the enterprise, therefore Ruby is not the language for you. There are people doing a lot of work in ways that people in the enterprise suddenly looked at it and said, wow, I didn't know Ruby was able to do that. I thought it had to be like active record. I thought if we use the database with Ruby, we all of a sudden lost all of our database optimizations, for instance. And there's no reason why that should be the case. There's no reason why we should, as a Ruby community, be projecting that out to the world. Us saying fuck you to the enterprise is effectively us saying there isn't a way in Ruby that you can do this and that's silly. There are big databases in the world. There are big applications. There are cool things that Java has done. I wouldn't want to use Rhino, Hibernate or Struts, but if you go out and look at Rhino, Hibernate and Struts, there's actually cool stuff in there that we can learn from. Also the trade-off, not the trade-off for using Struts, but the trade-off for making our code work well with big databases and big applications is actually really minimal because Rails taught us a really important thing, which is that you can have sane defaults, right? So you can put sane defaults in front of a really configurable system, which is what Merb does. That is possible. So what Rails did is it said convention is really important and that's all there is, right? But it is possible to do exactly that to make almost every user who uses your tool have convention, but then build it in front of a highly configurable system. And the trade-off therefore for most users is almost non-existent. There is a trade-off in writing the code obviously. Framework developers have to do it, but I think it's worth it for us to show the enterprise that Ruby is a language that isn't a joke. And we can also overcome the objections that people say by fixing them and by not giving them the finger. I think it takes some time. Some months ago I rewrote all the database drivers, the C database drivers in C, and that's now the core of Datamapper. Took me like a week, honestly. And that's not, I'm honestly not a C hacker. I like, that was the first time I did any significant large C project. And in fact, I think a lot of people who know C think that my C is pretty weak, but it is possible to take a couple of weeks and bang out something that overcomes what appear to be long-lived objections to things about Ruby, and it's worth it. Also, I know I say this a lot, that's funny, but Ruby is fast enough so that it's not a joke to say you don't have to live in millisecond land all the time. It actually is possible to take a look at your code and optimize it for getting a humongous number of tight loop requests. So in the web world, that means getting a lot of requests. But there's plenty of code that operates in a tight loop. And when Ruby code operates in a tight loop, it is possible to optimize it in the microsecond land. And it's worth doing. It's worth knowing exactly what sorts of things are fast and slow. I am not saying, even though a lot of people think I am saying that every time we write a line of code, we should be thinking about the performance characteristics. What I am saying is that we should always be thinking about the trade-offs that we're making. If we feel like writing something that's really elegant, we should know that it's also slow and we should say I know that this is slow and it's worth it because I care in this case about elegance. And then in another case, when you cannot rationalize that to yourself, you will actually have thought about the fact that you're about to do something really slow. So it's worth knowing what's slow and what's fast. Obviously we're writing in Ruby and not C because most of the time it doesn't matter. But when it does matter, it's worth knowing what you're doing. Just to highlight what I mean by microseconds, this is a mer-request. A mer-request on my MacBook Pro is about, takes about 500 microseconds. When I was doing this slide, I noticed that setup cookies in the controller takes 70 microseconds, or 75 microseconds, which is like a shocking amount of time. This isn't, I can't time how long methods take in microseconds, but I can profile things and know how long things take in total and therefore guess about their relative percentages. So can setup cookies for some reason is taking up a tremendous amount of time. The point is that it seems like, oh, that's 75 microseconds. If I get it down to like 50 microseconds, what's that gonna do? Well, it'll give me like an extra 100 requests per second or something, right? Seriously, if we're talking about a 500 microsecond process reducing 20 microseconds, it's gonna make a difference. It's gonna increase significantly the request per second. This used to be 600 microseconds, and when it went down to 500, we went from like 1600 requests per second to like 2000. So it makes sense to know that inject is like three microseconds. Sometimes it matters, right? That's my MacBook Pro. Obviously, if you run it on beefier hardware, you'll get better performance. Also, that's obviously a single more process, so if you have a box that is capable of having more, you'll get better performance. The second sort of learning thing is Ruby's not an API. When you treat, when you say, okay, I have a bunch of stuff, or this is sort of the example, I have a bunch of things that work together, do whatever you want, you can obviously make it work, you get like a tangled mess, right? A much better thing is to think about what you're doing in terms of modules, in terms of the API that you're trying to build, and make it so that it's clean and that all the pieces work together in the same way, so that you're not just smashing everything together. So a couple of examples of what I mean by that. First of all, alias metha chain is a code smell. I am not gonna say that you should never, ever, ever use alias metha chain, only because when I say that, someone comes over to me and I have to argue some edge case of when it might be possible, and I don't care to argue that edge case. What I am arguing is that the vast majority of times when you're using alias metha chain, especially on your own code, it's because you did not build the interface correctly. It is almost never the case in your own code that you have to actually go and change the code that you wrote already via some metaprogramming trick. If it's your own code, you can always go back and change it. If you have multiple cases, you should make the interface capable of handling the multiple cases, right? So this is a rail stack trace, okay? This is a rail stack trace with the things that came from alias metha chain highlighted. Okay, in black. So process without session management support, process without filters. If for no other reason, don't use alias metha chain because it makes stack traces like this. You will not be able to track down what the hell is going on, okay? A merge stack trace looks like this. And one of those, three of those steps are synchronizing the mutex out of eight, okay? So code without interfaces, what does that look like? This is gonna be like CS 101. It seems really easy if you're making an account to do adder accessor funds, and then at some later time, you receive the request for funds, so you're like, oh, I've done adder accessor funds. I can go modify my account, right? And at some point, you're gonna get to exception handling, and you'll of course handle the exception, the awesome class, because that's where you're doing all the work, right? But code with interfaces looks like this, right? You've made an account, you've decided when you deposit it, you do this, and when you withdraw it, do this, right? And then your awesome class does the check off, because that's the right place for it, and you do account that withdrawal amount. I don't, I'm only doing this, this is like CS 101. You've seriously learned about this probably in CS 101. Or like when you first started programming, someone showed you the account withdrawal example. But for some reason, a lot of people are writing code in the Ruby world like this. I see it a lot. Tons of code is written like this. And just don't do it. Just take the time to figure out how to write, sorry. Take the time to write the code with the interfaces, sorry. Which is this, right? Take the time to do it, right? It seems like the reason why people don't do it is because this is really easy, okay? It's really easy to do this. And it's really easy the first time to do this. But this is a really stupid case, right? If you actually take the time to do the right thing, what ends up happening is that you have same places where things belong. So what I'm suggesting is that you should do it. I'm suggesting that the Ruby community in general needs to spend some more time thinking about it. So in general, the general takeaway is spend more time thinking about things. I think that it's because Ruby is an awesome prototype language and we can get things up and running really quickly and the things that we get up and running really quickly actually work. We don't necessarily spend a lot of time thinking about what we're doing. I'm lying. We do spend a lot of time thinking about the code we're writing. We do not spend a lot of time thinking about the architecture of the code we're writing. And I think that BDD actually has also, while it's an awesome way to test drive the code as you're writing it, it also makes us feel extremely secure about the fact that we have something that fits together. When in fact, if all you ever do is BDD style unit tests, you have no test that's integration test that tells you like, here's what I actually expect the whole system to do, right? I think we should spend a lot more time writing test to test the entire system and a lot or maybe the same amount of time writing unit tests. But a lot significantly more time writing test to test the entire system and significantly more time thinking about it. And the final thing is, if you ever find yourself implementing a hack because it works, try to make, try to let it weigh on you. Try to, when you go to bed think about it that you just did something that's a hack and try to spend some time figuring out how to take the hack away because yes it is true that when we do the day to day work that we do sometimes we have to get something working so we have to write a hack. But it is also true that if you think about the hack that you just did and you don't just say, well I had to do it, that's just the way it is. You'll usually come up with a good solution over time. So spend some time thinking about the crazy bad things that we're able to do in Ruby that let us get our jobs done and fix them. And I have a block. And it's all.