00:00:15.360
Hi everyone! Can everybody hear me? Well, yeah, beautiful! Alright, let's begin.
00:00:26.000
First things first, let's go on an obligatory whirlwind tour of some random stuff about me: where I work and where I'm from, because you know, that seems to be the thing to do.
00:00:32.719
My name is Alan Skorkin. I'm known as Scorcs around the interwebs. I usually look like that. Obviously, I also look like this. Like most people, if you Google my name, I'll actually come up first.
00:00:44.719
To make things easy, I'm Scorcs just about everywhere—on Twitter, GitHub, and my blog is called skorgs.com. So feel free to add me on whatever! Open some issues on my projects, that’s fine.
00:01:07.280
I come from Melbourne, Australia, which, as it turns out, is really far away from here. It's pretty safe to say that out of everybody at this conference, I've traveled the longest and the furthest to be here.
00:01:19.200
This is pretty cool because I was once at a conference where I traveled about 100 meters to be there. So I've done both things now.
00:01:30.320
I work for a company called Envato. I've only been there about three months, but they were nice enough to send me here. There are lots of companies that are way less successful but way more famous than Envato.
00:01:41.759
I thought I'd say a few words since I'm obviously the only person here from their company. One of the things we do is marketplaces for digital goods.
00:01:48.399
So if you've ever done any WordPress work, you would have heard of ThemeForest. It’s probably one of the biggest Rails sites in the world, getting somewhere around the 100 million page views per month mark.
00:02:01.360
We also have a blog network, which is where I get to play with Rails and Ruby stuff. It doesn't get quite as many page views as the marketplaces, but our traffic is still quite substantial.
00:02:13.920
So, as I said, I’m running a blog in Rails. I never thought I’d be able to say that when people ask me about my work, but here we are. In fact, when I tell people that, they look puzzled and say, 'Really? What do you actually do?'.
00:02:31.680
Envato is a completely privately-owned company that has never taken any outside investment. Half the companies in Melbourne, Australia, are the other half that works from all over the world. Our software developers these days have pretty much infinite choices when it comes to work.
00:02:44.640
But it’s always nice to know there’s another interesting place to consider if you're ever looking.
00:02:52.320
As I said, I come from Australia, and since I'm in the U.S., I can’t very well not say a few words about Australia. The expectation is that people from Australia will talk about wild animals.
00:03:03.200
So I’m going to try to honor that tradition and say a couple of words about a cool Australian animal: our idea!
00:03:15.680
I’m going to make a bold claim and say this is the best animal in Australia. Here’s why: it’s small and cute, but it has wicked big claws, and it can dig really really fast. It doesn’t strike you as much of a sprinter; I mean, have a look—it doesn't look like a greyhound or anything. But it can actually run pretty quickly, faster than most of us here. But here’s the most interesting thing: I'm not kidding, it will literally try to sit on invaders and crush them.
00:03:38.800
So if you're in Australia and you see a small wild animal, and it's staring at you, you're probably in big trouble, and you should run for your life!
00:03:45.440
Which won't be all that fun, but it's still a nice thing to know.
00:03:51.840
Anyway, enough of random stuff—let’s talk about some Ruby and some Rake.
00:04:04.799
Rake is ubiquitous in the Ruby community. Every project you come across on the web or in a gem is going to have some Rake in it.
00:04:20.799
In fact, if you ever come across a project without a Rakefile in the root, it looks a little weird—much like a project without a README. A while ago, I was writing some Rake.
00:04:34.160
There are times in your life as a software developer when your tools just annoy you. For me, this was one of those times. Needless to say, I was feeling a little bit frustrated.
00:04:48.400
I kept asking myself a question that we all ask about every tool we've ever used: why? Why did you do it that way? I mean, I wouldn’t have done it that way; I would have done it better. And in my case, that led to wondering, 'Why is Rake so pervasive in the Ruby community?'
00:05:06.800
Is it just a matter of being around long enough? Why hasn’t anything clearly superior come along to replace it? And why hasn’t anyone switched to that replacement?
00:05:20.400
This was the start of a very long journey for me, and I’ll try to give you a sense of that journey over the next 30 minutes or so. I’m sure it will be awesome.
00:05:34.160
Every good story begins a long time ago, in a galaxy far, far away. And as luck would have it, this is where the ancestor of Rake actually comes from.
00:05:48.959
I'm talking about Make. As we all know, Rake is based on Make, and Make comes from the C world.
00:06:01.199
And that’s the wrong C world. Of course, it means this one. Rake is literally Ruby Make. Make is extremely curious because there are still many things wrong with it.
00:06:12.560
Despite this, it's used so widely that it might as well be the only tool of its kind in the C world—and once again, it’s this one.
00:06:28.880
If you've ever done some C programming, you may know some of this already, but here are just some highlights of some shortcomings.
00:06:43.919
Make is a programming language, but it has no lists or hashes—just strings. It has limited support for conditionals like if statements, and in fact, it has only very limited support for loops, which makes it really hard to do useful things.
00:06:53.520
All variables are global, and for some reason, it’s designed that way. But as we all know, global variables are not great.
00:07:01.120
The only thing I can really say about that is this: sometimes whitespace is significant and sometimes it’s not. Commas are the same, and of course, a little bit of randomness in your programming language keeps us on our toes.
00:07:09.360
Make has very poor performance, and in fact, its performance scales non-linearly with the size of the project you use it on.
00:07:16.080
For larger projects, Make will be much slower.
00:07:20.800
Then there's this issue: the only way to do it is to execute it over and over manually until you are sure it works.
00:07:29.760
But of course, Make is very unreliable, so sometimes when you execute it, it’ll fail for no good reason.
00:07:38.320
So you have to do Make clean and try again, and hope that it will work this time. This cycle doesn’t help its performance either.
00:07:49.440
Make isn’t the worst looking programming language, but it often feels like one that was designed to make writing useful progress very hard.
00:07:57.520
Another footnote is that Make is often so bad it led to the creation of Automake to help generate Makefiles.
00:08:06.880
So we have Make, which is the tool we use to put together C projects, and then there's Automake, which helps us use the tool that we use to put those projects together.
00:08:21.760
But of course, to use Automake, you have to use Autoconf, which helps us use the thing to put together your C projects. It’s a bit of a house of cards.
00:08:38.400
And yet somehow, we’re still able to write significant software using niche tools, thereby improving once and for all that software developers secretly enjoy pain.
00:08:48.160
Of course, I’m exaggerating a little bit. C developers might enjoy pain, but the rest of us have a really high pain threshold. But surely we’ve learned our lessons!
00:09:04.240
Surely Rake is much nicer! Well, in some ways it is, but we didn’t learn nearly as many lessons as we think we did. Rake is just a revenue cell of the rules.
00:09:15.760
So it still won’t be under the hood. Let’s take a closer look.
00:09:23.920
So firstly, say what you will about Make, but C needs something. We have to compile, we have to link; there are steps to be taken before we get a usable program in C.
00:09:35.840
Ruby has no such troubles; we don’t need to build anything. So in Rake, we have a build tool for a language that doesn’t need a build tool.
00:09:46.560
If we summarize what we know about Rake so far, we get this: it’s a very popular but nuclear tool and a solution just for a problem that doesn’t exist.
00:09:54.400
That’s not a very auspicious beginning.
00:10:02.000
But it almost feels like we have to find a use for it, so we did. Now, I thought long and hard about the best way to describe what we use Rake for.
00:10:10.720
Here's my best effort.
00:10:14.439
So, that's Rake. We've scrutinized the idea, but let's look at the actual technology.
00:10:21.679
What is so bad about Rake? First and foremost, defining a task to take command line arguments can be extremely awkward.
00:10:33.680
It looks complicated, and passing arguments to Rake tasks is even worse. What do these arguments even mean? And which one is which?
00:10:46.000
But at least it works, right? Well, let's try using it in that shell.
00:10:53.760
That's not very nice! I mean, what have we done to deserve that?
00:11:01.760
And of course, you have to quote it because that’s obvious! That's the arguments and the name of the task.
00:11:08.400
The real solution that most of us use is to avoid writing tasks that take arguments in the first place. You're better off writing a special case of your task and then putting the original task in a new one under a separate namespace for clarity.
00:11:22.960
Speaking of namespaces, what’s a good convention for namespacing Rake tasks? Oh, I'm not too sure; it's kind of nebulous.
00:11:36.960
It makes sense, kind of, like regular Ruby classes, but we've been thinking and studying our design for ages.
00:11:45.440
There are many different principles with Rake; do what feels right is the only principle that I’m aware of.
00:11:56.240
How do you structure your Rake files anyway? Perhaps you would just namespace so fast and then put them all into one file, and that works!
00:12:09.920
But what about when it gets too big? How do you structure your larger files then?
00:12:20.480
In any case, how do you implement the functionality of a Rake task? You just write the code inside the task itself.
00:12:31.360
That doesn’t seem very modular. And how do you write specs for that?
00:12:39.040
Maybe we can push functionality into a class and try to make each task implementation keep to one line.
00:12:47.520
That’s a reasonably nice solution because it will bring us back to that good old Ruby design. And this is why heavyweight design should be a fundamental skill.
00:12:56.160
But Rake isn’t really giving us any help.
00:13:01.679
What about documenting Rake tasks? We’ve got our one line of description! So hopefully, you're really good at expressing yourself.
00:13:08.640
But if you forget the one-liner, you get a mystery task.
00:13:15.200
Because everyone loves surprises! There’s no way to even know that a task exists unless you read the code.
00:13:26.560
I’m going to go out on a limb and say that 90 percent of Rake tasks out there have no specs.
00:13:43.760
But we love specs in the Ruby community—whether it’s for unit tests or anything that helps us make sure that our stuff actually works.
00:13:52.560
So what do we get? It’s still a little daunting to run these things in production, and it makes me feel a little lost.
00:14:00.480
If you think about it for a while, you'll realize it’s not that surprising.
00:14:13.920
Here's an example of a typical Rake task that I pulled out of Rails.
00:14:23.680
Now, I don’t know about you, but I tend to agonize over methods that are longer than a couple of lines in my classes.
00:14:30.799
But a Rake task that looks like this seems just fine. In fact, this one is probably alright!
00:14:39.200
Sadly, you’ll see these kinds of Rake tasks all the time.
00:14:48.000
The problem with Rake, especially considering how ubiquitous it is, is that it has no idioms.
00:14:56.720
We love the idea of moving forward with well-defined practices. Here are some pretty awesome practices, which I've prepared.
00:15:05.840
Opinionated software has been the mentor for years, and it's a good thing. You can get significant work done on Rails just by following the conventions.
00:15:13.039
But Rake is not opinionated. If anything, the geometry of Rake is a monolithic task, and we need to refactor it.
00:15:22.879
The question we should always ask ourselves is: does Rake encourage bad design?
00:15:30.639
And even if it doesn’t by itself, the way we’ve been using has become a problem.
00:15:39.600
Programmers have come to adopt the look of the code that has been overwhelmingly poorly written. Badly written Rake tasks are everywhere.
00:15:46.559
So, the cycle of crappiness just perpetuates itself.
00:15:54.079
But of course, Rake is not all bad. Regardless of its lack of idioms, namespacing is a good idea.
00:16:02.560
Chaining Rake tasks is pretty awesome, and of course, Rake has a memorable name.
00:16:12.560
So anyway, I think the world should be a much nicer place with plenty more good things and fewer bad things.
00:16:22.400
As a software developer, I can actually roll up my sleeves and do something about my work.
00:16:36.160
Let’s go back to a highly relevant description of what Rake does, which also kind of sounds like what we use command line apps for: random tools, scripts, and stuff.
00:16:47.920
So here’s a thought: what if instead of writing Rake tasks, we wrote command line apps instead? This might make you feel encouraged!
00:17:04.000
Although you might be thinking, 'These scripts writing with OptionParser are even worse! Those things have no structure whatsoever. And once again, how do you write specs for them?!'.
00:17:18.240
We don't want to be doing that. What we want is a framework that makes writing command line apps easy and makes our command line awesome, just like Rails or Sinatra do for web apps.
00:17:31.920
Surprisingly, I’m not the first guy who had that thought.
00:17:37.919
When we talk about command line apps, they typically come in two basic flavors. There are basic command line apps, like curl, which have no subcommands, just options and arguments.
00:17:50.880
Then we’ve got command line suites like Git, which also have options and arguments but can have subcommands as well.
00:18:04.480
So what about command line apps? Well, they’re truly familiar. We use them all the time on macOS, Linux, and in general.
00:18:14.640
Getting documentation for command line apps is also really easy; we all know how to do management help, which should spit out something useful.
00:18:22.760
Of course, passing options is part of basic functionality, so special cases become very easy.
00:18:35.440
That’s the Unix way: a tool that does one thing and does it well.
00:18:51.680
Unix is awesome because we all want to embody that strong tradition, and we also have to acknowledge those who pioneered these ideas.
00:19:06.560
There’s a book called 'Build Awesome Command Line Applications in Ruby.' I highly recommend reading it if you want a crash course on what goes into command line applications.
00:19:17.280
In the book, the author describes at a high level what makes a good command line app. Command line apps should be easy to use.
00:19:30.240
They need to be helpful too—if you manage to invoke help, it should spit out something useful to understand how it works.
00:19:45.120
They should play well with others; they should be part of the Unix ecosystem, allowing you to redirect their input and output and do all those kinds of standard activities.
00:19:57.600
Command line apps should also just work—they should have sensible defaults for both options and arguments.
00:20:05.040
You should be able to configure your command line app, and that configuration should be simple.
00:20:18.000
Of course, it should also be easy to distribute, test, and maintain.
00:20:32.240
If you think about it, Rake doesn’t measure up too well against these high-level ideas, which is great for me because I get to come to Austin and present here.
00:20:48.960
But in general, it’s not so great for the community because we create command line frameworks that could check all those boxes.
00:21:02.720
There are already many different command line frameworks in the Ruby world that can tick most of the above boxes, like I mentioned before.
00:21:17.120
Most of these frameworks provide a DSL for building command line apps and some support for configuration.
00:21:30.560
This makes apps built with those frameworks pretty easy to use, write, and maintain. But why are those frameworks still relatively niche?
00:21:43.120
Well, standalone command line apps are not the only context where we want to script things. We want to be able to write apps and suites.
00:21:54.000
But we also want to write good scripts for our websites, so we want those scripting frameworks to support multiple environments.
00:22:03.360
This also means the configuration for our app should support multiple environments.
00:22:16.000
And speaking of configuration, we sometimes run for machine configuration and per-user configuration as well.
00:22:29.360
Often when we mix all of these, none of the frameworks I mentioned above have support for that stuff.
00:22:41.760
Let’s look more deeply at the features that a hypothetical command line framework needs to provide.
00:22:52.800
A nice DSA is a good start, but we have to consider our Ruby design as well.
00:23:05.200
We want straightforward, readable syntax that integrates seamlessly with Ruby without losing Rubyishness.
00:23:18.720
An example of this seems reasonable. But if you want to write specs for the actual functionality, there’s no nice way to look into it using existing tools.
00:23:29.920
So what do I do if I want to refactor? What guidelines do I follow? This isn’t just something that looks like Ruby but tries hard to imitate it.
00:23:40.720
On the other hand, this looks just like a regular class. It’s very similar to the previous example, but if I want to write some specs of the functionality and execute a method, it’ll be much simpler.
00:23:55.840
And I can easily imagine how I would be able to break apart these classes for refactoring purposes and also to compose them.
00:24:02.560
There’s still an element of DSL here, but let’s just work with Ruby and give it a little extra.
00:24:14.040
And less documentation! We’re all used to seeing something like this.
00:24:23.280
Any app built with a framework should be able to produce documentation automatically. This is practically infinitely more documentation than we would get from Rake.
00:24:34.960
And then there’s environment awareness! Why doesn’t every framework have that support already?
00:24:48.000
In web programming, it’s something we do all the time. So if my app is called Block, I shouldn’t have to build boilerplate for this over and over.
00:25:02.880
Multiple levels of configuration would be great: machine level, user level, project level. But that configuration needs to be environment-aware.
00:25:14.560
For example, if your configuration is in JSON format, you want to use a structure like this.
00:25:28.320
Or alternatively, you might break things up into separate files per environment, just like Rails.
00:25:42.400
Having the capability for configuration files to be environment-aware is crucial.
00:26:00.480
Another feature: I want to be able to build simple command line apps and complete command line apps! But I also want validation for my options and for my arguments.
00:26:15.520
A lot of frameworks out there come with option validation but not with argument validation. It’s still user input—we need to validate it!
00:26:30.080
Things like option conflicts and required options are useful.
00:26:43.120
OptionParser simply is not good enough! There are far too many limitations that stand in our way.
00:26:55.680
Now, we also want elements embedded that support us in creating good design.
00:27:10.160
Separation of concerns should be something we do instinctively.
00:27:22.960
There were sensible ways to structure our app; opinionated software is awesome. Like I mentioned before, Rails gives us structure for our web applications.
00:27:37.920
A command line framework should give a similar structure for command line applications, but it should definitely be opinionated.
00:27:52.160
We want to make writing specs for our command line apps easy; we don’t want it to be hard because otherwise, we simply won’t do it.
00:28:05.600
There’s just no good reason for the logic of your DSL to make it hard to write specs!
00:28:19.520
Encouragement for modular design over monolithic design should be the goal.
00:28:28.720
And if all this wasn’t enough, just wait—there’s more!
00:28:42.320
Your command line framework should come with ignorance built into it, or at least with things that we can gradually improve over time.
00:28:55.040
Aspect is a really good example of this—this stack is full of items that have become standard in the aspect over time.
00:29:08.720
We need to think about what should go into a well-designed app built using our hypothetical framework.
00:29:19.680
It’s nice when you don't have to wait for your command line app to start up before you can do stuff.
00:29:33.600
This is very important because if you’re writing a script for Rails, you might want to load the Rails environment, and we all know how fast that can be.
00:29:44.600
But this is something to strive toward; we want to be as fast as possible!
00:29:57.760
Initialize the support Rails has if you’ve ever built a significant Sinatra app.
00:30:09.760
It’s useful. Even if we’re writing a command line app, we might still be using other gems.
00:30:20.400
We might want to use Twitter and pass an API key from the command line to configure our Twitter gem so we can initialize it.
00:30:32.080
We want our apps to have more output or less as needed.
00:30:45.440
And then, of course, the framework itself should be well-designed so that people can come in, read it, and contribute.
00:30:57.440
Good luck with documentation and examples, because we always fail that one!
00:31:08.720
Lastly, we want an awesome name. Because it’s a Ruby thing, I vote for an acronym that isn’t used by anything!
00:31:21.520
It’s hard to find an acronym that makes sense. And if you say the full name out loud, it’ll make everyone laugh!
00:31:33.760
That’s a lot of features—Rake is familiar and ubiquitous.
00:31:43.440
If a framework wants to compete, it needs to offer a lot of stuff out of the box. More importantly, there shouldn't be too many situations where you can’t do something.
00:31:56.520
Because Rake is so unopinionated, you can always hook it in one way or another.
00:32:07.520
We want first-time users to go, 'Wow!' just like the first time at a Rails block presentation that DHH did.
00:32:18.720
Because that gives the project real momentum! In fact, there’s already confusion: Can you have command line apps?
00:32:32.320
We have Rake, maybe Migraine, but we also have Rails generating migrations.
00:32:46.440
What is Rails generated migration? Well, it’s just a command line! From another perspective, it’s a command line suite.
00:32:59.920
So why not instead make it more cohesive? If I have a Rails app called Food, I want to be able to do this: 'Food generate migration'.
00:33:15.280
That would be my rake, and anything else I can think of—and that would be really, really nice!
00:33:29.520
So, what kind of developer would I be if all I did was theorize about this stuff? I rolled up my sleeves and tried to make my thoughts a reality.
00:33:46.000
Of course, at the time, my thoughts weren’t as well-formed and opinionated, but we’ll come back to that.
00:34:00.320
I built a command line framework and called it Escort, which turns out to be really unfortunate.
00:34:19.840
Because if you Google it, you can imagine what comes up on the first page—and that’s not my framework!
00:34:32.880
This is not the only unfortunate name in the Ruby world. We also have gems like this one. The popular stream of discussions is called 'Rails Three Way'.
00:34:45.280
I mean, I wonder how many of those conversations were about the ending process, when they released the Rails Four Way.
00:35:02.560
This even makes me feel a little bit less depressed about my own naming choices!
00:35:10.560
I’m not the only one. Escort, as I pointed out, my thoughts weren't as developed back then.
00:35:19.680
Unfortunately, Escort ended up with most of the same issues that we talked about earlier—it hit some of the notes but completely missed others.
00:35:30.480
It was just good enough that I’ve been able to use it a lot for many different apps across two jobs.
00:35:44.240
This is how I arrived at my wish list of what a great command line framework should be.
00:35:56.320
Maybe I can find something nicer one day, but right now, Rake is still king.
00:36:08.160
But here’s the thing: it’s fun using your own gems to see how other people use them.
00:36:15.760
You get to see just how thick your documentation is and which pieces were less than awesome!
00:36:27.520
Trust me, it will be like this; one point, a friend said it would be great if Escort had a simple example.
00:36:37.520
So people could get the gist of how it works at a glance. And I was puzzled, because right there, it's there!
00:36:47.760
Another time, there was some major confusion about how our configuration works and I was once again puzzled!
00:36:55.520
I told them, 'Look, what do you mean? Because it's right there! It’s in two places!' I mean, all you had to do was look!
00:37:09.120
I spent hours writing the documentation—why won’t anybody read it? What’s the point of writing it if it’s just ignored?
00:37:20.280
The point is, it doesn’t matter what you think; what matters is how other people use it.
00:37:37.679
Even if you think things are obvious, if people can’t or won’t find it, that’s really valuable feedback.
00:37:50.720
The feedback you get from having your users right there is absolutely amazing; this is how I compiled the list of features that a command line framework really needs.
00:38:06.280
While I’m on this subject, here are a few thoughts about open source and the people who do it.
00:38:17.600
If you ever meet somebody who does open source—even if you actually hate what they do—shake their hand and say thanks.
00:38:28.480
Because open source is really hard; it takes up a lot of time.
00:38:39.120
Having said that, lots of open source code is really poor quality because open sourcing is tough—it takes a lot of time.
00:38:54.080
So you kind of choose between code that works and code that’s nice—it's an unhappy medium, and also, documentation is tedious.
00:39:07.440
But no one will use your project if you don't have it, so here's the general lesson.
00:39:20.080
I don’t expect everybody to stop using Rake tomorrow.
00:39:32.240
But hopefully, every time you run a Rake task, it’ll make you think a little. Because great change begins with a single step.
00:39:46.160
Hopefully, a single presentation in this case will inspire that change.
00:40:00.800
Consider writing some command line apps—they're easy, fun, and very Unix-like!
00:40:12.080
Maybe try Escort—it’s decent! But if you don't want to try that and really love Rake's syntax, try Thor!
00:40:19.840
Because Thor was written by this nice little guy, and can't read any code at all because it has no opposable thumbs.
00:40:27.760
What I mean is you can try something like Glee, because it was written by the guy who wrote this book.
00:40:34.680
So when people ask you about it, you can say, 'I’m using a tool written by a guy who literally wrote the book on command line apps.' That’s kind of cool!
00:40:45.520
Ultimately, I think it’s important to always question the established way.
00:40:56.960
Just as a language needs to keep evolving and moving forward, so does the community and ecosystem.
00:41:09.920
We are so fast-paced, and we need to take the next step.
00:41:25.280
If you think about it, at one point, this guy had a thought—and he still might question how to make web development better.
00:41:39.680
In any case, we got Rake! We took a step forward as a community, and in fact, the whole software world took a step forward.
00:41:52.200
Even before that, this guy had a thought, and his thought might have been asking if the world could be less complicated.
00:42:05.600
And if those steps hadn’t happened, we wouldn’t be here right now.
00:42:18.040
And that’s what I have to say. Thank you!