 Well, first of all, I'd just like to start off by thanking you all for attending. There were some pretty good sessions up against this one, and it's the morning session, which means if it was me, I probably wouldn't have made it, actually. It's my own session. But since I'm giving a talk, I didn't have much choice. So Ruby Waves is, you know, another framework. I think hopefully as we go through this, you'll see that it has some different twists over what some of the other frameworks are offering in a different angle and approach to the problem. And that's really what I'm trying to kind of get across in this talk is if I had to pick one thing, it's that it's more of an architectural framework than an applications framework. And the focus is really around resource-oriented architecture, which I think is an extremely... And we've seen the emergence of, you know, REST as a paradigm, people talking about service-oriented architecture and about, you know, REST and RESTful applications. And that's because there's a lot of power to that paradigm. And Waves' objective really is, as it's grown up, is to sort of help you... help developers in general take better advantage and write more truly resource-oriented applications with fewer obstacles to doing so. Before I get into some of that, let me quickly just introduce myself. My name is Dan Yoder. I work with AT&T Interactive, R&D, out in Los Angeles, which is a lot of fun. Like a lot of people, we're really desperate for really elite Ruby programmers, so I'll leave my pitch at that, but it's a great place to work. Some of the things that we've been working on, a lot of interesting things around the Ruby community, mobile development, and rich client interfaces. So if you have a kind of an R&D bent and you like really nice weather, you know, get in touch. So that's me. And so let's just dive in. So this diagram, I think, is a really cool diagram. Well, not the diagram itself, but the historical significance of it. It was apparently one of the first attempts by Tim Berners-Lee to describe the architecture of the web as he envisioned it. I'm not sure what the date, if this is circa like 93 or 94, or exactly where it was. But one thing about it, and it's just neat because it's got, you know, some sort of historical significance, but one thing that's really interesting about it is that it's not an MVC architecture. And if you follow, and most of you in this room, you know, and it's even a little intimidating talking about this because it's a learning process for me, you know, are probably aware that there's really a whole very rich architectural domain and a lot of thought that was put in to the architecture of the worldwide web. And in fact, although some of the success of the web is probably a little bit accidental and good timing and some of those other things, the more you dig, the more you realize how much thought was really put into some of these things that, you know, at a casual glance can seem like they just sort of popped up as ad hoc solutions to problems. And for those of you who've read Roy Fielding's thesis on REST, you know, he was also a major influencer on the HTTP specification that we use today, and a lot of those things in there really were attempts to sort of round out an architectural framework, really, or as they call it, a style, which is also an important distinction. We'll focus on the web and HTTP mostly in this talk, but it's not obviously limited to those things. Now, because of the power of resource-oriented architecture, if you want to kind of get a feel for, you know, we've already seen the vast success of the worldwide web, but what we're also seeing now is the emergence more and more of running everything in the cloud, even databases, running, you know, all of your, you know, doing Amazon EC2 type of things. Things are moving more and more into the cloud and we also see lots and lots of APIs. Every week there's new announcements from Yahoo or Google or, you know, hopefully in the future from AT&T Interactive as well. About, you know, new APIs that you can consume in the cloud without having to really actually, you know, go out and, you know, buy something, install it and configure it. You just point into web service, get your credentials, whatever. And there you go. So the next question, though, is that a lot of people ask, you know, you say, well, you know, people are always asking you this when you do something kind of silly like try to write your own framework. You know, well, why? Why would I do this? Why would I use it? And, you know, you can say resource-oriented all day, but for a lot of people it comes a lot more down to what, what does that really bind me? Why are my apps running better? And the real answer is that you're leveraging what the web has already figured out. All of this thought that's gone into how do you do massive scaling with all kinds of disparate systems, many of which have different underlying semantics or assumptions about the way that they're expecting to operate. And the way that this all works is, you know, widely known as sort of loosely coupling and making sure that, you know, there's a certain amount of tolerance in the way that everything comes together. That's where the scalability comes. So resource-oriented architecture, scalability. If you're looking at an architecture and you're evaluating it based on its openness and its standards, compliance, and so on, you know, the web can, the resource-oriented architecture and the web sort of offers that as well. Over a thousand APIs are now out there published on a programmable web. This was a screenshot from last night that I took. So, you know, there's a lot of examples that reuse and packaging services for other people to consume is really working. It's an idiom that can work not only for big companies like an Amazon or a Google, but internally for the things that you're working on. So, you know, we're talking about scalability. We're talking about open standards. We're talking about reuse. And then maybe one of the biggest things that's easy to overlook is just this amazing amount of infrastructure that is already in place that will help you. Edge caching, proxy servers, a lot of very mature, stable technology that has been tested and proven to be robust. So when you're looking again at an architectural idiom or an architectural style, resource-oriented makes the most sense. But again, you know, a lot of web apps are really starting with MVC and then trying to make it and adapt it to be more resource-oriented. And Waze is kind of flipping that around, saying there's so much value in resource-oriented architecture we should be starting with resource-oriented architecture and then layering on the pieces that we specifically need in a given context. So the next question then comes up, well, that's fine, I can understand that, but I'm not going to try to get into a purist definition. This isn't really a definition up here because, you know, I don't know for sure. I mean, there's a lot of people that are, you know, people like Lloyd Fielding and Mark Baker that take a pretty rigid stance on what qualifies as a, you know, as a true resource-oriented application or API. But I think, you know, like with a lot of things, I mean, there's sort of a pragmatic aspect of this. If you do most of these things pretty well, you're probably going to start to gain a lot of the benefits over time of a resource-oriented architecture. One of the things that is probably worth sort of pointing out, one of the things that I, at least I, I struggle to understand is the importance of the content negotiation aspect of it. It's something that's only recently begun to really get, you know, the attention that it deserves over the last year or two. And so this is things like, you know, checking to see what's the content type and actually not just assuming that the content type and the accept headers that are being passed in by the client in the request are what you were expecting, but actually, you know, just saying, look, I know that there's a bunch of standard content types and I'm going to start trying to develop around the possibility that I may have clients connecting later on that will use them. They're standard media types. In many cases, they're not hard to support or add the support for it. So why not just do it and, you know, have, you know, the logic to go through. And this is a great example of where frameworks like Waze can help because there's actually sort of a complex little algorithm about proceeding through the possible things that the client is saying that they can accept and picking the one that they prefer. It's sort of the least common denominator algorithm. And, you know, it's quite a powerful specification, but it's not in wide use. And one of the goals of Waze is, again, to make that a little bit more accessible to developers so that it's not as painful to do this. Now, like I said, I'm going to start, really, in zero in mostly on HTTP as the focal point, although, again, you can imagine a framework and Waze over time, I think, to begin to support other schemes besides HTTP and HTTPS. But HTTP has the advantage of being a great case study because it's really one of the only protocols that was really designed around or with resource-oriented architecture in mind. So somewhere in the, I forget which section, it's like 5.1 or something in the HTTP specification, there's a line that basically says that HTTP is about methods calling or operating on a resource. If you're a Rubyist, you're thinking methods on a resource, hey, you know, I need a resource class and I define some methods and there I go, right? So it looks something like this in a naive implementation. You know, I just instantiate a resource based on a request and then I start calling the methods on it and the methods sort of look at the request and figure out what to do. The problem with this is that, you know, as everybody knows looking at this, I mean, this is an incredibly naive example. I mean, most of the time it's much more complicated than this and, you know, you'd end up with, you know, I'm going to make sure I don't fall off here, a whole list of these things and that's where things like Rails routing has come in and someone to try to make that more manageable. Waze takes a different approach to trying to solve the problem Let's keep the idea of a resource class with methods intact and in fact, you know, let's look at the whole request because requests in HTTP are extremely, it's a very rich specification actually. There's caching, the content types, you know, the URI, the type of the body. And we can look at this in a way as a method signature. Now Ruby doesn't really have these kinds of method signatures. Ruby is very loose and flexible and that's partly why we all love it because you can do a lot of really crazy things in Ruby. But if we just take a step back and kind of put our computer scientists hats back on for a second and think of an HTTP request as having a signature and let's take... I'm not funny enough. You know, when you do these slides, you always have these jokes and then you get a little bit intimidated and nervous and I forget to tell mine, but he's got it down. You stole all your jokes. That's it, that's it. I was about to tell that one. The philosophy must be very funny. That was the thing. When I saw that talk, I thought, man, that's a compelling talk. I need to put something about Play-Doh maybe in my next talk. Anyway, so this, if you're familiar with the notion of, as I'm sure you are, of method signatures or function signatures, this looks, if we take get as an example and we say, look, you know, it's got a content type, right, that it's saying, hey, this is what, you know, I'm requesting. These are the formats that will accept it. Here's some options that I would like to pass on in and, you know, you can do that to put, post, delete and so on. But in Ruby, we don't really have those kinds of method signatures. We don't have method overloading. And so, in a somewhat weird kind of convergence thing where you realize, you know, all this was sort of implemented backwards, you know, of implementing things just for kicks and then realizing, wait a minute, now I can solve this other problem. And it's actually, there's probably a whole thing about how Ruby being fun causes you to go experiment and then discover whole idioms or paradigms that you wouldn't have actually thought about if you were trying to be too analytical about it and get your design correct up front. So, Functor is a gem that I just on a whim, a guy named Tofer Sill, I don't know, he's written a book, has some really interesting blog posts. I don't know if you guys have heard of him, but you should look him up. He wrote it without the Chris. And you wrote this thing called Multi. It's a neat little gem called Multi, which provided multi-method dispatch or sort of an overloading pattern, argument-pattern-based matching. I took that idea and I sort of just kept adding to it. And to understand a little bit about how Waves does things, it's important to kind of briefly go into what Functor is. So this is kind of the canonical functional programming example implementing the Fibonacci sequence using pattern matching on the argument. So in the Fibonacci sequence, zero and one are sort of seeding the function. And then from there on, we just take an integer, that's actually not quite correct because that could be a negative number, but we take that and we just implement the Fibonacci sequence in terms of the function itself. So kind of recursively there. So that's an example of how you would define a Functor object using the Functor library, but you can also define Functor methods. And this is where you start to see the time because I can implement the same kind of logic that we were talking about before, but now I've got pattern matching in the mix. Now here all I'm doing in this example is I'm just pattern matching apparently on the path. That's what this is implying. And so I can actually now have a couple of different get methods and different post methods that are operating on different resources or paths and returning whatever. Does that make sense to everybody? Okay, cool. Now, so then we build a little further from there and we define a notion of a Request Functor, which is just a Functor that we define, a Functor method on a resource that's intended to match a Request. Nothing too terribly tricky about it. And then we add to that because of the fact that as I noted earlier, requests in HTTP, it's a very rich expressive little DSL really that's there. And so we need a little bit more than just matching on the path. And so we add some DSL features that make it possible to do that. Using built-on Functor, these DSLs will just generate Functors, which in turn are really actually just methods and I'll show that in a little bit. So now here's what it actually looks like and again, this is still a very simplified example, just kind of building up here to the complex part. And I'm saying, look, on a get method, if the path says name, return FIDO because all of the dog resources apparently are named FIDO. The other thing we've done here is we've dispensed with a little bit of bookkeeping and mixed in a bunch of helper methods with this mix in from Waves, which generally you put in, you don't have to, but then you'd have to do all that stuff yourself. Now Waves, again, is an architectural framework, so there's a lot of things where, hey, this is the way that we're doing it, but you might well think of a better way to do it or have a different spin on things or add in different helpers. We have a layer called MVC, which makes it a bunch of MVC helpers in addition. So just to kind of give you an idea of the flexibility, it's an architectural framework. We do have a, there is a, well, I'll get to that in a second. So here we are on a simple example. Let's look at a little bit more complicated example. So it's the same basic idea. Here I'm matching on a URL that consists of, you know, slash location, but it's also saying, you need to pass me two query parameters, a lat and a long, and those need to be four digits long. So if that reg X doesn't match in the second line there for those query parameters, that actual request functor is not going to be run. So this way I can overload on the query parameters. I can also overload on the accept header. So if you're familiar with, I think some of the other frameworks use the thing where you check it and you sort of have, okay, if it was this format then do this and this format then do that. In ways what you would actually do is for each of the different formats you might specify different functors to actually handle that kind of scenario so that they're just distinct request functor methods. So there's a lot more to request DSLs. We're documenting frantically. We just pushed out the 081 release of waves actually this morning. So there's a lot of things you can do. You can do most of the typical things you'd expect, capturing path components, matching them against regular expressions. You can also do kind of wild card matching, saying, you know, match against 0 or to n or 1 to n or even 1 to 3 components if you know that it's specifically going to be 3 units. So there's a lot of flexibility there. You can do path generations same paths and rails. So there's a lot there. The documentation and some tutorials and so forth, some sample apps are actually on the website. So I'm not going to try to go through each one of these examples because there's a lot of possible combinations. But the main thing to think about here is that this is really a DSL intended, ultimately it does not at this time, still 0.8 and we're still building out some of this. It's intended to be able to match against the entire range of possible requests that can be expressed in HTTP. And that's sort of the key to being able to write truly resource-oriented apps is to really take that request seriously and inspect it and do interesting things with it. But at the end of the day, just to kind of hammer this point home, all we've done is define methods on a resource just like when it's actually instance methods on a resource class, but it's pretty closely, it's about as close of an analogy to HTTP as you can get in Ruby, or it might not be, but it's as close as I've been able to figure out how to get it. So I don't want to overstate our success there. But if you look at this here, we're just saying, hey, let me check to see if I actually have a method called get put post-delete on my story resource. This is from an actual sample app that you can find in my GitHub. I'm D. Yoder on GitHub, and there's an app there called Pages, which is an open source CMS based on, multi-tenant CMS based on waves. And so this is actually code I ran just to demonstrate that that actually is really just creating methods on a resource. Now, each application typically is going to need to handle more than one resource. And this is, I think, a big advantage of the resource-oriented model with waves, the way it works, and I'll get into why in a second. It's important to understand that there is the typical, unless you have a very, very simple app, which I'll show you one in a minute, unless you have a really simple app, usually you're going to have a lot of different resources, and it's not that different from having all the different controllers or models in an MVC type of framework. So you're not, you know, unless it's a really simple app, you're not just going to have the one resource that's going to handle everything. You're going to have a bunch of resources. And the way this is done is that there is a sort of proxy resource for the entire application that sort of says to the web, if you will, look, I represent all of these other resources. I'm their agent. And so if you want to get a hold of them, you know, send a request to me and I'll make sure that they get the message. And with these proxy resources, and for historical reasons and waves, they ended up being called maps by convention. You don't have to call them that, but that's what you'll see a lot. Because we used to have one big, what we call, it was like our routing file was a big map file, and then we realized, wait a minute, we can break this into pieces. So what we do is, you know, we say, hey, you know, just look at enough of the request that you can figure out where this guy goes. So for example, I might actually look at the first component of the path, and that will tell me, that kind of will tip me off which resource I'm going to. It could be a subdomain matching. Because again, we can match on anything in the request or we're getting there. We can definitely match on domains today. So I could say, well, if it's this subdomain, it's actually going to this resource, or if it's this path component. So I'm trying to do, like, you know, just enough, I don't want to look too much, because then I slow things down. I want to look just enough to figure out where I'm delegating this to. And then I'll send it off to something that actually does a little bit more detailed inspection of the request. Now, that structure is a little weird and takes a little bit of getting used to, and we had a lot of back and forth in arguing about whether or not moving away from the more conventional notion of just having all this stuff kind of in one place was good or bad. And I'm going to try to convince you that it was a good decision. There's three main reasons. One is that resources are just ordinary classes. So now I can do things like inheritance or mix in things. I can leverage the full expressive power that Ruby gives me to sort of support reuse and good modular encapsulated code design. Right? There's not a special kind of construct. They're just methods on resource classes. Instance methods on resource classes. So now I have inheritance in all of the power of Ruby if I want to use it or mix in. The other thing is, if any of you have ever dealt with large applications in Rails or any other kind of route based framework, one of the things that happens after a while is it starts to get really, really difficult because you get enough of these things in your app and it's hard to know where to insert the new one in or exactly which thing is matching that request. I mean, you have to sort of go through the whole thing. By breaking this down and following just basic software design principles for this, we get really quickly to the point where, you know, hey, we've got five or ten request functors in a resource, a typical resource, or 15. And you can use the same metrics that you would use with any class to say, well, maybe we need to actually further decompose this resource into multiple pieces but it's a little bit easier to understand what's going on. And then, accidentally out of this, we actually picked up a little bit of a performance benefit because if I go back through this picture real quick, the map actually will take a look at a handful, like in this case I'd probably have four actual request functors in my map trying to figure out where to route things. And then, so I've made it most, you know, on average probably two or three comparisons there. And then I only have, you know, a handful in each one of these. So instead of, if I had maybe a hundred or fifty of these routes in a normal routing situation, I'm actually only, and I might on average say, look at, if I tuned it just right, I might be able to get it down to an average of like thirty comparisons when I'm doing my matching. In this case, I'm actually only going to match on, you know, eight or something like that. A few in the proxy, the map resource, and then a few more in the actual resource that I'm delegating to. Also, I'm a little bit remiss here at not talking a little bit more about the notion of foundations and layers. So, as I said, it's an architectural framework for resource-oriented architecture. Waves is. So, here's an, this is a very simple example of what I'm talking about. It sticks in a bunch of stuff, the sort of bare minimum that it takes to run a waves app in what's called a foundation. And so, we've got foundations and we've got layers. A layer is just a module, basically it overrides the included method and then goes to town in many cases. It has license at that point to pretty much, if you're including a layer in an application, it may even be modifying the waves framework. Taking full advantage of the fact that it has classes and so on. Now, foundation is just a layer that says, look, I guarantee you I'll do the, I'll bring in to the execution environment exactly the things that you need to really run a waves application. And compact is sort of the minimal version of that, right? So, in this version, we just say, look, this is bringing in a configuration. It's sort of setting up our map to begin with. And then we add a simple hello world rule and that's hello world in waves, basically. And what we're really trying to do here is say, look, we want you to have the ability to do resource oriented. We want to try to take the obstacles away from doing that and make it more natural to express resource oriented architectural implementations in your applications. But at the same time, I mean, we don't want to kind of restrict it to that and say, well, that's all you're allowed to do. So the layers and foundations essentially provide a way for you to then pick and choose the features that you really want to include in your application container. And we're decoupling that from the way that the resources are handling the requests. So, for example, we have an MVC layer that kind of comes in and then we add some additional helpers to the request to the resource so that you can use any of your request funders to call out to models and controllers very simply. So here's an example of how that would work. This is a slightly simplified version of what we call the classic being more around what the idioms that Rails and SunMBC have established. And one important point to look at is two, really. The first one is that we're saying, hey, listen, you're only going to load the code that you need at the time that you ask for it. So all of this stuff isn't sort of all into Waves course. When it comes up, if you don't use it, if you don't use the layers, you don't pay for it. You don't increase the size of your app's footprint because you just don't happen to need inflection in that application. Now, as a little sidebar, just the last couple of days, one of the things that one of my colleagues came up with is this thing called Hoshi that you should definitely check out. And it's a new, it's kind of a Markerby-like, but it takes some of the things that are tricky about Markerby and takes them out. The Classic Foundation today does not use Hoshi, but I put it in there just for fun. We will probably have it in there shortly. If you go to, well, I think I have a link here later. If you go to GitHub slash peep, I think you'll find the project there and the source. And it'll be released as a gem, hopefully shortly. Very cool stuff. So then the next thing we do is we include those layers into the application and in turn they go do their thing. So this guy is obviously really just sort of a composite layer. It doesn't really have a whole lot that it's doing. Like I said, this is a little bit simplified. Here we're basically layering in some of the intelligent code reloading features. Note on that, it takes a little bit of learning, but if you study the way that the Classic Foundation is set up, you'll notice how the code reloading is totally configurable. So if you don't particularly want to have a directory, say, called views and you want to call it templates or you want to call it foobar, you can actually set that up so that the app knows to load foobars from the foobar directory. It's a whole DSL for setting that stuff up and that's what that auto code guy does. And then we're bringing in MVC and inflection and some helpers for the views and so on. Those aren't the only features. Those are the big picture features. I know the description of the talk said I was going to walk through an app, but I still feel like I'm at the point of kind of introducing people to what we're doing that's a little different. I could do the five minute blog demo, but A, most of you have seen variations of that by now probably 30 times. And B, we have those. I mean, there's a sample blog app that's in the... If you install the gem and then you go look in the samples directory there, you'll see a blog app and we're going to have a whole bunch of sample apps coming out. Well, their pages is one of them. If you go to my repo and look at pages, you'll see one. So there's some sample apps coming out and hopefully between that and some tutorials that we're still in progress but that are rapidly kind of coming online. There'll be enough for you to be able to walk through building an app and picking even which sort of flavor of app you want to experiment with. So obviously, I'm not going to be able to go through that in the remaining time, but one feature here that I kind of want to emphasize that is a subtle one and it's a little bit difficult to talk about because there's not any specific thing that it does. But throughout Waze, and hopefully if you were looking at the source code, you would start to see this, is a desire to try to think before implementing something, how does Ruby already implement this? So Layers is a great example of that where we realize there's already an included hook for modules that gives you pretty much a license to go do anything. And once you're in there, you know, you've just been included, you know, you can go crazy. And so there was no need for us to think in terms of, okay, do we need a component API or a plugin API or something? All the pieces in Ruby are generally there. Inheritable configurations is another thing. We just define basically accessor methods for configuration values on a class. And since class methods are inheritable, that works out great. You can have a whole tree of configurations if you have a really complex set of deployment scenarios. You know, no big deal. You can just whatever's changing in each one of those, you can inherit from, you know, higher, more abstract, you know, development becomes, you know, development and then subclassed into test and maybe production has, you know, QA or staging and so on. So everywhere in Waze, we're trying to make use of what Ruby already does because that's the main point of the whole thing. The whole reason I, you know, the whole reason I code in Ruby is because I love what Ruby does and not, so the framework's trying to stay out of the way as much as possible. So this is my nephew who just had his first Halloween and that's how I feel about Waze. You know, we're just getting going. We've got our little rocket scooter, you know, we're feeling, we've got our, you know, our little costume on. We're feeling pretty sexy and ready to go. Now that said, we have a long ways to go and we're definitely interested in, there's a lot of things on the roadmap. I'm trying to keep, if you go to rubywaze.com slash roadmap, you can see sort of the things that we're looking at working on. We have sort of a planned monthly release schedule that'll be coming out. So if there's things on there that you're particularly interested in doing, you know, let me know because, you know, there's plenty of, you know, plenty of help needed to get all those things done and the more people that are kind of involved in it, the better. So far, I mean, we've had some people come in and out, a lot of really good contributors, but the main thing about it is that they, you know, every one of them I think has, even if it wasn't something that's still sitting there and their legacy isn't always in the code, it's in the code that we rewrote because they had ideas that were better than the ones that we started with. So I won't go through this, the whole roadmap here, but this is kind of a snapshot of the things that we're planning and working on and one of the things that I found by focusing more on resource oriented is an architectural paradigm that needs more support within the Ruby framework world is that it seems to be taking us into implementing features that are a little bit neglected or there's not a lot of things done around them. You know, there's a thing called RAC Cache which just came out, which is a RAC middleware. Wage uses RAC if I didn't mention that. And, you know, it does a nice job of beginning to implement HTTP caching properly so that you can just leverage the RAC Cache module. So this stuff is starting to happen but the fact that there wasn't a RAC Cache module to begin with kind of gives you an idea of, you know, we're maybe getting into new territory so I apparently have to wrap up. I'm taking all my cues from this guy. I gotta go sit down with him, have him coach me. So we... What's the... I guess that's good that it's not a relative but I have no idea who she is though so she doesn't even know my name. You have to have the one gratuitous photo with a name like Waves. I've only begun to scratch the surface of what's possible with the imagery. So we're on GitHub. We're on Google Groups and Ruby Waves which we do, we check all the time. It's not terribly active because mostly we're on FreeNodeNet Waves, Waves channel. So we're... I'm on there every day. We've usually got two or three people at least sort of on there answering questions and arguing about why my last commit was stupid. And then the website RubyWaves.com So, you know, that's basically it. I wouldn't... We were missed if I didn't give a shout out to some of the folks Krishna over here, so there he is. Pete Elmore, a couple of my colleagues at AT&T Interactive and a number of other folks Nanorails Lawrence Pitt was CopaWaves who've all done a great job just like I said. They've left a lot of great ideas that are now baked into Waves because of their feedback. So with that, I hope you came away with a better idea of what Waves does and you'll check it out and maybe play around with some of this stuff and give us some feedback and maybe get involved. So, thank you.