Author Archives: Jason Swett

How to get traffic for a technical blog

Have a Focus

Many technical blogs are just a mixed bag of peripheral tips and tricks. A developer will fix a problem, then toss up a short post on how he or she fixed it.

The weakness of this random-topic approach is that it doesn’t lend itself to building an audience. Just because I’m interested in one random tip on your site doesn’t mean I’ll necessarily be interested in any of the other random tips you offer.

What’s better is to build your site around a single focus. When I built AngularOnRails.com I decided to talk about Angular/Rails applications and nothing else. This means that if you’re building an Angular/Rails app you’re likely to find the majority of my AngularOnRails.com posts interesting.

Target Long-Tail Keywords

Long-tail keywords are long, specific queries like white 1995 porsche 911.

The opposite of a long-tail keyword is a “head” keyword. An example of a head keyword would be something like porsche or just car.

Long-tail keywords have two benefits. First, long-tail keywords tend to be easier to rank for because there’s less competition. I imagine that if I were to put up a page with the title of “White 1995 Porsche 911”, I’d have a much higher chance of attracting some search traffic than if I were to put up a page simply titled “Car”.

Second, long-tail keywords are more intent-revealing. If a person googles car, who knows what the searcher is after. Do they want to learn about the history of cars? Do they want to buy a car? What kind of car? On the other hand, if someone googles white 1995 porsche 911, we have a better idea of what the person wants. They probably either want to buy one or they want some desktop wallpaper. At the very least, we would have an idea of what to talk about on our page.

This is why on AngularOnRails.com I would go after very specific keywords like angular rails heroku or angular cli webpack heroku, both of which I managed to rank #1 for.

This brings me to my next suggestion which has to do with coming up with keywords in the first place.

Exploit Intersections

Angular is backed by Google. Google has an incentive to produce documentation for Angular. Ruby on Rails is backed by Basecamp. Basecamp has an incentive to produce documentation for Rails.

But no single entity has a very strong incentive to produce documentation for the Angular + Rails combination. That’s why there’s a gap. That’s why, in 2018, there still aren’t a heck of a lot of great resources out there for Angular + Rails.

This fact—that big companies tend not to have an incentive to document combinations of technologies—translates to an opportunity for someone who wants to build a high-traffic blog. Since there’s very little (for example) Angular + Rails documentation out there, the bar is low to create the best Angular + Rails documentation in the world. This low bar is what allowed little old me to attract a fairly consistent 3,000-5,000 unique visits a month on a site that had just a handful of posts.

There are certainly many more underdocumented combinations of technologies than combinations that are sufficiently covered. And as new technologies emerge, new combinations are possible—combinations that could really benefit from some documentation.

There are a lot of possible intersections to cover. Here are some ideas off the top of my head:

Obviously a person could brainstorm a much bigger list than this. I googled each combination above and discovered that only one of the above combinations has a website 100% dedicated to it: my own AngularOnRails.com. So if you want to take advantage of the document-a-combination idea, the world is your oyster. Just make sure to pick a combination that has a high ratio of popularity to existing documentation. You don’t want to dedicate years of your life documenting a combination of technologies only used by 8 people worldwide.

Don’t Code Your Own Platform

You want to invest your time in building your blog, not building the platform that runs your blog. You shouldn’t build your own blogging platform for the same reason a carpenter shouldn’t forge his own hammers.

I use WordPress for all my blog sites even though I hate WordPress. The advantage with WP is that since 25% of the web uses it all the common features I’ll need are pretty well-worn paths. Themes, contact forms, SEO tools, content management—it’s all available.

I really don’t like the way most things work in WP but it’s less bad than the alternative of building it all myself, which I’ve tried. I’m not optimizing for a good user experience for myself. I’m optimizing for getting a successful blog off the ground in a reasonably short period of time.

Use Analytics Tools

Google Analytics

Obviously it’s nice to know how many people are visiting your blog each day/week/month. Aside from that, one of the main things I use Google Analytics for is to tell me what my most popular posts are:

This tells me what’s working and what’s not. Once I see what’s working I can double down on those topics in order to get more traffic. The topics that don’t get traction I can stop writing about.

Google Search Console

Google Search Console tells me what keywords I’m ranking for, what my rank is, and how many people are clicking. Below is a snapshot of the last 90 days for AngularOnRails.com.

Most of the top keywords are some variation of angular rails. It’s nice to see that those keywords are doing well but it’s not very useful information. The question I want to answer is, “What do I write about next in order to get more traffic?” I’m going for long-tail keywords to minimize the pool of people I’m competing with.

I do see a couple keywords mentioning test coverage, so that’s a candidate. Perhaps more broadly, I could talk about Angular testing and go deep into specific testing topics, topics that would lend themselves well to long-tail keywords.

Studying analytics is just one way to help decide what to write next. In order to make intelligent decisions I also ask myself:

  • What have I personally found to be lacking online? What documentation do I personally wish existed?
  • What have my readers been asking me to write about?

Crazy Egg

Crazy Egg lets me see where people are clicking on any page of my site. Are they clicking where I want them to click or somewhere else? If people aren’t giving attention to the parts of the page I consider important, it means I need to do a better job of structuring the page.

Build an Email List

An email list is a way for you to keep in touch with the people who are interested in the topics you write about.

From the other direction, an email list is a way for people who like you to be able to hear from you every time you have something to say.

Without an email list this type of ongoing relationship would be difficult. Your readers would have to remember to periodically check your site to see if there’s anything new.

Having an email list won’t directly help your search rankings but it’s so important that I wanted to mention it here. Presumably the reason you’re putting a bunch of work into your technical blog is because you eventually want to sell something, either literally or figuratively. You might want to sell:

  • Ebooks
  • Courses
  • Consulting services
  • The idea that the reader should work at your company
  • A philosophical idea (e.g. “pair programming increases productivity”)

Whatever you’re selling, it’s much easier to sell to someone with whom you have a relationship than it is to sell to a stranger. Regularly communicating with someone over email (which, unlike social media, is one-to-one and private) is a very effective way to build that relationship over time.

And again, this isn’t just about advancing your business agenda. It’s also good for readers who want to hear from you every time you have something to say.

Create an Authority Piece

Google’s main ranking factor is the quantity and quality of links pointing at your site.

If you want to get links, create content that people will want to link to. That advice might sound overly obvious but for me it was really helpful to get into that mindset. Whenever I think of writing something I ask myself, “Will this be so good that people will want to share it?” Often the answer is no. In those cases I scrap the idea and move onto a new one.

I’ve noticed that big, long, definitive resources tend to get shared and linked to a lot more than brief, thin posts.

A good example of one of these big long resources would be Michael Hartl’s Ruby on Rails tutorial. I can’t count how many times over the years I’ve pointed people to this tutorial as the best starting point for Ruby on Rails that I know of.

Another resource I’ve personally shared a lot of times is Brennan Dunn’s Double Your Freelancing Rate. This product started out as an ebook and has morphed into a course.

I wouldn’t be sharing these things if they were just 500-word listicles. These are hefty resources that have the potential to seriously help the reader.

This is what I mean when I say “Authority Piece”: some in-depth resource that demonstrates expertise on a particular topic by being incredibly helpful.

An Authority Piece could be an ebook, a print book, a publicly available online tutorial or a paid course. A blog itself can even serve as an Authority Piece. But the technique I’m describing here is that of putting an Authority Piece on your blog.

For me, my biggest authority piece on AngularOnRails.com is my ebook, Angular for Rails Developers. After that it would probably be my Get Started with Angular 4 and Rails 5 tutorial (which I’ve now moved to CodeWithJason.com).

My Authority Pieces aren’t major ones. My ebook started out at fewer than 50 pages. My “Get Started” tutorial isn’t that long. It doesn’t always take a grand effort to put together something worth sharing, especially if you employ the “Exploit an Intersection” tactic to play in an area where very few people are competing.

Plug Into Other People’s Audiences

I’ve learned that one of the fastest ways to build traffic is to plug into someone else’s existing audience.

One of the biggest traffic sources for AngularOnRails.com is GitHub. Someone created an issue on the Angular CLI project asking about deployment. I had written a post about Angular CLI deployment so I wrote a comment on that issue with a link to the post. People appreciated the link since it was helpful and relevant. That and a couple other similar links have been big traffic contributors for me.

I was also able to send traffic to AngularOnRails.com by being a panelist on Ruby Rogues. Ruby Rogues has a large listener base. Listeners got to know who I was and found out about my website. We also did a whole episode just about Angular and Rails which definitely drove a lot of traffic.

Podcasts are probably among the best ways to drive traffic and earn links. Podcast interviews are relatively easy to get. A link is nearly guaranteed. As a bonus, the act of hearing someone’s voice is a much stronger and faster relationship-builder than just seeing someone’s written text. When you hear someone’s voice on a podcast repeatedly over time, you start to feel like you know the person.

If you want to guest on podcasts I would recommend that you find a podcast guest similar to yourself, then find out what podcasts he or she has guested on, then reach out to those podcasts for an interview.

There’s also the tactic of guest posting. I understand that Google doesn’t necessarily view guest posting in the most favorable light, so guest posting might not bring a ton of direct SEO benefit, but in the right circumstances it might help drive substantial traffic.

How to Deploy a Rails Application with an Angular CLI Webpack Front-End

I’ve written previously about how to deploy an Angular CLI Webpack project without Rails.

I’ve also written about how to deploy an Angular 2/Rails 5 project, but not one that uses Angular CLI Webpack.

Following are instructions for deploying a Rails 5 app with an Angular 2 front-end that was generated with Angular CLI, Webpack version. (Specifically, Angular CLI version 1.0.0-beta.11-webpack.8.)

Create the Rails App

First, create an API-only Rails application.

Create the Angular App

Before you create the Angular app, make sure you have the following versions of the following things installed:

Angular CLI: 1.0.0-beta.11-webpack.8
NPM: 3.10.6
Node: 6.5.0

Then, just like I had us do in the Angular-only version of this post, we’ll create an Angular app with the silly name of bananas.

In this case it’s important that we call the Angular directory client. Don’t worry about why right now. I’ll explain shortly.

$ ng new bananas
$ mv bananas client

And also just like in the Angular-only version, we’ll want to make sure we can run ng-build without problems.

$ cd client
$ ng build

If you try it and it doesn’t work (which is very likely), just refer to the other post for how to fix it.

Modify package.json

We need to do a few things to package.json. Don’t worry if you don’t understand every item. I’ve shared my package.json below which you can just copy and paste if you want.

We want Heroku to do an ng build for us after the build. So we need to add this line:

"heroku-postbuild": "ng build",

We also need to move our devDependencies into dependencies because we need some of them in production.

We’ll want to remove the "start": "ng serve" script because it doesn’t apply.

Lastly, an absence of node-gyp will cause error messages to appear. So we’ll add this line:

"preinstall": "npm install -g node-gyp",

Following is what my package.json looks like.

{
  "name": "bananas",
  "version": "0.0.0",
  "license": "MIT",
  "angular-cli": {},
  "scripts": {
    "lint": "tslint \"src/**/*.ts\"",
    "test": "ng test",
    "pree2e": "webdriver-manager update",
    "e2e": "protractor",
    "preinstall": "npm install -g node-gyp",
    "heroku-postbuild": "ng build"
  },
  "private": true,
  "dependencies": {
    "@angular/common": "2.0.0-rc.5",
    "@angular/compiler": "2.0.0-rc.5",
    "@angular/core": "2.0.0-rc.5",
    "@angular/forms": "0.3.0",
    "@angular/http": "2.0.0-rc.5",
    "@angular/platform-browser": "2.0.0-rc.5",
    "@angular/platform-browser-dynamic": "2.0.0-rc.5",
    "@angular/router": "3.0.0-rc.1",
    "core-js": "^2.4.0",
    "rxjs": "5.0.0-beta.11",
    "ts-helpers": "^1.1.1",
    "zone.js": "0.6.12",
    "@types/jasmine": "^2.2.30",
    "angular-cli": "1.0.0-beta.11-webpack.8",
    "codelyzer": "~0.0.26",
    "jasmine-core": "2.4.1",
    "jasmine-spec-reporter": "2.5.0",
    "karma": "0.13.22",
    "karma-chrome-launcher": "0.2.3",
    "karma-jasmine": "0.3.8",
    "karma-remap-istanbul": "^0.2.1",
    "protractor": "4.0.3",
    "ts-node": "1.2.1",
    "tslint": "3.13.0",
    "typescript": "2.0.0"
  },
  "devDependencies": {
  }
}

Create public symlink

When someone visits /index.html in the browser, the file they’ll actually be served is Rails’ public/index.html. We can do a little trick where we symlink the public directory to client/dist. That way when someone visits /index.html they’ll be served client/dist/index.html, thus loading the Angular app.

Let’s kill the public directory and replace it with a symlink.

$ rm -rf public
$ ln -s client/dist public

Create the Heroku app

I’m assuming you have a Heroku account and you have Heroku CLI installed.

$ heroku create

Specify the buildpacks

Lastly, we’ll tell Heroku to use two certain buildpacks:

$ heroku buildpacks:add https://github.com/jasonswett/heroku-buildpack-nodejs
$ heroku buildpacks:add heroku/ruby

Remember when I said we needed to call our Angular directory client? The reason is because of my custom Node buildpack. I’ve modified Heroku’s Node buildpack to look for package.json in client rather than at the root. This is what allows us to nest an Angular app inside of a Rails app and still have Heroku do what it needs to do with each.

Deploy the app

Make sure your code is all committed and do a git push.

$ git push heroku master

When it’s done, open the app. You should see “app works!”.

$ heroku open

If you want, I have a full repo with the code used in this example.

How to Deploy an AngularJS/Rails Single-Page Application to Heroku

Note: this post is somewhat aged. You may be interested to check out the Rails 5/Angular 2 version, which still applies somewhat to Rails 4/Angular 1.x.

Why deploying a single-page application is different

Before I explain how to deploy an Angular/Rails application to Heroku, it might make sense to explain why deploying a single-page application (SPA) is different from deploying a “traditional” web application.

The way I chose to structure the SPA in this example is to have all the client-side code a) outside Rails’ the asset pipeline and b) inside the same Git repo as Rails. I have a directory called client that sits at the top level of my project directory.

Gemfile
Gemfile.lock
README.rdoc
Rakefile
app
bin
client <-- This is where all the client-side code lives.
config
config.ru
db
lib
log
node_modules
spec
test
tmp
vendor

When I’m in development mode, I use Grunt to spin up a) a Rails server, which simply powers an API, and b) a client-side server.

In production the arrangement is a little different. In preparation for deployment, the grunt build command poops out a version of my client-side app into public. Rails will of course check for a file at public/index.html and, if one exists, serve that as the default page. In fact, if you run grunt build locally, spin up a development server and navigate to http://localhost:3000, you’ll see your SPA served there.

But it would be pretty tedious to have to manually run grunt build before each deployment. And even if you somehow automated that process so grunt build was run before each git push heroku master, it wouldn’t be ideal to check all the code generated by grunt build into version control.

Heroku’s deployments are Git-based. The version of my client-side app that gets served will never be checked into Git. This is the challenge.

Automatically building the client-side app on deployment

Fortunately, there is a way to tell Heroku to run grunt build after each deployment.

First let’s get grunt build functioning locally so you can see how it works.

Change the line dist: 'dist' to dist: '../public' under the var appConfig section of client/Gruntfile.js. For me this is found on line 19.

Now remove the public directory from the filesystem and from version control. (Add public to .gitignore is not necessary.)

$ rm -rf public

If you now run grunt build, you’ll see the public directory populated with files. This is what we want to have happen in production each time we deploy our app.

Configuring the buildpacks

Next you’ll want to add a file at the root level of your project called .buildpacks that uses both Ruby and Node buildpacks:

https://github.com/jasonswett/heroku-buildpack-nodejs-grunt-compass
https://github.com/heroku/heroku-buildpack-ruby.git

You can see that I have my own fork of the Node buildpack.

In order to deploy this you might need to adjust your client/package.json and move all your devDependencies to just regular dependencies. I had to do this. Here’s my client/package.json:

// client/package.json

{
  "name": "lunchhub",
  "version": "0.0.0",
  "description": "The website you can literally eat.",
  "dependencies": {
    "source-map": "^0.1.37",
    "load-grunt-tasks": "^0.6.0",
    "time-grunt": "^0.3.1",
    "grunt": "^0.4.1",
    "grunt-autoprefixer": "^0.7.3",
    "grunt-concurrent": "^0.5.0",
    "grunt-connect-proxy": "^0.1.10",
    "grunt-contrib-clean": "^0.5.0",
    "grunt-contrib-compass": "^0.7.2",
    "grunt-contrib-concat": "^0.4.0",
    "grunt-contrib-connect": "^0.7.1",
    "grunt-contrib-copy": "^0.5.0",
    "grunt-contrib-cssmin": "^0.9.0",
    "grunt-contrib-htmlmin": "^0.3.0",
    "grunt-contrib-imagemin": "^0.7.0",
    "grunt-contrib-jshint": "^0.10.0",
    "grunt-contrib-uglify": "^0.4.0",
    "grunt-contrib-watch": "^0.6.1",
    "grunt-filerev": "^0.2.1",
    "grunt-google-cdn": "^0.4.0",
    "grunt-newer": "^0.7.0",
    "grunt-ngmin": "^0.0.3",
    "grunt-protractor-runner": "^1.1.0",
    "grunt-rails-server": "^0.1.0",
    "grunt-shell-spawn": "^0.3.0",
    "grunt-svgmin": "^0.4.0",
    "grunt-usemin": "^2.1.1",
    "grunt-wiredep": "^1.7.0",
    "jshint-stylish": "^0.2.0"
  },
  "engines": {
    "node": ">=0.10.0"
  },
  "scripts": {
    "test": "grunt test"
  }
}

I also registered a new task in my Gruntfile:

// client/Gruntfile.js

grunt.registerTask('heroku:production', 'build');

You can just put this near the bottom of the file next to all your other task registrations.

And since the Node buildpack will be using $NODE_ENV when it runs its commands, you need to specify the value of $NODE_ENV:

$ heroku config:set NODE_ENV=production

Lastly, tell Heroku about your custom buildpack (thanks to Sarah Vessels for catching this):

$ heroku config:add BUILDPACK_URL=https://github.com/ddollar/heroku-buildpack-multi.git

After you have all that stuff in place, you should be able to do a regular git push to Heroku and have your SPA totally work.

How to Change Your WordPress Site’s Title Attribute, Site-Wide, Using the Yoast SEO Plugin

  1. If you haven’t already done do, install the Yoast SEO Plugin.
  2. In your website’s admin area, find the SEO menu item on the left. (It should be near the bottom, below Settings.) Hover over the SEO menu item (or click on it) and then click the Titles & Metas submenu item.
  3. Click the Post Types tab. Note that there are three sets of fields here: one for Posts, one for Pages and one for Media. You’re probably interested in Posts and Pages.
  4. Under the Posts section, notice that the Title template field will probably say something like %%title%% %%page%% %%sep%% %%sitename%%. This might look kind of crazy and confusing to you, so I’ll give you an example of what this might work out to. If your company is called Ben Franklin Labs and the visitor is viewing, say, your About page, the title might work out to this: “About | Ben Franklin Labs.” That cryptic %%sep%% stands for separator and the default appears to be “|” (called a pipe character). In the next step we’ll change the title from something like “About | Ben Franklin Labs” to “About | Grand Rapids Web Design and Web Development | Ben Franklin Labs.”
  5. For my example, I chose to add “Grand Rapids Web Design and Web Development” because those are terms I’d like my entire site to rank for in Google, and because Ben Franklin Labs actually is a web design/development company. If you’re, say, a wedding photographer, you might like to use “[Your Town] Wedding Photographer.” Once you’ve decided what phrase you’d like to insert into your title, change the Title template field under the Posts section from %%title%% %%page%% %%sep%% %%sitename%% to %%title%% %%page%% %%sep%% <strong>Your Phrase Here %%sep%%</strong> %%sitename%%. (I made the new part bold.)
  6. Repeat step 5 for the Pages section.
  7. Verify that your changes worked by viewing at least one blog post and at least one page. Your new phrase should appear in the title attribute for both.

Where to put Rails modules

The TL;DR answer

You can put any module in /lib as long as you have autoloading set up properly.

The more nuanced answer

The truth is that you can put your modules anywhere. Personally, my main use for modules is to create namespaces for my Active Record models to help keep things organized. Those module definitions just end up in the same files as my Active Record models.

I have kind of a rule for myself when it comes to Rails file organization. My Rails apps tend to be structures as a mix of Active Record objects and Plain Old Ruby Objects (POROs). The rule is:

If a particular model class (whether it’s an Active Record model class or a PORO model class) pertains specifically to my application, it goes in app/models. If the model class has nothing specifically to do with my application (e.g. it’s a utility class that could conceivably be open-sourced and used in any application), it goes in lib.

How to set up autoloading for modules located in /lib

Modify your config/application.rb to include the following line.

# config/application.rb

module MyApp
  class Application < Rails::Application
    config.eager_load_paths += %W(#{config.root}/lib)
  end
end

Restart your Rails server and you should be good to go.

How to define and include a module

You can define a module like this:

# /lib/foo.rb

module Foo
  def hello
    "hello"
  end
end

When you include that module in a class, you can use the hello function in the class from which you included the module. See the below for how you would use this Foo module.

How to use a module in an ActiveRecord model

You can include a module in a class in your Rails project by using the include keyword followed by the name of your module.

# app/models/customer.rb

class Customer < ActiveRecord::Base
  include Foo
end

Now you should be able to do Customer.new.hello and get “hello” as a result.

Further reading

If you’d like to know more of my thoughts on structuring Rails applications, I’d recommend the following posts.

Extracting a tidy PORO from a messy Active Record model
For organizing Rails projects, domain objects are good and service objects are bad

How to Delete an Item From a List in AngularJS

I had a real bear of a time figuring out how to remove an item from a list in AngularJS. I found the solution in this Stack Overflow answer which I’m simply stealing and pasting here on my blog:

$scope.flumps.splice($scope.flumps.indexOf($scope.flump), 1);

So I guess you just have to do it with plain old JavaScript.

If you’re interested in seeing how you might update the server side as well, here’s an example for that:

Flump.delete({ id: $scope.flump.id }, function() {
  $scope.flumps.splice($scope.flumps.indexOf($scope.flump), 1);
});

 

Variable name anti-patterns

Overabbreviation

Bad examples:
passwd
fname
cust
o

Good examples:
password
first_name
customer
order

Explanation: Abbreviations like passwd violate the Principle of Least Astonishment. If I know a class has a password attribute I should be able to guess that that attribute is called `password`. Since `passwd` is pretty much totally arbitrary, it’s a practically unguessable. Plus, how valuable is it to save two keystrokes?

I have a saying: It’s better to save time thinking than to save time typing.

Exception: Abbreviations are fine when they match up with real-world abbreviations. For example, SSN, USA and admin are all fine because these are predictable and already familiar to most people.

Naming Scalars Like Objects

Bad example:
store = "Jason's Capsaicin Station"

Good example:
store_name = "Jason's Capsaicin Station"

Explanation: If I see a variable name like store, I think it’s an object. This problem becomes especially severe when the codebase does in fact have a class called Store and some stores are instances of that class and some stores are just store names.

Naming Counts Like Collections

Bad example:
products = 0

Good example:
product_count = 0

Explanation: If I see a variable called products I would probably expect its value to be a collection of some sort. I would be surprised when I tried to iterate over the collection only to discover that it’s actually an integer.

Naming a Variable After Its Type

Bad example:
array = []

Good example:
customers = []

Explanation: A variable called array or hash could contain pretty much anything. By choosing a name like this you’re forcing the reader to do all the thinking.

Use of Mass Nouns For Collections

Bad examples:
news[0]
inventory[0]

Good examples:
articles[0]
inventory_items[0]

Explanation: There are certain words that have no singular form. Examples include “stuff”, “garbage” and “laundry”. This anti-pattern especially applies to database table names.

Key/Value Mystery

Bad examples:
products.each { |key, value| puts value }
products.each { |k, v| puts v }

Good example:
products.each { |name, price| puts price }

Explanation: Names like key and value have almost no meaning. There’s almost always a more purpose-revealing option.

For Programming, Is College Worth It?

Today a friend of mine asked me if I had any advice for a cousin of his. My friend’s cousin is about to graduate high school and wants to get into programming work.

Here are my thoughts on how to think about the college/no college decision.

Right Choice vs. Wrong Choice Mentality

Most people seem to view the college-or-not question as a matter of what’s the “right” choice. I think right vs. wrong choice might be a false dichotomy. Neither one is right or wrong, it’s just a matter of what kind of experience you want to have. You can reach your ultimate destination—a programming job—via either path.

Let’s examine the pros and cons of the college route and no-college route.

Pros and Cons of Going to College

I went to college on and off from 2002 to 2007. For me the biggest benefit was unquestionably the social experience.

The best thing about college is being surrounded with a bunch of people who are all at the same stage of the same journey, and being in that situation without “adult supervision” for the first time.

Meeting people at work is usually not nearly the same as meeting people in college. As I’ve gotten older my social circle has shrunk. My free time for socialization has shrunk. My opportunities for meeting like-minded new people have diminished down to almost nothing. College is an opportunity to meet people who will become the closest friends you’ll ever meet. After college, for most people, that opportunity goes away.

One big con of going to college is of course the cost. If you’re not lucky enough to have outside help you’ll be paying student loan bills for a long time after you graduate.

A pro of going to college is that it can of course open up career opportunities. The quality and quantity of these opportunities depends on certain things like how good of a school you go to and how well you network during college.

There are a large number of programming jobs that are equally available to degreeholders and non-degreeholders given enough work experience. I would say most programming jobs. Certain types of companies are more picky about degrees. Big companies and government organizations tend to want degrees.

I wish I had given more thought to where I went to college. My options were limited because my grades in high school were bad. I never cared about grades because I didn’t think about why they mattered.

I’ve learned over the years that going to a prestigious school like MIT or Harvard can have some really serious benefits later on. It’s not just that it impresses prospective employers when you tell them you went to a place like Harvard. It seems like the main benefit of going to a really good school is the network you develop there. You’re more likely to meet someone at an Ivy League school whose dad can give you a sweet job, for example, than if you go to some community college.

Pros and Cons of Being Self-Taught

I don’t know what it’s like to go down the path of a 100% self-taught programmer because although I didn’t complete my degree I did go to school for Computer Science for some years.

I would strongly suspect that you can start your career younger if you skip college. If you start trying really hard to get a programming job right after you graduate high school, it probably won’t take you a full four years to get your first programming job.

On the other hand you might always have a nagging feeling in the back of your mind that you should have gotten your degree. There’s a genuine social stigma around not having a degree. You might always wonder how things might have turned out differently, especially if your career turns out not to be anything that grand. I have personally experienced this sense of lack although it has gone away over time. At this point I’m 100% at peace with the fact that I don’t have a degree.

What Matters More Than a Degree

In college I had two friends who both majored in Political Science. When they graduated, one moved to Washington, D.C. for a job in government. The other got a job at a pizza place.

I know developers who have had boring, undistinguished careers at no-name companies. I know other developers who have written books, get interviewed on podcasts, and get paid to travel the world working for household names. What matters much more than a degree is the level of resourcefulness and ambition you apply to your career. It’s what you do during your programming career, not before it, that determines the arc of your career.

My Advice

What would I say if a high school senior asked me if I recommended going to college? I would say go. The social experience is worth it.

And if you’re going to go, might as well make the most of it. If I could go back in time and talk to my 12 year-old self I’d say this: You don’t want to be stuck in a crappy career your whole adult life. Study how to get into the best colleges so you open up as many career opportunities as you can. Try to get good grades. If you have to do all this stuff anyway you might as well get as much out of it as possible.