RR Book Club: Growing Object Oriented Software Guided by Tests with Steve Freeman and Nat Pryce
- Published on:
Testing and Design as a Holistic Process
7:10 - Design and Development Philosophy
- Context Independent Pieces That Work Well Together
8:07 - Focus on the communication between pieces, rather than the pieces themselves.
9:36 - Falling into the "communication as an afterthought" trap.
- Monad Bubble
16:51 - Event Driven System vs Batch Driven System
20:04 - Code in Main as a Matchmaker
- In Contrast to a Mediators
20:55 - "Tell, Don't Ask"
21:26 - My System - Aron Nimzowitsch
23:16 - Outside-In Development
24:44 - Ports and Adapter Architecture
- Deferred Decisions
28:13 - Deployment to Production
33:31 - Rhythm
- Development Within Highly Integrated Systems
- Success is Addictive
- Warning: Projects May Appear Too Simple
- The "Release / Get Shouted At" Cycle
48:21 - The Power in Naming (or Renaming) a Concept
- Trying not to name things after patterns
- Use a thesaurus!
- Code should express why it exists
58:38 - Improve the Diagnostic, Improve Your Understanding
Our next book club: Service Oriented Design with Ruby and Rails by Paul Dix
CHUCK: Alright. I’m back. I have a “STOP” sign I put on my door to signal to my kids not to come in.
JAMES: Does it work?
CHUCK: Ah, yes. It’s only failed once. And it was because she was already in trouble and was coming to appeal to me to not be in trouble.
[This podcast is sponsored by New Relic. To track and optimize your application performance, go to rubyrogues.com/newrelic.]
[This episode is sponsored by JetBrains, makers of RubyMine. If you like having an IDE that provides great inline debugging tools, built-in version control and intelligent code insight and refactorings, check out RubyMine by going to jetbrains.com/ruby.]
[Hosting bandwidth provided by the Blue Box Group. Check them out at bluebox.net.]
CHUCK: Hey everybody and welcome to Episode 68 of the Ruby Rogues podcast! This week we’re going to be talking about our book club book and that’s “Growing Object Oriented Software Guided by Tests”. And we also have the authors here, and that’s Steve Freeman and Nat Pryce. We’ll talk to them in a minute. I just want to introduce our panel; first we have James Edward Grey.
CHUCK: We also have Avdi Grimm.
AVDI: Hello hello!
CHUCK: I’m Charles Max Wood from devchat.tv and let’s go ahead and introduce you guys. Steve, why don’t you go first? Just tell us a little about yourself.
STEVE: Oh hi! So I’m based in London where I’m a freelance software person. Slightly complicated check, complicated history which evolved working for all bunch of things including software houses and consultancies. Never directed for a certain client, usually I have either through a consultancy or as independent. Stopped for a PhD along the way, which gave me a chance to get in touch with a few things a bit deeper. And along with that sort of early member of the London Extreme Tuesday Club, which is a group of like-minded people who got together about 12 years ago now. And as we say on the book, a lot of the materials has come out of a decade of arguing and pubs. It’s been quite thoroughly road tested before we wrote it down.
CHUCK: Awesome. How about you Nat? Do you want to introduce yourself?
NAT: Hello. Just like Steve, I also am a freelance independent computer programmer and have worked in a variety of industries: some banking, some sports visualization and the first dot com boom. I’ve done a PhD. I’m currently doing some embedded Java stuff for a major broadcaster for a set of boxes. Again, I met Steve and XTC and many other people banked these ideas around and that’s carried on with until they became a book. I think that covers it really.
CHUCK: Awesome. So have you guys worked on the same projects then following this process? Or is it just something that you guys kind of came together and said “Yeah. We kind of do things the same way”?
NAT: Toward the latter, we have worked on the same projects but only a few times. But we have separately applied these techniques to a number of different projects both in Greenfield and Brownfield projects. I’m sort of honing along the way that’s why I’m talking to other people who have been sort of trying them out and applying them in different areas as well.
STEVE: Yeah. I don’t think that we’ve actually ever been on the same team other than the few that ever made it yet.
NAT: We have done... briefly
STEVE: Briefly, but we did have some time in the same room.
NAT: Same room, different teams.
JAMES: That’s interesting. I mean it’s really interesting to talk about how the ideas have been road tested you know by talking about them with other HP folks and stuff. But you basically ended up writing I think what to me seems like it’s kind of becoming the economical test book lately. Everybody talks about it as probably about the best approach to testing and stuff. I was wondering though from the intro, was that really what you set out to do? Or is that more of the happy accident and you ruined your set out to, you know, show people how mocks are supposed to be used for example?
STEVE: Just to interrupt for a moment. I don’t... Let me rephrase that. I don’t regard this as a book on testing.
NAT: No, I don’t.
STEVE: I could write a book about on stuff like that, ‘guided by tests’. That’s why it’s called that.
NAT: Yeah. I think we pitched it as a book about test driven design and development. But we picked the word “guided” rather than “driven" because it is sort of less “forceful” in a way. It more accurately reflects how the tests do guide development. But secretly it was really a book about how to do OO design in a particular style and how to make that design style emerge through a kind of holistic process where sort of design and the way people work together and the way you test, is all part of the same thing rather than it being a book just about testing or just about design.
STEVE: Actually, I think the history as far as I remember is, I did actually want to write something down about the mock objects then because I was tired of people disagreeing with what I haven't said. So for I know, we write a book and at least we'll disagree about what I said, not something else
...which never happens anyway but we got a little bit of a way in and realized it’s actually about something else altogether. So we pivoted, I think is the appropriate phrase, because again we realized that a lot of the arguments about mocks and not mocks are actually completely the wrong level. And it’s more about a design philosophy. And that’s what we are trying to get across and then the mocks sort of fall naturally out of that, if that‘s what you’re interested in. So as much more about that I said that the design philosophy and development philosophy that we try and follow.
AVDI: How would you sum up that philosophy if you had to?
STEVE: Collaborate... Lots of little pieces talking to each other.
NAT: Compositional component... Composed and designed where you compose your systems, your behavior out of context independent pieces that compose well. What do you think Steve?
STEVE: Actually, firstly I think there’s a picture in there somewhere. So, the big difference is so you got a system that’s built up back lots of little of bits and pieces talking to each other and you can either focus on the pieces or you can focus on the communication or protocols. And lots of people focus on the pieces, which is fine. That’s their privilege. We tend to focus on the communication, which is how we ended up where we are and how the pieces talk to each other. And this goes back to Alan Kay’s famous line about “It’s all about messaging”. It’s about how the pieces talk to each other which what I just said. And that pushes you in certain interesting directions which you can choose to or not and I think one thing that became clear after we sort of plowed through this is that a lot of the arguments we’re having were actually much more fundamental than when to use a particular technique for testing or not. But we’re about whether you’re interested in the pieces or the links, the nodes or the edges.
AVDI: Right. You actually point your ideas, going back to Alan Kay and one of the things I wonder about...
STEVE: At least.
AVDI: Yeah at least. And one of the things I wonder about is often, what is it about design that, we’ve had these ideas for a long time and yet we’ve seen so many development projects kind of go into the territory where it’s talking more about model the problem with our classes and we’ll figure out how they talk to each other sort of as an afterthought. Why is that so easy to fall into?
STEVE: It’s probably the training, so having been through the OO bubble. One of the things when you get to a certain age and you’ve been through several bubbles, you start to recognize the pattern.
NAT: Yes, we’re about to enter monad bubble I think.
STEVE: What was I going to say? Is that the way a lot of OO was taught, was taught in terms of classification.
NAT: Yes, and sets.
STEVE: And particularly, I think because at the time most people are doing C++, the dominant language in the OO world, I guess.
NAT: I think it also comes from I guess sort of the generation before OO was very database centric and entity relationship modeling. And certainly when I learned OO at university 20 something years ago, it was more focusing on class hierarchies and a class is a set and set theory, rather than focusing on message-passing protocols. My PhD ended up in looking at process calculi for concurrency. So that influenced my thinking about OO design and OO programming when I ended up going in the industry and using things like Java and stuff.
AVDI: That’s interesting. ‘Cause that’s something that we’ve noted a few times in discussions on this show is that a lot of the concurrent programming systems that are becoming popular now actually have a lot of properties, you know like Erlang; and some of the stuff, and Clojure have properties to them which are actually very close to some of the original ideas of cellular objects sending messages to each other.
NAT: And again, I didn't think that the education was that formal but then again I was doing distributed stuff. We spend time thinking about, again thinking about messages and the sort of at a larger scale for the cellular approach.
CHUCK: Well it’s funny that you guys, you’re talking about “way back when I was in school” like you’re really that old but I do want to point out, I mean I graduated with my bachelor’s degree in 2006, which really is not that long ago. They were still teaching it the same way with the classifications, your inheritance model is like your key to the whole thing and they were teaching us Java.
CHUCK: So, I mean I still think that there are a lot of people that still don’t understand it and institutionally, they’re still stuck in that mindset.
STEVE: Yeah. And again, one thing about it is particularly when you’re teaching it and you don’t do it all day, which is what? You know most of kind of mix up code for a living obviously, is certainly they don’t do maintenance for a living. The class stuff is the easiest to see and the easiest to teach.
STEVE: Because it’s there and compartment can partly cache it for you.
NAT: And you can draw it with UML.
STEVE: Oh yeah.
NAT: UML, it’s like an entity relationship modeling notation more than a message protocol definition notation. You can use sequence diagrams and some state machines and things. But they’re not very much focus upon almost all your narratives, static past relationship diagrams.
STEVE: I mean the irony is it’s actually all in there but like a lot of things with UML, people don’t use it.
NAT: Right, ‘cause it’s all in there.
STEVE: That's right.
CHUCK: Well I think that’s interesting too because in a lot of cases we talk about, we think in the objects. We usually don’t think about the edges as oppose to the nodes in our system. Just because in the physical world, the things that we really identify with are the end points. We don’t really think about the street. We’re not thinking about the pipe. We’re not thinking about the power line. All we think about is the appliance and the power plant. And so, it is a lilt bit different thinking, realizing that the relationship and the message passing are really the parts that matter because those are the parts that define the shape of the system.
STEVE: Well, the irony is that these days you have lots of consumer devices that you have no idea what’s going on inside. You have a few buttons on the front that you can press which is effectively the protocol. When we’re teaching, one of the diagrams… We have pictures we use which is now a very old hi-fi system because… it’s probably saying not even a hi-fi system updates me. But yeah, it’s got interfaces, it’s got plugs going in various directions and some knobs on the front and a dial, and that’s what we use in the picture because it’s the kind of the model that we teach.
JAMES: When I was reading the book, I was struck by (and I think you do actually mentioned this at one point) maybe it was the great example you chose but in the book you’re dealing with Swing and then a XMPP library so lot of asynchrony going on. And you pretty much have to resolve a lot of app by callbacks and stuff. I think you actually mentioned at one point in the book that those callbacks are almost OO in a almost pure form, because the objects are barely just communicating with each other by sending messages at the right times, when they need to do that thing. And that struck me as interesting as I was reading and watching current development stuff because a lot of times we do, even make models something fairly well, but then executed almost linearly. You know call this, then call this, then call this, which really isn’t all that different from procedural code but with objects involved. Was that intentional, like in the selection of your example, did that just fallout off the code naturally?
NAT: Pretty both I think. The style that we present in the book is that you create a graph of objects that talk to each other, you poke them and they just sit there ticking away, making the system run and you thought step back; you don’t care how they do it after you’ve wired them together. That style does like I say, does fit an event-driven system much better than a batch-driven system or a system that’s doing a lot of transformation. It’s like a web app has an event-driven layer at the bottom handling the HTTP request but then it’s getting the resorted the transforming it into representations to send back to the client. That bit is very transformational, a bit more batchy than more functional in style. So we sort of picked an example that demonstrated this style well. And a lot of system who you write do fit that style; they are event-driven to messaging or there’s a GUI aspect of whatever. So yeah, they’re both.
JAMES: I like also that you chose that strategy because I think people view evented systems and stuff just as more difficult to test in general. You know with the callbacks and the stuff. And you actually, in the book, you have several chapters in the 3rd section about how do you test separate grids, separate processes, stuff like that where something is happening in a different stream of execution. I thought that was really great of you to tackle what’s traditionally considered difficult.
NAT: Yes, it’s difficult. There are some techniques that we used to simplify somewhat; doesn’t take away the difficulty altogether. Actually we’re very vigilant when working on tests of asynchronous systems not to let race conditions and things like that slip into your test and then make the mock become unreliable.
STEVE: Yeah, and the other thing is as we see things like now this is that there probably are sort of limits on how much you can understand that complete event-driven system, is that probably it doesn’t scale up conceptually or cognitively that well.
NAT: I think the nodes and styles of lots and lots of closures, callbacks are nested out into each other. I’ve seen that done in GUI programs. You know, back in the days when most desktop apps where rich clients and you can't just maintain that. But objects are a technique that it let you tackle that complexity because you build this little communicating event-handling state machines and then you plug them together into richer behaviors and as we say in the book, that plug-in together is a declarative description of what you want a system to do as long as you’re focusing on making these things compose cleanly and easy to understand; when you compose how they behave, predictably that when you compose they'll behave predictably. I think that’s of the sort of tricks. Maybe we don’t really sort of mentioned it much in the book but it’s kind of like key to this style. And that does help tackle the complexity because now, you’re working at higher level. We’ve created a new language, lifted yourself up to way where you can now describe things close to application domain and working in more bigger chunks of functionality.
JAMES: Yeah, about a metaphor in the book to kind of along these line is, you talked about the code in Main as a matchmaker.
JAMES: You have all these objects that do their own thing and Main’s job is just to introduce everybody like “Oh yeah! You’re going to get together with him and do this.”
STEVE: That was in sort of in contrast to a “mediator”. That sort of terminology we use in there. Mediator sits in the middle doesn’t actually introduce objects to each other by just go, “Well I’m going to tell you to do something. I’m going to ask you something and then I’ll tell him to do something.” Our sort of style is well we have this thing that we call the matchmaker or whatever introduction. So if it just goes, “Okay, you talk to him. You talk to him. You talk to him. I know the way they talk to each other so I know that you’re compatible. Off you go.” And then steps back and we’ll garbage collected away.
CHUCK: I think that really ties back into the whole concept of “Tell, don’t ask” and then you actually said asking there, “I’m going to ask him this and tell this other guy this”. So yeah, you’re still telling but you’re asking in certain circumstances to mediate the connection as oppose to just saying “Okay, this is your new friend and this is how you’re going to interact with him.”
JAMES: I think we should talk a little bit about the format of the book. I’m a big chess player and in chess, there’s a classic book called “My System” by Nimzowitsch. It’s a really great book where the first half of the book, he kind of explains his thinking. And then the second half of the book, he gets in to these involved examples. And as I was reading your book, I kept thinking of Nimzowitsch’s chess book. It’s kind of similar. The first third I guess chunk, you explained your thinking and these processes on why you make these decisions. And then the second chunk of the book is one long large example, which I thought was a wonderful way to get around problem of technical book examples usually being too trivial.
JAMES: By devoting a whole section to it, you were able to tackle something fairly big. And then the third section, you basically just did digging into details. “Here’s some of what we did and here’s some of the complications that arise if you follow that further things like that. I really like the format of the book. How did you land on that?
STEVE: That was good. I mean I felt quite strongly about having a longer example because I was getting very tired of, you know the first round of books is how to test drive a list or a stack. I think it’s stack rather than list. That’s a good place to get started, but then now I have to write some real code. I felt a lot of what I saw was seeing around with people who hadn’t quite understood how to scale it up. And particularly the other thing that we won't see in that people who understood was the outside thinking that we do. Actually starting from the outside of the system, they’re trying to figure out what they are suppose to do and then drilling in. There are other schools who taught of test driven where they start more on the middle and work their way out. So, I was quite sort of keen that we do that. We kind of ran out of space and time because the next plan or the plan for the next few chapters was to show introduce a sudden change in direction to show the system cope with that. I think we’re going to go web-based instead of Swing-based. We can never go around it because partly it was long enough already; and partly it was, we were running out of time. Perhaps if we get to do this again, we can do that.
NAT: Yeah, on second edition. But the story arch of that example actually came together quite nicely at the end which was, we start with this code that we are not apparently having any design style in at all. It’s just all smashed into Main and then slowly through adding tests and refactoring, some structure emerges. And by the end of the example, you have a very clean ports and adapters architecture but we haven’t started out making one. It’s just something that we know. The things we want to separate from each other are separated by a ports and adapters architecture and the refactoring that we do to cause that separation ends up making the ports and adapters architecture emerge from the process. So, I thought although we didn’t have an entire grand plan for that example, the actual story that it told turned out very well.
STEVE: I think one of things that became clearer while we’re still working on it, because it took about 6 runs to get that kind of balance but once you get the balance between something that looked realistic including some mistakes and something that didn’t look like we were complete idiots and didn’t know what we’re doing. But, I think one of things that became clearer was that this idea of leaving rough patches in the code until we’d figure out where it would suppose to go and having that a little bit of tolerance. Not too much but a little bit of tolerance to unfactored code.
NAT: Yeah, it gives you an option.
STEVE: It’s cleared sort of before we started, at least for me.
NAT: And it’s certainly something that people commented on. They are like “Oh my god! You a like a star. You’re example, your code is such a mess." And it’s such a tiny piece of code. I don’t really feel the need to make it really clean. It’s literally a screen full of code. I can see in one glance. So only as it gets bigger that I need to carve pieces off that so that I don’t have to think about it anymore and focusing on the thing that I want to change.
NAT: And I don’t know how to do that yet until I’ve actually got the things in there that I then start feeling that this bit I don’t want to look out. I’m looking at this bit right now. I can see where the edges need to be put in.
STEVE: Of course the caveat for that is we do actually we go back and do that rather than just carrying on writing more code.
JAMES: Yeah just skip that later stuff, right? The book talks a lot about your deferred decisions which is basically what you’re talking about right now. “Maybe I could refactor this now but if I wait a little longer and see how it actually ends up getting used, I have more information that I can probably make a better choice.”
STEVE: Yeah. And that’s a subtle balance that only comes with the experience because you have to go too far in each direction to realize where the boundary, a good boundary is.
NAT: I think yeah. You just continually oscillate around what the optimum level is ‘cause you can never really tell it. It’s very context dependent on a bigger team, than you have to be a little bit more careful about organizing your code because it’s so easy for it to snowball out of control and lots of people are just, you know, being… a lots of people are deferring their design decisions at once then it can just get out of control quite easily. We have to be careful to decide based on happy good teammates and experience levels and what have you language, you know, and tool support and also exactly how much mess is bearable.
CHUCK: So I want to hark back a little bit more to the beginning of the book just for a second. One thing that you said that I thought was really interesting is the project is getting started one of things you test is deployment. And I understand some of the benefits of that where you know that everything’s in place, the right technology is there, the right packages are installed, things like that, but what’s the best way of doing that? I mean do you stand up kind of a duplicate of production and then deploy to that?
STEVE: What I’ve done and it worked best, I’ve deployed into production within a week or two’s time in project. Obviously that depends very much on the organization you’re in. In some places it takes 6 months and 19 teams to commission a machine and that is unfortunately not an exaggeration. And in some you can get a VM within a minute by going to a website and by hitting a button or something. So, certainly trying to get the deployment as smooth as possible so then you can just not really think about it much. And it’s not just the deployment; it’s like the integration into the entire environment, the run-time environment that you’re going to be integrating with. So, how do I get it onto a machine? How do I talk to, I don’t know, the data sources that they want me to integrate with? Not so much a database that I’m going to use internally to my system, I might defer that decision for as long as I possibly can. It’s more about where I know if I’m going to be receiving market data from such and such of provider. While first I could do is can we integrate with that easily? And think about lead times if I have to get a licensing approved. Now the whole bunch of issues, if you leave it too late, it can be that too late and you got to find out as early as possible. And then as your system grows, like little changes can become easier to automatically deploy. You can change the deployment more easily over because you understand that your system works and any if it starts failing that you got a small thing broke, if you leave it late, it can just be an enormous amount of work to actually get a deployment process automated and because of all the different things that can break.
NAT: I think it’s one of things that’s very difficult to explain to people who have never done any of this is that if you get to work on a really clean project with a whole soup to nuts but it’s done properly from scratch is although it looks very sort of constraining to it, it is how much comfortable it is that you can just tackle a bit of a code, commit it and be certain enough that it actually hadn’t broken anything and you can just carry on and do the next thing and just think about one thing that’s timed. And it’s like a lot of things in this world. It’s very difficult to explain until you’ve experienced it. And I think a lot of people that I see, they get closer to it but they don’t fully appreciate how much further they can go.
JAMES: You have a really good chart in the book that kind of talking about this where you show how the process feels so heavy upfront because you breaking your first end-to-end test, you’re getting the entire integration, deployment and stuff set up and it feels like “Wow! We’ve put in 2 weeks’ worth of the work. We already done this one test that really doesn't do much.” And how it feels so heavy but then the graph shows that as you go along overtime because of all that’s integrated and setup and the process is in there. You know that overtime it's just smoothly adding features after that and almost flat lines. I thought that was real like I loved that picture when I saw it, I was like “Oh yeah, that’s a great way to think about it.”
STEVE: It is problematic sometimes some gigs sometimes try to run out of contract and quite often on a side it’s a bit of a mess. One of the biggest messes is the build. So I then disappear into a corner and spent some considerable period of time messing around with ant run or whatever it is in the Java world, cursing and swearing, and being generally unpleasant. I can’t stand that stuff. It has to be done. And there's no visible progress whatsoever. All they can see is this day right being spent not some currency, what’s going on? Because what I’m actually doing is trying to get the thing under control and stable. So you can actually tell what the hell is in the build and what’s not, so you can actually move up to the next stage but that’s often a difficult transition.
CHUCK: Yeah, one thing that I really, it really kind of hit home for me in a couple of different ways. One was when I was talking to David Brady the other day, he’s only the regular on the Ruby Rogues show that’s local where I can actually go and have lunch with him. In this case, we had breakfast, anyway, we were talking about some other things and then we were talking about the last job we would get and it was basically we both agreed that when they laid us off that they had laid off basically that the people who set the rhythm for the team. When I was reading this section of the book, what really kind of hit home to me there was that this is kind of setting that rhythm. Like that whole process of setting this up, you write your first end-end test. You get all the unit tests that go in between. You do all of the other things that need to happen. You need to make sure that deployments are working, that the CI is setup and then that kind of does set the rhythm for the way that things get developed because then people start to follow that process. They start writing those tests and they do those things that demonstrate that the system works and allow further tests to guide the development process. And all of those things that kind of get set up were there and as the team adopts them and if you can maintain that adoption which that team didn't after we were gone, then you really do get that rhythm and you move forward because you know which direction you’re heading.
NAT: Yeah, I think that idea of rhythm is good. It gives you the feeling of accomplishment, of achievement as you go through this, write their sort of functional test or exceptions test and build out the units and see if they’re still working and what the acceptance test like gradually parts more and more into it. It’s complete and you can confidently push that into production. It’s a sort of comfortable feeling. You don’t have worry that you see a lot of teams have that they have no idea if this change has been broken or not until maybe a QA team 3 weeks later will tell them something seemingly related has stopped working. That kind of always have that sort of daggers over your head. It makes the job unpleasant really. It’s supposed to be a fun job.
CHUCK: One other thing that in contrast to that project, another project that we built that was highly coupled, it really had a lot of the problems that you point out that the tests will tell you are there. If we had been following this process and been aware that having trouble with the tests in those ways indicated those problems, it really would have helped us set the right rhythm where this is the process you follow and here are the telltale signs that you're doing something wrong.
NAT: Yeah, I think that listening to tests is absolutely key and sort of like stopping the line and fixing a problem so that difficulty goes away. This what makes the whole process sustainable and without it, it can just like grind to a halt way you've got. I've seen thousand-line tests where they were setting up likely as 600 local checks I think. That is not helping.
CHUCK: (laughs) Only 6,000?
STEVE: Very, very dedicated to the testing.
JAMES: (laughs) Yeah.
NAT: At the end of the day, you can make your life easier, you know.
STEVE: Just to step back a minute. So one of things we won't have our sort of economical projects and the one I worked on, one of the guys said later that the great thing about having always infrastructure in place is he just didn't have to remember stuff. You could focus on whatever it is you're doing now and not worry about the rest of the world, because you have this safety net to catch you, which you know you have to be careful and make sure it really is a safety net and hasn't got holes in. But on the hole, if you're thinking of releasing that's probably alright. The other thing actually just to mention at this point, not I was talking about progress there's this sort of management psychology book which is called "The Progress Principle" which says what does people in is not making progress even if it is just a little bit of progress, that's what people keep going, makes them happier. And the great thing about this sort of style of of drama to see you are on the hole always making progress. It has its stresses but it's a much more comfortable place to be than try to do at least without the infrastructure.
JAMES: That's a good point right? That's success is addictive.
STEVE: It does cause you problems in some organizations because you're not seen as sufficiently committed because you get home at 5 o'clock and at least with a lunchtime rather than a weekend and all these stuff. I know a team who's had that problem is that, because the thing goes as smoothly, they've been sort of downgraded by in management perception. Because that old classic, that's obviously a simple problem.
CHUCK: Yeah I love those.
JAMES: Right in the blizzard about the release of Diablo 3 or something. They'll always put up pictures of their programmers' rooms and you see the guys desk and you see his little pallets, sleeping bag behind it. It's almost like they're bragging about that and I think Wow! There's a process that's gone tragically wrong.
STEVE: And the other example I was thinking off was, I was with a team that was doing, it was some kind of an investment bank trading front office I think and their tradition was that they do release and then sit in fear the next morning while the phones are ringing to get shouted at.
And yeah, so we put a few things in. It wasn't the whole, we've start putting a few things in place and a bit of those infrastructure and some sanity testing and stuff. And they did the first release in the new regime and they sat down the next morning and nothing happened. And they were astonished, “how could this be?” They never had that sort of ease of release.
CHUCK: Yeah. Well it's so funny to me too how many of these really do get downgraded to OD that' so simple. I think a lot of us have been in that place where you don't credit because you've done it right in the first place and now it just kind of flows in with everything else.
STEVE: It's a bit like, years ago when our research days we had a problem, she said wait for you to see first what you do in academics she goes to some conference and see some big shot. He presented new findings and she go, "Oh! That's so obvious." And he actually learned a while she goes to some conference and she see some pictures to present his findings "That's amazing. That's so obvious."
STEVE: The obvious stuff, the simple stuff is hard to do on whole.
JAMES: I want to take the conversation in a slightly different direction for a bit, but I think another advantage of how you guys did the book in process is that I found just lots of small little great tips that you guys give as you're working through the problem. I think the reason you are able to do that is that it really was your process. You're just doing real programming and you're doing that and then it was "Oh yeah! And usually when I do this, it's because..." and I didn’t know, was that intentional with the way you set up the book or was that just natural out of how it flowed out of the process?
STEVE: Again certainly from our side I wanted the the book that was based on concrete experience 'cause that's what I was always desperate for. How do you this really? And the first generation of books was all about the concepts and isolation or most of them were. And we've given it on the 2nd or 3rd generation of the book and it was now what do we do everyday. And now we've tried actually this for a bit. So it was certainly a motivation for me to fold in real experience.
JAMES: There's some awesome tips in there like some of my favorites. I wrote some of them down one is you're doing a refactoring at some point and you noticed that the class is violating SRP (Single Responsibility Principle) and the way you noticed that is because of the include statements; that you're including a bunch of unrelated packages.
STEVE: Oh, imports?
JAMES: Right. Imports. Yeah. Sorry. Yeah. I used Ruby more often than Java but it has its dependencies on unrelated packages so obviously, you're doing multiple things because they're unrelated. I thought that was a great tip. There's a great rant on logging in there at one point from Steve I think, but it was really good. I've never really thought about logging like that and you challenged my beliefs in that and that it is a feature and it made me wonder like frameworks like Rails in Ruby, which where I'm used to. They make all the decisions for you. That can be a good thing but it can also be a bad thing, right?
NAT: I think there our preferences more for having small self-contained things that do something well but then we can easily hook up into a system rather than a framework that tries to do everything but then you have to add plug-ins to. So, I mean the Java world has got like some huge hulking frameworks like Java EE in Servlet and Spring and I personally, just prefer to stay away from those and just like build things out of convenient little libraries.
CHUCK: I think it's funny that you present the plug-in model is kind of an antithesis to the simple Single Responsibility Principle where, basically you have this framework and you use all these different plug-ins, not to simplify it, but to add more stuff on to what it actually does.
NAT: Yeah. Obviously if you place the plug-ins then you place the frameworks. I think for long-term evolution frameworks, whole app frameworks like J2E or Rails; I've never really used many Rails. They will have a sudden step change at some point where, they supported you and you are so far but you just need to do something that is way out of this zone and deal yourself like how do I find out how to make this huge piece of code do this thing that it doesn’t really know how to do. And that can be a problem so I sort of prefer to take more time writing code if it will save me time changing it later and it's my preference.
JAMES: That's a good point. Yeah.
CHUCK: Well that was the point that you made at the beginning was that it's ultimately not going to make a huge difference to the machine you how wrote the code and so ultimately, you should be optimizing it for the developer, for readability. And that's the point I think Kent Beck made when he was on the show too. It's just something that rings right to my mind.
STEVE: Well again, obviously it's a very old idea. And go back and think about the imports and the clash in the packages. It's the same, it does a symptom of you try it within a compilation you knew whatever it is or code units, you try and get a coherent language and some of that is made visible by inappropriate imports. And again, possibly we didn't stress this enough and certainly coach your training, I keep going on on and on and on about trying to make it readable, trying to be clear and readable that what it is you're trying to achieve.
NAT: And fixing on the language and being careful about the language. It tells you a lot. Like, if you see in the middle of my application domain model, a whole lot of stuff about XML or TCP or something. That shows that I'm sort up mixing 2 domains up in one place instead of separating the concerns out more clearly. I'm probably missing some abstractions that will make the code more easy to understand if I could pull up all the TCPs out into something and push more towards that ports and adapters architecture for example. And you can actually you can analyze the language in your code and get a lot of useful information out of it. I've done some sort of latent semantics indexing code and you can see I take my domain description, you know, required documents or whatever and then I compare the language in that against language in various practice in my code. I can see which ones are my domain model and which ones aren't. If my domain model is not like very close to my natural text domain model description then I know that our code is not that really very clean so it's really rough and ready sort of analysis of the natural language text in your code can give you a quite useful feedback.
STEVE: One of things we’re trying to avoid is naming collaborators after pants. So we’re trying to avoid the excessive services, the thing manager and the thing manager service factory...
STEVE: ...yeah, I guess you laughed but it’s all true. And it’s incredibly, a lot of these things I’ve been trying to get reminded about them. I had it a while ago, where we named a user service or it was like a user service and we renamed it to a... I forget what it was, its counterparties or something like that. Yeah, let’s say counterparties. All of the a sudden, various methods on this service didn’t read right. This just didin’t make sense. And became very clear very, very quickly that they were in the wrong place and you see lots of code where because something is called the “service”, you’re not really, you’re less pressured into getting the right features into that service, on that object. And it starts to become a dumping ground for anything associated with that, you know that concept. And then it becomes impossible, it drags dependencies all through the code. And it’s really nice small example of something as simple as not naming something a service, by giving it a meaningful domain name can change what you see and can force the code in different direction. And again, I regularly forget this and I have to be forcibly reminded by this code.
CHUCK: So you should name after what it does instead of calling it “service factory thingy-ma-jigger”?
STEVE: Well what you’re trying to do which is sometimes a real struggle is you try to name it after something in the domain. And the trouble that a lot of logged domains are not good, for example, collective nouns. The classic is, rather than having a “customer service”, you might have an address book ‘cause that makes more sense. That’s relevant to whatever code it is that you are writing. Sometimes it’s really, really hard to find a good name and it sort of there aren’t space at your desk for half a day.
AVDI: Okay. It just seems like a hugely important part of what you’re doing and the approach that you’re taking. It seems like one the hardest problems, when I’m working with people I think one of the blocks that I see really is naming. It seems really like a minor thing like you could write the same code even if you have a poor name, but in truth,so often I see a lightbulb go on as soon as you introduce a new name for a concept. And you do that sort of all through the book. I was kind of flipping through to find a good example. I couldn’t find one of my favorite examples, but one of things I went pass was just like the point where you introduced the idea of a snapshot. You know sniper snapshot.
AVDI: And isn’t the sniper, it identifies a state of the sniper and its value object and it was term that I had not thought to use in the past for anything like that and it kind of opened up things for me because I realized, “okay, we can actually have this object which identifies a little more about it than just like a string which is the state” or something like that. And it seems like that’s just an Aha! moment for a lot people and for me. I don’t know. Are there drills you can do to sort of expand your ability for naming things? Because it seems like it’s so important.
NAT: Try not to name things after patterns is like a really good thing to do. I was on a project where it was calculating quotes where you calculate for a price or something and then you add some extra values in and creates some extra fields in, like an extra fields factory “What on Earth is this doing? It’s actually calculating fees.” and you pass 2 different kinds in depending on some reason that we couldn’t work out. And actually I was like “Well it was just like 2 different ways of calculating fees depending on the kind of client.”, “Okay, we’ve got institutional fees or any individual client fees.”, “Oh right.” Suddenly the whole logic is out of reason for that partciular piece of code was clear. When it was just patterns, it wasn’t clear. I think that’s key. Maybe wasn’t a factory, maybe was a strategy or something. But the thing’s you can actually write down what it is, rather than how it’s doing it suddenly because the reason for it to exist that’s difficult to understand is the reason something to be changed. And that’s what you’re trying to, what the code should be expressing to the reader; why is that code exist not what’s it do because you can see what it does. Any competent program should be able to look at a code and see the patterns that it applies.
STEVE: So there’s no point in putting them in the megs, they should be able to look at it pretty well. That object creatse another object for it to be called factory. They need to call it a factory.
NAT: I think and I’m going to the point where from position to higher coders again. Nevermind a coding test and have them in certain mind games in English, write some English. See if they can string a couple of paragraphs together, ‘cause if they can’t do that, the chances of being able to string reasonable some proof-readable code together are pretty low.
JAMES: That’s a really good point. There’s another awesome example in the book. I can’t remember exactly where it comes up but, it’s when you’ve been passing strings around for a while and then you finally replaced those strings with a type. And then by doing that, that gave an obvious place where some functionality that you hadn’t known where fit then fit on that type. Kind of long on the same lines about how that just opens up. Once you find the right concept for this thing then a lot of times that’s “Oh yeah! That’s where this part belongs.”
AVDI: Somebody introduced the terms “string-typing” for that recently. When a string really ought to be a type on its own. I love that term. You know when I’m pairing I actually feel, I feel a little embarassed of that naming because I feel like well we should be writing code now, but I really want to do is I want to sit back. I want to stare into space until the right name occurs to me. Have you ever had that problem?
STEVE: Oh yes. So what suggests nearly a thesaurus on the desk. My experience for that, it’s useful but it’s a good thing to do it but I actually never found the name of thesaurus that was right. It’s nothing else just a good reminder.
NAT: Yeah. If I can’t think of a name quickly, I probably put in something that’s obviously a temporary name as something, something thingy or something like that. Because I do a lot of work in Java and refactoring a Java is less than a second to change the name or crossing the base with modern Java development tools. So Java code is very malleable so you don’t have to decide very early. You can just try something, “Oh yeah. That’s cool as roughly. It’s okay. I’ll leave that name in for now.” And then a week later, “Oh! That’s a much better name so much it’s changed.” Instantly. I think the better the refactoring tools are, the less stressful the naming is. As long as you’re always like to trying to improve the names all the time. And I think about the naming, you don’t have to do it instantly that write that class or write that method. Often as you can but if you can’t, it’s not a big deal.
STEVE: You should tell them the story about that .NET project you were dropped on.
NAT: Oh yeah. So I was dropped in on a .NET project that was a day before release and it was late. You join this project and my thought was I know Fred Burkes, I can put my feet up because I won’t be a project any later. But actually this project, it had someone to me it was absolutely fanatical about naming to the point that the rest of the team really were annoyed by him. But, I gave him something to be added into the system, I looked at other identifiers there, the classes were named, it made sense so I could find how things had to be related. I did the fixes. I finished it in a couple of hours. It was amazing. I really got to joyous project and just sit there and trying to understand how, for days and days and days. And actually it was really, really clear. And now it’s because of that fanatical approach to naming and careful, careful separation of the domains. The diffrent domains and the codes so they will have consistent naming conventions and clearly expressed why they were doing things in domain terms. So i think it does pay off.
CHUCK: So Fred Burkes is the guy that wrote “The Mythical Man Month”. Is that right?
STEVE: Yeah. Adding people into a life project makes it ---.
JAMES: This is the...
CHUCK: We need to get to the picks soon. I s there anything else that we want to cover before we wrap this up?
JAMES: Yeah. Maybe one thing I have that was kind of tangent to what we’re just talking about, aboutimproving understanding. In the book, you talked about you go to a section where you build the test and you run it and fails, but it fails for a silly reason. That’s not really related to what you’re doing. And then you spend some time getting it to fail for the right reason. We see that all the time in TDD, but it’s funny a lot of times when I do see that, I think “Oh. That person’s being a little silly. We obviously know what’s going on there. We could just skip that stuff.” But I really like you guys kind of formalized it and said that by improving the diagnostic, what we’re doing is improving our undestanding or showing that we know what’s going on so that then “Oh yeah. Now I know that I can do this because I understand what’s happening here.” And I really like that process of how it was the knowledge we were gaining more than the code we were writing. I thought that was a great focus.
STEVE: Alright, it’s good. Yeah. I think we mentioned that some, again a lot of people, teams that we see, seems to forget that test is suppose to fail in case way. They’re not doing their job if they never fail.
STEVE: I know it’s hard to believe, but when you do fail, it’d be really nice if they told you. The trouble is to tell you what the problem was. Particular system whenever high level tests. Unit tests tend to be a bit more obvious. And this is something that I think certainly to make an approach in the very early days was put the dang comment in. It doesn’t have to be a big deal, but just take you to the write place immediately and not waste anybody’s time. I certainly have this experience, the system with old test where it goes red and then dropped in 3 or 4 days of stepping and debugging and tracing, trying to figure what on Earth happened ‘cause I hadn’t quite around to putting in the appropriate infrastructure.
CHUCK: Oh come on. You guys didn’t say anything about feedback being important.
JAMES: So, one last question before we kind of get over to the picks.
JAMES: I didn’t expect to see the word “Ruby” anywhere in the book but it is actually in there.
STEVE: Did I mention?
JAMES: Yeah. You do. Nat has this mock library in Ruby.
STEVE: Oh yeah.
JAMES: A long time which you say in the appendix is kind of some where the Genesis of some these ideas comes from.
STEVE: So I spent a couple of years doing smalltalks so everything else is a disappointment after that.
CHUCK: It’s too bad Josh is not on the show.
JAMES: Yeah, Josh is our resident smalltalker. He’s usually here but where he couldn’t make it this week but he pretty much agrees with that directly.
NAT: Yeah, bitter twisted smalltalker.
CHUCK: I don’t like that, bitter and twisted.
CHUCK: Alright, should we get to the picks? Did I warn you guys about picks when I emailed you?
STEVE: No. That I can’t remember.
CHUCK: I have failed.
STEVE: You mentioned picks to me.
CHUCK: Oh, okay. Well picks are basically stuff that you like. It can be technical or non-technical. So I mean it can be tools, it can be movies, TV shows, books whatever. So you know, if there’s something you’ve enjoyed lately, just let us know what it is. Let’s have Avdi start us off just kind of get a flavor for how this goes.
AVDI: Hmmm. Let’s see. How to be a paragon of picks? Actually I don’t think that I have any development-related picks right now. Actually here, let me throw one out. It’s just sort of sparks of thought. You can subclass modules that the module class in Ruby. And I’ve been having some fun with that lately. Actually I’ve had fun with that for a long time but I’ve been playing with it more lately. And I’m not going into great detail now but kind of something interesting to play with is that you can create your own kinds of modules in Ruby. So if you’ve never done that, play around with it some time.
Anyway, non-development pick. Let’s do a booze pick. I have done a lot of sort of “pricey booze pricks” lately so I’m going to do a cheap booze pick. Teacher’s Scotch, if you are on a real budget and you want some scotch that is not entirely undrinkable at a very reasonable price. Teacher’s is actually not that bad. It’s just the blended scotch. It’s not a single malt or anything like that but I feel like all I ever do is reccomend these things that are like on the top shelf and cost a ridiculous amount of money. So just like an around the house scotch, Teacher’s pretty darn good. I wish I could get it around here. Usually I only get it when my mom brings some from the New Jersey.
CHUCK: The only scotch I’ve only seen teacher’s use is tape.
AVDI: Har har.
CHUCK: Is that your picks?
AVDI: Yup, that’s it.
CHUCK: Alright James, what are your picks?
JAMES: I was dreading you calling on me this week. Actually i tried several new things this week thinking they make good picks and I didn’t like any of them. So, I’m not taking them so that’s my gift to everyone. So then I decided I’d go pick an oldie but a goodie and I thought of several candidates and I went to our picklists and they have all been picked. So, so much for that idea or two. So I’m going to cheat. I was going to pick Ack (A-C-K), which is my favorite tool for just combing through code base looking for names or things like that, searches. That was picked way back when, of course, but i mentioned it to Avdi when we were talking recently I’m like “Oh yeah. I switched over to Emacs and I need to find some cool ack integration.” And he told me about full ack which is Emacs extension that blends with Ack. It’s really great. I played really a little bit of this week.
In addition to all the great goodness that is Ack, it has some Emacs nice ease like it’ll try to figure out where your project is based on which file you trigerred into inside. So if you’re working at some file and you trigger Ack, it’s going up to tree looking for like “.git” directory or something like that. It’s got a few tests that it use to try and figure out where the root of the project is and you can customize that. And then it searches from there inside those files assuming you’re looking for something and saying project, which is really nice. And it also gives you ways to search in the same kind of the file that you’re in right now or you can search in any file in the project. So if you’re in a Ruby file and you just want to find something in Ruby files then you can trigger in a certain way and you can can have a look at my Emacs dot files if you want to see how I configured. I’ll put a link in the show notes for how I installed it and then another one for the key bindings I gave it to do the 2 different kinds of searches: same file and then new files. Anyways, if you you’re an Emacs user and you like Ack which we’ve recommended before then Full Ack is an even cooler way to use the Emacs in my opinion.
AVDI: I knew this would happen.
AVDI: I knew this would happen. I suggested it to you like last week and you already know like a thousand more things about how to use it than I do.
JAMES: I just looked in there a little. So it was really awesome. It was a good pick so really, Avdi deserves a credit for that one.
AVDI: Now you have to teach me how to really use it.
JAMES: (laughs) Alright.
CHUCK: Awesome. Alright well I’m going to go next. So my first pick is something that we read or listen to as part of the Podcast Mastermind which is a group of guys that I talk to about podcasting in business and stuff. And our assigned reading for the last meeting was Earl Nightingale’s “The Strangest Secret”. And I’m not sure if you guys have read it or heard it. It actually was recorded for people who were working for Earl Nightingale and his organization. He recorded it back in the 50s, like ‘56 I want to say. And he actually recorded it on vinyl record. And he gave it out to his employees and his employess came back and said, “Hey! I need to get copies of this for my wife, for my brother, whoever.” So, he actually recorded it and sold it and it’s like 35-40 minutes audio. Honestly, it has totally changed the way that I think about what I want to do and how I spend my time and what’s important to me. It was just amazing to me how a 30 or 40 minute audio could really help me approach life in a different way. And so I highly, highly recommend it. I’ll put links in for both the transcribed version and the mp3 version on Amazon. Since that’s where I got it, it was like 30 cents or a buck or something. I don’t remember exactly, for the audio and the Kindle versions only a couple of bucks as well. But anyway, just incredible. It’s totally changed the way I look at some of the stuff.
My other pick is basically just in general networking. I highly recommend that people go out and find other people they can connect with and chat with. I have a small group of Ruby and Rails freelancers that I connect with. Some of them are on the Ruby Freelancers Show, a bunch more of them are just in this Skype chat that we have but those guys havereally helped me in a lot of ways figuring out some of the the stuff and know what I’m doing as far as building my business and doing things right. So, just go out and find a bunch of people who think like you and maybe think a little different than you, have a little bit different experience but who you can balance ideas of and really kind of get a feel for what you ought to do and what you oughtn’t do and just make that work for you. Because it really does pay off to be able to kind of think out loud with these guys and have them tell you what they think. Steve, do you want to go next with your picks?
STEVE: So I’ve got a couple of things. On the technical side, you probably have this already. Last night, I’m involved in a... on the side a little start up based around the Raspberry Pi. You have heard of this yet. The Raspberry Pi is a slightly larger than credit size computer that’s intended for, well originally it’s intended for education but a lot of gits have been jumping on it. I think a little 700 megahertz shared, about 4 gig of RAM and quite a powerful digital processing chip. Entertainly, it’s one towards than a magnitude than the machines I did my PhD research on. So although it’s physically small, I’m not sure if it can work as a small machine.
NAT: It costs $35.
STEVE: Yeah $35. The motivation for the guy who started this at University of Cambridge, was he was noticing over the years, the kids knew less and less as they came in because what was happening was that older machines that they were playing with were locked down; that they were either expensive home computer which they weren’t allowed to play with, or the ones in school where the USB ports have been soldered or superglued. Although there are consoles where there’s no way in and they no longer had access to tinkering. This is a completely, in fact it comes without the case when you buy it for $35. An d it just got pins on it so you can attach all sort of external devices and things. And it’s designed to be a reasonably functional nearly disposable of the computer that anybody can play with. It’s been exploding over here until to some extent in the states. Return into my solderer. I haven’t done any soldering for many decades and just started doing it again putting balls together.
CHUCK: James, don’t you have a Raspberry Pi?
JAMES: Yeah, you guys turn that well. I get obsessed with it a couple of weeks ago I got when I’ve been hooking it to everything. I can’t believe how much fun it is to tinker. Try it and get it to work with this stream iTunes off my Mac and then things you know. I played games on it. I complied Ruby on it which it took like 2 hours just to compile Ruby on it, but it was still fun and the IO ports where you can just hook it to anything. You can even from Ruby, you access those ports. Really great. It’s totally, totally a hacker thing.
CHUCK: So here’s a Ruby Rogues exclusive. This is me unpackaging mine. I got mine a couple of days ago.
STEVE: There’s 4 of us in a row.
CHUCK: Yeah, they just sounded cool. I talked to a few people who’ve been playing with them. And there you go. That’s kind of cool. So yeah, I’m looking forward to some cool applications for it. If you guys have any ideas of things they should try out with it, just tell me.
STEVE: I’m not sure in which I recommend but there’s an ocean of material out there coming on now.
JAMES: Yeah. It really like if watch the blog and stuff, everybody is always got a new project that their trying all kinds of crazy stuff.
NAT: They’ve got amazing stuff there. Someone is putting in bloom taking photos so that the curvature of the Earth, people are making in robots with Raspberry Pi in center on it. Yeah, it’s pretty fun. It’s sort of like an Arduino and desktop sort of combined in a way. That’s a way a lot of people using it.
STEVE: The obvious first easy application would be something like a bit of dull but they say like a build monitor. It can cost a fraction. And you don’t have to go to buddy purchasing to get a machine.
STEVE: For the non-technical thing, there’s a Boston surgeon called Atul Gawande who’s written several books and also writes for the New Yorker. And anything of his... it’s really good stuff and it’s good for us because a lot of issues that he faces and then he writes about like how do you improve stuff? How do stompfed under that people? Maybe not that for us but very relevant for us, one of the books is called “Better” which is how do you improve practice, practicing what you are doing. It’s just wonderfully well-written. So anything by him, and he just had an article out recently in the New Yorker. I think a lot of is available online. So there’s my reading recommendation.
CHUCK: Awesome. Alright Nat, do you have any other picks?
NAT: Well, thinking about the Raspberry Pi was just, mine has been... I’ll recommend Codea for iPad users which is programming environment where you can write animation and games and apps on your iPad, just like a programming model a bit like processing but in runs on your iPad. And it’s got support for multi-touch and physics engine and 3D meshes and 2D meshes and animation and all audiosynthesis. It’s really great fun to play with. And can just do it on your iPad with the on tune keyboard, they have a customized keyboard to make editing easier. And yeah, it’s really good fun. I highly recommend it.
CHUCK: Well if that’s it then we’ll go ahead and wrap up the show. Thanks guys for coming. It was really great and I reall, really enjoyed the book.
STEVE: Thank you.
CHUCK: It’s so funny to me about the book in the sense that normally I get a tech book and I’ll force myself to sit down for an hour so on and read it. And this one, I mean I blew through it like I was reading a novel. (laughs) I think it really says a lot both for the writing style, the clarity and just how compelling the content is.
STEVE: Actually we did, to let a little secret is, in an earlier version, we were going to put sort of Victorian subtitles on the chapter headings
...in which our hero discovers plug-ins or something.
AVDI: I love those. Why don’t books have those anymore?
JAMES: It was a great book. Thanks guys.
STEVE: Thanks a lot.
NAT: Thank you.
CHUCK: Bye. So next week our next Book Club, did we decide that we were going to do SOA book?
JAMES: Yes, do you remember what it’s called? “Service Oriented Design in Ruby”? Is that right? I’m looking it up.
CHUCK: It’s called Amazon says...
JAMES: It’s called Service Oriented Design with Ruby and Rails by Paul Dix I think.
CHUCK: Yes, by Paul Dix exactly.
JAMES: We’ll do that when in about 2 months so starting now about 2 months from now.
CHUCK: Yup. And other than that, I don’t know that there are any announcements. You can go join Ruby Rogues Parlay by going to rubyrogues.com and just folllow the thing on the right with PayPal. And I’m working on getting it so you can sign up without using PayPal but I’m pretty swamped and pretty focused on some other things so give me a few weeks and hopefully we’ll get that up. Yeah, be on that. We’ll just catch you all next week and thanks for listening.