CORALINE:
There’s nothing like rum drinks in a rainbow painted playhouse.
NOAH:
Absolutely true. It has the advantage that I can head up there and scandalize the neighbors by drinking 10 feet in the air.
[This episode is sponsored by Hired.com. Every week on Hired, they run an auction where over a thousand tech companies in San Francisco, New York, and L.A. bid on Ruby developers, providing them with salary and equity upfront. The average Ruby developer gets an average of 5 to 15 introductory offers and an average salary offer of $130,000 a year. Users can either accept an offer and go right into interviewing with the company or deny them without any continuing obligations. It’s totally free for users. And when you’re hired, they also give you a $2,000 signing bonus as a thank you for using them. But if you use the Ruby Rogues link, you’ll get a $4,000 bonus instead. Finally, if you’re not looking for a job and know someone who is, you can refer them to Hired and get a $1,337 bonus if they accept a job. Go sign up at Hired.com/RubyRogues.]
[This episode is sponsored by Codeship.com. Don’t you wish you could simply deploy your code every time your tests pass? Wouldn’t it be nice if it were tied into a nice continuous integration system? That’s Codeship. They run your code. If all your tests pass, they deploy your code automatically. For fuss-free continuous delivery, check them out at Codeship.com, continuous delivery made simple.]
[Snap is a hosted CI and continuous delivery that is simple and intuitive. Snap’s deployment pipelines deliver fast feedback and can push healthy builds to multiple environments automatically or on demand. Snap integrates deeply with GitHub and has great support for different languages, data stores, and testing frameworks. Snap deploys your application to cloud services like Heroku, Digital Ocean, AWS, and many more. Try Snap for free. Sign up at SnapCI.com/RubyRogues.]
[This episode is sponsored by DigitalOcean. DigitalOcean is the provider I use to host all of my creations. All the shows are hosted there along with any other projects I come up with. Their user interface is simple and easy to use. Their support is excellent, and their VPS’s are backed on Solid State Drives and are fast and responsive. Check them out at DigitalOcean.com. If you use the code RubyRogues you’ll get a $10 credit.]
CHUCK:
Hey everybody and welcome to episode 207 of the Ruby Rogues Podcast. This week on our panel, we have Jessica Kerr.
JESSICA:
Good morning.
CHUCK:
Coraline Ada Ehmke.
CORALINE:
Hello.
CHUCK:
Avdi Grimm.
AVDI:
Hello from Tennessee.
CHUCK:
I’m Charles Max Wood from DevChat.tv. And this week we have a special guest, Noah Gibbs.
NOAH:
Hey. Good to be here.
CHUCK:
Yeah, we had you on a few weeks ago. But do you want to introduce yourself anyway?
NOAH:
Sure. So, I wrote a book called ‘Rebuilding Rails’ about understanding some of the tradeoffs in Ruby on Rails by building your own framework structured the same way. So, it’s sort of the ‘understand the internals but necessarily all the APIs’. And you had me on a few weeks ago to talk about deployment because I’m also teaching a class called ‘Rails Deploy in an Hour’, which is basically a quick setup with all the tools you normally want to use for deployment. Chef, Capistrano, stuff like that. But I just give you all the code and initial setup instead of making you work through all the systems.
CHUCK:
Got it. I’m kind of curious to get this started. Did you build things the same way that they’re built in Rails or did you explore different ways of doing the same things that we have in Rails?
NOAH:
Mostly I tried to keep the structure the same because a lot of what I’m doing is trying to show why Rails does it the way that it does.
CHUCK:
Okay. And so, it comes out as a guided tour through Ruby metaprogramming. Because a lot of Rails is structured around the way Ruby lets you do it. I talk a little about other ways to do things. But primarily, it’s once you understand how the metaprogramming that’s available works, it’s obvious what the tradeoffs are with Rails. Not everything’s like that. There are a few things that I structure a bit like Sinatra, especially say, my early routing.
CORALINE:
So, is part of your goal to dispel the idea that Rails is too magical?
NOAH:
Part of it is to guide people through the magic. I think dispel the idea is a little bit strong. My experience is that if you teach people deeply about metaprogramming they either decide, “Oh, this isn’t magical at all,” and they love it and they dive in, or they look at this and they go, “Wow, this is horrible now that I understand how it actually works.”
CHUCK:
[Chuckles]
NOAH:
And they pull farther back out. I’m a big fan of special purpose tools. A given tool is usually really useful in some cases and not others. And I find that just by showing people all the details of how this metaprogramming stuff works, yeah most people tend to either really dive into the tool or really pull back from it. So, dispel the idea is a bit strong. It’s totally possible to come through my book hating all the stuff Rails does instead of loving it. But at least you’ll hate it in an educated way. [Chuckles]
CHUCK:
I like that.
NOAH:
I love it, of course. I wrote a book on it. But yeah, it’s not for everybody. One of the joys of this explosion of server tools we’ve got and all the users don’t have to have all your stuff installed is we can just use tools that are not appropriate for every situation as long as we pick the right ones. So, that’s always been my focus, is I’m going to show you this special purpose tool that is really good in these cases and then tell you what cases I think it’s good for.
JESSICA:
And which cases you think it’s bad for?
NOAH:
Yeah. Sometimes explicitly, sometimes by implication. But if you mean what tools do I think Rails is bad for? Just off the top of my head, it’s not the best thing in the world for building an API, and I’m still looking at the Rails 5 modifications. But the fact that they’re adding a whole bunch of stuff to make it good for APIs means they’ve noticed that it’s not perfect for that. The magic and the amount of structure that it’s got means that it’s not amazing for high performance. It also means that if you’re doing something simple enough that Rails doesn’t help you much it complicates debugging, having those extra layers. So, mostly Rails is not as good for really simple cases, API sort of cases, high-performance cases.
CORALINE:
That doesn’t leave very much.
CHUCK:
[Laughs]
NOAH:
It leaves a lot. It leaves a lot. So, one thing that it’s really good for is a small team throwing up a website that will be used by human beings using HTML in a hurry. And it turns out, that’s nearly every startup. And the reason it’s good for that is because your framework can do a certain amount for you security-wise. And Rails does about as much as any framework can do. Even in say Rails 4 they were still adding new things that gave you much better security by default. And then they’ve got the Rails Security Guide which does a really good job of explaining what they can’t do for you.
One thing that I think is underrated is that if you’ve got a small team that is putting stuff together in a hurry and they’re going to be kind of sloppy, a somewhat sloppy, built in a hurry Rails site is going to be more secure than almost any other sloppy, built in a hurry site you can do. And then you can further secure it when you’ve got the time. But it’s going to come out less horrible security-wise when they’ve done that.
And nothing stops you from putting an API server beside it. Nothing stops you from building you API in Sinatra quickly, building your app in Rails quickly, and given the Rails routing system you can do that in a massive hurry. One of the things I explore in the book and talk about is how Rack is used all the way up and down the Rails stack. And so, if you’ve got a Rack app, like say a Sinatra app, it’s really easy to shove that directly in your routing table. It’s really easy to just route certain requests to it. And so…
AVDI:
I’m curious about the origins of this book of yours. I hear from a lot of people a lot of, particularly first time authors, that they wrote something because they wanted to understand it better. Is that part of your motivation here?
NOAH:
That’s a little of my motivation. What I really did here was I wrote the book I wish I had had. So, I’ve had a 10 to 15-year career in C and C++ and systems programming, deep down in the bit stuff, and hadn’t done a lot of web programming when I came to Ruby on Rails. And so, what I thought was missing when I got there was a book that assumed somebody understood programming pretty well but didn’t necessarily know the stuff that was specific to Ruby and really didn’t know the stuff that was specific to Rails. And so, taking that apart layer by layer was exactly what I wish I could have done right when I started. I did all that on my own before I wrote the book. But the book was my way of handing that knowledge to somebody else the same way I had to do it for myself.
AVDI:
Something we’ve talked about on this show before is the practice of code reading. I’m curious. How did you go about learning everything you needed to know to understand how Rails works?
NOAH:
Sure. So, I was as I said a C and C++ guy for a long time. I’ve always been a pretty fast code reader. And when it takes hundreds or thousands of lines to do anything interesting, you get pretty good at seeing the overall structures but stopping when something’s complicated or interesting or looks bad to really drill into it. So, this will sound worse than I mean it, but in some ways reading Ruby code feels like preschool posters to me. There’s just so little there. And it’s so easy to read it all that I can analyze it pretty deeply while barely having to pause. C code is just harder to read [chuckles] for a given amount of functionality, because there’s so much more of it to do the same thing.
And so, I was used to if I’m going to read code, sit down for hours, plan to go deep into these weird special cases. And mostly Ruby code just works better and reads easier. And of course, the Rails codebase is very clean. It’s extensively peer reviewed. It’s really well put together. They rewrite little chunks of it all the time. There’s the whole bug database. If there’s something you’re curious about, you can go back through the GitHub history and you can get the annotations and you can search through their Pivotal Tracker. Compared to any C codebase I have ever read, the Rails codebase is like literature.
CHUCK:
So, if somebody wants to jump in and rebuild Rails or build their own web framework, where do they get started?
NOAH:
So, there are a couple of places you can get started. I began with just making a second library so that you have an app, just making a miniature framework. It’s not big. You can do that in 20 or 30 lines or less. But controllers are probably the next thing. You can render the text in the controller instead of having a view if you want to. So, you can cut off the views that way. It’s really easy to just not call the models and so you can cut off the models there. I’m not saying that’s best practices and you should always do that. But if what you want is the smallest little lib framework that you can get, controllers are a good place to start.
And then the next thing is probably views. You can implement a controller framework in 15 or less lines, depending on what you want. You can implement a view framework in a similarly small number of lines. ERB is built right into Ruby these days and Erubis is really easy to use. Most of what surprised me as I was building this was how small the smallest version of each of these things can be, how small your simple view framework can be. I’ve got a talk I give called something like ‘The Five-Minute Ruby Web Framework’. And it’s literally a 13-line mini Sinatra. It only supports GET. But you can write the Sinatra style routing language in under 15 lines easily.
AVDI:
I think a lot of people see something like that and they think, “So, what is the rest of this cruft?”
NOAH:
Yeah. And sometimes that’s a fair question. I will say that Sinatra itself is kind of dirty in internal structure. I had the good fortune to work with the folks at OnLive until recently. The company sank. But I built a custom Ruby framework on top of Sinatra. We did some really interesting things there and we did at least manage to open source that. But one of the problems we persistently had is that Sinatra is structured a little bit weird. And so, if you want to replace parts of it or hook into it, it’s hard to do. That’s not always a criticism. Sometimes a framework is just very self-contained. It’s not designed for hooks. But Sinatra is structured a little weirdly in several ways.
If you want to build on top of a framework I’m told the Cuba framework is a much better place to start, just because it’s smaller, not structured in quite the same way, and it’s basically designed to be hooked into in the way that Sinatra is not.
CORALINE:
Have you looked at the Lotus framework at all?
NOAH:
No. I have never looked at the Lotus framework.
CORALINE:
It’s supposed to be a lot more modular.
NOAH:
That makes a lot of sense. Yeah, Sinatra is not at all modular. Sinatra is definitely not built to be taken apart. So, what I would say with Sinatra is that if you’re looking for a framework at that level, you can build a very simple framework on top of Rack. I think some of the cruft in Sinatra, some of the additional line count, is because Rack was not as good when they started. Rack has grown upward as the frameworks have grown downward, to take over more and more of the functionality. One of the things I’ve found in Rails repeatedly was it was surprising how much interesting deep Rails functionality was entirely handed over to Rack, as it couldn’t have been in much earlier versions. So, things like cookies and sessions and how they track that stuff, Rack does the vast majority of that at this point. And it didn’t originally.
CORALINE:
Can you talk about what the core functionality [is]?
NOAH:
The core functionality of Rack?
CORALINE:
Yeah.
NOAH:
Okay, sure. So, I usually start by saying Rack is the Ruby equivalent of CGI with as you would hope for from the Ruby equivalent of CGI. It is a compatibility library over all of the different application servers for serving requests, for returning responses, and for the things that most web interfaces are going to want to do. So, sessions and cookies and parsing the things from the environment, the same things that would be passed in CGI environment variables like what domain you’re serving, and whether…
JESSICA:
Can you define CGI?
NOAH:
Oh, I’m sorry. CGI [chuckles] I’m an old C programmer. I take too many things for granted there. CGI which stands for Common Gateway Interface, is the interface that a web server provides to whatever program it’s running to serve the request. It’s a way to write a little program that is not itself a web server that serves web requests. If you are running PHP or you’re running a C compiled program or something like that, the web server is going to call that program and it’s going to set a bunch of environment variables to send in the information about that request. And then it will receive output from the program. And so, CGI is an API for web requests to run an external program. There are much more complex interfaces than CGI these days. But CGI is sort of the granddaddy of them. But that is the API that your web server is using and passing to your program to serve that web request.
And so, Rack is like that. Rack is the API that your Ruby program uses. And because all of the different Ruby application servers have all implemented the same standard, Rack, it turns out that you can, no matter which app server you’re using, be sure that you can write the lowest level Ruby program that can talk to any of them. So, Unicorn and Thin and Puma and Passenger all implement the same API for web requests.
Obviously you could just write a free standing web server. It is entirely possible to write a little Ruby program that talks directly to Apache or that just opens a TCP socket and serves web requests directly. But you wouldn’t ordinarily do that because you’ve got this, the application server is already written directly or already written. It’s a lot easier to just write a program that knows how to serve a web request but doesn’t know how to do all the very lowest level web stuff. You don’t want to necessarily rewrite that code yourself as much for correctness as anything else.
SARON:
So, I’m jumping in a little late. So, forgive me if you’ve already answered this question.
NOAH:
Please.
SARON:
But I’m wondering. What is the use case for ‘Rebuilding Rails’? If I’m picking between different frameworks that to me is a decision we’ve definitely talked about many times on Ruby Rogues. But rebuilding a framework seems like a much bigger mountain to climb potentially, especially if you haven’t done that before.
NOAH:
Yeah.
SARON:
What is the right situation when you would do that?
NOAH:
So, the primary reason I wrote the book is that I was coming from being a programmer but not a web programmer, in a different language. And a lot of the tradeoffs in frameworks seem weird when you’re coming from that level. For instance, I don’t know if you’ve looked into how Rails does automatic requires for instance. But that’s a great example of a subtle functionality where when it breaks, it’s not clear why it breaks, to a programmer who hasn’t looked into the internals of it. Once you understand what the Ruby metaprogramming underneath it looks like, it’s completely clear why it breaks and it’s completely clear most of what they’re doing. But until you’ve seen how it’s built it never really fully makes sense.
A lot of what ‘Rebuilding Rails’ for is to understand those tradeoffs and to be able to debug them. A lot of Rails seems extremely magical until you’ve seen how it’s built. And in some ways it’ll still seem magical after you know how it’s built. But you’ll know a lot more about how the magic works.
CHUCK:
I just want to point out that you said that coming from outside of web development into web development, that yeah it’s hard to understand these tradeoffs. And then you went to a tradeoff that I don’t think most people talk about when they’re talking about the tradeoffs between the frameworks. Generally what we’re talking about is the APIs that we have to use, not the internals of the framework itself. And so, the automatic require is something that I don’t think most web developers even think about when they’re doing Rails. And so, I just thought it was interesting that you went there instead of say, well the routing or the asset pipeline or the way that you handle certain types of requests.
NOAH:
Absolutely. So, I would say that like most large frameworks, Rails is a combination of those two things. And it’s hard to tease apart. You can’t say I want Rails but I don’t want to do the automatic require thing for instance. It’s getting better about some of the pieces being separable. But at the top level it’s everything all the way down. If you want to separate it the first thing you do is scrape the top level off, like you can just use Active Support or you can just use Active Record. So yeah, to me those are the same kind of tradeoff. But I agree, a lot of it is not exactly web related. Rails is both a programming model and happens to also be used for a web server, if that makes sense.
The programming model is interesting. Avdi for instance has written a book on why that’s not perfect for large projects. And I think he’s right on that. I’ve always been a fan of the idea that Rails is a wonderful frontend framework but is clearly structured around fielding individual requests. Once you get to the point of having a longstanding service that wants to keep doing things Rails is a terrible pattern for that. And you should separate that out of your Rails codebase and into a second codebase sitting next to it. But yeah, so Rails is both of those.
The web patterns are interesting. But I would say that most of the web patterns rather than the programming model patterns are not quite as weird. They’re a little weird if you look at how controllers pass variables to views for instance. That’s something that feels really natural to a novice when they use it. But the implementation isn’t necessarily obvious unless you’ve seen how Ruby does metaprogramming and then it’s obvious again. So, that’s nice because that actually feels a lot less magical when you’re done. Oh look, I can get a list of instance variables. Oh, I can turn that into a hash table. Oh, I can pass that hash table through and set it as variables. Until you realize that that’s a pretty standard Ruby thing to do, it looks like magic. And as soon as you realize Ruby does that, it’s not magic anymore. That’s less of a tradeoff. That’s actually one where I wish I had explored the tradeoff more in ‘Rebuilding Rails’.
Have you seen the gem called decent_exposure?
CHUCK:
I think I’ve heard of it.
NOAH:
Okay. I found out about it because Obie Fernandez mentions it in ‘The Rails Way’. It’s interesting because instead of… it tries to replace the model of passing instance variables through as much as possible. And what you do is you declare a sort of view method where you say, here’s the method name, here’s how you generate it if it gets called. Then go ahead and do this. But the idea is that the controller defines pieces of data that the view will have access to. And instead of setting them into a variable it makes a method that’s callable on demand usually by a bunch of different view methods. And so, the controller actions mostly go away. As much as you can you make the controller actions go away. And it’s not a response to the request as much as it’s a set of pieces of information the view can have and things the request sets as parameters are how that gets looked up. It’s a very functional programming way to look at it. I’m not doing an amazing job describing it.
It actually looks very natural when it’s done right.
AVDI:
I’m curious how you feel that approach compares to an approach that I’ve seen advocated more recently, which is to try to just instantiate a single view model type object. So basically, a controller besides for the built-in variables, a controller is going to just be setting one instance variable and passing that down to the view. And that instance variable refers to a view model object which has everything else that the view might possibly need.
NOAH:
Is this pretty much the same thing as a presenter object? This sounds like a presenter object. But I might be misunderstanding.
AVDI:
It could be. I think they could be considered related. In my experience presenters know a bit more about formatting.
NOAH:
Mm, okay.
AVDI:
About translating data into HTML. A view model is really more about, here is the collection of information that the views might possibly need. But there are also form objects that are similar to this.
NOAH:
So, I’m a little lukewarm on the view model object stuff that I’ve seen. I’m probably out of date. I remember, it’s always been the goal that your controller will set a single instance variable that’s passed to the view. That’s been part of style guides for Rails for certainly three or four years, and probably longer. I find that very often the views that I produce need to know several things about objects that are not necessarily related to each other.
So, to admit bias here I’m mostly an analytics guy. And so, a lot of what I build in Rails are analytics dashboards. And an analytics dashboard is very often, here’s a bunch of different graphs, show a bunch of things about those graphs. And I can make them single object really easily by breaking it into a bunch of independent Ajax requests. But then I’m making decisions that have latency implications in order to keep my code clean. And to me that always feels, I don’t know, weird. If clean code is making my overall performance substantially slower, I usually treat that as a smell in my methodology.
So, the idea of just combining these multiple otherwise unrelated things into one object so that I can package it and pass it to the view, I don’t know, to me that’s not a win. Putting it in a single… it’s like if you had a single app data object and you just shoved everything into the app data object, pushed it through, and then pulled it out of the app data object instead of using instance variables. You could do it. There’s nothing especially wrong with it. But it’s taking something that Rails does really well and getting rid of it.
CHUCK:
Yeah, usually what I’ve seen is you essentially have this view model which you can think of as a presenter that’s mostly about the entire view.
NOAH:
Yeah.
CHUCK:
I’ve seen presenters where it’s a presenter for a particular piece of the view.
NOAH:
True.
CHUCK:
And so, this is generalized across the entire view. So, it’s not just a container that has all the information in there. And yes, you could do all of this with the instance variables or at variables, or whatever you want to call them. But basically it’s then intelligent enough to say, okay I want the user’s name so instead of doing presenter.user.name, you just presenter.users_name and have it work out that way. And so, you can put a little bit more logic and tune it a little bit more toward what data needs to show up there.
NOAH:
Yeah.
CHUCK:
And I think we talked about a similar pattern last week when we talked about Trailblazer, as part of what it does. But yeah, there’s a lot of, I think you really when you were talking about frameworks I think the same thing applies with a lot of these approaches. There are tradeoffs. And it may work out better for you or it may not.
NOAH:
One of the things I like about presenter objects is that very often it’s not clear if particular logic is business logic or visual logic, view type logic. And sometimes the distinction between, this is business logic that belongs in a model versus this is formatting logic that belongs in a view, is really blurry, is very, very blurry. And so, a presenter gives a unified place to put both of those. A presenter is allowed to have business logic as long as it’s about how you lay out something the UI is showing. And so, I see a lot of value in unifying the model logic with the helper logic in that way. I
see a lot less value in making sure that there is one object that has everything the view is going to use passed through. I may be missing it. It’s totally possible that it’s a tradeoff or just that it’s a solution to a problem I don’t usually have that absolutely happens. But I will say I haven’t found a problem the shape of that solution.
CHUCK:
I want to go back into the framework design and Rails, how Rails is set up. I’m curious. What are things in Rails that we take for granted, or most Rails developers take for granted that they don’t even realize the framework is doing for or to them?
NOAH:
Sure. So, Rack is the big thing I wind up talking to people about here. Rack is interesting because it’s not only the lowest level interface, it’s also an intermediate interface. You can have what are called Rack middlewares. I like to think of them as like pancakes because you can build an app out of a stack of them. But the request can be processed on the way it. It can be fielded by the middleware. It can have parameters changed. It can just be passed straight through with no modifications. And then once the app has handled it, it can also filter it on the way out.
So, you’ve got simple middlewares like say, add a content type to the headers, or you’ve got middleware for things like do basic HTTP authentication and if the password doesn’t match then just don’t let it through to the app. Rails already builds a giant middleware stack. I think it’s on the order of 20 pieces of middleware for most configurations at this point. And that’s just getting down to the Rails layers. That’s not counting the stuff that is effectively Rack middleware but isn’t necessarily registered with Rack in the same way.
And so, routing is the same thing as Rack. What I mean by that is what the framework’s doing for you is it’s routing all the Rack middleware stuff for you down to the routing layer. And then in the routing layer everything is made of Rack apps. And so, the big thing Rails is doing for you that is really powerful if you know how to use it and you don’t necessarily know it, is building the whole stack out of the same pieces with the same API all the way up and down. If you want to insert your own Rack middleware into the middle, it turns out there’s a really easy way to do that.
If you want to bypass large chunks of Rails, things like on this particular request at this particular path I don’t want to use the whole routing layer. I just want to skip all of the Rails overhead for that request and skip all the Rails processing for that request, and here’s my little Rack app that will process that. By the way it always returns this string. You can just do that. The Rails controllers and every controller action is a full on Rack app. You can use them anywhere you could use a Rack app. But the controllers also have their own built-in Rack app stacks as well. So, they’ve basically got their own layer just like your app server provides for you. And so, I think Rack is probably the biggest thing of that kind that you don’t realize the framework provides you.
There are several other good ones. We talked about security a little. And I’m not going to be able to go over all of it. It’s a broad topic with a lot of interesting deep implications. But in the same way, that’s one that the framework provides you. And if everything goes right, you’ll never see it. [Chuckles] Rack is the same way. Until you need the power you should never need to worry about it. But once you do need the power, you wind up asking a question, look on Stack Overflow, and one of the first things people say is, “Oh, well you can fix that by putting a piece of Rack middleware and here’s how you insert Rack middleware at that layer.”
CORALINE:
So, you’re describing a Rails app as a stack instead of a typical [MVC].
SARON:
It sounds like she’s trying to say MVC framework.
NOAH:
Ah, okay.
CORALINE:
Yes.
NOAH:
Thank you. Yes. So, a Rails app is both of those things. But the MVC framework is buried under a number of layers in the stack and has additional layers in the stack through the whole controller layer. And so, the controller layer especially but also sort of wrapped around that MVC stack, you have this stack of Rack middleware. So, I would say that it is still an MVC stack. But it’s kind of an MVC stack buried in these layers. And with the whole C part of that, composed of these layers. So yeah, both.
SARON:
You’ve described a lot of what you’ve seen about Rails to be weird. And I’m wondering. What is the weirdest and strangest most surprising thing that you’ve discovered?
NOAH:
Wow. Well, when I realized every controller implemented its own Rack stack, that was up there. That was definitely part of it. What’s the weirdest thing I’ve discovered in Rails? There are also some fairly strange things in Active Record. But they’re not… I don’t know, it’s not like Ripley’s Believe it or Not weird. It’s just, ‘Wow, why did they decide to do that that way?’ weird. Active Record keeps reminding me that SQL is not a standard and really never has been. [Chuckles]
SARON:
What do you mean by weird? Is it just the background and expectations? Or how do you define weird in this context?
NOAH:
Sure. I usually say that what makes a tool a good match for you or not in a lot of cases is your taste, which in turn is your previous expectations. One of the things I loved about Rails is that it just feels right to me. Ruby and Rails were both like this. When I reach for a tool or an API, it’s usually there. I can’t always immediately find it. But if I look for something that should be there, usually it is there. What’s interesting is that Rails has a layer like that, that feels utterly natural. And Ruby has a layer like that, that feels utterly natural. When I look for a particular API it’s usually there. And it’s implemented with a bizarre series of hacks that clearly were, “We know what we want it to look like on top. And we’ll do anything necessary to make it happen on the bottom.”
This is how I feel about, say the automatic constant loading. Because the way they make that work is, “Oh, well we’ll use directory names. And the directory names will all just work, even though some of them are lowercase with underscores and some of them are uppercase with mixed caps.” And there are a lot of things like that where the effect is utterly natural. You reach for the thing and it’s there. But once you think about the implementation, your first response is “Ew. Ah. They did it…well, I guess you’d have to do it that way. But really?”
That’s part of the reason that I say Rails is also a programming model. They need an enormous standard library to do some of these tricks. Like the fact that you have to tell Rails how you make certain words plural or not so that it can successfully turn your singular words into plural words for a database entry. And so, you have to decide how you want to make the word octopus plural, things like that, which is necessary for what it’s doing. If you have a model called octopus then you have to decide if it’s octopi or octopodes or octopuses or something else, because you’re going to be reaching for that database table. And Rails is going to pluralize it however you say to. [Chuckles] Octopods, says Avdi. Yes. [Chuckles]
SARON:
I wonder how often that happens. Is that a problem that’s unique to Rails? Or is that just a side effect of trying to make something feel so natural and so obvious that the internals almost have to be a mess. Is that usually how it works?
NOAH:
So, I’ll again show my bias here. I was a C programmer and a systems programmer for a very long time. And the way that that usually works out in that world is that the codebase is so huge and it’s so hard to get an overview of it that they try to keep it internally consistent at the lowest level, because the lowest level is most of what you can see. Many of these kinds of cleverness are considered are serious code smell in that world, because the projects are so big you know one person can’t keep the whole thing in their head.
Ruby is very different from that, because very often one person has a serious overview of it. There’s just a lot less code in the same amount of functionality, which is wonderful. But it means that a lot of these kinds of being friendly and making sense and being structured like you expect and being structured sort of like English are possible. It didn’t use to be possible. And so, the way that they handle this in Java or in C or any other sort of performance-oriented giant line count languages is usually just to avoid almost all the cleverness. Does a Java framework do this? No, not at all. You will have to manually describe how each of these things happen in most Java frameworks. Does a C framework do this? C programmers would laugh at you based on this.
The idea that any part of it would be friendly to human beings is considered… I hate to call it a macho culture because that means something specific, but it’s got very much its own sort of, this is the hard core way we do it. This is how it’s done. And a lot of it is that cleverness is considered really bad. And I get it. That comes straight from electrical engineering culture. And it works really well for the kind of projects they do. And a web app done in that culture would be misery and horribleness. And so, that’s one of many reasons that you don’t wind up writing your web apps in C, because the culture would generate things that were hideous as web apps. Even aside from the fact that the language isn’t terribly well-suited for it either.
JESSICA:
Noah, you mentioned that in Rails there’s an expectation that one person can hold the whole program in their head.
NOAH:
It’s a possibility.
JESSICA:
Is that like… I see that as this fail point, at which point one Rails app isn’t working anymore.
NOAH:
Yeah, I would agree with that. So, the Rails basic pattern, the basic idea of how it structures controllers, how it structures views, it’s designed to be fairly friendly. You can pick up any controller or a view if it’s well-written pretty easily. But I agree in general that when a Rails app gets big enough that one person clearly can’t see the interactions, it’s time to start taking chunks out of that Rails app. Separate it into other apps, separate it into services. I would agree with that. Rails is designed to be small enough one human being can comprehend it.
And a lot of the tradeoffs it makes, like having these additional services, additional libraries that are just magically available, are very much designed around the idea that one person can keep the [non-local] effects in their head. Whereas a lot of the scaling decision that it makes like say the routing layer being able to be a whole bunch of separate apps, are designed to make it really easy to cut that up into multiple pieces so that you can limit the non-local effects so that the pieces are small enough one person can keep them in their head.
JESSICA:
Exactly. It’s not really just Rails. It’s any application needs to be broken up at the point where one person can keep it in their head, eh?
NOAH:
Absolutely. Having pieces that small is really, really valuable. Not everything can do that. What I say about say Java is that if you were going to have 100 programmers all working at once on a
giant monolith, no question that monolith should be in Java. Whereas the Rails approach is what if you…
JESSICA:
[Laughs]
NOAH:
Well, it’s a language that is designed to limit the amount of damage you can do to other programmers. It intentionally limits non-local effects as much as it possibly can. Now, my take on that is that you should not have 100 developers all working on the same giant monolith. Just avoid that situation as much as possible. But for the same reason, I can’t remember where I saw this great discussion on IDEs, but talking about how every Java IDE has to be able to scale to multiple million-line codebases. Wait, didn’t you just tell me that the big problem is that the codebases are too big? And now you’re making sure the IDEs make it easier to handle the big codebases? Isn’t that bad? At which point, if you’re talking to an IDE developer they’ll laugh and then go right back to what they were doing. And the answer is yes, that situation is bad and we are making it worse. And then we laugh and go right back to making it worse.
JESSICA:
I’m a big fan of the IDEs for reading those million-line codebases. And then I go switch over to vim when I want to write something intelligible.
NOAH:
Yup.
CHUCK:
[Laughs]
SARON:
[Chuckles]
NOAH:
Yeah. Well, if you write tools that make you keep it in your head, then you’re going to produce code that is small enough to keep in your head. And you’ll get laughed at more by people who consider themselves real programmers based on line count. But you’ll also produce much better code.
JESSICA:
Exactly.
NOAH:
I don’t know.
CORALINE:
In that vein, do you think that Rails [inaudible] be better programmers?
NOAH:
I think that Rails programmers have a combination of pressures from the framework which make them much better programmers in some way and much worse programmers in others. So, where I see Rails’s sweet spot being, the thing that it’s much, much better than anything else and nothing else can come close to it, is a small team putting together a new project on a tight deadline to try out an idea where there’s a really good chance that that idea won’t work out. Which again, is almost every startup these days. And the reason that I think that that is absolutely Rails’s sweet spot is that it makes sloppy programming forgivable, again like the security thing we talked about. It makes it really easy to take out a giant loan of technical debt by using other people’s third-party, not necessarily well tested libraries. It makes it easy to put something up that works, not necessarily perfectly, really not heavily bulletproofed. But it works. You’ve got a proof of concept and you can test it.
And the reason I say there’s a pretty good chance the idea won’t work out is that if you put this together really fast and really sloppy, you’re going to have to put all the effort that you would take to rebuild it well in order to get it working well. But if there’s a 75% chance the idea doesn’t work out, well great. Three out of every four things you build, you’re just going to let it sink. You’re probably going to get rid of it. At best you’re going to modify it to try another idea. And so, whether you rebuild it in Ruby afterwards or whether you rebuild it in ta different language, which is mainly a performance thing rather than anything else, whichever or those you rebuild it in it’s going to take you as much effort to build that full version as it would always take you.
It’s just, you save the effort on those other three versions by building it in a language where you can do it fast, you can do it sloppy, and not put in the extra effort. Which again, is wonderful as long as what you’re trying to do is to solve problems that you’re not really smart enough for. And more and more, all the interesting problems are problems that one person is not smart enough for. And so, they’ve got to do it with a trial and error approach. They’ve got to do it with an iterative approach. The interesting problems are all things where one human being can’t just work through it and get the right answer by brain power ahead of time.
CHUCK:
If we don’t have the constraints that put us into that sweet spot for Rails, then how do you decide which framework to work in, or what language?
NOAH:
I look at what my big constraints are. On any project that’s at all interesting, there’s going to be some set of interesting constraints. Like if you tell me that absolutely every request to my server is going to have to come back in a 20th of a second or less, then you’ve told me what my 99.999th percent worst latency is. Great. That constraint’s my tool choice. That’s a big deal. If you tell me that I’m going to have to put it together with three guys in two weeks, well then I’m going to look at something like Rails where I can put something very quickly together but it’ll still work well. If you tell me that it’s going to have to link to a giant big data backend, I’m going to do it in something on the JVM. Maybe that’s JRuby, maybe that’s, I don’t know, Clojure. But that gives me a constraint that I can work with.
If there are no interesting constraints on the problem, well then why are we doing it? There’s got to be some use for it, right? If you’re doing it in a startup sort of situation where you’re trying to make money off it, your constraint is almost always time. Because it’s money and those interchange. But an interesting problem has almost always got either a hard constraint or a goal. And the goal makes a constraint. The goal tells you what’s important. So yeah, I find what the interesting constraint is and then I pick a tool that’s designed for that constraint. And these days there are so many languages, so many tools, so many frameworks. I can find something that’s aimed at that constraint.
AVDI:
So, here’s a question for you. Given that you see Rails’ sweet spot as being the ability to throw something up really quickly and see if it sticks…
NOAH:
Yup.
AVDI:
Arguably Rails is sort of intentionally that way but also sort of accidentally that way.
NOAH:
Yeah.
AVDI:
The application it was extracted out of wasn’t exactly an application where… it wasn’t exactly just throwing something together to see if it sticks.
NOAH:
No. I mean…
AVDI:
I’m curious if you think…
NOAH:
Sort of, but…
AVDI:
Sort of, yeah. But I mean…
NOAH:
Sorry, go ahead.
AVDI:
I’m curious if you think that there are other frameworks that maybe are now addressing that need more directly. I guess one that springs to mind is Volt where it’s putting an assumption in place that you’re going to be using probably something like Mongo and you’ve got this whole stack set up.
And in return, you get to basically type stuff into the server and see stuff appear live on the page.
NOAH:
Yeah.
AVDI:
And so, you have even more live-ness, ability to play around, than in something like Rails.
NOAH:
Yeah. That’s potentially a really interesting thing. I have not looked enough at frameworks like Volt and Meteor to know if they also have the other handrails that something like Rails does. Again, I emphasize the security thing and I emphasize that the reason you’d use Rails is if you’ve got human beings talking in HTML. Because if you’re going to put up a site that serves HTML to real browsers on the open internet, security is a huge, huge constraint. It’s one of those things where building that backwards into something that doesn’t already have it is not just phenomenally expensive, not just phenomenally time consuming, but it requires a genuine expert. You have to understand a lot of interesting attacks in great detail. And it’s a genuinely adversarial setup. So to me, that’s part of why I say in a quick situation use Rails.
And that’s what I’ve… I haven’t looked into Volt. But I’ll say that JavaScript frameworks for doing things like that, like Node.js for instance, that’s where they tend to fall down. That’s where they tend to say, “Oh, well a skilled programmer can do that.” Yes, but you shouldn’t make a skilled programmer do that. A skilled programmer can do almost anything with incredibly bad tools. That doesn’t mean you should hand them bad tools. But I may not be giving Volt its due. It’s possible that Volt does a good job of fixing that. But that’s one of the things that’s hard with a really dynamic language. Rails has had some of this, too, is that constraints like that, it needs to be reasonably secure, are hard to build into something that’s very flexible.
AVDI:
That’s true, yeah.
NOAH:
But I think there’s definitely a place for that. One place that I think Rails falls down hard is highly server-interactive applications. You’ve probably seen how bad it is setting up a chat server properly on Rails. Anything where you exchange a lot of information with the server after the page is served. And while that is in some ways an HTML limit, HTML’s not designed for that either, a good framework can get around that to a large extent and Rails doesn’t really try. It sounds like they may be trying to do it with Action Cable. Active Cable? I forget what it’s called. But I will say that the Rails 4 Live events were not enough or anything close to enough to really make that usable. It’s possible that Rails 5 is going to do better on that. And it’s clear they’re trying, which is nice.
But yeah, there’s definitely some room for that. For starters, if I was going to do something with server push I wouldn’t start with Rails. Because while it’s good for prototypes in general, it’s not great for prototypes of that. And so, there’s definitely… there’s plenty of room, even in that space. There’s plenty of room for something to be a really good tool for something small. If you told me there was another tool that was really good for, like you say doing live stuff and pushing directly to the server and back to the page, you can do better than Rails does that way trivially. I’ve seen very simple little Node.js frameworks that do exactly that and do a great job of it. And it’s because even where Rails is basically competent it definitely has its flaws.
CHUCK:
Anything else we want to go after with this before we go to the picks?
NOAH:
A couple of things I’ll hit quick just because I wrote them on a piece of paper, maybe important, maybe not. You talk about choosing a framework. One of the big things I do when choosing a framework is to read through the code. And reading through the code is a lot easier after you’ve written code like it. And so, I’m all in favor of people choosing a framework. And I think that building some parts of your own framework makes that, I won’t say easier. It still takes time to read. But it means you can make a much more informed decision because you know better what you’re looking at. Enough code reading will do the same thing. But I’ll say that good code reading, one of the things you should be doing is experimenting with that code. You should be tweaking it and seeing what’s different.
And in the same way, very often knowing the framework down to the Rack level makes it a lot easier to get around the framework limits. Rails is nice as far as you can patch into the Rack middleware stack. But just knowing what you can do is usually something you accomplish by looking down underneath the framework. If you want to get at cookies before Rails touches it or you want to do an interesting kind of authentication before it gets into there, anything like that.
Cool, so that’s what I’ve got.
AVDI:
I have one more question for you.
NOAH:
Please.
AVDI:
At the top of the show you said that ‘Rebuilding Rails’ was the book that you wish you’d had.
NOAH:
Yes.
AVDI:
I’m curious if there are any technologies, frameworks, languages, where you’re feeling that again now.
NOAH:
So, I’m doing a lot of analytics and big data these days. And I would say I’m not smart enough in that domain to know exactly what that book would look like. I think every so often about writing a big data book like this, because I’ve done a lot of poking into say Cassandra, which is really interesting under the hood, down in the data structures, stuff like that. But what I really want is some kind of a down deep understanding of the distributed systems stuff. And once I’m smart enough to write that book, I probably will. But I’m pretty sure that book doesn’t exist yet. I really wish it did.
JESSICA:
Oh no, I have a recommendation for that.
NOAH:
Oh, okay.
JESSICA:
Martin Kleppmann is currently working on a book about big data and distributed systems and the tradeoffs that the different technologies make. I’ll find a link and post it in the show notes.
NOAH:
Sounds great. Yeah. I found a lot of tradeoff stuff. What I’d really like is, do you guys know Aphyr? He does the Jepsen Call Me Maybe stuff.
JESSICA:
Yes.
NOAH:
Yes, so that’s a lot of what I feel like there’s a big gap on. And I can’t be the only one. There’s a reason his stuff is so popular. I understand a lot of the differences in the tradeoffs that the different technologies think they make. But what I don’t usually know is enough to see the holes in what they’re doing. I can see some of them. I can find the big obvious holes in what they’re doing. But that’s what ‘Rebuilding Rails’ taught me enough to go do with other frameworks. And what I just don’t have the ability to do in distributed systems yet, with the understanding that distributed systems, it’s a lot harder to do that than with Ruby web frameworks.
AVDI:
Cool.
CHUCK:
Alright.
JESSICA:
Yeah, that makes sense.
CHUCK:
Let’s go ahead and do the picks. Avdi, do you have some picks for us?
AVDI:
I have a pick. And this is going to be another of my silly office supplies picks. But I’m going to pick a brand of garbage can. I’m going to pick simplehuman garbage cans. We got one for our kitchen sometime last year I think. And it has been the first step, I don’t even know what they’re called. The kind where you step on a pedal and the lid comes up. Been the first garbage can of that kind where the pedal hasn’t broken within three months. They’re just, they’re really sturdy. They’re most expensive than most of the stuff that you would go out and find and you’re thinking, “Hey, let’s go buy a new garbage can.” But it seems like they’re worth it. They’re pretty well-designed. So yeah, simplehuman garbage cans. That’s all I got.
CHUCK:
Alright. Saron, what are your picks?
SARON:
Sure. I have two. They’re both articles. So, the first one is called ‘Etsy CTO on Its Conservatively Crafty Tech Philosophy’. And it basically interviews CTO Kellan Elliott-McCrea. I don’t know if I’m saying that right. And he talks about how they pick tools and what they used to do and what they do now. And he talks about their tech philosophy and I thought it was interesting in the context of picking different frameworks and picking what you use. He goes in depth about that at Etsy. So, I thought that was cool.
The second article is called ‘Death of a Programmer. Life of a Farmer’. And it’s a story about someone who was basically just tired of being a programmer and decided to raise, I think it’s lamb or goats or farm animals and farming. And talks about their trials and tribulations and what it was like. And I thought it was an interesting read.
CHUCK:
Alright, Jessica. What are your picks?
JESSICA:
I have one pick. It’s a great pick. So, the other day a couple of weeks ago I was at Craft conference in Budapest. And it was a great conference. It was really amazing. It had some great themes about things like why micro services are not going away that really came out in the opening keynote of the second day by Mary Poppendieck. And it’s amazing. So, I’m going to pick her keynote. The video is available. And it’s called ‘The New New Software Development’ I think. But she starts from 40 years ago when she started programming and gives a lot of context about why the industry is moving in the directions that we’re moving. And what that means for the teams of the future and the software of the future. That’s my pick
CHUCK:
Cool. I’ve got a couple of picks. The first one, I just want to let everybody know we are doing Ruby Remote Conf. Several of the Rogues are actually going to speak at that. And I’m really excited about the lineup we have. We also have a few other people you may have heard of like Dave Thomas. Steve Klabnik’s going to be speaking. Just a whole bunch of people. And yeah, it’s just going to be terrific. It’s at the end of June. You can get tickets now. Go to RubyRemoteConf.com and sign up. The tickets are $200 apiece.
And another one that I want to mention is an event that’s happening here in the US. It’s called Rails Camp. Rails Camp West I think is what it’s called. It’s going to be in northern California. It looks really great I’ll put a link to it in the show notes. And you can go check that out as well. Bobbilee Hartman reached out to me and let me know about it. And it looks really fun. I wish I could go. I just don’t think it’s going to happen this year. Anyway, that’s another thing worth checking out.
And finally I’ve been reading this book called ‘Traction’. Now if you go look on Amazon there are two books called ‘Traction’. One has a yellow cover and the other one doesn’t. This is the one that doesn’t, though the other one is really good, too. This one is basically about how you run your business and how you organize your business. And it’s making me think about the way that I arrange things and think about accountability in the business and things like that. So, if you are running a small business or you’re an entrepreneur then I highly recommend that book. I recommend the other ‘Traction’ book, too. But this one’s really good.
CHUCK:
Noah, what are your picks?
NOAH:
First off, I recommend ‘The Codeless Code’. It’s a website of Zen programming parables in the style of ‘The Gateless Gate’. And it’s amazing. It is good Zen. It’s good programming. Good Zen to the extent I know anything about it. But it does a beautiful job of keeping the enlightened style. And I’m an increasingly old programmer. And so, programming parables are always interesting to me. These are done really well.
I’d also recommend ‘Ruby under a Microscope’ by Pat Shaughnessy. I expect somebody’s recommended it before. But it’s worth more than one recommendation. It goes down deep into a lot of the Ruby data structures like the hash table and extensively how hash tables work and how they perform and how they’re set up. It goes down deep into the Ruby parse tree stuff, which I think more people should look into. Ruby’s a complicated language for parsing. Anyway, ‘Ruby under a Microscope’ by Pat Shaughnessy is fabulous.
And then as a last pick, so my book does a really good job of hitting the overall structure of Rails. But it doesn’t do a good job of hitting the individual Rails APIs and talking about that. Many of my things have different names for the methods. I certainly don’t have a giant extensive Active Record.
I’m mostly doing just enough of the Ruby methods to show you the structure of Rails and tradeoffs of Rails. So, the opposite approach is ‘The Rails Way’ by Obie Fernandez. I think they’re up to ‘The Rails 4 Way’. And so, if you want a companion book that does the things I do well badly and the things I do badly well, just to get the balanced view, ‘The Rails 4 Way’ by Obie Fernandez is a great choice for that. And that’s me.
CHUCK:
Alright. Well, thank you for coming and having this discussion with us. If people want to find out more about you, about ‘Rebuilding Rails’ or get the book, what are the best ways to do that?
NOAH:
Well, ‘Rebuilding Rails’ is at Rebuilding-Rails.com. My blog on lately more deployment topics but Ruby topics is at Codefol.io. And you can also find my class at Rails-Deploy-In-An-Hour.com with dashes between the words. So, those are all great ways to find me. I’m easy to google. It’s not hard to find my email address. So, I’m very happy to field questions from anybody who’d like to email me. You shouldn’t have any trouble finding me. But you can comment. Leave a comment on the blog if you have any trouble finding my email address. I’m pretty friendly.
CHUCK:
Alright. Well, thank you everyone for listening and we’ll catch you all next week.
[This episode is sponsored by MadGlory. You’ve been building software for a long time and sometimes it’s get a little overwhelming. Work piles up, hiring sucks, and it’s hard to get projects out the door. Check out MadGlory. They’re a small shop with experience shipping big products. They’re smart, dedicated, will augment your team and work as hard as you do. Find them online at MadGlory.com or on Twitter at MadGlory.]
[Hosting and bandwidth provided by the Blue Box Group. Check them out at Blubox.net.]
[Bandwidth for this segment is provided by CacheFly, the world’s fastest CDN. Deliver your content fast with CacheFly. Visit CacheFly.com to learn more.]
[Would you like to join a conversation with the Rogues and their guests? Want to support the show? We have a forum that allows you to join the conversation and support the show at the same time. You can sign up at RubyRogues.com/Parley.]