046 RR Objects in Rails Part 2
The Rogues discuss Objects in Rails, part 2.
Show Notes
The Rogues discuss Objects in Rails, part 2.
Transcript
JOSH:
Oh, you know, I finished all of my water. So if you can wait 30 seconds--
CHUCK:
Yeah, 20 minutes, we are going to have to wait 30 seconds again so that he can take care of all the water he drank.
AVDI:
[Laughs]
JAMES:
That’s awesome.
CHUCK:
We are going to hear his chair creaking because he is wiggling in it.
JAMES:
Yeah, I know. We should have intermission music. [Music plays]
JOSH:
Somebody got shot?! What?
JAMES:
[Laughs]
JOSH:
What did I miss?
[This podcast is sponsored by New Relic. To track and optimize your application performance, go to rubyrogues.com/newrelic]
CHUCK:
Hey everybody and welcome to Episode 46 of the Ruby Rogues podcast. This week, we are going to be following up our discussion that we had with Jim Weirich about six months ago, about “Object-Oriented Programming in Rails.” And this week on our panel, we have Avdi Grimm.
AVDI:
Hi I’m Avdi and by the time you hear this, my new book “Object on Rails” should be available for anyone to read at objectsonrails.com.
CHUCK:
Alright. We also have James Edward Gray.
JAMES:
Good morning everyone!
CHUCK:
We also have Josh Susser.
JOSH:
And here I am.
CHUCK:
I’m Charles Max Wood from teachmetocode.com. And let’s go ahead and kick this off. I know that you guys have been thinking a lot about this and so I’m kind of curious to see where it goes. So, does somebody wanna just jump in and start talking about something? I suppose we should mention Avdi’s book even though he told us that he didn’t wanna promote it.
AVDI:
Yeah that’s why I started out the show by promoting it. [Laughter]
JOSH:
You got out all the “shameful” self-promotion out of the way.
AVDI:
[Laughs]
JAMES:
We are going to talk about Avdi's book against Avdi's wishes.
CHUCK:
Yeah I didn’t get a copy of it so I don’t even know what’s in it.
AVDI:
What?!
CHUCK:
It must be good. [Laughter]
JAMES:
You're not on the end list? [Laughter]
CHUCK:
I tried to just shame my way onto it just now.
AVDI:
Everyone gets hooked up by the time this goes out so. [Chuckles]
CHUCK:
You are releasing it for free online or something?
AVDI:
Yeah it’s going to be free to read online and then there’s a downloadable version for various eBook readers for $5.
JAMES:
So Avdi, what made you decide to write that book?
AVDI:
I think laziness.
CHUCK:
[Laughs] Book is a lot of work.
AVDI:
Anybody who’s been to my blog knows that it’s named after The Three Virtues of a Programmer -one which is laziness. And it was just a matter of I kept on getting into these conversations at conferences or online and stuff about doing OO and Rails, and things like… the fact that I like to start out with just plain Ruby objects that model my business concepts and then sort of add persistence in later as an afterthought and treat Active Record as an implementation detail and stuff like that. And I’d always wind up saying, “Well, I’d write a blog post about it -- to explain what I’m talking about.” Then I finally started writing those blog posts and they got bigger and bigger and turned into more of a book.
CHUCK:
Yeah that’s kind of how often I hear that happening, where people kind of wind up writing like a dozen or so blog articles and they are like, “I still have so much more to write about!” And then they realize that they yeah, put in a book.
AVDI:
Oops, I accidentally a book. [Laughter]
JAMES:
I’ve read the book and it’s neat. It’s kind of an exploration of how can we do object-oriented design inside of Rails, how they kind of makes sense. And it just kind of neat because it just kind of explores around and plays with different ideas. And as usual, with Avdi’s writing, it has some neat tricks in it. My favorite thing I learned from it is whenever he is manipulating time; he always passes in the clock object. So basically, it could just be the time class or something but then, by doing that, he is later able to change the clock object for his purposes – be it testing or forcing some particular scenario or something like that. It was pretty cool.
CHUCK:
So Avdi, where did you learn to manipulate time? That would be a handy trick to know.
AVDI:
[Chuckles] Gallifrey.
JOSH:
Right answer. [Laughter] I’ve used a different technique on that. There was an internal library at Pivotal that predated Timecop that we called a “clock”. And instead of using time -- the time class -we used the clock class and it was just easily hackable time global. I prefer actually passing it around as an argument like Avdi recommends, but hacking the global works ok too if you are multithreaded stuff.
JAMES:
Yeah I’ve used Timecop in the past, but actually when I read the book, I thought Avdi’s approach was more clever. And I can’t remember the exact example now, but at one point, he needs the time to be a certain thing. So he just makes an object that returns the right thing and passes that in.
And it was really cool.
AVDI:
Right. One of the examples that I gave is that you know, it makes the testing easier but then later on, if you decide, “Oh, I need to do something like postdated blog post,” or something like that, it’s very easy to come up with specialized clocks which do something a little bit different from the regular clock. So there are some versions to it.
JAMES:
So the other thing I thought that was kind of cool about the book is how non-radical you are.
AVDI: [Chuckles]
JAMES:
You know, you just kind of say, “Ok, let’s start with a Rails application, yeah. But I'll just make some normal Ruby objects and then I'll work my way up. And oh, ok maybe now it’s time to inherit from ActiveRecord and stuff.” where I suppose most people kind of have almost crazy ideas about the way to structure an app like, “I’m going to move all these in to lib. And you know, until we roll that off in its own little garden” or whatever, and you took -- I thought – a real pragmatic approach.
JOSH:
Yeah.
AVDI:
Oh, go ahead.
JOSH:
Well, you know, respond to that and then I have a question.
AVDI:
Oh I was just going to say, I think it’s a good segue into this episode in general because I would shy away from saying, “Rails encourages bad practices, we must bring object-oriented programming back to Rails,” because that’s ridiculous. I mean, I’ve been sort of hearing some things like, “No you are not extreme”, but I’ve been sort of hearing stuff like that lately. And you know, Rails sort of made concrete a bunch of pretty solid patterns that came out of the classical object-oriented programming for enterprise applications literature. So, I mean there are definitely some oddities in there, but there is also a lot of good stuff in there and there’s a lot of good practices. And especially with Rails 3 now things are getting a lot more modular and pluggable. It’s a really good foundation.
CHUCK:
I just wanna point out too that one thing that I have found in programming Rails over the last 5 or 6 years is that, in a lot of cases, there are things that I look at the controller, I look at the model and go, “I’m not really sure what the right API is to do this,” and I go hunt for it and I don’t find it. Well it is, it is a Ruby class. And so when it comes right down to it, you know, if you treat it like a Ruby class, then you can get whatever you need from it. And there’s a lot of power there that I think a lot of people are like, “Well there's not a build it Rails API for it so obviously you can’t do it,” then it’s just not the case.
JOSH:
Ok so let me follow up with the last point on Avdi’s book before we spend too much time on it. But I wanted to ask Avdi what is your intended audience in terms of experience level. And let me unpack it a little bit and say that there’s say three types of developers who are working with Rails applications -- beginners, intermediate and advanced. And I think a lot of what you are talking about, I wasn’t really sure where in the maturity level you were aiming for. I found that a lot of what you were doing was either… it seemed potentially really tedious and maybe oriented at someone who was maybe less experienced in building those kind of patterns. Just like walk it through everything.
AVDI:
Well that’s— [Crosstalk]
JOSH:
Or, on the other hand, you can look at it and say, “This is a pretty advanced technique because there is a lot of discipline and methodical process here,” and you have to be advanced enough to be able to operate at that level. So I’m not really sure what was going on.
AVDI:
At risk of limiting my pool of readers, I kind of felt like I was aiming it more towards intermediate to advanced developers -- mainly people that have a couple of Rails apps under their belts because I’m definitely… I mean there’s total familiarity with the framework already assumed. I'm not stepping anybody through how Rails works. As far as like the tedious bits, that a good point. What I will say is that, you don’t have to follow along step by step. I guess one thing I’m trying to do is sort of step through these, like, tedious disciplines for you and just sort of demonstrate maybe some of the positive things that can come out of going through those disciplines -- if you every now and then decide to do them methodically.
JOSH:
Mh-hm. OK.
JAMES:
So I like what Chuck was saying a little bit kind of moving a little bit away from the book I guess and talking about how about Rails is just Ruby under the hood -- or maybe a layer on top of Ruby is a better way to think about it. And I think that insight is one of the key insights to getting better at programming Rails. I worked with multiple people before where I’m talking them through something and then I say, “Well let’s just make a class for that,” and I'll just create some file and app models or whatever and build some plain old Ruby object and throw it in here. And you can tell this is a light bulb moment for them. You know, like “Oh, I can create a class that Rails didn’t create for me.” It can be part of the system and work normally. And you know, I feel like… I often write a controller methods or helpers that take blocks and then I call them all over the place, customizing the inner bit using the block code or whatever, and people don’t think to do that. And I think it’s just that because Rails is kind of structured and stuff, people feel like a bit of a resistance to veering off the path and once you tell them that’s ok, kind of opens up a whole new world for them.
CHUCK:
James, you are such a rogue. [Laughter] Quit breaking the rules.
JAMES:
You know me.
AVDI:
I don’t know about you guys, but I’ve almost never used generators. I think the only thing I really use them for is creating migrations.
JAMES:
I do actually use the generator just because I was on a Rails app one time where I spent like a day debugging something and it was because somebody had made their own model object and put a typo in the class definition, like the first line of the file. And the quickest way to get Rails to get horribly, horribly wrong is make something go wrong when loading.
AVDI:
Yeah.
JAMES:
It always surfaces as like some bizarre error 90 million miles away.
AVDI:
Especially in development mode.
JAMES:
Right. Yeah, in development mode.
CHUCK:
That’s funny. I tend to use the generators… It would be less than half the time, but I do find them kind of handy if I just want to create a really quick boiler plate restful, you know, interface that I can just play with and not really have to worry about. But the funny thing is about half the time, I wind up using the generator just to get the structure in place and then heavily modify what’s there.
JAMES:
You know, spoiler alert, but I’ve heard there’s this cool book called, ‘Crafting Rails Applications’ that shows you how to modify the generators to make them do whatever you want them to do, which is kind of cool.
CHUCK:
I should read that book.
JOSH:
Yeah you should. The last week or so, there was a conversation on the Rails core list about removing scaffolding from Rails proper. And the conversation there was pretty interesting. A lot of people were talking about how useful scaffolding was for, “Oh, we’ll just customize it and then it will create things the way I usually do them.”
JAMES:
Yeah I actually… I never used scaffolding, and then after I read Crafting Rails Applications recently, when it showed how you could make the scaffolding generate what you like, you could just replace the template or stuff like that, I started getting kind of wild ideas of like, “OK, there’s a couple of things I do pretty often I would love to have it do.” You know, so yeah, I think I may try that in the future.
JOSH:
Mh-hm. So I think he place that we've all been talking about throwing down is about the mixture of functional and object-oriented programming styles within Rails -- and Ruby itself even.
JAMES:
That’s a good point.
CHUCK:
Do you kind of wanna set the stage there? Because I think… I kind of have an idea of what you are talking about but in some sense, I’m not sure I completely follow where you are going.
JOSH:
Yeah I’d love to. I’ve actually been whining about this for a while and I need to either write up a blog post or do a talk at a conference or something to fully expound my thinking on this, but maybe I can just do a summary here and that’s that Ruby has an interesting lineage, I usually say it’s the love child of Smalltalk and Lisp, raised by a fairly eccentric nanny.
CHUCK:
[Laughs]
JOSH:
[Laughs] And I have to give credit to Adam Keys for the “eccentric nanny” bit.
JAMES:
I'm still trying to work that through to my head.
CHUCK:
Yeah, we should have somebody Photoshop a picture of Mary Poppins with Metz’s face in there. [Laughter]
JOSH:
Yeah. Ok but and anyway, there’s a lot of functional stuff that is available in Ruby and there are several patterns that you see either in Rails itself or just commonly used in Ruby that crop up in Rails applications. And my thesis (after having done this for quite a while) is that, having two different design centers in your application makes for crazy code. Now in object-oriented programing, we have this big book of patterns. They are all object structure and generating objects, things like that. There’s also functional patterns that are very different from object-oriented patterns. And when you start organizing your code using two different paradigms, you get crazy. So that’s my thesis and I’ve been looking at all the application code I’ve been playing with for the last year or two through this lens and I see a lot of crazy. Mostly I’ve seen it in JavaScript. JavaScript I think has an even more precarious balance between functional and object programing.
JAMES:
Yeah I definitely agree with that because the functional or the object-oriented system in JavaScript is kind of unusual.
JOSH:
You can get as crazy as JavaScript in Ruby if you want to; it’s just why you would? It’s just because Ruby has a lot of better mechanisms for a lot of that stuff. But I’ve seen a lot of people do things like programmatically creating modules within a particular scope, so that they can act as something like a Closure but it’s more like how you create things in JavaScript where you have nested lexical scopes. And somebody programmatically created a module so that they can be within different scope so that they could distant variables and then pass that along to an object and that just made my teeth hurt looking at it.
AVDI:
So I have made the contention and I would defend it that JavaScript is -- from a language design perspective -- is fundamentally closer to a Lisp or other functional programming language than Ruby is. It really does have first class functions which Ruby, much as you can sort of emulate them sort of does not.
JOSH:
And JavaScript is actually very close to the original Smalltalk implementation -- Smalltalk 72. In Smalltalk 72, classes were functions just like they are in JavaScript. And they realized after a couple of years of playing around with that that was a pretty crappy way to organize your objectoriented code and then they came up with Smalltalk 76, which I think is probably the first real object-oriented language.
JAMES:
So I kind of agree with what you are saying about, “don’t have two designs” I definitely I agree with that point. Like you know, don’t your application from, “Oh, we'll do this part in a beautiful OO design and then we’ll do this other part that it’s going to talk to in a very functional way.” I definitely agree with that, but my opinion is (and I’ve actually written about this a little bit recently on Rubies in the Rough) that Ruby actually is kind of a melting pot language and takes ideas from functional programming and scripting and stuff like that. And the good Ruby is actually a mix of those concepts to some degree. So like, I agree with you that I don’t want two fundamental design principles. But at the same time, I do want to use the parts Ruby has stolen from functional languages like for example Blocks and then Closures and stuff. And I believe we can use those and still be doing good object-oriented design because-- [Crosstalk]
JOSH:
I agree.
JAMES:
Yeah, because Ruby’s designed for that, that it’s… that that’s part of what… so I guess what I'm saying is, yes I want good object-oriented design, but I want the Ruby kind, not the Java kind.
JOSH:
Right. So where I draw the line there is I will structure my code in the large. I’m very serious about having that be object-oriented and within methods of classes, I tend to use a functional style, so I have a single exit, I will pass things explicitly as parameters, I try and have very little mutable state within the method. And that seems to work great as long as I don’t go overboard with it, but I don’t do things that will break encapsulation or confuse polymorphism. [Crosstalk]
JAMES:
Yeah and-- [Crosstalk]
AVDI:
Yeah and that’s something you see in… go ahead.
JAMES:
No, go ahead.
AVDI:
[Chuckles] Well, I was going to say I started to read “Growing Object-Oriented Software Guided by Tests”, (and I’m sure I got the title wrong) recently and that’s one thing they comment on is that they find that code tends to be more functional inside of implementation of methods and then more of… in order to support the object-oriented nature of the interactions between objects.
JAMES:
Right.
JOSH:
Mh-hm. So.
JAMES:
I just don’t go all the way to like having immutable objects and then like returning a new string every time I need to make some change or something like that.
JOSH:
Oh, heck no.
JAMES:
Yeah, yeah.
CHUCK:
We all had pain! Pain!
JOSH:
[Chuckles] OK. So there was something announced just a couple of days ago about “Lazy Enumerables.” And I had a pretty visceral negative reaction to that and I don’t know but… I guess David did but he is not here to chime in on that. James, he had a different position so I wanna hear how you think it’s awesome.
JAMES:
So yeah-- [Crosstalk]
CHUCK:
Can I stop you guys for a minute?
JAMES:
Sure.
CHUCK:
Because I’m a lazy programmable and I haven’t actually seen this yet.
JOSH:
[Chuckles]
JAMES:
Yeah I’m going to explain it.
CHUCK:
OK.
JAMES:
So, I saw I think… it was yesterday they had a patch that had been applied to Ruby 2 (which will become the next version of Ruby) that’s “Lazy Enumerable”. So the idea behind it is you can take some enumerable object, like an array and you can call the ‘.lazy’ method and then after that, you can chain on some iterators. So in the example with the post, they do a “map” and then a “select”. And there’s basically two things that happen there. One, because you’ve called lazy, the evaluation is not done immediately. So you just get like some lazy enumerable object, but it’s not done. You can think of that as much as same way the current version of Active Record does queries, right? When you call “where” or something like that, you just get back a lazy relation object that represents that query. And then when you are done chaining methods on it and you finally, in a view or something, call each on it to run through the results, that’s when the query actually happens. And we know from functional programing languages that lazy evaluation can often be beneficial because sometimes there’s times when you set something up but it doesn’t actually get used because that particular path of code isn’t going down or whatever. So the advantage of doing it lazily is that sometimes you don’t have to do it at all, right? If that value never gets used. So that’s one thing. The other thing that happens in this new patch, because it’s lazy, when we do finally evaluate it, we know all the things that have been strung together and everything that’s going to happen. So again, to use the Rails analogy, you can tag multiple layers on there and Rails ends up constructing those into one where class, right? Which is the and some parenthesis and that case. But the idea here is if we did a map followed by a select, if we do that the old fashion way, then we have to run through the list and convert it to another list and then we have to run through that list and pick out all the items and there’s intermediate arrays along the way and stuff like that. But because we know the whole transform at the time we are actually doing it, we need just make one pass over the collection and transform it and see if that value should stay in the result list and blah, blah, blah. So it’s kind of an optimization thing as well.
JOSH:
Right.
JAMES:
Does that explain it?
JOSH:
That does. And I wanna rebut that now. [Chuckles] So you just had your TV address now I got my radio response. [Laughter]
JOSH:
So lazy lists are a typical functional programing thing. And the first functional language I learned which was -- I won’t even mention it because no one will remember it -- but it is an old functional language that was a precursor to Haskell; and it had lazy infinite lists. This was a very pure functional language; it wasn’t like common Lisp where you had dynamic variables that you could mutate. This was a stateless language that anything was immutable. And lazy… their lazy weren’t just lazy; they were infinite. OK I will say it; the language was St. Andrew’s Static Language (SASL) because people would wanna know [chuckles]. But anyway, so they have this lazy infinite list.
JAMES:
Do you guys feel like Josh buy programming languages off the back of a truck or something?
[Laughter]
AVDI:
I can’t say anything. I learned to program in Rex, so… [Laughter]
JOSH:
And I had to walk ten miles to class in the snow uphill both ways. [Chuckles] OK so lazy list, they weren’t just lazy, they were infinite. Meaning that you could ask for element 10 thousand and it wouldn’t figure it out until it ask for it. So this was a hack that allowed them to deal with trying to iterate when they had no iteration and they had no mutable state. And it’s a brilliant hack for that and mathematically elegant and it works well within the pure functional paradigm. The problem with doing this kind of stuff in an object world is if you look at the sample of doing a map and then a select, that that’s kind of breaking the encapsulation boundary of the array. And you know, its ok because enumerable is part of array whatever, but if you think about what you are expressing there saying, “OK, I have a collection of numbers and then I wanna multiply them by ten and then now I wanna pick the ones that are over thirty,” you could just do that in one block. [Chuckles] You can say, “Here is my array, select where x times 10 is greater than 30.” So you can do it all in one block; you don’t need to have the lazy list for that example. But the other thing is, instead of just expressing that in code, you can actually move that combination of the blocks into a method somewhere that turns that into a single concept on a class somewhere rather than having this very functional style of block feeding into a block, feeding into a block. And that stuff is cool and I think it’s great doing that a lot of times. I’m a big fan of enumerable, but when the language is oriented towards optimizing these things with the technique that is going to... Ok if I wanna do good functional… good performant code in Ruby, I’m going to use these lazy lists so I have to organize my thinking around my code in this very functional way and that was my big response to it.
JAMES:
Now, do I get a rebuttal on the rebuttal?
JOSH:
Yeah, please do. [crosstalk]
AVDI:
I want--
JAMES:
Go for it.
AVDI:
Well, I was just going to say that I think it depends a little bit on how you look at what those are doing. So like, with the ActiveRecord example, with the ‘where’ clauses, I look at that as a builder pattern. So what you are doing is you’ve got like a tiny little DSL for building a query which involves repeatedly calling where adding bits to that query. And what you are doing is you are actually… in the background, what you are doing is you are building a query object. So I think if you structure it and if you think about it as a builder pattern where you are adding constraints bit by bit to a query object, then it’s not an un-OO pattern. But yes, if you think of it as notionally, this looks like send map to the collection then send select to the resulting collection etc. but what’s really going on is its being optimized in the background due to magic knowledge. That’s rather messy from an objectoriented perspective.
JAMES:
So what I wanted to say on it is it was kind of interesting for me because just like one day earlier, David Brady had sent me an email about this chunk of code he was playing with and its long and involved (because its David Brady), I’m not going to go in the whole thing, but one point he has this scenario where he has the one group of iteration and then he is breaking it down into the map (and in this case, actually I need checking but the two iterators like what we see in this feature). And he argued at the time that he liked that better because it separated the two things; that the mapping operation was the mapping operation and then what he was doing in each that was his own thing. And at the time, I took exactly the view Josh expressed where it was like, yeah but then you are giving up a lot of performance if you have something like list of a hundred thousand items and you got to go through it twice, that sucks. So it was interesting then that I saw this patch a day later and I was like, “Well, not anymore. If you do this, we can do it all in one pass,” which is kind of an interesting argument for that I think for what David is claiming that by doing these separate, you can have the map part, focus on the map part and then select or whatever and do just that one thing. And the cool part about that is what turns out to be cool about the current ActiveRecord syntax is that you can build up these things, right? So you can start with some generic where clause and then you have the object but it hasn’t been evaluated yet, so then you can branch on some conditional. “If it’s this way, lets add in this part and if it’s this way, lets add in this part.” And then at the end, you get down to the end and you are like, “OK, I'm ready. Let’s run the query.” And now, that will give us the same way this is going to give as a similar ability with enumerable methods, right? So we can say, “OK, I know there’s going to be this transform of the data, but maybe we allow the user to inject some… OK but I also wanna select these entries.” And you can kind of build up these enumeration and then trigger the whole thing and not pay a performance penalty for the fact that you had to do that, which is much harder to do if you are really going to try and do it in one pass; you’d have to write the code very carefully to handle that. So I thought that was kind of a neat option that it adds.
JOSH:
Ok, that sounds fine [chuckles].
CHUCK:
[Laughs]
JOSH:
But the thing that… you remember when Kent was on here, he was talking about one of the primary motivations in the patterns in Smalltalk Best Practice Patterns was you break things apart into smaller and smaller pieces which was to keep your code dry and you only say one thing, you say something once and only once, so you just decompose it into smaller and smaller pieces and then you can compose them up later in multiple ways. Great, we all do that in our programming. The thing is, where you break things apart matters. And what are the boundaries there? I think that when I see systems that have things broken apart along object boundaries and then other things broken apart on algorithmic boundaries, I find the code confusing to navigate and there’s a lot of impedance mismatch when you are trying to weave together a lot of these little pieces and they are built according to different orientations.
AVDI:
So I have something I wanna bounce of you Josh.
JOSH:
Yeah.
AVDI:
I would say that there’s a very OO pattern or idiom -- which is similar to this -- which is ‘Streams’.
So if you have a stream of objects which sends objects into a filter and it then selects some of them and then it sends them on to another filter and then it’s like some of them. I would say that sort of slight tweak on what we are talking about is a very OO way of doing things. And also I guess you could also turn it around and have it be the version where the last filter pulls something from the filter next up the chain that might be close to the same level of OO thinking.
JOSH:
Mh-hm. Yeah, I’d agree. Smalltalk had streams and infinite streams and— [Crosstalk]
AVDI:
Yeah. So I think you know, it’s like a very slight… you know, rotation of… (it’s the wrong word anyway), very slight tweak on the idea, but if you think about it in terms of streams sending objects to each other or sending through filters, and I actually I’d like to see more of that in Ruby. One of the interesting things in Smalltalk is that it uses stream so much. Like there’s less string processing and more streams processing so you know, you print things to streams and then you can have filter streams and stuff like that.
JOSH:
And you know, that works out great. So I wanna bring this back to Rails because that is normally what this conversation is about. [Laughter]
JAMES:
I can give an example in Rails of kind of stream-like behavior.
JOSH:
Ok.
JAMES:
The find_each method kind of works like that. You don’t know if you can load the entire table set into memory, that might be dangerous so instead, you call ‘find_each’ and what it does is batches of finds. So get first thousand objects or whatever you can tweak it and then yield those in one at a time and then you get the next thousand, yield those in one at a time. So even though you may be processing a data set that is actually larger than your memory, you can work through them just like a normal each, right? Which is one of the advantages of kind of a lazy stream evaluation kind of thing.
AVDI:
Yeah.
JOSH:
Yeah everybody that I know who is doing Rails 5 years ago built that for themselves and then they came out with it in a release of Rails and everyone said, “Oh great, now I don’t have to build this again myself.”
JAMES:
Yeah, absolutely.
JOSH:
Yeah so I think that’s great. But I there’s a lot of little things, I think, in Rails that are… like filters in controllers. If you look at that, like round filters etc., that ends up feeling a little functional to me, but then again it ends up not being a problem most of the time.
AVDI:
Well, it feels like aspect-object oriented programing, which is of course is basically structured ‘come from’ from INTERCAL.
JOSH:
Yeah.
AVDI:
If you are not familiar with the INTERCAL joke language, ‘come from’ is a construct where you put a ‘come from’ somewhere in the code and you say where the processing should “come from” at that point. And at some totally other place in the code, that has no annotations or anything, it notes that that’s a ‘come from’ point and your processing jumps out of the code there and shows up at the come from. So it’s a joke on ‘go to’, but it’s basically, this is exactly what aspect-oriented programming is and it kind of speaks to the confusion that can cramp up at any time you have like something where you can insert say, “Oh, around these methods, I actually want these to happen.” And you could be looking at the method and trying to figure out, “Well, how come the processing never made it here?” And it’s actually because it got lost in a filter somewhere.
CHUCK:
I've run into that with in particular where I tell it to load the resource and authorize it, and for some reason, it’s something that doesn’t need a load of resource and so it crops out before its anywhere.
JOSH:
By the way, my favorite definition of continuations is that they are non-local computed come froms.
AVDI:
[Laughs] Yes.
JAMES:
So I agree kind of what you guys are saying, but also at the same time, this kind of goes back to what I’m saying about I want us to define the Ruby style of programming. And like we do have blocks and I thought it was Eloquent Ruby that did the best job of explaining, a block is just an around filter, right? It’s some chunk of code that you get and then you can choose to do something before it or after it or store it away for later whatever; but that is part of Ruby and I’ve used that. It’s a great advantage. Sometimes I’ve taken controllers that were crazy complicated and made some simple method that took a block and that let me just rewrite the whole controller in trivial syntax.
JOSH:
Oh, yeah it’s great.
JAMES:
And— [crosstalk]
AVDI:
But it’s explicit.
JAMES:
Right, right. It is explicit. Yeah.
AVDI:
I often find that to be a better choice than the implicit jumping around of the filters.
JAMES:
Gotcha.
JOSH:
OK. So in terms of recommendations or our favorite practices for doing the “right way” anywhere else, what do we got here? Yeah that’s not biased at all.
AVDI:
I got a real simple one for controllers, (since we are talking about controllers) and this goes to one of the most common complaints about encapsulation breakage in Rails, which is that controllers try to treat views as sort of kind of controller methods. So they copy the instance variables over from the controller in to the view context, which is a little hanky from an encapsulation perspective. And it’s not just the purity thing. I mean, that can lead to a whole lot of issues where you have… you accidentally don’t set an instance variable in a particular context where that view is used but there’s absolutely no indication you needed to and stuff like that. And as far as I can tell, (and I’d be happy if somebody would you know, prove me wrong… or not too happy) but as far as I can tell, there’s no reason to pass data to views using instance variables in Rails 3 because we now have the helper method macro where you can say, “This method on my controller should also be exposed as a helper method to my views.” So if your view needs a post object, you can have a post accessor method on your controller which is then is exposed as a helper method and the view can just reference that and that just works great and it doesn’t have to reference an instance variable. And the great thing about it is that then, when you start refactoring your views into partials that just naturally, without any change to the partial code, that naturally goes into being a helper method reference on the controller to possibly being a local variable reference in that partial.
JOSH:
That’s great. But I think you are making an assumption there that I wanna make explicit, and that’s that as a group practice, you should not directly access instance variables in view partials.
AVDI:
Yeah. That’s what I’m saying is that this is a way to forever get away from that.
JOSH:
Well, even if you are using instance variables in the top level view, when you go in to partials, you should pass those values in explicitly as locals to the partial and that— [Crosstalk]
AVDI:
What happens when you start out a big partial and you start out with a big main view and you start breaking it up into partials and they retain their instance variables as a side effect of that breaking up process.
JOSH:
So there’s another technique that I’ve used and that’s… it’s a little different from how you were doing your stuff in objects on Rails. And I was working on an existing code base and they had a very complicated view system and they had tons and tons of partials and they were passing around literally like something like 8 to 12 variables, from one partial to another in cases. And I just went through and I created an object that I called it “the presenter” that took all of that state, put it into one object, so I could pass this one object around from partial to partial. And then all of the code and these views had a lot of code inserted in them using ERb, I pulled all of that code out except for simple conditionals and turned it into methods in the presenter. So state and behavior, put it together and build a class and I could then pass those things down through the big hairy network of partials without changing the organization of the partials, all I had to do is clean up the within them.
AVDI:
And that’s the parameter object refactoring, right?
JOSH:
Yeah, but I also put a lot of behavior into it. So, maybe it was somewhere between the parameter and the method object.
AVDI:
That is exactly the purpose that the original… that Jay Fields introduced Presenter for. JOSH: Yeah.
JAMES:
See, I feel like that’s almost the… when we were reading Smalltalk Best Practice Patterns that we talked about how sometimes once you extract that method object or something like that, then you realize, “Oh, cool, now I have a place to hang all these functionality.” And that’s where it ends up going. I too use that trick a lot of building an object too. And sometimes it doesn’t always have to be with views and stuff; you can just with them models. Sometimes I want to work with that model, sort of, but actually in a totally different context. So I just put a method in that model that returns a normal Ruby object that is the other context that I wanna work with in the and passing itself into it as it goes and then I can build that Ruby object normally and then work with it in a way that makes sense.
CHUCK:
Yeah I really like that approach; just the whole idea of having something that behaves the way that I need it to in the view where I wouldn’t necessarily wanna interact with it in the same way in the controller or from other models.
JOSH:
Ooh, awkward silence.
CHUCK:
Yeah. I’ll get it out, I’m sure.
JOSH:
OK. So aside from that, do we have particular approaches that people like? Oh, here's one; I’ve been playing around with… well, I’ve been using fixture scenarios more and more. I think I’ve mentioned it before. I think it was my pick one time. It’s a way of generating a bunch of data to go into fixtures and you can use factor or whatever to generate the data in memory and then it dumps it into a bunch of YAML files for you that you can load fixtures with all of the performance advantages of doing that.
CHUCK:
Cool.
JOSH:
So that’s been great.
AVDI:
*inaudible*
JOSH:
Yeah? I thought you were asking --
AVDI:
I said “neat”.
JOSH:
Oh, yeah cool. Yeah so that’s been pretty cool. The thing that really made that click for me was taking all of the… because I did like 2 projects with it where I just had this big procedural task that went and put all that stuff together and dumped everything into a fixture, but it was like literally this 200-line method that went and did all that. And then I said I’m not doing this anymore and I created a class that I started composing up the pieces that I wanted, so I had to like create guest user method in this class and I could call that from anywhere I wanted. So I could decompose the, “OK I have a blog post here it has a bunch of comments and I could destructure it using a vocabulary that I built up within that class.” So I found that to be a pretty handy technique. I’m using this in my application now and I don’t get overwhelmed by the confusion of all the weirdness that happens when you are trying to create all of your c data in your database. So that’s been a pretty cool technique for me. It’s probably worth a blog post at some point.
AVDI:
Absolutely. I mean, that reminds me of something similar that I tried to do which is that I feel like if I have an object which takes more than a couple of lines to instantiate in a reasonable way, then I
need to find some way to put some sugar over that. Because basically, if I can’t easily manipulate an object from the console – from IRB – if I can’t just play with it, or if I feel threatened… if I feel intimidated from playing with it, like, I’d have to do so much set up before I could even fiddle with that object manually, I feel like that hobbles my development efforts. There's a huge advantage to manipulability.
JAMES:
That’s kind of another way In that I think Rails sometimes, not even purposely, but kind of accidentally pushes us to bad habits in that the Rails structure, it’s really common to have a method that just takes some insane hash of arguments, right?
AVDI:
Right.
JAMES:
You definitely don’t wanna be diving in on IRB kind of thing. But yeah.
CHUCK:
God, I love those.
JAMES:
I absolutely agree with that. But you know, if you are struggling to instantiate an object, then your interface is wrong.
CHUCK:
All right. Well, we probably have to get to the picks. Is there anything that you guys are just dying to share before we do that?
AVDI:
One other topic that we talked a little bit preshow about addressing, I don’t think we can really talk about it in any great depth but it’s just there’s one kind of argument that’s made about objectoriented programming -- about why it’s unrealistic -- that I hear more often than most other arguments which is just the idea that in object-oriented programming, you are supposed to create simulations of objects in the real world. You are representing real things with your objects. And the argument that’s made then is well, that’s a lost cause. The real world is a messy place; we can’t possibly accurately simulate the objects that we find. And that’s the cause of many errors or problems in programs. Do you guys have anything to say to that?
JOSH:
It’s kind of silly. [Chuckles] I don’t wanna come off as dismissive, but I think that— [Crosstalk]
JAMES:
--dismissive.
JOSH:
Oh! Nice! [Chuckles] So I do wanna come off as dismissive then. I think that there’s so much that you model in software that is at an abstract or conceptual level and object-oriented programming is just fine for that events. We use events all the time.
JAMES:
Or “undo” if you follow that argument, you can have an undo track or— [crosstalk]
JOSH:
Yeah, command patterns.
JAMES:
Right. Yeah.
JOSH:
But the other thing is that stuff in the real world… So ok, if you are Bertrand Russell, you work at everything through category theory; you can throw everything into the right bucket. But in real life, things are actually pretty complicated and there’s of multiple inheritances going on for lack of a better term. And that was a big problem when we are in Smalltalk and we had single inheritance. Ruby, you get mix-ins through modules and you can solve that problem in a different way. But that didn’t mean that in Smalltalk, we couldn’t model the real world. We just did it a different way; we just didn’t use multiple inheritance.
AVDI:
Right.
CHUCK:
Right. Well, the other thing is every time I see an example of modeling, something in the real world;
it’s always a contrived example. And so, it’s like you have this object that’s the car and the car has all these parts, blah, blah, blah. It’s like why would you ever wanna break it down like that?
AVDI:
[Laughs]
CHUCK:
And for me, really what it comes down to is that you abstract a way that you need to abstract away, and you highlight all of the things that are important -- and that’s good object-oriented programming. Now you have to be careful because sometimes, you do need to break things down – and you don’t – but that’s part of the process and its part of learning how to do good objectoriented design. So really, when it comes right down to it, if you are modeling something in the real world, you really only modeling the parts that are important; the parts that you care about. And it’s not like your code is set in stone anyway, so you can always go back and change the way that your object models the world, if it doesn’t quite fit what you need to know about it. And so, you know when you are talking about modeling the entire world, every small component of every little thing, ultimately, a lot of that probably doesn’t matter. So, if it really does fit with what you’re trying to do, then terrific. Stick with it, work through it and make it work. And you know, just like everything else, it’s not suited for every problem, but if you are dealing with things on that level, then it’s definitely suited for those problems and if it’s not, then go find something else that allows you to model your problem in a better way.
JAMES:
Yeah. Myth busted!
AVDI:
[Chuckles] Yeah I feel like… I don’t wanna like get to the whole dci discussion or anything like that. But I do feel like the best that we can hope to do when we are dealing with objects that have some sort of nominal existence in the real world is to represent roles in a given interaction. And that’s the best that we really need to try to do is to represent world at something placed in interaction. I don’t know if you guys agree with me or not.
JAMES:
Yeah, actually I do. I mean like there could be scenarios where it makes no sense to model a car and a boat as the same thing because the way they are going to be used, it doesn’t make any sense at all. But then, there can be other scenarios where absolutely a car and a boat should just be a vehicle and you know, because the way that they are going to be used is all the same.
AVDI:
Products and registry or something.
CHUCK:
All you care about is point A, point B and how fast you get there. It doesn’t matter if it’s an airplane, a car or a boat. So anyway, let’s get into the picks. Josh, why don’t you go first?
JOSH:
Ok. It’s been a while since I’ve done… I think a fun reading pick, so my first pick is For the Young Wizards series by Diane Duane. And Diane Duane, she’s written a bunch of Star Trek stuff -especially a lot of Romulan stuff. She wrote Spock’s world and what was it… anyway, she wrote a couple of… Oh! “The Wounded Sky” I thought that was pretty awesome as well. While I’m mentioning those, my real pick is for her Young Wizards series of books. And the first one is called “So You want to be a Wizard.” It came out in 1983, so it predated Harry Potter by quite a while and she now has 9 books in the series. And they are basically about kids who live in our world, not who live in this separate wizarding world. They live in our world, but they are wizards and their job is to protect the world from death and stave off the heat death of the universe as long as possible. And the thing that I love about these books is that wizardry is basically like writing software.
CHUCK:
Oh, interesting.
JOSH:
Yeah. It’s a linguistic operation for them. But they are really fun books. They are little less silly and whimsical than the other series of wizardry books. [Chuckles] So I can actually imagine knowing someone who is a wizard from these books as opposed to like the Harry Potter books where I would just laugh at them. They are entertaining but they are not real people. And instead of having athletic matches that are the big thing going on in the books, it’s like, “OK, we have to save the world from total destruction. So, I think they are good young adult books. Probably 10 or 11 is old enough to read these books. I’m not sure since I’m not a parent. But anyway, they are great. If you have kids, they are good for the kids. They are actually really great for grown-ups as well. And then there’s an associated series about cat-wizards. It’s set in the same universe, but the themes are a little more for grown-ups. And Diane Duane just does absolutely hysterical job of having cats and dogs as characters in her books.
JAMES:
So wait, when they added in the cats, then it got more adult?
JOSH:
Oh, yeah. [Laughter]
JAMES:
Ok. I didn’t expect that.
JOSH:
Yeah it’s the other way around from what you think. Anyway, these are really good books. Diane Duane released them recently all in eBook format, so you can read them on your iPad or your Kindle or whatever. And it’s at youngwizards.com is the site for that. And then my other pick is for something that’s still vaporware but it’s so awesome that I have to talk about it, and that’s cerealize.com and this is spelled c-e-r-e-a-l-i-z-e, like breakfast cereal. And this was a creation of one of the startup bus trips going to south by southwest last week, and a friend of mine was on the bus and they decided, “OK, let’s do custom cereal subscriptions.” So you go to cerealize.com and they have a site there already, it’s pretty slick and you basically pick what your grains is in the cereal, what your dry fruit toppings are, what your nuts are, what your yogurt bits are or whatever.
And then the idea is that that will just show up in your house.
JAMES:
That’s awesome.
JOSH:
[Chuckles] So I’m really looking forward to this. So I figure I'll direct people towards it so the more buzz and support they get now, the more likely it is to actually happen.
CHUCK:
Nice.
JOSH:
Yeah, go to the website and check out the cereal brands, it’s worth looking at just for that.
CHUCK:
Do they have like the supreme pizza version where you put everything in it?
JOSH:
[Laughs] I expect they will. Ok that’s it for me.
CHUCK:
OK cool. Avdi?
AVDI:
So I think just one pick today. I don’t think this has been picked before. My pick is Less Wrong blog. It’s a blog about—
JAMES:
Woohoo!
AVDI:
[Laugh] It’s a blog about cognitive biases and the ways that we unwittingly screw up in our thinking, and it seems to be sort of dedicated to equipping people with the mental tools to get around their cognitive biases. So you know, I don’t always have time to read their long-ish posts but, every time I do, I learn something interesting. Like recently, I learned that the scientific system itself actually has some interesting biases in place. For instance everybody knows that if you wanna confirm a fact, you should look to see if it has been written up in a reputable scientific journal. What I didn’t realize is that a lot of the biggest journals have a bias where they will publish novel new findings, but they will not publish other studies that come after that say we tried to reproduce that novel finding and we are unable to do so, because novel findings are more interesting from a publishing point of view. So you know, you can have one novel finding and then a dozen that say, “You know, we couldn’t reproduce that,” and the novel one is the one that gets published. So I’m probably over simplifying that, but it was a very interesting read.
JAMES:
Yeah that’s great stuff all around.
CHUCK:
Sounds interesting; sounds like they should start a podcast. James, what are your picks?
JAMES:
OK, so I’ve tried like 50 new million things this week and I hated them all, so by not picking them, I’m helping you.
CHUCK:
[Laughs]
JAMES:
But I will pick one thing. Josh recently picked the Machete order article for Star Wars, which was really cool. But the thing I got out of reading that that I didn’t know about was the Harmy’s Despecialized Editions of the series. So if you don’t know what these are, this guy has basically gone through in using all like seven different sources, rebuilt the series and getting very, very close to how it was in the theater except that its now for HDTV kind of thing. So, you can actually go and get these and burn them into Blu Rays, right? Which is just absolutely awesome and they look fantastic if you are then you will really appreciate this that they are like pretty darn close to the way they were in the theater. All the major plot points have been fixed, you know, whether or not Han shoots first you know, early spoilers and stuff like that. So it’s really great. I mean how he's done this is just amazing. I mean just gone through and clipped scenes, used video filters to remove elements. But you get the beautiful gorgeous updated… you know, the light sabers look great and stuff like that. So it’s really kind of cool. It is kind of lot of work to put these together. I’ve actually been doing it. So you got to get them off of torrent first of all. If you don’t have much experience with that, I use this Transmission client on the Mac that seems to work really great. So I’ve got a lot of luck with that and you have to go find all the torrent files which that part is not too tough is you get lucky with Google. And then you also need (obviously if you are going to put them on Blu-ray like I did, you need tools for that because Macs don’t do that out of the box) so I grabbed a Blu-ray burner and I'll put links to all the things I use. You don’t necessarily have to use these things. There’s obviously other ways to do it. But then you need some kind of program that can burn Blurays and I used Toast for that -- Toast Titanium 11 -- and I never used that program before because I’ve always just used the built in disc utility or something where I do CDs and stuff but it seems to work great. I mean, work just fine. So I was pretty pleased with that. And then depending on how far you wanna go, you can really kind of go all out. They come with like inserts for the cases and stuff and you can pick up the cases on Amazon and the printer supplies to print your own inserts. And then you can get like the disc covers. You can kind of go all out and make like your own little series and it’s really fun if you don’t mind the hassle to do it all. And so, I’ve enjoyed that and that’s what I’m sharing for what I’ve been up to.
CHUCK:
Nice. So that’s the version where they took out all the stuff that they added in the last revision of the Star Wars movie? Is that what your—
JAMES:
Actually since basically all the revisions, because they’ve been obsessed with tweaking the series since then and just been slowly changing them, and really sad in a lot of ways. I mean, and a lot of the things that changed were super stupid and have even become internet memes like the “Han shot first” or whatever but also he spoils the surprise in Empire Strikes Back early and you know, like just things like they changed the Ewok music in Return of the Jedi into something like wouldn’t be the tools they have around all of a sudden it’s like this techno kind of stuff. And yeah so totally taking it back to like the theatrical, what made it great, but now it’s also gorgeous and looks great on your HDTV. So it’s kind of cool.
CHUCK:
I want one.
JAMES:
Yeah it’s fun stuff. You should try it. It’s great. My wife is a super big fan. Her birthday is coming up and I’ve been making these for her.
JOSH:
Yeah, my birthday is coming up too.
JAMES:
[Laughs]
CHUCK:
You know, it sounds like a whole lot less work; I’ll just put in an order to James.
JOSH:
[Laughs]
CHUCK:
Alright. So I guess it’s my turn. So I’ve been playing with a few things here as well; one that I’ve really been enjoying that I picked up from JavaScript Jabber, we talked to Paul Irish about the Chrome dev tools, which is so, so handy. But I’ve actually been using Chrome Canary, which is kind of pre-release… I don’t know if I wanna call it pre-release version Chrome, but basically it’s pretty stable, it updates every day and it has a lot more features and functionality than either Chrome does. Chrome I guess catches up like every week or two. I don’t remember the exact schedule but he goes over it on JavaScript jabber so if you go listen to that episode. But anyway, the tools in that are just awesome, like totally just amazing and so I’m loving that. And so if you have to debug JavaScript or if you wanna fiddle with CSS on the fly and see how it modifies your page and those are just some great ways to go to or some great tools in Chrome, particularly in Chrome Canary that will kind of get you a little further down the road. One other thing that I have been playing with lately, I’ve picked it up because I've been listening to the Mac Power Users podcast, which somebody recommended back when we were talking about Evernote or something.
JOSH:
Yeah that was my pick.
CHUCK:
Yeah so I have been listening to it from the beginning and they’ve kept talking about “Scrivener” and so I went and picked up Scrivener. And I’ve been reading through the tutorial that they have in there because I wanted to use it to organize my talk and I realize I didn’t have enough time to go through the tutorial and so I’m kind of fudging there. But just off the first part where it shows you about how all the organization stuff works and things like that, I can totally see myself using this in the future to organize and write blog posts, organize and write online courses, organize and write conference talks and really just kind of cohesively gather information and then put ideas together in order to put these stuff together. I’m hoping to get some eBooks written though I haven’t finalized what any of the topics would be. But all in all, it just seems like a really terrific way to go if you want to pull some sources together, get your drafts together, put notes into it, organize it however you need to organize it and then get it out. So those are my picks and with that, I think we'll wrap up unless you guys have anything to add. Alright so, really quickly, in 2 weeks we are going to be talking to Jose Valim about “Crafting Rails Applications”; that’s our Book Club.
JAMES:
It’s a good book.
CHUCK:
it is. It’s really good. And it’s a really quick read too. Like I sit down for half hour and I mean it through like 10% or 15% of the book. I mean, it’s really easy to get through and really, really interesting stuff in there. Who are we talking to next week? We are talking to Dan Kubb about “Code Organization” is that right?
AVDI:
Disciplines. Coding Disciplines.
CHUCK:
Coding Disciplines. There we go. And then we have some other stuff coming down the pipeline and we’ll announce those as we get a little closer. One other thing is we are going to be at RailsConf.
JAMES:
Woohoo!
CHUCK:
So, come and see us. We might look a little different when we are there, but it should be fun.
JOSH:
Well, yeah we will look totally different from how we look on the podcast. [Laughter]
JAMES:
By “different”, you mean superior.
JOSH:
[Laughs]
AVDI:
Embodied.
JOSH:
Yeah you can check out the RailsConf schedule. We are doing a live recording of the Ruby Rogues episode. What’s our topic? It’s “What Rails Developer Should Care About.”
JAMES:
Yes.
JOSH:
And we'll take questions before hand online and live in the audience.
CHUCK:
Yeah absolutely. One last thing, we are in iTunes so if you wanna go get the episode there, you can leave us a review there while you are at it. If you are on some other pod catcher or something then there is an RSS feed on the website that you can pick up the episodes from as well. With that, we also really appreciate your ideas and votes on our topic suggestion, so if you go to rubyrogues.com you can either click on the feedback tab or you can click on request a topic and or suggest a topic I think it is and then you can go ahead and put in what you would like us to talk about and then as it get closer to the talk, then we go ahead and attack those. And you’ll notice the object-oriented programing in Rails actually wont because if you go in, it will be marked off. It at the top, it was actually at the top by double the next thing in the list.
JAMES:
So many votes.
CHUCK:
Yeah so we are going to make a whole bunch of people really happy. Anyway— [Crosstalk]
JOSH:
Or really mad. [Laughter]
CHUCK:
That’s not what I wanted.
AVDI:
We barely mentioned Rails.
CHUCK:
Yeah, who needs Rails?
AVDI:
[Laughs]
CHUCK:
Anyway, so that’s it. We'll catch you next week!
JAMES:
Bye everybody!
AVDI:
Bye!
JOSH:
Ciao!
046 RR Objects in Rails Part 2
0:00
Playback Speed: