 The talk that you guys have found yourselves in is better hacking with training wheels I'm gonna keep it short because I'm efficient But you're gonna get your money's worth I'm gonna introduce you to a Ruby library that you all Already need I guarantee you need it And you know, I don't know why I know what to put it out there before but I'll do it just to get it started just Give you a little bit of history train wheels has a you know, quite a rich history It's been online for two days now about 40 hours more or less and I Came up with this idea When I was just I was tripping out of my mind on On RJ DJ anybody try that Some somebody knows I'm talking about if you guys have iPhones get our date RJ DJ it'll it'll expand your horizons But so anyways, I came up with this idea based on a simple concept And that concept was we all have a stake in each other You know, I don't think I have to sell this concept anyone here You know if you guys are you know part of conferences and stuff like that. I think you understand that But what I didn't want to do is misrepresent my talk. I know this sounds kind of like collectivism So I wanted to offer some evidence to the contrary But this is not about collectivism. That's how you can get hold of me That's It's not a joke. I'm really capitalist on on all that stuff Anyways Back to my point. We all have a stake in each other and what I mean by that is It's nearly impossible To exist in a vacuum and you know in the Ruby community Almost everything you do, you know, just by the nature of the way we break up our work and the nature of the way You know everyone contributes you're using other people's libraries for everything you do or you're using their platforms to run your stuff on You know, it's kind of just the way separation of labor has occurred in the Ruby community so You know because it's evolved that way we all have a vested interest in each other to you know to help each other grow and You know and some would call it you know altruism, you know Ruby people are nice people You know others like like myself, you know, it may be that you know I want to see you guys do well because then the Ruby community as a whole does well and You know, I make more money or have more friends or something like that so One of the things that we do as a community is we talk about what we do a lot So like parsley and my feed reader I've got like probably a hundred of your blogs and you know It's really difficult to keep up with everything. You know if I go on vacation for three days, you know I've got 2,000 entries to read when I get back I watch everyone's peep cast so our screencast if you may want I've seen it so You know I try to keep up with with all the best practices that you guys are sharing with the libraries You're putting out there So if I encounter that problem then you know then I'll know about the library and know it exists but what I wanted was a more efficient way to To have that pop up when I need it so, you know, let's say today. I saw a talk on You know little tricks to increase performance, you know of your application, you know I mean little stuff like don't do a nil check because you can use whether something has a value or not as a boolean So you don't need the extra method call and just stuff like that. So I want to be reminded of those things like I'm I have terrible memory I want to be reminded of those things when I need them. So that's what training those is all about is You know, let's make a portable way To to introduce or to pass around all these these will be idioms. So Yeah, that's that's my unicycle I'm still still learning but So when we talk about a best practice or you know or an idiom or you know, the best way to use a library You know, we still do it in text, you know, we passed around and blog posts or we do videos and stuff like that But we're rubious So, you know, I would like to see us do that in an automated fashion in a way that you know We can share it with everyone and they they get it when they need it So this is an example of kind of how we work now You know, if you're working on a library or or something like that You know, you're writing your ruby code You're writing it to to see if it does what you want and the Ruby interpreter is going to ensure that you have valid syntax Because you know, what happens if you leave an end out, you know, you're going to get a crazy error that unexpected in because it Wanted a K in or something like that So it's you know, that's type R. That's you know, syntax checking built in so the next step is testing one of the things that has just been absolutely harped on and That's a negative connotation, but you know, just really reinforced by by everyone is testing You know, whether it's test unit or our spec or should it we want to verify that our results are what we expect them to be all the time so So testing kind of verifies our results, but the problem is there's nothing in the middle. We have, you know Basically all this flexibility available to us, you know, as far as Ruby goes But we have nothing to you know to ensure that we make good use of it And we don't have literally nothing there's like this is becoming kind of fashionable as of late to do Code analysis like treating the code is data And there are some really awesome tools out there that you know, they're a fairly young Like flog and and heckle and flay and they all do like, you know a certain kind of analysis whether it's you know checking for duplications or You're mutating your code to see if your test still pass or something like that So they do a good job of treating your code is data to analyze it and make sure that you're doing You know this stuff, but what I wanted was an easy way to To dash off, you know a certain example. This is a pattern I just saw and I want to use it, you know when I need it So I put together this slide where I started thinking about Here's all the scenarios where you could use something like that So let's say you had a way to easily encapsulate one idea one best practice pattern Well, if you're learning a new library, how many people? Raise your hand if you like you pick a library that you're going to try to use and you just fire it up You don't go through all the docs. You know, you just try to actually instantiate whatever it is and that's actually about half your hands If you're learning a new library imagine if it had like a directory that shipped along with it called wheels and in wheels was just This the small set of classes that the library developer put in there for you And this goes for the publisher library as well. They put in there for you and as soon as you instantiate a class that you weren't supposed to or you know, you start using this You know it could tell through analysis looking at your code Like what you're trying to do and suggest via either standard out or you know a ground notification Whatever suggests some way for you to you know to actually use it the way they intended And so as a publisher what you know, you could cut down on like a lot of like questions I don't know if everyone here has published something open source, but you get a lot of questions and they're the same questions over and over and Open source developers like the ones I've encountered are incredibly gracious about answering You know the same questions over and over But the slide that we saw in Matt's keynote this morning that said we're gonna have four million Ruby developers You know that kind of scared me because I'm not sure how far that's gonna scale and I'm not sure if you know If everyone's gonna shut down because they have four million Ruby developers asking them You know, how do they use their library and stuff like that? So those are a couple ideas if you've ever trained a colleague I've had to do this a couple times and one of the things you can do is You could just automatically have whatever your you know your corporate You know data style requirements are you can encode those in Ruby and you know and actually Drop them in the developers wheels directory and that you know that style would be enforced as they're working So and lastly I've learned Ruby down there Just because you know with with anything you could have these training wheels running just against playing Ruby for you know Common Ruby idioms and stuff like that So let me get into a jump into what a wheel actually looks like And this is just my start on on a DSL for a way to encode Idioms right so Here here's one where I'm working on the or a sign operator So if you're new to Ruby you've probably never seen that operator You don't know how to use these these methods trigger and suggest Those are just you know what I came up with You know when I was dashing out this prototype for this talk You know trigger would be what it's looking for You know so if you do a you know an actual mill check just to assign a variable it could spot that And just to give you an idea of how I started doing this under the hood There's a tool called parse tree And you know I'm sure a lot who's familiar with parse tree All right looks like about most of you so parse tree breaks your code down into a standard structure called s expressions and so what's cool about code like this is Even if I did that if condition as a post condition the s expression comes out first with the same So a matcher can you know still match it up regardless of how they actually chose to write it? So what you do like what trigger does is just break that code down to an s expression And then as it's analyzing any of the code they write as they save files like I stole I stole the file checking stuff out of our stakeout if anyone's ever used that so just sits there and runs Every time you save a file analyzes it and tries to match it up against these patterns And then right now suggests all it does you see it's just a string because it just spits it out and standard out But when I was playing around with this I had it spit it out to I piped it to say on the Mac So it was you know it was reading it out to me So I didn't have to go look at it and then you know I shot it out to growl But these are just you know two methods that With just those two methods and a DSL you could do a whole lot Well, one of the things I want to do when the other examples was I was going to do a framework example And so I wanted to do alias method chain There we go So I need to introduce a little more flexibility So I made it where with with trigger you could pass a block to and if you pass a block It basically works where the first pattern that's like Says pay attention to whatever's blocks is pay attention to or do whatever this block says So it spots this first pattern and immediately rewrites what it's looking for in this case to you know to spot this second pattern So if it sees you alias method twice in a row, then you know it can suggest alias method chain and You know this this exact example is a little brittle because maybe you really alias method twice in a row for a good reason And I'm not doing any analysis on the literals and the prototype, but you could So maybe you could make it as strict as if they did some method without Something then you know, they're just adding a feature. They're decorating a method that already exists So that's just an example of you know, how flexible this DSL could get while still being really readable Like if you have a thought I want you to be able to just really you know jot it down in a wheel To remind yourself when you need it and and drop it in like a wheels directory in your home directory or something like that So if you know if we can get you know just a handful of people in the habit of doing something like that Then we can end up with this you know this giant automated library that enforces good patterns so It's also really easy to add other methods, you know, so based on like what James was saying I don't have to put all the stuff you could do In here you guys could open this up You know just download training wheels and open it up and add your own methods to the to the DSL And so here's an example of that one So let's say on my alias method chain. I want to do some more Explanation, you know air the blog had a good a good article explaining it So let's say I wanted to you know to drop out to a gist that everyone can work on and fine-tune the explanation So that you know that people get it. Well, you know, I could have a method You know this method I wrote and just included in there to illustrate that is you're just just with the just ID and So as soon as this pattern is triggered it'll just you know open up that gist and you know, and that's it so Like I said, this talk is it's pretty short But that's the repo that the train wheels is in and so Anyone have any questions Very good Right now you can't do because right now all it's doing, you know It's just to illustrate this that we need this way to you know to encode these idioms This is all I dropped in but you know, that's a great idea for a feature And so, you know, maybe we could have it where the trigger takes like I want something That's pretty like a hash of you know Here's pay attention to literals or you know, don't pay attention to this method name because maybe they'll use blank or something like that Or you know, maybe we can do it with with interpolation right there in some way that looks pretty You know where we interpolate something, you know something in there that indicates this part can be anything So does that answer your question? Once I get to the part with the literals like the args for a method or something I ignore it because I haven't put in My bar equals anything What you want? What you might want to consider is a way in the trigger to say my bar equals Anything and that anything means ignore the expression from here on down That's actually how it is now because what happens is it sees a variable in this case an instance variable So it sees I bar Assignment and some literal so that's actually how it is now is because once it gets to some literal It doesn't care what you're signing. It just says, you know, you're signing a literal so and actually Really, we could make it even more general than that because what if you're signing another variable that will trip up the matcher right now Because it's looking for literals only so we have it where just because it sees this assignment After a after a nil chat, then it knows that needs to you know suggest this certain pattern Yes That's the thing that I thought of and that's that's not built in so we have this is like Conditional trigger Right, so we have this now, but like what you're saying is like there could be Five ways to suggest, you know that you need to suggest something and so yeah There's no reason that like right now all it does as soon as you call trigger It just stores an instance variable with that s expression in it. It's just called trigger pattern there's no reason we couldn't make trigger pattern an array and then you know when it's passing in the nodes to that Wheel to check if it matches they could just iterate over that array and and see if any of those match Does anyone have also besides questions? I like to hear ideas of where this would apply because you know I'm just starting on this and you know so anything of where it could apply would be useful So you know what the code looks like now and you know what you want it to look like based on the suggestion So auto refactor it say right now it says dot now actually replace that with or equals Yeah, you could do that like so let's say you captured the literals that they used you could Output you know the exact code to copy and paste into there. So You got a contextual suggestion as opposed to just you know, here's you know Here's an example with your code yeah use remind me another another idea had in that performance talk What if you had like a block that was like? You know this method ran in you know two seconds But you could profile it like right there on the spot and say you know if you change it to This it does the exact same thing, but it runs in you know 1.5 seconds or something like that But there's no reason this DSL couldn't have stuff like that in it as well Any other questions or ideas This is like great for kind of Tactical level three factors like language usage stuff, but larger kinds of refactoring you would really need more You need to be able to stay sort of more state or something so you could say this entire application as Too many classes or they're too couple or something like that It doesn't like right now this thing's reading code from files But partially can read stuff right out of the object space so you could have it you know Rooting around in the object space and looking for you know for certain patterns that you used you know Across files that you couldn't spot just within one file. So yeah, that's something else I thought of or like Somewhere else this would be useful Where I originally tried to do something like this was Upgrading to rails to a long time ago and it came out You know if you're one of the problems with web frameworks is when you change something everyone freaks out and So you know it takes a long time for those changes to actually propagate across You know all your users where you know they're used to it They're comfortable with the new way of doing things But if you know if training wheels shipped along with your app if there was a set of wheels that just went through let's say It's pagination and went through and saw everywhere you were doing pagination Which would be really easy and says you know we use plugins for this now your choices are classic or will paginate You know or something like that it'd be really easy There's something there holding your hand as you're trying to upgrade your app to the newest addition of you know of that framework Yes, sir There's a lot of cases where You're gonna want to do stuff with literals like let's say you know I was using Some some configuration some library that requires a configuration and I pass in some number that just doesn't make sense Like to a method that has an acceptable range what we might do now is Like raise an error. That's just a string to alert the developer That's really annoying it stopped and you know and the program airs out and stuff like that Well, you can have a training wheel that just like actually looks at the literal arguments and says that's not a good idea Here's why Like this is my proof of concept I'm saying you're right that they absolutely need to have a way to to work with the Yes, sir When you see this pattern So maybe maybe one of the ways that suggests could output stuff is is by actually raising it as an error for for continuous integration I even think though Suggested and there might be like an error Where instead of suggests you just call air and then it knows like we could have suggest or growl or say or air or you know Yeah, and just yep and build out this this like I'm not the best library designer I've put this out here for that reason to put it out here and to get people interested in it Because I want to see the community You know develop this automated way to pass patterns around because I want your patterns Yes, sir It actually does yes to both cases like I was being lazy with the example when I picked I did the nested trigger just to show that hey we can pass blocks to these things that allow us a lot more flexibility That's why the tile size more flexibility is a really bad example to just use another pattern That needs to see because it absolutely could have and would have actually made more sense to just be in the same trigger in the first place Yes I haven't seen that one so it I mean I'm judging by the name. Oh the question was you know Have I seen reek? I'm judging by the name that it does like maybe code smells, you know, just Okay, I just say they're in general the problem with smells and and detectors like that is You know you guys know that a lot of people are very opinionated So I wanted something that was more general where the the whatever you're looking for is outside of the library So if you don't like it, you can just delete it, you know, just take it out You know, and maybe we'll have a way for you know to have like a wheel RC file where you can permanently ignore certain wheels that you don't ever want to see Yes, sir I'm sorry, what about You What about triggers in the absence of code So, yeah, we could have like let's say a trigger that That spots, you know in the case that he gave is multiple saves Maybe they need to be in a transaction So, you know, maybe the trigger is actually those saves and then it looks like you know The framework stores for the wheel the previous nodes that it saw they could go back and check if it saw a transaction And say, you know, maybe you should use the transaction The other questions. Yes, sir. I like the idea So in the proof of concept that I put on github, there's a bend directory and there's a binary called training wheels And there's one called training wheels auto and the only difference is the training wheels one you you pass it a glob and It just runs any wheels that can find and right now it looks in the examples directory But I'll probably make it look in like a home wheels directory I mean the training wheels auto one you run it like auto tests or something like that You know, it runs just like our stakeout because that's where I copied the code out of And so with that one you just run it and every time you save a file It'll reload that code send it back in a parse tree and and parse tree will pass all the nodes to all the wheels that are Make it as a plugin for common frameworks to where you just load it And so if you have the server running training wheels is running, you know, as long as it's in development mode or something like that So his comment is that you know, maybe we can make this even cleaner by By doing something like story runner and that's that's a brilliant idea Like we could use like a treetop or something like that and actually do like some kind of parsing where we can get You know even cleaner with with how we run this Like one of the things that irritated me when I was making this proof of concept is I needed to instantiate the wheels because I needed to be able to run multiple copies of them Like let's say you you spot one alias method while now I need another wheel looking for it again If you want to run a separate instance of that because now this one after it spots at the first time It's looking for the second instance, so I Need to instantiate them So I had to put those methods and initialize block because I couldn't figure out how to go from a static class method Which is how I started with these and somehow write that down into an instance Variable, so I ended up just wrapping the whole thing in initialized block, you know just to get it done any other questions Yes, sir. That's where it is online What sense Rather than In addition to reading the code and finding out what I may have just misapplied your attention They were to give me a little block of introductory You know, we'd be type info. I don't know. Maybe that's just over the time Yeah, so Here's what you can expect out of it. And by the way, you're done You didn't read this first You know, maybe there's a way that we can output more documentation other than like the examples I had had just a sentence and That's that's actually the main reason I put in that gist method was I was thinking, you know along the same lines that you know if you farm it out to gist then People can fork that documentation if they don't like it So like if they're gonna give that wheel someone else they can fork it change the ID and say Here's my better explanation of this, you know, this certain pattern or something like that And that's the same reason it's on github. I mean, it's an amazing tool And so I put it on there and you know and really the tool says really in place I think for the first time for us to do something like this with With parse tree and unified Ruby and Ruby Ruby and all that stuff We have such in like a robust tool set to actually do something like this for the first time and to my knowledge We'd be you know the first, you know large community doing it So with github like, you know, I'm gonna be a steward of that thing I'm gonna be looking for everyone fork in it and you know any good ideas that they have in there that we can You know, we can move over what I'm hoping is you know developers better than myself really, you know Actually think it's a good idea and really jump in and you know and fork it and something like that Another thought I had based on the documentation veins What if we could do something with with the way our dock works now where like you get your wheels for free somehow? Just by doing something, you know along with your your stuff that you put in for our doc But you know, I don't know our doc won't have to actually come up with with anything concrete on that Any more questions? All right, that looks like it. I appreciate you guys, you know, spend your time Learn about train wheels and if you have, you know any ideas at all You know either for the repo or at the very least Twitter them over to me or something like that Because you know, I want to see the same build out and us actually build a catalog of wheels for Ruby and you know And all the big libraries and stuff like that Thank you