JOSH:
So here's just a far out idea…
JAMES:
Okay.
JOSH:
When we had Kent on, we talked a lot about Kent stuff, but actually didn’t talk a lot about the patterns very much. We could do a follow up and actually talk about the patterns.
CHUCK:
Hey everybody and welcome to episode 24 of the Ruby Rogues. This week, we have one our panel, Avdi Grimm.
AVDI:
Good morning. And today, I am a female object pattern.
CHUCK:
[Chuckles] We also have James Edward Gray.
JAMES:
We've been hearing complaints that people don’t like awkward introductions. How awkward is that?
CHUCK:
Yeah, I feel awkward about that.
AVDI:
We should have an awkward silence now.
[Silence]
CHUCK:
What?
AVDI:
Well done.
CHUCK:
We also have Josh Susser.
JOSH:
Yeah, hey. This is Josh Susser, so you can recognize my voice. That’s the entire point of this awkward self-introduction.
CHUCK:
Yeah, and I'm Charles Max Wood. This week I opened registration for my Testing Ruby on Rails course, as well as my Advanced Ruby on Rails course. So go to Rails Rookies and sign up. All right, we are going to go ahead and let Josh introduce our topic today, and then we'll get started.
JOSH:
Okay, so I'm calling this episode Part 2. [Chuckles] We had a great time with Kent last week, but there was a ton of material in the book that we didn’t get to address. We had too much fun talking with mister the amazing, to spend to spend too much time going into detailed conversations about the patterns. We had a nice hole in our schedule this week, so we are going to keep working on the patterns from Smalltalk Best Practice Patterns book, and see if we have can a little more conversation about them, and what that could tell us about programming in Ruby. Did I miss anything, James?
JAMES:
I think it was perfect.
JOSH:
Okay, do I need a definition?
CHUCK:
[Laughs]
JOSH:
[Chuckles] A definition for a sequel?
JAMES:
Define ‘James,’ go. [Laughter]
JOSH:
I don’t think I wanna reopen that class.
CHUCK:
[Chuckles] Go ahead and create a module to monkey patch him.
JOSH:
Yeah, that’s our best practice there. [Chuckles] Okay, so James I think you probably have the most copious notes for all the different patterns, so why don’t you pick our first pattern to get started.
JAMES:
Okay, so I'm trying to pick something I didn’t talk about last week. One of the earlier sets of patterns in the book that I liked and I didn’t write down the exact name, sorry. It’s actually something about a conversion constructor, and then the other one is just conversion method or something like that. Basically, the idea is sometimes we have a conversion method on a class. So to give an example, in Ruby we have to_a, to convert something to an array. And you can do that on anything that has enumerable mixed in to it.
But sometimes, we do conversion constructors. Like a good example I can think of there is date, right? You do date.parse, and you pass in a string which is really just a conversion from a string to a date object. And what I love about the synergy of these two patterns, is they tell you when you do which one, when you do a method on the object itself that just converts, and when you do a conversion constructor and before anybody asks, no, Ruby does not follow those rules.
JOSH:
[Chuckles] So these are converter method, and converter constructor method.
CHUCK:
Yeah. I was reading those, and one thing that stuck out to me, and I kind of had to work through it was that you have the converter method, which is converting something into else that you call on the object. And it really made me think because you have like to_s that convert something to a
string, and it made me wonder, “Okay well, then is to_s a bad idea, because then the integer or whatever has to know how build a string, and it’s not really it’s job.” But at the same time, when I was thinking about it, I was thinking, “Well if I have my own object, and I want to it to a string, then it has to know how to build a string to put them together, so it can print it out. And so, it was really interesting to see, “Okay, in these cases maybe to_s does makes sense,” and there this other cases, it really doesn’t; where rather than saying this object to this other object, it makes more sense to say this object construct from this other object.
JAMES:
Right. And Kent’s actual rule for the conversion was if they are converting to an object with basically an identical interface, then it’s okay for that object to just go ahead and have a to_’whatever’ on it. If you are converting to an object with a completely different interface, then that’s better handled through the constructor conversion. And so to give it examples of that, depending on how we take the meaning of identical interface. I think things like to_a and to_set from the standard library are probably okay because you use them on enumerables and you are getting an enumerable object back. So as far as them still being Ruby’s idea of a collection, that’s probably okay. But the other case of date.parse, you take a string and then you get back a date. So it does a completely different interface. The object that’s getting returned. So that’s more correct using the conversion method. But as Chuck already stated, there's plenty of spaces in Ruby, where we don’t follow that convention. For example, integer to string and stuff does not really follow that.
CHUCK:
Right but at the same time, I mean there are a lot of things out there that use the to_string, so one example is if you are putting to the console or something, you have to know how to convert the object to string. And it makes more sense for the object to know how to convert itself to a string, than it does for a string and how to convert every object in your system to a string.
And so the other rule that he has, is there's only one reasonable way to implement the conversion. And for me, the to_string in most instances, it’s much more reasonable to put that on the class that you are implementing, as opposed to trying to make string aware of the structure of that class, that how to convert it itself.
JOSH:
I agree with that. You don’t wanna educate string about all the kind different kind of things that might want to be stringified. However, if you look in Rails, there's this oddity that crept in the early days of passing a symbol that named kind of format that you want it to convert something in to for the string. So if you have a date, you can call to_s and pass in a symbol which is a :db, so it will format the date for the database Or you can pass in short or long or what have you and it will come out with different formats. I guess that taking that under to_s was not too … I would have rather seen that as some sort of format method.
JAMES:
I agree. And I think one of the reasons I don’t really care for things like that, is I love it when I can replace the object, and not change the actual call. Like for example, I use include? a lot, because it’s on array, it’s on hash whatever. And so if I swap out the data structure, it still works. But if you do something like that to to_s, start tacking symbols on to it, then if you call back that on anything else, it just blows up.
JOSH:
Yeah, Ruby tends to… the style of Ruby’s programming where people tend to overload existing methods rather than create new methods. Do you think that there’s a resource conch for method selectors?
JAMES:
I don’t know. That’s a good question.
JOSH:
There's a scarcity of potential method names?
JAMES:
Maybe there's a scarcity of good method names.
JOSH:
Okay, we can agree on that.
CHUCK:
[Chuckles]
JAMES:
So Josh, I think you said method object was one of your favorite patterns in the book. You wanna tell us about it?
JOSH:
Yes. So method objects.
CHUCK:
What page is that on?
JOSH:
I'm looking for that right now… and it’s page 34. We don’t have David here doing chaptered verse for us.
[Laughter]
Page 34, section 12. Okay, so method object. This answers the question, “How do you code method where many lines of code share many arguments and temporary variables.” This I think was a fascinating… this probably I think is the most fascinating write up of a pattern in the book, because there's this huge history behind what happened here is that they are trying to refactor a giant method in the middle of a different class. In the middle of a class, breaking it apart into different pieces that can communicate with each other was too messy and intrusive to the rest of the class. Would you say that’s a good summary, James?
JAMES:
Sure.
JOSH:
Okay, so the point is that you isolate the functionality of that method in a separate object entirely, where it can use instance variables in that object, to communicate between the different pieces of the method code as you refactor it around. You know, part of the problem is just sharing state. Think about it; before, you got a giant method that has 8 or 10 local variables in it or temporary variables and you want to do method extract refactorings on it, and you don’t wanna be passing around arguments all over the place because that’s making… you have things that were temporary variables in the method, turning them into parameters that you are passing to extracted methods, makes it much harder to refactor that method. So if you just pull it out, put it in a separate class, turn it in an object, then all those locals in the method become instance variables in the method object, then the refactoring becomes much simpler because you are not having to massage your code around those much; you are moving it around instead.
AVDI:
Right, you can quickly just like do a Composed Method on any chunk of it. And for the most part, it will just work because it’s all sharing the same state. So there's a couple potential outcomes of this; one is you have this refactored method object and you’ve been using it. And that’s a perfectly fine outcome. But the other thing is that you can do a lot of transformations that end up simplifying things enough, that you've reduced it to a form where it could be pulled back into the original class in a much simpler form. I don’t think Kent talked about that in his write up.
JAMES:
Yeah, that was really the aha moment for me, when I was reading that pattern was he said, he kind of admits in the example, “You know, I was looking at this and I didn’t really know what to do, and I was stuck but I just knew it was too much going on, so I just try to… well, I don’t have a better idea, so I'm extracting this into a method object.” And then once he had done the abstraction, he was like, “Oh well, now I see.” And then he just was able to make things so much cleaner, because he had got it out of there. He basically decoupled it in his mind, from the mess of everything. And it was like oh, this is just a simple object-oriented programming. And just like Avdi said, he’s just using the tried and true tool Composed Method, and splitting things up and then it was cleaner. And I think you are right Josh, and eventually you'd realize, you know what, this actually is something else and it evolves into something else, but that was kind of the whole point to me of breaking it out was that you free your mind to think about it as something separate and treat it that way, you know?
JOSH:
Yeah, so I thought that that was just a really beautiful application of object orientation.
AVDI:
Actually one more note about that pattern; the thing that sprung out to me is one of my other favorite programming books talk about that. Michael Feather’s Working Effectively with Legacy Code. That's one of the patterns for getting a nasty method under test in the first place, one of those chicken and egg, ‘I can't test this until I pull it out, but I can't pull it out without putting test over it’ solutions is that same pattern of puling it out into a class, and making all the temporary variables instance variables.
CHUCK:
Yeah, it does make a lot of sense you know, where you are basically giving somebody else the job of making that happen. Because if you are tracking all that state in temporary variables and things, I think it really is indicative of the need for something like that. It’s not just that your code is messy; it’s a code smell that has a solution here. We also keep bringing up Composed Method, and I really, really liked that approach to things, just because I'm trying to remember who it was at Rocky Ruby Conference, I think it was like the first talk. He was talking about who’s an API designer, you know and like five people raised their hands. And he said, “Wrong. You are all API designers.” And if you want a clean API, and were not just talking about the API that you expose to people who are going to be using even if it’s a library, you know its exposing certain public APIs, but the private API is something you have to deal with as you build on your project. And the Composed Method really made a lot of sense because ultimately what you are doing then is you are being highly descriptive as you build out your application from the top down.
JAMES:
Yeah, I think Composed Method is probably one of the most important patterns in the book. And I
kind of spoke about this a little bit in our last episode, but if you only learn one thing, definitely sit down and learn Composed Method, because as Kent basically said, it’s your basic tool of composition which is the key. But my favorite part about it is it allows me to dive into the code and think, “I'm going to wanna do this abstract thing. And in order to do this abstract thing, I would need to do these five concrete steps, and I just write those steps down, making up method names for them as I go. And then I go fill in those methods later. And I find it much easier to program that way.
CHUCK:
Yeah, if no one else has anything to run across the section that I kind of got excited about was collections, just because there was so much in common in Ruby.
JOSH:
Big surprise there.
JAMES:
[Chuckles] Right.
JOSH:
[Chuckles] The Ruby collection stuff was just lifted from Smalltalk, and then expanded.
CHUCK:
Yeah, you won't hear me complain about that, but it’s really interesting when I first started with Ruby and with Rails, I wound up doing a lot of this stuff by hand coding the loop; so I just have array.each do and then I’d have like a some variable that I set to zero beforehand , and then I just loop through and add everything on. And I had a few people point out inject, and that became my favorite method for like a month. [Chuckles] You know, just things like that, I mean just really understanding the powerful interface that you have to these objects. And it’s everything from the each or in Smalltalk’s case, the do, all the way down to inject or collect or map. If you go and look at the enumerable documentation for Ruby, and you realize that you can do this on arrays or hashes, then you start to really understand just what a powerful interface you have to these collections of objects and what you can do with them.
AVDI:
I kind of like the Smalltalk do syntax as oppose to each, just because I think each tends to suggest iteration over a collection, which can sometimes box you in in your thinking a little bit. And just the idea of… do is basically apply this to yourself, apply this bit of code to yourself, or with your elements, but it’s saying absolutely nothing about what you are. And you know, you can have things that aren’t collections; you can have things that are trees, you can have things that aren’t collections at all. You know, maybe it iterates… maybe there are some places where it makes sense instead to go through a subset of an object’s attributes instead of going through some collection. Maybe it’s things that are pulled off as stream. There are just so many options for what that can mean, and it’s a really powerful way of thinking about it.
JOSH:
I find it amusing that in Smalltalk, you say ‘collection do each’ and at Ruby, you say ‘collection each do.’ [Laughter]
JAMES:
Yeah, but let’s face it; if we rename Ruby’s each to do, then we are going to have ‘do do.’ [Laughter]
AVDI:
One of the things I liked in that collection section is the collection accessor method.
JAMES:
Yes, I love it, but it comes out much more beautiful in Ruby, doesn’t it?
AVDI:
Doesn’t it?
JAMES:
Yes.
JOSH:
Smalltalk doesn’t have special syntax for accessing collection elements, they use the textual method at and put. So yeah, I love the square bracket stuff in Ruby; It’s nice that you can redefine that yourself in your own classes.
JAMES:
Maybe I'm thinking of different case, actually. Yeah, I am.
AVDI:
So collection accessor method is when you have an object that has collections… you have an object that has an attribute, which is some collection of object. And instead of just exposing that collection and saying, “Okay, if you want to… I have an knapsack and if you want to add things to my knapsack, you can just say ‘me.knapsack insert some object,’ You actually say I have a method called add to knapsack which will give you an object.” And so you supply explicit methods for adding or removing elements from a member collection. And I really like doing this. I think it keeps things nicely encapsulated. And it really, really opens things up to extension… or to changing the semantics in the future in the way that directly accessing member collections doesn’t, because you can add validations for what you put in. It can react, it can have sort of events that happen when you put certain objects into the collection -- and all kinds of stuff like that.
JAMES:
So you are right Avdi, and I was thinking of something different. Although what i was thinking of is related. I do like what you just said though about encapsulating the collection and then that way, if you need to do something to an object as it’s going into the collection or something like that, its trivial to do, you know. Things like that. But the one I was thinking of is actually in the state chapter, and it’s called enumeration method, which is basically they tell you just define do… define do for that, that collection so that they can run over it. And basically, he was talking about the reason to do that is to give them read-only access to a collection, without exposing the collection to modification and stuff. But that’s the one that I think comes out significantly more beautiful in Ruby, because we can just call to_enum and return an enumerator, and then they get access to the enumerators in read only fashion. So, they basically get a read only version of the collection.
CHUCK:
Is that in Ruby 1.8 or just in Ruby 1.9?
JAMES:
It’s available in 1.8, if you load the enumerator library. In Ruby 1.9 is built in to the core.
CHUCK:
Okay. All right, I'm going to jump in on another pattern that real quickly, it was a simple one, and that was the Constant Method. And it’s really, really simple because it’s just a method that represents some value in the system; but rather than use some magic number, I really liked it because it communicates what it is. And so if you have like some maximum numbers of cookies in the cookie jar, then you can set up a method that’s max cookies, and then you know what that maximum is and you don’t have to worry about, “Oh, is it 20, is it 30?” Because we have this meeting, we discussed it. You just redefine it in that method, and you don’t have to worry about it anymore. And its highly communicative; “This is what this is. It’s not 20, it’s the maximum number of cookies.”
JAMES:
I like that one because Ruby’s constants are sometimes weird to me, as far as like how they inherit and stuff. So when you have the method, you just know that you can override that method and that’s the way it is, you know?
JOSH:
Yeah, I far prefer using methods and understandable inheritance to using hardware constants. The other thing about constants in Ruby is that they are not. [Chuckles] So variables in Ruby are just you can still assign to them, you can use set constant methods, things like that. I like the constant method in Ruby even because while an inheritance is understandable, but to, it’s not something that anyone can come along and clover, just by monkey patching your constant. So it’s a different beast and I think it actually acts like constants more than Ruby constants do.
CHUCK:
Yeah, well it changed my programming patterns, so that’s why I liked it is because I would tend to just put the magic number in there and assume that people knew what it meant, and now I don’t.
JOSH:
I have one -- so page 70 for those of you reading along -- pluggable selector and its close kin pluggable block immediately follows. So this is something that people who have programmed using active record should be familiar with this, because we see this lot in like the validation callbacks that you put on your model class, where you can say validates and then our give it a symbol, which is the name of the method in the class that gets called to do validation. So the pluggable selector is okay, you wanna have some code that gets run conditionally one way or the other, but you don’t want to litter your object with a bunch of conditionals all throughout it. If you drop a name of method in there, and all these places where you would otherwise have conditionals, you just do a self send and send yourself that method.
JAMES:
One of my favorite places to use that is when I'm designing a state machine, which by the way state machines are just awesome and that we need to talk about that at some point. But whenever I'm design a state machine, I usually just have some variable that tracks state, and then when I want to transition to a new state, I just throw a new symbol in that variable, because that’s the method I´ll be calling next.
JOSH:
Right. So you send yourself the state method to do that thing.
JAMES:
Right.
AVDI:
Yeah, I love the highlight… I just realized the highlight is in the section at the very end. Kent says the interesting observation… so they've got this example of instead of having points in space, and instead of having separate classes for centered relative point and top left relative point, etcetera, you can capture that one little bit of variability, which where the point is relative to, as this pluggable selector. So you just create an object that has the what its relative to, as its pluggable selector and then you avoid this really big class hierarchies that only differ on one point.
JAMES:
Right.
JOSH:
Yeah, so I think that’s a pattern that I think lot of Rails developers are comfortable using codes that’s been built that way. And even playing along with the pattern, so I think a lot of Rails developers have built validation methods, that can use the pluggable selector pattern with. And I like that, I really prefer doing that rather than throwing the lambda instead, with just next this pluggable block. But I haven’t seen a lot of application code within Rails, where people are doing this sort of tricks. I think that it’s been working about is you dig in to building models with variable business logic.
So pluggable block is the next pattern after this. When you do a validate method or like a before validation hook in your active record model, you can either give it a symbol for the pluggable selector or you can just pass in a lambda, that will get executed instead. And I think that that’s… I
don’t like that as much most of the time, because it doesn’t play well with inheritance or polymorphism. And if you want to be able to create a sub class of your model that does something slightly differently in that validation, I think it’s easier to deal with a code when it’s in a full pledge method that you deal with pluggable selector.
CHUCK:
Right, because you can overwrite the method in your super, if you need to.
JOSH:
You have all sorts of flexibility that you have in ordinary object-oriented programming. And as soon as you start passing around blocks, you are essentially in the realm of functional programming, which have its own ways of structuring code, and you are going to start getting some tension when you wanna dig into that block and do refactor it or do things in a different way.
CHUCK:
Right, but don’t you still have options… I'm not sure if this falls directly under pluggable block, but where effectively you can pass the block at the end of a method call, so you have a method call do and then a block there, and that will also change the way that that method behaves. And so you can see this in other things that you build, as long as it has a yield statement in it somewhere.
JOSH:
Yeah, so that’s a different pattern. The pluggable block is really about just avoiding creating a lot of specialized sub classes, that are only varying in a small way. So this is just let’s drop in a block that contains the variation or the variability. So it’s just a different way of doing it from the pluggable selector. The thing about pluggable block is that you can inject code into another class if you are doing it that way. You can set a variable for the block.
JAMES:
It’s interesting where Ruby has blocks as such a prominent part of the language, and yet pluggable block is kind of underused. I mean, we have uses of blocks that are very common, the iterators DSLs and things like that. But I do use pluggable block a lot, where like these things are almost identical, except they do some special thing in the middle. And whenever I think of that, I do a pluggable block. I have it extracted out or pass it in as a block, and then run code around it or whatever and call the block at the right time, but I don’t see that a lot in Ruby code. Like I'm surprised how much I don’t see that.
JOSH:
So I have a theory about why that is. Would you like to hear it?
JAMES:
I would love to hear it.
JOSH:
[Chuckles] So it comes down to how collection are sorted. And in Ruby, you have a sort by method on array, so you can just go, “Okay, I've got an array, and I call this sort by method and I pass a block,” and the use of the block is ephemeral; it’s a transient thing. You start the collection and you get a new collection or a new array out of there that’s sorted, but it doesn’t retain the sortedness for any length of time. It’s just another array that happens to be in that order. But in Smalltalk, you have a class called sorted collection, which has a block as part of its state. And anything you add to that collection will get sorted into the contents in their correct position.
JAMES:
Okay, so I'm going to side track here. There are a small portion that have been fighting a fight on Ruby core -- literally for years now -- to get rbtree added to Ruby Standard Library. And rbtree, it stands for for Red-Black Tree. It’s a binary tree but it’s basically exactly what you described. Rbtree has a sorting to it. When you put objects in, because it’s a binary tree, it balances the tree and that keeps it in order. And so if you iterate or something like that, you iterate an order. And in fact, Ruby’s standard library was actually meant for this, because Ruby has a set class in the standard library and when you load set, it checks your to see if you can find rbtree . And if it can, it uses rbtree. And if it can't, it falls back to a much dumber implementation based on Ruby’s hash. So it’s such a great compliment, and it’s a great all around general programming tool. And there's been those of us who’s been trying to get it in the standard library for a very long time for basically the reasons you just described.
AVDI:
What is the objection?
JAMES:
I really don’t know. I'm frustrated with the…
AVDI:
That seems like such a basic container.
JAMES:
Yeah, one of the objection that's been raised recently, we've been fighting this argument again, it’s basically a perma argument. We’ve been fighting it again just last week, and one of the objections as of last week is the name of the library is bad; that its tied to the algorithm that it uses. And so I said, “Okay, let’s just call it a tree.” [Chuckles] And they were like, “That sucks.” And so I'm not clear why tree sucks and why array rocks and hash rocks, but yes, I would very much like see this library added. And now that we have talked about it in the podcast, I'm definitely going to post a link to this section, so everybody can go listen to it.
AVDI:
Hash totally doesn't suggest its implementation.
JAMES:
It’s algorithm [inaudible], yeah.
AVDI: [Chuckles]
JOSH:
Yeah, that was one of the things I thought that was definitely a step down from clarity in Smalltalk. In Smalltalk, the class is dictionary, which suggest you, okay great; I got a name and a definition. Or a key and a value. So let me get back to my point, which is that Smalltalk has a sorted collection with a block associated with it. And that block is a pluggable block on the sorted collection. So I think that you just grow up with your basic data structures in Smalltalk, you learn about sorted collection, and you internalize that pattern. But in Ruby, I can't think of many, or even any examples where that block is something that you keep around the state. Even in places where you are using magic pen style blocks, they don’t seem to hang around very long.
CHUCK:
Magic pen?
JOSH:
That was a term coined by David Black a couple of years ago. I don’t know what the name of pattern is in Kent’s book, but it’s sort of pluggable behavior, but it doesn’t stick around as something that was done over and over.
CHUCK:
Okay.
JOSH:
It’s like file open. I guess that would be the round behavior in Smalltalk Best Practice Patterns.
JAMES:
Kent also give some great uses for set in this section. And I just wanna mention this on the podcast because too many people don’t know about it, Ruby does include a set class. It’s in the standard library, so you can just require set and you get set and sorted set, both. And they are really great classes and people tend to use an array for these kinds of things. And really, array suck at these kinds of things. And Kent actually goes into some of the reasons why in his set examples. So if you are looking using a set for a set like behavior, or even some for the places where Kent recommends using a set, he says, if you want a unique collection of objects, you convert to a set, because by definition, that’s a unique set of objects. So things like that, you should load Ruby’s set library and that will give you like a method on array called to set, so you can easily do the conversion. And there's methods for testing subsets and classifying elements, depending on which way they fall. It’s good stuff.
JOSH:
So James, the set operations that in Smalltalk you use the class set for… and by the way, set is the most overloaded word in the English language, so prepare to be confused. So in Ruby, arrays do most of what set does in Smalltalk; and you even have the unique bang method on them to make them unique, to remove duplicates.
CHUCK:
Is that faster or slower than converting to a set?
JAMES:
Generally, using a set will be faster, because if you do any operation on an array, you are going to have to follow it up by a unique bang or something in order to… you know what I mean? So you are constantly retraversing that array, because you got to ensure that you don’t introduce a duplicate, right?
CHUCK:
Okay.
JOSH:
But arrays do intersection and union and… the various composition operations for sets. I don’t use sets very much in Ruby, just because arrays just do the job just fine. And it’s simpler to me only have to deal with one data structure type instead of two.
JAMES:
So this gets into kind of an interesting tug of war in… its even in Kent’s book, because as I mentioned before, he says if you have a list, and you wanna guarantee there’s no duplicates, he says, just convert it to a set. That's the fastest way to just guarantee a set doesn’t have duplicates. So, that’s a way to guarantee it. But then in other places, Kent takes the argument of why doesn’t Smalltalk have a back or queue. And he says, “Because you don’t need them.” Oh, I forget the what’s Smalltalk expand the array called? Ordered collection, I think.
JOSH:
Ordered collection.
JAMES:
Yeah. Ordered collection, which is the equivalent of Ruby’s array. Is functions find as a stack or queue; so we just use that instead. Which is an interesting interplay but I'm going to say, Josh, as much as I hate to say it, I think you are wrong about the set thing. The set library in Ruby is really great. And the problem with using array is like I said, if you do anything where you put something else in the array, you are going to have to unique it again, to make sure that you didn’t put a duplicate in there; which means you are going to be traversing that collection all the time. And it adds baggage; every time you got to do that, you have to keep that mental model of, ‘this object is not enforcing the no duplicate criteria that I am keeping in my mind.’ And set is more like, “It’s a whole conversation with the reader thing again,” right? If I use a set, then you are showing this has no duplicates. It’s a set.
JOSH:
So in active record, do you think that it has many association should return a set rather than an array?
JAMES:
That’s a good question. I guess no, because as much as I would like it to be so, it’s not true that it has to be unique in SQL, unless the appropriate foreign key constraints are used.
AVDI:
Right. Or you can define a really weird query on that, which had duplicates in it. And in some cases, that might actually do what you want.
CHUCK:
The other question I have is, “Are sets ordered in Ruby?”
JAMES:
There is a sorted set also that you get when you load the set library. And the sorted set, you can set an ordering to, just like Josh was discussing.
AVDI:
But frustratingly enough, and I just remember what was bugging me when I was reading this section on the book. Ruby, as far as I know, does not have an ordered set, which is not a sorted set.
CHUCK:
What would be a difference between an ‘ordered set’ and a ‘sorted set’?
AVDI:
An ordered set, like any set, it would only let you put an object in, if it wasn’t in there already. But it would keep the object, it would guarantee that the objects would always be in the order that you insert them in.
CHUCK:
Oh, I see.
JAMES:
So if we wanted that, if we can win this fight on Ruby Core… so how many listeners do we have, everybody go to Ruby Core and vote for adding rbtree to the standard library…
CHUCK:
[Chuckles]
JAMES:
Okay, that’s Jame’s public service announcement.
[Laughter]
CHUCK:
Well, a tree structure is actually very, very handy and would probably be something that we would all benefit from. And you have enumerated a lot of the benefits there, so I'm not going to go into it, but it’s worth discussing.
AVDI:
It just occurred to me though that, so tree by default without rbtree, tree is implemented as a hash. And I guess in 1.9, hashes have ordering, so I guess sets are implicitly ordered in Ruby 1.9.
JAMES:
They are implicitly ordered in Ruby 1.9 because under the hood, if you do not have rbtree in your pack, it defaults to a hash. And hashes is ordered in Ruby 1.9, so yeah that’s more of a mistake, I think, but yes.
AVDI:
I wish I explicitly ordered class like… ordered hash in Ruby, just because that way, it would be easier to write backward compatible code, because we could have that just be an ordinary hash in 1.9, but then it would be a different sort of beast in 1.8.
JAMES:
Right, that’s one of the problems with relying on hash is ordering if you have to go across Ruby versions since you can't count on that.
AVDI:
Yeah, very subtly breakable.
CHUCK:
Yeah. all right, is there anything else? Because we’re about at that point where we need to start doing the picks.
JAMES:
I wanna mention one more, just because I enjoyed this one. This is all the way back in the behaviors chapter, so we are kind of skipping back in the book now. There's a pattern called Intention Revealing Message. And when I read this one, I realized that I could actually define eras of my programming growth, in when I did and did not understand this pattern. Because before I understood it, if I saw a method somewhere that just had the line of code in it and was only called one time, I would just reflexively inline that, right? I would grab the body of method, yank it out, and just stick it in line and remove the method, without ever thinking about it. And then I pass the threshold where I began to understand this pattern, I realize that now I actually sometimes will create a method, that’s only used in one place that I extract a line into. And I'm doing it for this purpose right here, which is in this case he's highlighting something, but the code to highlight something is because its two colors it’s just a reverse on the colors, which isn’t very… it doesn’t really tell you what it’s doing. It’s more of an implementation detail than what its actually doing is highlighting something, so he extracts it into a method and calls that highlight, and then you don’t need a comment or anything like that because it tells you, “I'm highlighting something.” So, I think I
can actually track my programmer growth by when I understood this pattern.
CHUCK:
Yeah, I had that one. And the role name temporary variable, I don’t remember exactly what the pattern is called, or something like that, where it’s similar thing where this temporary variable, it’s his job to do this thing or to keep track of the state or whatever.
JOSH:
So we all know that a comment is a lie waiting to happen; and intention revealing name is also a lie waiting to happen. Just because the comment is in the name of method or the name of the variable, doesn’t mean that you don’t have to pay attention to how it’s spelled anymore.
JAMES:
Yeah I think that's true, but the great thing about the intention revealing message to me is that it’s a way to specify, like when I feel myself wanting to write a comment, I would much rather extract that code into a method, you know.
JOSH:
Oh, absolutely. Or write a test that explains what the comment would say.
CHUCK:
If you are refactoring the method, then you should be refactoring the name as well. Red green refactory name.
JOSH:
Ooh, okay. [Chuckles]
CHUCK:
I don’t know.
JAMES:
That’s hilarious though. I definitely agree with what you are saying that they can be misappropriated or grow into other things, but you know, that’s true of any method in an object, I think.
CHUCK:
Yeah, but if you are being attentive about what you are communicating, then you are recognize this as take cookies out of the cookie jar, where in fact, it’s dumping the cookie jar out. And so you need to change the name to reflect what's going on.
JOSH:
So I have one last little quickie to slip in here, and that’s about streams. And in Ruby, we have the << operator for arrays, and think that, for the most part, takes place of a huge case of what you use streams for in Smalltalk. In Smalltalk, the order collections are okay, but there was a fair amount of overhead in the implementation for how they would grow. So streams are really how people would put together collections that a bunch of people had to add stuff to. But in Ruby, we have the array << thing and that seems to take the place of all the uses for streams that I see Kent talking about in his book. It’s an interesting pattern.
JAMES:
The streams are kind of interesting, because they can also be used… like if you need to put two collections together, streams maybe have a slight win there, but I guess in Ruby, assuming it’s an array or something, we can just array plus array. And then if it’s a hash, I guess we can just call merge, so. It seems like we have other ways of doing those things. But the idea of having a streams as the first class citizen of the language, I find kind of cool. Like you can do some really cool processing with like infinite streams for example.
JOSH:
Yeah. There was definitely a big part of that Smalltalk data processing model. And so, in Ruby there's the class IO class, that is very stream like. And the IO class stuff in Smalltalk was just a sub class of the stream, because they were these infinite streams, and you were just always pulling something off of the head of the stream, or pushing it on to the stream, so.
AVDI:
Yeah, Ruby really kind of brought the Perl in in that regard. The way Smalltalk does it is how pretty much… I mean, a most carefully architected language did it before was the idea that this thing could be really, really big, we can't possibly process it all it in memory. And so everything should be done as a stream; every kind of operation should be done as a stream. And Perl is like, “We can suck a whole file into memory. Why not?” Which turns out to be incredibly convenient for the cases that it was true. It was just so much more simpler. And like people take that stuff for granted now, but man, the first time I saw that Perl could do that, could just suck a file into a variable in one line, I was like, you mean the strings aren’t bounded?
JOSH:
[Chuckles]
AVDI:
[Chuckles] And it doesn't like make the machine fall over and die when you do that? They are efficient? [Chuckles] So that’s the the sort of pragmatic Perl influence of, yeah most of the time, we can just play around with strings and it will be easier.
CHUCK:
Yeah, all right. Well let’s get into the picks. Sorry to cut you guys off. Let’s go ahead and have Avdi go first.
AVDI:
All right, so this I think is something that has been discussed and picked before, but it’s got a new version coming out. VCR, the library for testing your app’s interactions with external rest APIs, is it’s on beta of its 2.0 release. And has Myron has been blogging about some of the changes to it, and there's some really nice changes coming out. Some stuff with making it a lot easier to customize how HTTP request are matched and played back and stuff like that. This is an incredibly, incredibly useful like life saver library for trying to do repeatable tests at a high sort of integration level with HTTP services. So check it out. Check out some of the blogging that he's doing.
For a non-code pick, I have been sort of trying out various booking systems lately, systems to enable people to like book an appointment with me, so I do various types of consulting, and I also will just do remote pair programming with people that wanted to do some open source work. And I have been pretty disappointed in all the systems that I’ve tried. The one that I'm using right now has caused me I think the least grief of all of them, so I thought I’d call it out. It’s called, You Can Book Me. It’s youcanbook.me. It’s made me rage less than the others, so there you go.
JAMES:
We will now have to start booking our appointments with Avdi to record the show.
AVDI:
[Chuckles]
CHUCK:
Yeah, no kidding. All right James, go ahead.
JAMES:
Okay, so I have two picks this week. I don’t wanna pick code brawl, because it’s been picked before way back when, but I did write a code brawl challenge this week, and it’s kind of a neat, just playing around around with Ruby and what you can do, kind of thought experiment, don’t take it too seriously. I've already do that messages about, well Ruby 1.9, makes this significantly better. Yeah, yeah I know. Let’s see if we can make it even better. What can we do?
This week’s code brawl challenge is to find a way to handle situations where methods need to take multiple blocks. So obviously, this was inspired by my recent playing around with Smalltalk, where in Smalltalk passing multiple blocks to a method is nothing. They do it all the time. In Ruby, we don’t do that because the syntax wasn’t really designed for that. There’s quiz, experiments, there’s already been like 12 people who submitted for it, so it’s kind of fun. So I think guys you guys should check it out.
And my other pick for this week is a game I've been kind of hooked on this week, which is called Space Chem. And it’s about like combining molecules and bonding them and stuff like that, but actually, you'll find as you get in to it, it’s kind of a lot like it’s kind of a visual programming environment, and you are using these various instructions, and you're having to wait on things to happen before you can do other things. it’s really similar to how processor processes instructions, so kind of optimizing thing. It’s totally been eating my free time, so this is a fun game to play with for programmers. So I´ll put links to both of those in the show notes.
CHUCK:
All right, thanks James. Go ahead, Josh.
JOSH:
This isn’t a great week for picks for me, but I´ll do my best. One of my picks is Marcel Molina, who is at Twitter and used to do Rails Core. He answered a question on, “What are the good books to learn object oriented programming?” I really like his answer. He had a good selection of books. I've read most of these books, the classics and if you are not at least familiar with them, I urge you to become so. By the way, Quora has been turning out to be much more interesting than I thought it would be, so I´ll just have that as my insularly pick on that one. And then the other one, and I'm totally cheating here, because James turned me on to this site is thisiswhyimbroke.com. So it’s just basically completely bizarre stuff that…
JAMES:
Sorry, did you mean “amazing”?
JOSH:
Yes, I meant amazing. Completely amazing stuff [chuckles] that if you had infinite money, you would buy all of it. Everything from the sandals that leave animal footprints to R2D2 beanie caps. I think my favorite though is the hoodie with a picture of a raptor, and you cross your arms and make a mouth with your elbows.
JAMES:
So awesome.
JOSH:
[Chuckles] If I had a child, I would buy that for him. [Chuckles]
CHUCK:
All right, I'm going to do my picks real quick because I can hear my two year old coming at the stairs, crying. One pick is teleport. I don’t know if I've brought this up before, but teleport is an app that allow you to share screens between your computers, and is super handy. And the other pick, I've been spending a lot of time with my father in law, and there's a store out here. I don’t know that it’s all across the country just out here. It’s called Harbor Freight, and it’s a tool store. And I've been buying all kinds of hardware, not computer hardware, but like real hardware that you use to fix stuff with. And so I've been going out there and buying more crap than my wife would like me to. So those are my picks and I'm sorry to have rushed them, but I don’t want my kids screaming on the podcast. [Chuckles] We'll go ahead and wrap this up. I just wanna thank the panel for coming again. Again, we have Avdi Grimm.
AVDI:
Happy hacking!
CHUCK:
James Edward Gray.
JAMES:
This is definitely not an awkward goodbye.
CHUCK:
Josh Susser.
JOSH:
Uhm… goodbye.
CHUCK:
[Chuckles] And I'm Charles Max Wood. If you wanna get the podcast, you can find it in iTunes, just search for Ruby Rogues. Were definitely in there. Leave us a review if you like the show. You can also leave comments on the blog at rubyrogues.com. If you have suggestions for the podcast, you can go to RubyRogues.com, and click request a topic. And we've been trying to consider those to figure out which ones we wanna do.
Next week, we are going to be talking about Logging, and we have Tim Pease coming. And so we'll be doing that. This week, we were going to be talking to Corey Haines, but something came up, so we'll probably reschedule that, so keep an ear out for that one as well, thanks!