DAVID:
Hi everybody and welcome to the… Sorry, I'm just messing with you.
CHUCK:
[Chuckles] Hey everybody and welcome to the Ruby Rogues podcast. This is Charles Max Wood. And this week on our panel, we have -- in no particular order -- James Edward Gray, he is the author of the FasterCSV library, as well as Textmate book. He tweets @JEG2. And he's not on drugs this week. Yay, James!
JOSH:
Yay for less drugs!
DAVID:
We're so proud of you.
CHUCK:
[Chuckles] We also have David Brady. He is the author of the tourbus library, he hosts ADDCasts, he blogs at heartmindcode.com. And he is starting his own programming company at Shiny Systems and you can find them at ShinySystems.com, is that right?
DAVID:
No, shinybit.com but don’t go there because the website looks awful. Because the first person we're going to hire is a web designer.
CHUCK:
Yay! So, he's hiring. So if you wanna work, talk to him.
DAVID:
Yeah.
CHUCK:
All right, and then we have Josh Susser. Josh blogs at blog.hasmanythrough.com. Last time I looked, he was still 51 on the committers list for Ruby on Rails. And he's an all-around smart guy; he tweets at @joshsusser. Welcome to the podcast, Josh.
JOSH:
Thanks. I can work on my Rails contribution.
CHUCK:
[Chuckles]
JOSH:
Hit the top 50.
CHUCK:
There you go. And finally, we have Avdi Grimm. He is the author of Exceptional Ruby. You can find that at exceptionalruby.com. He also blogs at Avdi.org/devblog, and tweets at @avdi. Welcome, Avdi.
AVDI:
Hello again!
CHUCK:
And I realize I keep saying Avdi. Is it ‘Avdi ‘ or ‘Avdi’?
AVDI:
It is Avdi.
CHUCK:
Okay. And I'm Charles Max Wood, I'm the host of Teach Me To Code podcast and screencast. I'm also the host of the Rails Coach Podcast. I do Ruby on Rails coaching, and I am preparing for a Ruby on Rails course that will be held July 26th, that you can sign up for at teachmetocodeacademy.com. And this week, we are going to be talking about Personal Design, Coding Practices and Patterns. It was a topic that was suggested by our illustrious Josh Susser. And so I'm going to let Josh take it away and explain exactly what he meant, and give us some ideas of what some good practices are.
JOSH:
Okay. So I started compiling a personal list of design rules longer ago than I care to admit; you know, you read things like, “Premature optimization is the root of all evil,” and there's only two hard things in Computer Science: naming things, cache and validation and off by one error. [Chuck chuckles]
JOSH:
So, I thought I should write down the ones that seem to make sense to me and keep them handy when I'm thinking about hard problems or even easy problems, I guess. So I have a few of these rules that I have acquired over the years, and I expect that most programmer do -- whether they write them down or not. So that’s where i just came from with my suggestion.
JAMES:
So Josh, you give this list to potential girlfriends or…
JOSH:
No. [Laughs]
DAVID:
Design rules: Must have own 32-bit stack.
JOSH:
[Chuckles] Yeah. I don’t think there's any design rules that work for relationships.
JAMES:
I see.
JOSH:
But coding, luckily, is much simpler.
DAVID:
What are you talking about? There's has , there's collaborates with, there's… [Silence] Oh boy, crickets are going loud. [Laughter]
JAMES:
All right, so tell us some of your favorite personal design rules, josh.
JOSH:
Mostly, these things are about context. So a framework for thinking about things. So, “Premature optimizations is the root of all evil,” is a great example of that, I think. And just because these are personal design rules doesn’t mean that I was the one who thought of them or I'm the only one who uses them. I think the premature optimization one is great; it’s something that everyone takes to heart because you’ve gotten into a situation where you try to make everything fast first before you made it work right – then you are screwed. So I don’t know if we have to talk about that rule at all, although there's a lot of people who like to counter it with post mature optimization is also pretty evil.
DAVID:
I have a favorite comment that I like to point out to people, is that it is a lot easier to optimize correct code, than it is to correct optimized code.
JOSH:
[Chuckles] Well done.
CHUCK:
So, premature optimization, is that the same or similar to YAGNI “ You Ain't Going to Need It”?
JOSH:
Sometimes.
JAMES:
Yeah, in a way. I think the main thing behind premature optimization is that, computers are really hard to predict, right? And if you try to guess where the time is actually being spent, a lot of the times, you just guess wrong, right? Like you spend a lot of effort optimizing that one function and it turns out that’s not where the majority of the time were being spent. So, good on you. But you didn’t really do much. And optimizing that 1% of the system versus the 90% of the system didn’t do much for you and the effort put in there. So I think it has to do with first of all, you shouldn’t do it until you really need to, right? Because the idea being that until it is slow enough that somebody notices, who cares? If you are using a construct that’s three times as slow as one you could be using, but it’s still much faster than I blink, who cares? I mean, if it’s not causing you problems, then it doesn’t necessarily matter. And then when it does, you can find the right part to actually go in and optimize -- which we all know that adding something like a cache or whatever typically complicated things, you know?
DAVID:
I have two things to add to that, to extend that thought which is the first one is, -- and this is just a quote from I wanna say Steven McConnell in Code Complete -- which is that never ever, ever optimize without taking measurements. Because if you fiddle with it, and it seems faster, the only thing you know for sure is that the code is now harder to read. And the second thing is that, I see programmers -- all the time -- who will just over and over and over “Premature optimization is the root of all evil,” “Premature optimization is the root of all evil,” and then they will sit down and they will say, “We can't do it this way; it’s too slow.” And I push back on them and say, “Premature optimization is premature, until you have a requirement and a standard. If you can't tell me how slow is too slow…” Okay, if you are writing bogos or its obligatorily stupid, I mean there's a difference between simplest thing and the stupidest that it could possibly work. But until you actually have a requirement that, “This needs to return in 800 milliseconds,” don’t optimize it -- just write it. Chances are that it is something… okay, it’s a loop that runs 10,000 times, but it only runs when you start the server and never gets run again. You know what, you don’t need to optimize that.
JAMES:
You know, I think another angle of that that I’ve seen over and over again is like, when a programmer first learns the proper way to cache something, you show them how you would use memcached, it gets something out of memory or you show them how to use Rails caching actions, so you can cache Rails action or something. You show them that and typically they'll have that reaction of, “Oh my god, I´ll just cache this whole thing!” And they go through it and they cache like 500 pages. And then they are surprised when their apps gets slower, right? But I mean, when you think about it, it's almost obvious, right? I mean, caching by definition, slows something down because before, you were doing some work returning a result. Now, you are doing some work, saving the work, returning a result. You are doing more things, right? So it’s got to get slower. But the advantage is that we hope to make it up over time in the future steps, where we can skip the ‘doing some work’ part and get faster. But I think that’s the point is that like if you just throw optimization at a problem, then whatever we say about regular expressions, now you have two problems, right?
AVDI:
I think the only place that I've seen where premature optimization might make a little sense is that a high architectural level. So you know, when you write a CMS and then belatedly realized that what you are actually trying to create was a messaging system -- which is what Twitter realized -that’s a case where maybe a little bit more thought about the architecture upfront might have been a good premature optimization; meaning that you can often say some things with reasonable certainty about certain high level architectural patterns. Now what this doesn’t mean is you can't just say, “Oh, we are going to use MongoDB because its faster,” or whatever. I'm not picking specifically in Mongo or whatever; NoSQL database or whatever. Those decisions, they can be a little overblown. But I think there is a case to be made for saying… it’s been observed that certain types of systems work scale well and are architected in certain ways and don’t scale so well when they are not architected those ways.
JAMES:
I think you’ve got a good point there about kind of picking data structures that model your data better. Like for example, I mean, the… [Silence]
CHUCK:
Well, you just cut out James. I'm going to step in really quickly. I did get a mention on Twitter by Fred Lee. He said that, “If you guys (and myself included) could ever so often just say, ‘this is Chuck,’ or whoever and then make your point…” he said it’s kind of hard to follow who all the voices are, so…
JOSH:
That’s a good point. Do I have to introduce myself as the ‘real’ James Gray, though?
CHUCK:
[Chuckles] If it makes you feel better.
JOSH:
So this is Donald Duck. And what I was saying is, I think that Avdi is talking about choosing right data structures. And that like you sometimes get the SQL structure being default because it’s a general tool that does okay in a lot of areas. But there is some areas where playing file storage on a file system is going to way outperform it, depending on your needs. If you had some hierarchical setup and that’s all you needed, where a folder structure maps beautifully to it or something like that. So you can get yourself pretty far down that data hole if you'd choose the wrong system.
DAVID:
This is David, or the ‘imaginary’ James. The, “Premature optimization is the root of all evil,” if that’s true then premature implementation is the trunk. And another design rule I have is, “Always relentlessly be the top-down whenever possible; don’t be bottom up.” And I recently, like last week come to realize that Rails is one of the most perniciously evil frameworks in that regard, because what do you do? You go to your stakeholders, you draw pictures, you get screenshots, you get these lovely PSDs on how the web pages are going to work, and you have this very high level architecture about whole system is going to work. And then what do you do with Rails? You sit down and you type ‘Rails generate migration’. You have just chosen a SQL implementation. I mean, you have just completely end run… you are up here in the top level and you went immediately to the bottommost level of your data. And now you are going to try and build up from there and boy, I sure hope when come up, when you finally break the surface, I sure hope the tip of your iceberg is inside the circle of the app that you were supposed to build… and yeah, so premature implementation is a bad idea. If you need transactional data, if that really is what you are doing is transactional operations, you need to be doing SQL. But if an object graph is more important, you should be using document database or object database. And if reporting is really what you are doing 90% of the time, you need to put on your big boy pants and look at calendar stores and data warehouses.
JAMES:
So, to go a different way with that, what about rule number 2, “Don’t do big upfront design.”?
DAVID:
The top down answers that, right? If you stay at the top down, if you basically say, “I need a web page, that’s going to show me all of my…” I’ve got a thing that’s shooting latitude and longitude in time out of my phone every 60 seconds, and I need to look at that, if you say relentlessly top down, your first two or three iterations you don’t have a storage model; you don’t have objects being persisted anywhere. You just have a web page that shows things. And this is some of the craziness I'm getting from Smalltalk, which is that until you actually have a requirement to persist stuff when the server goes down, just keep them in memory. Okay, I realize I'm talking really crazy stuff now.
AVDI:
That’s not crazy. I've been advocating that for a while. Start out with pure domain objects… There’s nothing in Rails that says you have to stick active record thingies in that model directory. Start out with objects, classical model you are domain in objects and then once you hit the point where okay, we need to start talking about persisting and stuff, that might be an iteration in, then start adding active records to those model. And the neat side effect to that is that you'll actually wind up for simpler tests because you won't be stubbing a lot of active record stuff like that.
DAVID:
Yeah. there's a specific code smell/pain point and Shiny Systems has a client right now… Oh, I'm already referring myself as a company, I love it… sorry this is new experience for me. But I have a client right now that is experiencing this exact pain point. They designed a database, they designed a very intricate polymorphic system, and then they had to go write their own special active record search methods and search optimized query generation to search this thing. And I sat down and said, “Okay, lets write an acceptance test. Let’s actually make sure that when we pull up the price of this product in the store, that its actually gets realized correctly to show up in the store with the correct price. And we found at the acceptance test level, it was almost impossible to do. It’s extremely painful to map this searching system up into the domain. And so yeah, if you just start at the top and work your way down, work your way down, work your way down… There certainly are some pain points that you run into right quick which is that you're used to… you are coding for ten years and you are used to persisting everything in a relational database and the tools are there and the top down tools aren’t all there… there's just some new ground which we are breaking, which is sad because this idea is really old.
CHUCK:
Yup.
JAMES:
So how do you strike the balance of knowing when we are doing too much upfront -- which is leading more towards upfront design and less towards being agile -- as opposed to when we need to do more upfront. How do you get a feel for when to do those?
DAVID:
For me it’s a matter of just knowing why you are doing something. Who is going to use this and why do they want it? And if you know who is going to use it, but not why they want it, you might not have enough big design upfront. You might be so Agile that you are acting stupid; that you are acting inefficiently. But if you know why they want it, I mean it’s okay in agile to look one or two iterations ahead and kind of know kind of where we are going with this thing. That’s my thought.
Anybody else wanna take it?
CHUCK:
Well, it seems like in a lot cases, people do a lot of big upfront design, meaning that they basically outline how the entire system is going to work. They get up and they say, “Okay, so I need to be able to post a tweet, “which means that, “I need a tweet model and I need a tweets controller. And the tweet controller needs to handle these couple of cases, and then pass it off to the tweets model that’s going to do all these stuff.” And yeah, that's way too much. That's a lot of big upfront design that just really doesn’t have to happen. However, if you are kind of taking it a step at a time, where you’re starting the outside and you are saying, “I need a form that I can put a tweet into and when I click ‘send’, it shows up on my feed.” And then your next feature is, “Okay, yeah when the server goes down, it comes back up, I need that tweets to still be there.” And so you really are not doing a lot of upfront design even though you starting from the top and working your way in. What you are really doing is you are saying, “Okay one step at a time.” “I need to be able to post a tweet and I need it to show up.” And so, relatively simple, you are starting from the top or from the outside and working your way in, but you are not necessarily doing a bunch of upfront design.
DAVID:
Yeah, you said there in your first example, you didn’t get in trouble until you said how. “I wanna send a tweet and here’s how we are going to do it.” That’s where you run into trouble and you start moving away from top down to what I call ‘bottom up on stilts’, which is that you are still pretending to top down, but you’ve already thought very quickly in your head that you are going to use SQL; you are going to use a polymorphic join. And so the very next top down thing you do is you start saying, “We are going to handle these objects by ID. “And wait, what do you mean by ID?” Oh… because you’ve already designed this as a SQL relational database solution in your head? You’re not doing top down anymore; you’ve silently done bottom up.
JOSH:
I don’t think that’s always a bad thing because if you have done that sort of thing before, it’s a natural reflex to just say, “Okay, I know how to do this in SQL. This is what I'm going to do.” but you know how to do it. So that problems that you run into doing that, you are going to already know how to deal with them. So, it’s not -- I think -- always a bad thing to do that kind of design.
DAVID:
Actually, I think you are dead on the money. You know that the key differentiator between when waterfall works and when agile doesn’t is, “Have you built this exact same product before?” If you have, then you can do waterfall, because you actually know how to estimate everything. And I'm taking it to an extreme. I think you are right; if you’ve built this system or this style of a system, you can still that you built for sure. There's pre-refactoring that can go on realistically. This one is taking it to the extreme, I think.
CHUCK:
I was going to go ahead and make the point that I've built a house before, let’s say and I know how that works, so I get in and I start pouring the foundation with cement and I do all the other stuff that I'm supposed to do. But if I'm building a house in the Philippines and it has to deal with the monsoon, I don’t want it to get flooded every time. So as long as I'm somewhere where I know that that's the kind of house that I need to build, or in the case, I know how to build the house for this area, then it’s okay for me to go ahead and start with the bottom, pour the foundation and just work my way up because I know how it goes together. I know where all the parts are, I know what's in the blue print and you know, it’s nothing foreign to me. But you know, as soon as you get into anything that’s different, anything that you haven’t done before that you don’t really necessarily have the experience to draw upon to say, “That’s how it needs to go,” then you are better off meeting the requirement and figuring out how to implement it.
JOSH:
We've been talking a long time kind of about premature optimization and maybe we wanna talking about other design rules?
JAMES:
I was thinking that we had kind of shifted rules. Like for example, it seems like now we are talking a lot about top to bottom, top down or bottom up design and whether or not that’s a good thing. But one interesting thing I kind of thought Chuck shifted it in his discussion when he had that example where you got stuck thinking through the abstract implementation, and it shifted back to the user interface, to refocus he went back to any disform here where user can put a tweet in, which is an interesting thing because I've noticed more and more lately that when I'm designing web applications, I begin with the URLs. That I like start mapping each individual URL to where it goes. And like I'm sure other Rails programmers would hate to work with me right now because I don’t think I use any Rails routing features the way they are meant to be used anymore, because I always try to fit the URLs to exactly where I think they should be -- which means I typically get away from the boring resource routing and stuff. But it was an interesting on I think we kind of got into what is the focus of design? what is the focal point? And it seems to be sometimes it can be this, sometimes it can be that and how do we know what that is?
DAVID:
That’s actually a really good point that… I'm sort of making a list of what my design rules were in preparation with the call and I actually came up with some meta rules, the last one I wrote on there was, “Try to always be open to your design rule not applying in this situation or just flat being wrong.” I have been a very bottom-up structured type programmer for 20 years, and I've always thought that that’s the way to do it and it’s very easy for me to go to a white board and begin talking about an application by drawing it and the relationship diagram and mapping the database and building up -- and it’s been painful for twenty years. And it wasn’t until I got started getting into object thinking and Smalltalk and I started realizing, “This is why this hurts.” And it was a really difficult ego for me to realize that, “Everything you know is wrong.” [Chuckles] “You know, everything you based your 20-year career on has a fundamental assumption that is wrong and you have to change that and that you have to be open to this particular design rule might actually be wrong.” So, how do you implement that? I have a really simple thing, and that is “Go for a walk.” Be willing to just back away. James, you like to map everything out in URLs, but you are going to end up in a pain point someday where your URL is local host 3000/kernel/lambda, and then you’ve got an expression that your website can parse. That’s time to step away from the keyboard and just kind of clear your head a little bit. I was recently doing to-do an application for a Pomodoro timing. And so, Pomodoro is absolutely centered around the concept of this 25 minute Pomodoro five minute break. And so, of course the most important object in this system is the timer. So we sat down and we started writing the timer. And just the app, we just could not get this thing to make heads or tails, or heads or tails and we finally went for a walk and we came back and we realized the timer is like the least important thing in this. You can build this entire system with no timer and just make the user carry a watch. The most important thing is what do I need to be working on right now and is it done? And we chased this for like 6 hours, trying to build this stupid timer and then we realized, “No, it’s actually figure out the workflow.” And then the timer got really stupid easy because at the end of 25 minutes, you mark off Pomodoro and you are done and you already build the ability to mark off a thing. Anyway, so yeah, be willing to walk away, clear your head, get an idea and come back fresh.
JAMES:
So what about another rule? Getting back to Josh’s idea; who’s got a design rule that they live or die by?
JOSH:
I have another one I can throw out there, just to maybe direct things.
JAMES:
Go for it.
JOSH:
This is something I cribbed from Allan K. And Allan said, “Make simple things simple and complex things possible.”
JAMES:
That a good Ruby rule.
JOSH:
Yes. And I noticed a while ago that Apple computer used to be really good at this, back when they were ‘Apple Computer’ -- now they just ‘Apple’. And they are really good at making things simple, but they’ve kind of given up on the ‘complex things possible”. It’s no longer the day where you can hold down the option key and get the extra features in the menu…
JAMES:
[Chuckles] That’s interesting.
AVDI:
Good example.
JAMES:
Although as a counter example, I have a piece of hardware I'm using right now that requires a 32bit driver. And on this brand speaking new Mac Book Pro, I was impressed that I could reboot it and hold down the 3 and 2 keys while I reboot it, to get in to 32 bit mode. So yeah, some of it is still there, I guess.
AVDI:
I don’t know. I think that might just be making complex things obscure. [Laughter]
DAVID:
Yeah. What they don’t tell you is if you do it backwards, you will boot into 23-bit mode. [Laughter]
CHUCK:
All right, so I have a question about that, as far as ‘make simple things simple and complex thing possible,’ there are couple of things that are kind of wrapped up in that, that aren’t necessarily simple. And one of them is first, how do you recognize when things are simple, when they are not simple, and how complex do they have to be, to be complex?
JAMES:
Very subjective things. I think the takeaway I always use for that one is if I'm a user and I'm going to want to go in to your site and do x, and you make me click five times just to do that or answer a few arbitrary questions along the way, then you are missing simple path. That, “You know why I came, you know what I'm after, and you are harassing me to get better, right?” It’s kind of how I view that one. And libraries, I want my libraries to function the same way, like you know, most of the time, I just wanna use the library like this. There may be some rare circumstances where I need to crack the whole thing open and be weird with it. And let you do that, and it’s fine to make me suffer for that, but you know, most of the time, I just want the simple, smooth interface that does solves my most common need.
JOSH:
I think that Rails routing is actually a pretty good example of this, I think done pretty well; that the things that are straightforward that you do run over and over again like restful routes are really simple to setup; you just say, resources users and you are done. And then there are a whole bunch of other options you can throw in your routes to generate really complicated things that aren’t going to be as common.
DAVID:
I have a couple of ideas for how to translate that down to actual code -- if you guys are interested…
CHUCK:
That was my next question. Go ahead.
DAVID:
Okay, perfect. So, and I´ll just start and throw that to the group. One real obvious thing is that, if you are going to write the ‘each’ method in Ruby, you should also probably write the ‘map’ method because there's going to be one person who wants to hand you a block and iterate over the thing. And then there's somebody who just wants to get the freaking collection. And if you write ‘each’ and you don’t write ‘map’, you've now forced them to create an array, each yields into an array and it just depend, depend, depend…
AVDI:
That’s what enumerable gives you.
DAVID:
So yeah, enumerable gets that for you now, but I'm working with some code right now where they are not using enumerable; they’ve got literally this long function that begins with each thing is this and this and this. And it’s this really weird complicated object that’s like five levels deep. I tweeted a screenshot of actual code in which I basically had @plan.first.second.first.second.cost and…
CHUCK:
[Laughs] Oh, man.
DAVID:
Yeah, it was basically this huge anonymous data structure that was all positional. And I'm like, “We need to start doing some name calling in here.” And so basically yeah, if you write methods to be accessed in kind of a left handed fashion, write the right handed method as well, so you are not forcing people into… sometimes map is simpler than each. Avdi’s right; enumerable gives that to you, and I can't think of a good non-enumerable sample.
AVDI:
You should be able to inject enumerable to that object and then have a map for free.
JAMES:
In a way, I think that’s kind of an excellent example of the rule we are currently discussing; I mean that’s kind of a points of enumerable, that if you do the each method and then include extend enumerable whatever, then you get all for the normal iteration things. The normal things that we always do in iteration, those simple things, you get those for free, you know?
DAVID:
Yeah. The other thing that I found to make code simple or to keep simple code simple… and this is actually a revelation to me; again, I came from a structured proceduralist, formalist background and so I'm not afraid of long methods; I'm not afraid of large classes that do too much. And I had just an argument with Uncle Bob a while back where he was basically saying, “Short method, small classes that only do one thing.” And I said, “Yeah, all you really doing is you are taking the complexity of the system out of this particular object, and you are pushing it up into the space into the… between… you've now got 15 classes that do what this one class did, and the interaction between these is now hiding some complexity.” And then he kind of squinted and said, “Uh… kind of… but not really.” And what I'm finding is I'm getting into small talk and into this object thinking is he's right, I'm wrong. That was fud. If you are afraid of pushing complexity up into the … between objects by making small objects, you need to go read object thinking and you need to just sit down, shut up and do it right -- because it just doesn’t happen.
AVDI:
So I agree with Bob on that, but at the same time, I wrote a post a while back called Simplicity is Complicated, and I think a lot of the discussion in software, of the concept of simplicity suffers from a lot of hand waving. And it isn’t always as specific as it could be. In my experience, the vast majority of times when somebody says, “Well, this method A is simpler than method B,” what they are really saying is, “I would prefer to push this complexity into area 1, rather than into area 2,” whereas you seem to prefer to have that complexity being in area 2. Or “I would prefer to spread this complexity around, whereas you would prefer to keep it in a single place.” Most of the discussion that we do about making things simpler, I think from another point of view is a discussion about pushing the simplicities somewhere else. Like a bubble under a piece plastic; it’s still there; you are just pushing it around. And that’s okay, it’s just that I think a lot of the disagreements that come up about what is simple just stem from the fact that simplicity is complicated. And in a lot of times, one person’s simplicity is another person’s complicated. And it’s interesting if you try to frame your argument explicitly in terms of when you start to say, “It would be simpler if we do, blah, blah, blah…” rather try to frame your argument in terms of, “I would like to push this complexity into a different area.”
DAVID:
I will extend that by saying where you really get into the good flame … is saying, “It could be in A or it could be in B, but I know B inside out, backwards and forwards, and I don’t have a good grasp on A.” And so, “No, I know this is a document that we're dealing with all these crazy attributes, but I don’t know NoSQL, so we're going to stay in a relational database because NoSQL is evil.” You know what I mean? It’s like they really are touring equivalent; you could move it from A to B. But we as human being, it’s like we fear moving it out of the area of our expertise, even though it would make it much, much simpler.
AVDI:
We'll, if it’s an established code base, in an established team, that has an established expertise in SQL and complete non-expertise in NoSQL, that might be right for that project.
DAVID:
It might be the best possible solution. It might not be a good solution, but it might be the best possible solution.
JOSH:
Well, there's also room to innovate and improve. I was struggling with a lot of really crazy rewrite rules in engine x a while ago, and I got really tired of that. I got tired of not being able to pass them and having to deal restarting the server all the time. And so I just wrote some rack middleware to do the rewrites instead, and it ended up being a much simpler solution, but I had to deal with some complexity of creating the tool to be able to move the complexity out of the way. So I'm now I'm building an application. It’s simpler building the application; I just took the complexity out of the application and put it in a middleware.
JAMES:
Okay, so since we've been naming the rules we live by, I actually thought about when we decided we were going to do this topic, I sat down and thought, “What are my rules?” And I can only come up with two that I have. So I´ll give mine now and we can discuss them. My first rule is, “There is no rules.” And my reason for that is that like everything we've discussed today, being agile versus your big upfront design, or top down versus bottom up, etcetera, etcetera, I feel like there's always a tradeoff. And that there's always a time where you can give me this rule and you should say, “We should always do it like this, and I can come up with the pathological example where that doesn’t work -- or somebody can come up with it, if it’s not me.” So one of the things I do is I'm trying to treat everything as a guidelines. More like the Pirates of the Caribbean. That everything is just the things that are usually good ideas, but you sometimes have to accept that you are going to run into scenarios where the usually good ideas are bad ideas. And in those cases, it’s okay to flip the rule say, “You know what, it’s a good idea -- except this time,” and do it the other way. And I try to use that because I find that in boxes me in a lot less. I'm more open to try new things. And probably I make more mistakes that way, because sometimes I think the rule doesn’t apply this time and I'm wrong or whatever, but I'm more often to the ideas into trying other things that helps me see my way through the complexity -- which is basically in my opinion what these rules are all about; it’s managing complexity. So that’s my first one. My second one is that I believe we have to use the correct amount of paranoia -- the appropriate amount of paranoia -- for the problem. So I always try to tackle the hardest part first, and apply all of my good thinking there and leave the simple stuff as cleaning up. For example, if I'm doing something where I'm posting some blog post on a site, then I'm not very paranoid about that. I've written a lot of blogs, I can handle that part. It’s going to be okay. If it goes horribly wrong, then that person is going to have to go back and resubmit their post -- it’s not going to be a super big deal. Whereas if I'm working with credit cards and some kind of recurring billing system, or something like that where when it goes horribly wrong and I billed the guy’s credit card 500 times in the next hour, there's going to be a lot of angry phone calls. Well then, I up the paranoia level for that. I try to take more extra steps; put layers in there that would protect me from my own stupidity or things like that. That I try to apply the right amount of paranoia. It’s like I feel like I often see code where it’s like, you have this ridiculously complicated setup of this test harness, which does all these amazing things to make sure that that access you are relying with is working correctly. It’s like, “I think we'll just go ahead and count on that part being okay, and apply our paranoia where it serves us better.” So, those are my two design rules.
DAVID:
I’d like to extend that second when you reminded me of one that I absolutely do live or die by, and it causes fights quite frequently with teams. That second rule about the appropriate amount of paranoia. Woody Allen said that when people are really are out trying to kill you, paranoia is just playing smart thinking. But the rule that I it push on and live by is that, in almost every case, it is more important to know how to get the cows into the barn, than it is to guarantee that the cows cannot get out of the barn. And the reason why is because in securities, yeah you do have to invest a lot of time making sure that the cows can't get out of the barn, but like Sony demonstrated, they had really high wall and somebody figured out how to get through it and they had no strategy for getting the cows back into the barn, once they were out. So if you’ve got a credit card processing system, you wanna do your best to secure, but you have to be able to authorize an adjustment or a charge back or whatever to do it. And what I find is that if you can get the cows back in the barn, your paranoia level about keeping them in the barn goes down significantly. And this isn’t just about credit card transaction; this goes all the way down to how you design your objects. If you have passive data at rest in a register on a machine, and you are just trying to wrap an object around it to keep that register safe, you’re practicing the game of trying to keep the cow in the barn, but if you are on a threaded operating system, somebody can come along and just trash that memory. So it’s much better to be able to figure out, “How do I get the cow back into the barn if this happens.” And again, unit testing is like getting the quality back into the barn; where a static analysis compiler is keeping the cows in the barn. There's a point where I just can't do it. Am I making any sense here? If you can fix it, you don’t have to protect it as heavily.
JOSH:
So that’s kind of where Erlang came from. There's all of the stuff in Erlang for fault tolerance, because they were dealing with a lot of inherently unreliable stuff. So that's why Erlang is the way it is, and they don’t have the same level of… I guess of preventing things from breaking because it is really easy to fix things; pick it up and try again. Related to that, I wanna say John has a great tweet a while ago. He said that, “If you don’t have a remediation plan for something, don’t bother monitoring it.”
JAMES:
That’s awesome. I like that.
DAVID:
If you can't fix it, don’t bother checking.
JOSH:
Yeah. [Chuckles]
JAMES:
I often design things in my system like, I´ll try to think of edge cases where they might could go wrong and I'll put in guards to prevent it so that it will just stop; if it even starts going down that path, that would just immediately stop and start yelling for help, sending me emails or whatever. The places that I hope it never gets into but if it does, I wanted to just lock itself out and let me know right away.
CHUCK:
All right, well it seems like this is a good stopping point. We're going to wrap this up and go ahead and get into our picks. Everybody here has been on the podcast before but for our listener, I just wanna explain really quickly: every week, each of us will go through and list one or a few things that we think are useful or nice or something that we found that we liked. And we just share it with the group and then we post a whole bunch of links up on rubyrogues.com, where you can go and find that stuff. And we’ve had everything from board games, to books, to Legos to whatever. So just whatever it is. We'll go into that. It seems like Avdi has something to share real quick.
AVDI:
As I was listening to everyone else, I finally came up with like with my rule if I had to pick one, and it’s, “Listen to your tests.” My personal design rule is, “Listen to your tests.” If your tests are ugly, if your tests are tedious, if your tests have way too many mocks and stubs in them, if your test are slow, if they are too large or too small… there are a different things that you can smell in your tests that you might smell for a while in the application code because your tests are all dependencies, they depend on your application code, and they in some ways map to and model your application code, and your tests can tell you so much about the direction that your design is going in. And I see a lot of instances where developers will find pain in their tests and escape goat the test and say, “Well, this is a bad way of testing. We shouldn’t test this,” or “we shouldn’t test it with these tools or maybe mocks aren’t such a good idea after all,” or “maybe unit tests aren’t such a good idea after all.” A lot of different ideas like that. And in my experience, you get a lot of mileage of listening to the pain in your tests, and saying, “What is this saying about the way my domain objects are factored.” That’s all.
CHUCK:
Yeah, that's interesting and I think a lot of us in general follow that rule. And it’s interesting because most of the rules that we talked about are things that I think a lot of us do to one extent or another, but I was trying to think of what my personal design rules were, and I couldn’t come up with anything but then you guys are talking about how everything is like, “Oh yeah, I do that!” and, “I do that too.” And it’s one thing to know what they are and another thing to kind of practice them because you have this intuition that it’s a good way to go.
AVDI:
Yeah.
JAMES:
And if you can't listen to your tests, just listen to Avdi -- it is almost as good.
CHUCK:
[Chuckles] Pretty close. Pretty darn close. Those test comes to pretty close to being as smart as Avdi. Anyway, so let’s jump in to the picks here.
DAVID:
My tests are no that smart.
CHUCK:
[Chuckles] David, why don’t you go ahead and start us out with the picks today.
DAVID:
Okay, I'm back to weird stuff again in this week. My pick this week Smalltalk Best Practice pattern by Kent Beck. This is an old book; it was written… I wanna say 1996. And it’s best practice patterns for a language most of us have never touched, but it’s a book on how to program a computer. It’s like, how to name a variable. He's got literally, how do you name a temporary variable versus how do you name the variable in an argument to a parameter. Now in Ruby, I would actually use the temporary rule in both cases, which is you should use the role; you don’t wanna use the data type, you don’t wanna use the class of the object; you actually want to say ‘ current user’ or what role are you playing. You don’t wanna pass in ‘user’ to blog post; you wanna pass in ‘author’ to the blog post, so that you can differentiate the author to the listener or to the reader, etcetera.
CHUCK:
You should just name them all ‘i’.
DAVID:
‘i’, yeah or ‘idx’. Yeah, because searching for ‘I’ is hard, so you should use ‘idx’ everywhere. And once you use ‘idx’ everywhere, that you would have use ‘i’ anyway, then you are right back to being comfortably unable to change that as well. But the whole book is filled with… some of the rules are specific to Smalltalk like method parameters, he said “Use the data type.” Because in Smalltalk, you actually have the role as part of the method signature; you cannot not write the method role. But the whole book is filled with, “When do you do this?” And he writes it in terms of code smells. Like temporary variables suggests… a role suggest the temporary variable name or data type suggest the parameter name. And it's just kind of like if you listening to your code and if the code could make suggestions on how to write me… it’s a very thin book; it’s like half an inch think and you don’t need to be a Smalltalk programmer to really, really appreciate it. It’s this is just a fantastic book about when to test, when to comment, how to name things, it’s just really, really good. When to monkey patch – there’s a rule in there on when to monkey patch. Yeah, good stuff.
CHUCK:
Great. Sounds good. All right, was there anything else before we move on?
DAVID:
No, that’s my big one.
CHUCK:
All right, sound like a good one. Avdi, go ahead.
AVDI:
The discussion kind of brought to mind a book I read a couple of years ago, Practices of an Agile Developer. I believe that’s the title. So one of the Pragmatic Programmer books. And I think it’s kind of about things like these personal design rules. It’s those little… it’s disciplines that you yourself practice rather than disciplines of teams; disciplines that you as an individual developer practice to improve your design, improve your Ruby communications with others, and stuff like that. It’s good stuff.
CHUCK:
Awesome. Yeah, I love the agile stuff and it’s interesting that it applies all the way down to one developer, so it sounds like an interesting pick as well. Was there anything else or should we move on?
AVDI:
I think that’s it.
CHUCK:
Okay. Josh, go head.
JOSH:
Okay. Let’s see. I have a book too. Its RESTful Web Services by Leonard Richardson and Sam Ruby. Have you guys picked that before?
CHUCK:
No.
JAMES:
No, but I love that book.
JOSH:
It’s a pretty awesome book. It is an O'Reilly book. It has a cute little picture of a Vulpine Phalanger on the cover. (I had to look that up. [chuckles]) It’s a really nice, thick book about writing HTTP applications from the restful perspective, and all the way down to the nitty gritty details of where are the appropriate response codes and when should you return a 422, that kind of thing; to how do you wanna architect things, what are the interaction patterns that you should be using, how to do negotiations for data types. So there's a lot in it. So I've been making my way through it and having a really good time with it. So I recommend it. The thing that I came to this book for that it doesn’t have -- but I don’t know if anybody has -- is the how do to do REST the way that it is meant to be done. [Chuckles] I feel a little embarrassed that I'm blanking on his name. The guy who did the dissertation on rest… I'm too old, I'm now forgetting names. [Chuckles] But his dissertation, talked about… He actually cut it short; he said it in his recent blog. There's a blog post going on about this. It’s not like building sop and you shouldn’t have to publish an API of, “Here’s the 30 or the 50 URLs that used to talk to my application,” your API should be one URL and then you find everything else by looking at what is handed back in the representation; so you can do a new in Rails app, you get back a form that includes a URL, which is where you post the request to create the thing. And there's apparently like a whole way that he have of thinking about applications, but I've never found anything written about how to do it that way, so.
DAVID:
It’s Roy Fielding.
JOSH:
Yeah, that's right.
DAVID:
And I'm not smart. I just Wiki’d it while you were talking.
JOSH:
[Chuckles] I was busy talking; so you could type. So that omission aside, I found that the Restful Web Services book was still pretty awesome and very useful.
JAMES:
That book does through like in a way though, it does answer the side of that of some times the applications we think of as restful -- like S3 as one of the examples people often hold up -- is not very restful in some ways. And that book does break down why.
JOSH:
Yes.
CHUCK:
Interesting.
JOSH:
Okay, so that’s it for me.
CHUCK:
All right, James go ahead.
JAMES:
So now everybody is recommending books, and we've already decided I'm always the one recommending the expensive stuff, I´ll make sure I go for something that costs way more than a book. But seriously, I got a new router this week, and my wireless network had kind of of devolved to the point where the whole thing was collapsing under its own weight. And it was one of those things where I started out with a certain router and then I added something on, added something on, and it got to the point where I had four different kinds of routing devices in three different rooms of my house, doing various functions for all kinds of odd reasons that I was just sure I had to have. And the whole system basically just began to implode under its own weight. And it was like, if you were siting in parts of the house, you would lose your web connection every 2 or 3 minutes or things like that. It really degraded to a horrible level. And my wife just pretty much threatened me, “Fix it or move out,” kind of thing.
CHUCK:
[Chuckles] Sound like AT&T.
DAVID:
Honey, his is what legacy code looks like.
JAMES:
[Chuckles] That’s right. So I finally needed to redo my wireless router and I've been dreading it because I hate networking; I suck at it. And it usually is just days of me getting mad and then reading thousands of web pages. But after some advice on twitter, I tried this Cisco Linksys E4200 router, the dual band wireless end. And that thing is a monster. I have to say, it was the perfect pick. And it did take me about a day, but I managed to redo my entire wireless network and I solved 100% of my problems -- which I think that maybe the first time ever. And it’s largely due to how easy or awesome this router is. So you have one of those so-so wireless networks in your house and you wanna make it really good, I would fully recommend this router. It has five 5Ghz band and it has the 2.4GHz band so you can basically have two different bands for your end devices and your BG devices. It does like a guess network that it lets you put restrictions and all kinds of cool setup features. Fairly easy to set up as far as routers go. I figured it out. I'm like a networking idiot, so that’s probably a really good recommendation. I did have to fiddle with the settings to get the speed to be good, I think due to some interference in my area. But once I got the right settings it was great and it’s definitely solved a lot of my problem. And it means I get to stay married, so I recommend the router, definitely.
CHUCK:
[Chuckles] Awesome. Yeah, got to love those toys. Was there anything else, James or should I go ahead?
JAMES:
That’s it.
CHUCK:
All right, so I'm going to have a little bit of a Pivotal Labs love fest here, because there are couple of things that have been awesome that I've been using or have discovered from pivotal. One of the first thing is pivotal tracker. I don’t know if it’s been brought up before, but it is an amazing piece of software for keeping track of projects. And I use it for my client’s projects and when I actually have to start paying for it, I will, but because it’s just totally worth it and it saves me a lot of time and trouble. And I have a couple of sub-contractors that work on different things and I could just add them in and make things work and then they can ask questions or I can answer their questions, or the client even sometimes gets in and answers questions and gets involved. It’s just a really great collaboration tool. The other one is -- and this is something that I found yesterday -- and I saw that it was included in my client’s project, the one that it inherited from a guy, who inherited it from Pivotal Labs and it’s a JavaScript… it’s kind of an extension for jQuery, called Jelly. And Jelly is just awesome as far as being able to not only dispatch you AJAX request, but send callbacks from your rails app and stuff. It does all kinds of really awesome stuff that it’s kind of hard to do. I mean, you could do it and I can see how you could possibly do it on your own, but they just give you a really easy framework for managing all that stuff. And I was really impressed to find that in there. The last one that I wanna recommend is also book. And it’s an oldie but a goodie, but it’s the pragmatic programmer book by Andy Hunt and Dave Thomas. And it’s an awesome book; it goes over a lot of things that I think we take for granted now, like having a source code repository or having the dry principle and things like that. It goes over some of the things that fall under maybe some of the personal design rules, but some of the stuff that they talk about, even though this book was written like 15-20 years ago, it still has some stuff in there that a lot of people miss and miss out on, and really ought to be doing their projects that could just make some powerful changes in the way that they build their apps. Anyway, that's everything I have. I'm going to go ahead and cue the music. I wanna thank the panelists for coming and having this discussion again. Last week was awesome. This week has been pretty good too. And I've really been just impressed with the breadth of knowledge that has been expressed through the whole discussion. Once again, we have James Edward Gray…
JAMES:
Bye, everybody!
CHUCK:
We have Avdi Grimm.
AVDI:
Good to be here again.
CHUCK:
David Brady.
DAVID:
I won't go! I won't go! I won't!
CHUCK:
Josh Susser.
JOSH:
Thanks for having me.
CHUCK:
And I'm Charles Max Wood. You can get the show notes at RubyRogues.com. There's also a link there to subscribe. If you wanna subscribe through RSS or through iTunes. We are in iTunes if you wanna leave us a review, that would also be terrific. If you have suggestions for topics for the show, then you can go to rubyrogues.com and click on ‘request a topic,” and we've been looking at those and we'll probably pick something off the list next week. Finally, we did a little bit of a recording after the show last week, and I never did get it out, but I'm going to start putting up the extras when we have them, so keep an eye out for that. I´ll probably get that up this week, and then if we have another little discussion afterward, then we'll also get that up this week and that way you can kind of hear what we didn’t have time to talk about and wish we had. So anyway, we'll wrap this up.
Thank you again for listening and we'll catch you next week!