A Simple Slim REST API Service

In a recent post, I showed how to write an AngularJS CRUD application using Firebase as the backend. In this post, we’ll be setting up our own REST service using the PHP microframework Slim.

Couple of introductory notes: this application will require you to have a server and a database. There are plenty of options out there, but this post will assume you know how to set that up. If you need a starting point for this, I’d recommend xampp which ships with phpmyadmin for interacting with the databse. That said, here’s the beginning of our file structure. If you’re using xampp, put phpang in your htdocs. Then you can go to localhost/phpang in your browser to view this application.

phpang
|
+--api
|  \--index.php
|  \--composer.json
|  +--db
|    \config.php
+-- css
|  \-- bootstrap.min.css
|  \-- starter-template.css
+-- js
|  \-- app.js
|  +-- controllers
|    \-- ListController.js
|    \-- AddController.js
|    \-- EditController.js
+-- views
|   \-- add.html
|   \-- edit.html
|   \-- list.html
+-- index.html

Moving on, let’s take care of our dependencies. Put this in your composer.json.

{
    "require": {
        "slim/slim": "2.*",
        "vrana/notorm": "dev-master"
    },
    "autoload": {
        "classmap": [
            "vendor/vrana/notorm/"
        ]
    }
}

With this file in place, open your terminal in phpang/api and enter composer install. You should see a new folder under api called vendor with a bunch of files and directories. You’ve just installed Slim and NotORM, which we’ll be using to interact with the database. You also set up an autoloader classmap for both services.

There is a tool that is really useful when building APIs in the Chrome Web Store called Advanced REST client. We’ll be using that to test our API service as we go along.

Next, we’ll set up our database. Create a new database, which we’ll call phpang, then import this schema. This just sets up a table called products and puts in a few rows of data. Now we need to fill in config.php with this:

<?php
//DB Params
define("DSN", "mysql:host=localhost;dbname=YOUR_DB_NAME");
define("DB_USER", "YOUR_USERNAME");
define("DB_PASS", "YOUR_PASSWORD");

As you probably already noticed, you’ll need to adjust that to fit the name and credentials of your database.

Now that we have our file structure in place, our dependencies installed and some test data in our database, we’re ready to start building our API.

Open up api/index.php in your text editor. These first few lines will put all the work we just did to use:

<?php

/**
 * requires 
 */

require 'vendor/autoload.php';
require 'db/config.php';

/**
 * db stuff
 */

$pdo = new PDO(DSN, DB_USER, DB_PASS);
$db = new NotORM($pdo);

/**
 * Instantiate a Slim application
 */

$app = new \Slim\Slim();

$app->run();

The requires bring NotORM, Slim and our database credentials into our app. Then we set up a couple variables which we’ll be using frequently to get information in and out of our database. Next we officially instantiate a Slim application.

Quick background on what we’ll be doing next. In my previous post, we set up a CRUD application. The API equivalent verbs to Create, Read, Update and Delete are GET, PUT, POST, DELETE. The first thing we’ll be doing is setting up GET to retrieve all our products from the database. Put all the rest of the code before the line $app->run();.

// Route for GET on all products
$app->get(
    '/products',
    function () use ($app, $db) {
        $products = array();
        foreach ($db->products() as $product){
            $products[] = [
              'id' => $product['id'],
              'sku' => $product['sku'],
              'description' => $product['description'],
              'price' => $product['price']
              ];
        }
        $app->response()->header(
            "Content-Type", "application/json");
        echo json_encode($products, JSON_FORCE_OBJECT);
    }
);

These lines of code set up the route localhost/phpang/api/products. When a REST client sends a GET request to that URL, a response is sent back in JSON with the data from our database. In our next post, I’ll go through refactoring the code from our AngularJS CRUD application to use this API, but for now, we’ll just be using the Advanced REST client from the Chrome Webstore. In that app, there’s a place to enter the url that the client should be hitting. In our case, that’s http://localhost/phpang/api/products. Select the GET radio button and hit send. It should look something like this:

GET

As you can see, when your client sends a GET request to localhost/phpang/api/products, your service responds with JSON object of all the products in your database.

Next, let’s set up a route for getting a single product.

// Route for GET on product by id
$app->get(
    '/products/:id',
    function ($id) use ($app, $db) {
        $app->response()->header("Content-Type", "application/json");
        $product = $db->products()->where("id", $id);
        if ($product[$id]) {
            echo json_encode($product[$id], JSON_FORCE_OBJECT);
        } else {
            echo json_encode(array(
                "status" => false,
                "message" => "Product ID $id does not exist."
                ), JSON_FORCE_OBJECT);
       }
    }
);

Now, when you send a get request to products/2, for example, you’ll get back a JSON object of that particular product. This code first checks to make sure it exists in the database, then responds appropriately. To test out the error message, try going to http://localhost/phpang/api/products/88 and you should see:

FALSE

This looked for a product with id 88 and didn’t find it so it gave us this handy little error message.

We don’t have a whole lot of products in our database so let’s set up a way to add them through an API. Here’s our POST route:

// POST route
$app->post(
    '/products/post',
    function () use($app, $db) {
        $app->response()->header("Content-Type", "application/json");
        $post = $app->request()->post();
        $body = $app->request->getBody();
        $result = $db->products->insert(json_decode($body, true));
        echo json_encode($body);
    }
);

This allows us to send a JSON object to products/post which is then entered in our database. Test it out and make sure you see this:

POST

You should be able to send a GET request to /products and see your new product in the list.

The PUT route allows you to update products.

// PUT route
$app->put(
    '/products/:id',
    function ($id) use($app, $db) {
      $app->response()->header("Content-Type", "application/json");
      $product = $db->products()->where("id", $id);
      if ($product[$id]) {
        $post = $app->request()->put();
        $body = $app->request->getBody();
        $result = $product->update(json_decode($body, true));
        echo json_encode(array(
          "status" => (bool)$result,
          "message" => "Product updated successfully."), 
            JSON_FORCE_OBJECT);
      } else {
        echo json_encode(array(
          "status" => false,
          "message" => "Product ID $id does not exist."),               
              JSON_FORCE_OBJECT);
      }
    }
);

By now, this code should be looking pretty familiar. If the product exists in the database, we update it with the new information. If not, we return a message saying it doesn’t exist.

Finally, we have our DELETE functionality to put in place.

// DELETE route
$app->delete(
    '/products/:id',
    function ($id) use ($app, $db) {
        $app->response()->header("Content-Type", "application/json");
        $product = $db->products()->where("id", $id);
        if ($product[$id]) {
          $result = $product->delete();
          echo json_encode(array(
            "status" => true,
            "message" => "Product deleted successfully."), 
              JSON_FORCE_OBJECT);
        } else {
          echo json_encode(array(
            "status" => false,
            "message" => "Delete failed. Product ID $id does not exist."),
              JSON_FORCE_OBJECT);
        }
    }
);

You now have a REST service that can handle GET, PUT, POST, and DELETE requests. You can clone working copy of the code here. You’ll also find an AngularJS front-end which was modified from my last blog post to work with this API.

MicroAgressors Anonymous

Trigger warning: this is written by a cis, white, male in his late twenties who is in the top ~0.3% of wealthiest people globally.

I didn’t want to write that. It was cumbersome. I don’t want to read that by others. I don’t want to put the author in a box. That only makes my reading experience worse. The less I know about an author, the easier the content can be accepted. There’s a logical fallacy called ad hominem for just such an occasion. We don’t call people names like cis, white, or male in an attempt to disqualify their arguments. Humans judge. We tend to think a certain way about people that don’t have the same skin color as us or dress or act outside of our cultural norms. These micro-prejudices are enough that in order to do an idea justice, we have to put on a blindfold.

And that’s just for ideas. Martin Luther King looked to a day when we applied this not only to ideas, but to people as well.

I look to a day when people will not be judged by the color of their skin, but by the content of their character. - Martin Luther King

Nearly 50 years later, we are still looking.

If you’ve been on a college campus or tumblr or lots of other places on the internet, you may have heard of microaggressions. It’s a new term meaning unintended slights, insults, and small offences by the majority against the minority, white against black, man against woman, etc. Micro as they may be, people are up in arms. People are dropping tumblr posts, shooting out tweets, hunkering down in facebook status updates. The victims of microaggressions are publicizing them more loudly and more frequently. Microaggressions are causing a shift in power. But the cis, white, males aren’t going to just let their power go without… playing the victims themselves. In the words of Christ, “The meek shall inherit the earth.”

50 years ago, people were writing about segregated water fountains. Nowadays, people are writing about white people using the word futbol. Glass half-empty: we are still judging by the color of their skin, gender identity, and sexual preference and not the content of their character. Glass half-full: we can all use the same water fountain.

Further reading:

An AngularJS CRUD App with Firebase

Someone recently mentioned AngularJS in passing to me and for some reason, I thought I’d check it out. Codecademy has a course on it and includes a couple projects to try. It just made sense to me. This is a post on how to make a simple CRUD application using Firebase as the backend. We’ll be using some basic bootstrap to make it look tolerable.

First off, let’s set up our file structure like so, using empty files for now:

CRUD Project
|
+-- css
|  \-- bootstrap.min.css
|  \-- starter-template.css
+-- js
|  \-- app.js
|  +-- controllers
|    \-- ListController.js
|    \-- AddController.js
|    \-- EditController.js
+-- views
|   \-- add.html
|   \-- edit.html
|   \-- list.html
+-- index.html

I like to be able to see my work as I progress. I usually have my text editor and browser open right next to each other and after each save, I refresh my browser and check the developer console for any errors. If it looks right, we move on. If it doesn’t look as we expected or we get an error, we fix it. I’ve arranged this post with that in mind so let’s start out by filling in the <head> of our index.html:

<!doctype html>
<html>
  <head>
      <meta charset="utf-8">
      <title>CRUD</title>

  <!-- Bootstrap core CSS -->
  <link href="css/bootstrap.min.css" rel="stylesheet">
  <link href="css/starter-template.css" rel="stylesheet">

  <!-- AngularJS and ng-Route -->

  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
  <script src="https://code.angularjs.org/1.4.4/angular-route.min.js"></script>

      <!-- Firebase -->
      <script src="https://cdn.firebase.com/js/client/2.2.4/firebase.js"></script>

  <!-- AngularFire -->
      <script src="https://cdn.firebase.com/libs/angularfire/1.1.2/angularfire.min.js"></script>

  </head>

Now let’s bring in all those files we just referenced. First off, I’m using the starter template from Bootstrap. Save these files as shown above in the file structure: bootstrap.min.css and starter-template.css. Remove the line text-align: center; from the starter-template class.

Next, notice the CDN references to AngularJS, ng-Route, Firebase and AngularFire. The routing part of AngularJS ships separately, and we’ll be using some routes for the the CRU part of our CRUD application. Firebase is a BaaS or Backend as a Service. AngularJS is a front-end web development framework which plugs in nicely to Firebase. Firebase holds your data and gives you ways to access it. AngularJS let’s you play with it and present it to your users. At this point, we’ll go over to Firebase and open an account.

After you’ve signed up, you’ll need to create an application. Call it whatever you like.

Ang-CRUD

Then you’ll set up hosting.

Hosting

In short, you’ll need npm to install firebase-tools, then do firebase init in the same directory as your index.html. You’ll need to follow the prompts to enter your firebase credentials and select the app you created for this project. Finally, firebase deploy puts all our hard work on the web. For now, that’s a whole lot of nothing but this is the command you’ll be running once your project is complete.

Let’s continue with the rest of our index.html.

<body ng-app="myApp">

        <!-- Navbar -->
        <nav class="navbar navbar-inverse navbar-fixed-top">
          <div class="container">
            <div class="navbar-header">
              <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
              </button>
              <a class="navbar-brand" href="#/">Ang-CRUD</a>
            </div>
            <div id="navbar" class="collapse navbar-collapse">
              <ul class="nav navbar-nav">
                <li><a href="#/">Home</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </nav>

        <!-- Container -->
        <div class="container starter-template">

      <div ng-view></div>

        </div>

        <!-- Module -->
        <script src="js/app.js"></script>

        <!-- Controllers -->
        <script src="js/controllers/ListController.js"></script>    
        <script src="js/controllers/AddController.js"></script>     
        <script src="js/controllers/EditController.js"></script> 

    </body>
</html>

Let’s go through this section by section, starting with <body ng-app="myApp">. If you open index.html in Chrome, you’ll see a navigation header, no content and this error in your developer console: Uncaught Error: [$injector:modulerr] .... (If you see any other errors, check to make sure you have all your files in place, even if they’re empty.) We have that error because ng-app tells AngularJS we have an app called “myApp” and we don’t yet. Let’s take care of that now.

Open your app.js and put this in it:

var app = angular.module('myApp', ['ngRoute', 'firebase']);

app.config(function($routeProvider){
  $routeProvider
  .when('/', {
    controller: 'ListController',
    templateUrl: 'views/list.html'
  })
  .when('/add', {
    controller: 'AddController',
    templateUrl: 'views/add.html'
  })
  .when('/edit/:id', {
    controller: 'EditController',
    templateUrl: 'views/edit.html'

  })
  .otherwise({
    redirectTo: '/'
  });
});

app.constant('FBURL', 
  'https://ang-crud.firebaseio.com/products/' 
  //Use the URL of your project here with the trailing slash                                                   
);

The first line of code gives us an angular app called ‘myApp’ which has the dependencies ‘ngRoute’ and ‘firebase’. We have also set up our routing and a constant (scroll down a bit to constant) for our Firebase URL. After you’ve saved and refreshed, your page should look the same, but you won’t have any errors.

Back on our index.html, we have our navbar section. This is just copied from the bootstrap starter template. Then we have a container <div> and another message for AngularJS: ng-view. This is where our views will be displayed.

We’re going to be CRUDing products, just by way of example. Our products have a SKU, a description and a price. Let’s put some sample data in our Firebase App. Sign in to Firebase and click on “Manage App”, then from your dashboard, click “Data”, then in the upper right corner, you’ll see a button to “Import Data.”

Save this in a file called sample-data.json, then import it.

{
  "products" : {
    "0" : {
      "description" : "Totally Rad Product",
      "sku" : "C4R5U8D4",
      "price" : 9.99
    },
    "1" : {
      "description" : "Coolest Gadget Ever",
      "sku" : "C4R5GD34",
      "price" : 19.95
    },
    "2" : {
      "description" : "A Thing You Need",
      "sku" : "OMG4201234",
      "price" : 99.99
    }
  }
}

Our first view will show a list of our products. For that, we’ll need a ListController and a list.html.

Here’s our list.html:

<table class="table" >
  <caption class="lead">Products</caption>
  <thead>
    <tr>
      <th>SKU</th>
      <th>Description</th>
      <th>Price</th>
    <th> Actions </th>
    </tr>
  </thead>
  <tbody>
    <tr ng-repeat="product in products">
      <td>{{product.sku}}</td>
      <td>{{product.description}}</td>
      <td>{{product.price | currency}}</td>
    <td><a href="#/edit/{{product.$id}}" class="btn btn-small btn-primary">Edit</a> <a class="btn btn-small btn-danger">Delete</a></td>

    </tr>
  </tbody>
</table>
<p>
    <a href="#/add" class="btn btn-success" role="button">Add New Product</a>
</p>

This is just a Bootstrap table, with some buttons for edit, delete and add. These buttons won’t work just yet. There are a few extras in there for AngularJS. The ng-repeat tells AngularJS to iterate through each product in our list of products. The parts in curly braces, e.g. {{product.sku}}, are called expressions. Notice for the price we use | currency which is a filter telling AngularJS to format that expression like so: “$19.99”.

Let’s take a look at our ListController.js so it makes a little more sense.

app.controller('ListController', ['$scope', '$firebaseArray', 'FBURL', function($scope,$firebaseArray, FBURL){
  var products = new Firebase(FBURL);
  $scope.products = $firebaseArray(products);
}]);

There’s a lot going on here in just these few lines of code. First, we’re defining our controller as ListController, then adding all our dependencies. $scope is where we’ll be putting all our data that we’re showing in our view list.html. $firebaseArray is how we talk to our backend, Firebase. FBURL is that constant we defined in our app.js. We start out with a Firebase reference in our var products. The we turn that into an array and put it in our $scope.

Now, if you refresh your index.html you should see a list of your products:

list-of-products

Moving on to the create part of our CRUD application.

Here’s our add.html.

<h1>Add New Product</h1>

<form class="form-horizontal" role="form">
  <div class="form-group">
    <label for="sku class="col-sm-2 control-label">SKU:</label>
    <div class="col-sm-4">
      <input class="form-control" id="sku"
             ng-model="product.sku" placeholder="SKU"/>
    </div>
  </div>

  <div class="form-group">
    <label for="description" class="col-sm-2 control-label">Description:</label>
    <div class="col-sm-4">
      <input class="form-control" id="description"
             ng-model="product.description" placeholder="DESCRIPTION"/>
    </div>
  </div>

  <div class="form-group">
    <label for="Price" class="col-sm-2 control-label">Price:</label>
    <div class="col-sm-4">
      <input class="form-control" id="price" type="number" min=”0? step="any"
             ng-model="product.price" placeholder="9.99"/>
    </div>
  </div>

  <div class="form-group">

    <div class="col-sm-offset-2 col-sm-10">
      <a ng-click="addProduct()" class="btn btn-small btn-primary">Add</a>
    </div>
  </div>
</form>

Again, this is just your standard Bootstrap form with one important thing added: ng-model. This is referencing the $scope of our AddController which doesn’t yet exist. ng-click calls a function addProduct() when the “Add” button is clicked. Let’s fix that.

app.controller('AddController', ['$scope', '$firebaseArray', '$location', 'FBURL', function($scope, $firebaseArray, $location, FBURL){

  $scope.addProduct = function() {
    var ref = new Firebase(FBURL);
    var product = $firebaseArray(ref);
    product.$add({
      sku: $scope.product.sku,
      description: $scope.product.description,
      price: $scope.product.price
    });
    $location.path('/');
  };

}]);

Similar to our ListController, we name our controller and bring in our dependencies. $location is used to redirect us back our list of products. $scope.addProduct() is a function that takes all the information from our form and adds it in our Firebase app.

Now if you click “Add New Product” from your index.html, you should be sent here:

add-product

Go ahead and add a product and see if it you are redirected to your list view with your new product in the list.

Next, we’ll add edit functionality. Here’s our edit.html.

<h1>Edit Product</h1>

<form name="edit_form" class="form-horizontal" role="form">
  <div class="form-group">
    <label for="sku" class="col-sm-2 control-label">SKU:</label>
    <div class="col-sm-4">
      <input class="form-control" id="sku"
             ng-model="product.sku" placeholder="SKU"/>
    </div>
  </div>

  <div class="form-group">
    <label for="description" class="col-sm-2 control-label">Description:</label>
    <div class="col-sm-4">
      <input class="form-control" id="description"
             ng-model="product.description" placeholder="DESCRIPTION"/>
    </div>
  </div>

  <div class="form-group">
    <label for="Price" class="col-sm-2 control-label">Price:</label>
    <div class="col-sm-4">
      <input class="form-control" id="price" type="number" min=”0? step="any"
             ng-model="product.price" placeholder="9.99"/>
    </div>
  </div>

  <div class="form-group">

    <div class="col-sm-offset-2 col-sm-10">
      <input type="submit" id="submit" class="btn btn-small btn-primary" ng-click="editProduct()" class="btn btn-small btn-primary"></button> <a href="#/products" class="btn btn-small btn-danger">Cancel</a>
    </div>
  </div>
</form>

It’s practically identical to our add.html, but ng-click is used on editProduct(). Let’s take a look at that function in our EditController.js.

app.controller('EditController', ['$scope','$location', '$routeParams', '$firebaseObject', 'FBURL',   
    function($scope, $location, $routeParams, $firebaseObject, FBURL){

    var ref = new Firebase(FBURL + $routeParams.id);
    $scope.product = $firebaseObject(ref);

    $scope.editProduct = function() {
        $scope.product.$save({
            sku: $scope.product.sku,
            description: $scope.product.description,
            price: $scope.product.price
        });
        $scope.edit_form.$setPristine();
        $scope.product = {};
        $location.path('/products');

    };

}]);

This is very similar to our AddController.js but with a few key differences. Here we use $routeProvider to get the exact $id of our FirebaseObject. We use $firebaseObject to manipulate this particular record. In our editProduct() we use $setPristine() and set $scope.product to an empty object to clean up our form and $scope after we’re done editing the product.

Lastly, let’s go back and add delete functionality. We’ll delete straight from our list view so open up your list.html and adjust the delete button like so:

<a class="btn btn-small btn-danger" ng-click="removeProduct(product.$id)">Delete</a>

We’re adding ng-click similar to how we did with edit.html. Now open up your ListController.js and add removeProduct(). You’ll also need to add $firebaseObject, just like in EditController.js.

$scope.removeProduct = function(id) {
    var ref = new Firebase(FBURL + id);
    var product = $firebaseObject(ref)
    product.$remove();
   };

Now if you go back to your index.html and click on the delete button, that product will disappear from your database.

There you have it: a fully functional CRUD application written in AngularJS using Firebase as your backend. There is plenty of stuff that you can do to improve this app like validation, pagination, or a modal to confirm deletions. Check here for more info on that.

You can clone a working copy from my github and play with a live demo. If you see any mistakes, please let me know in the comments or on twitter.

Extra Guac

John decided to walk. It wasn’t a heavy rain, but the constant wind made sure the legs of his jeans were getting soaked below his rain coat. Walking along the side of the buildings helped but the stair sets into neighborhood homes forced him back into the rain’s reach.

The rain was fitting. John was feeling melancholy. There are 7 billion people on this planet and not one of them had the least hint of desire to spend their time with him.

An overweight man wearing an Adidas windbreaker track suit made his way across the street and limped in front of him. John walked into the street to pass him. On the other side of the street, a middle-aged woman who had neglected to contain her ample, sagging breasts in a brazier ambled along, nipples poking through her damp, baggy blouse. “These people are truly sad,” John thought to himself.

Coffee Reincarnate was quiet. Most of the seats were filled with people staring at their laptops, some furiously typing out an assigned paper, others cruising their social media feeds. The scene was not unlike what you’d find in casinos only these were hip twenty-somethings instead of senior citizens.

The barista’s ears had gauges the size of a golf ball and her chest piece (something dark and from the middle ages) was poking above the neckline of her black top. She raised her pierced eyebrow at him and as she did, the piercing swung from the momentum.

“Nice greeting.” John opened.

The barista shifted her weight to her other leg and raised one of her hands to her hip. She looked to the side and blew a wisp of purple hair with a sigh. “Can I help you?” she said. He thought he saw her mouth “asshole” under her breath.

“Thanks for the reminder,” he said.

“What?” she looked at him and squinted, her eyebrow piercing swinging again.

“Does that eyebrow piercing block your vision?” he asked.

“Are you gonna order or what?” the barista snapped back.

“Strictly business with you, eh?” John snapped his fingers. “Don’t you ever engage in a bit of friendly banter with your customers?”

She turned around without a word and walked to the back. A full minute later, an acne scarred, scruffy haired twenty year old boy walked up to the counter.

“Can I help you, sir?”

“Cup of coffee and a breakfast burrito. And you know what? Add some guacamole to that burrito.”

“Your name, sir?”

“John as in John D. Rockefeller.”

The kid let out a nervous chuckle out of politeness.

John turned to look at some pamphlets that were strewn about on the counter. Yoga with Renee, Guitar lessons with Larry, along with other advertisements for starving artist types. Were these people making a living doing this shit? Must be all the upper middle income people in the neighborhood that needed to spend their money doing something creative.

He glanced around the room for the spot he’d spend what he hoped would be his final moments. With his luck, those pills wouldn’t work or there would be an after life. Then he’d spent his last few bucks on junk or worse, he’d have the same problems, only with an eternity to deal with them.

There was a table for two by the window facing the street waiting for him. He took off his rain coat and draped it on the back of one of the chairs and dumped his messenger bag on the seat. On the windowsill were a few books: “Secrets to Success: How to Break Through Your Creative Blocks”, “Mayan History and Culture”, “Rachel William’s Guide to French Cooking”. People read anything these days. Or maybe they don’t and that’s why they’re sitting here abandoned on this shelf.

“Burrito for John!”

When the coffee was good, John drank it black. This wasn’t good coffee, but black reminded him of the abyss of nothingness he was looking forward to. John asked for their hottest hot sauce. If he was going to burn in hell, he wanted to start getting used to the heat. He asked for a knife and fork. He wanted to go with clean hands.

As he sipped his coffee he started to feel the drugs playing with his brain. He paused and looked at his witnesses. They didn’t know they were witnesses. They didn’t ask to be a part of this but then again, he didn’t ask to be born and yet, here he was. He couldn’t help but feel a pang of guilt for putting these people through this. He stood up, pushed his chair back with his knees. The room was filled with silence after the abrupt screeching of the legs of the chair against the tiled floor. “Everybody leave!” a brief pause. Everyone stared at him and a few people in the back stood up from their revelry and to see what all the commotion was about. “NOW!”

A petite brunette introduced herself. “Hi… I’m Sara. Mind if I share this table with you?” John shook his head, looked down at his soaking wet legs, then back up at Sara.

“Uh… Sure.” He rearranged his burrito and coffee onto the closer half of the table.

“Guess we’re not the only two that needed a little ambient company today, huh?” Sara asked.

John gave a polite chuckle in response. “This poor girl,” John thought to himself.

Sara’s dress came down to the middle of her thick, pale thighs. Her dress was white with a scattered, blurred, blue floral print. He caught himself staring at her legs as she hid them beneath the table. He sat back down and pretended to look past where her legs had been.

He cupped his mug of black liquid with both hands and slowly raised it to his lips. As he lowered it, he peaked over at Sara who was arranging her notebook on the table, apparently oblivious to his company. His gaze traced down her neckline and turned into a long, held stare, directly at the bottom of her neckline.

“Getting a nice look?” he thought he heard her say. He looked up at her face, but she was still looking through her notebook. John returned his eyes to his cup of coffee, then down at his soaked legs.

“Your burrito looks delicious.” Sara offered.

“Uh… Sure,” was his ingenious response.

“It’s fine. I’ll leave you alone.”

“Oh, no. It’s just that I’m a little out of it. The rain, ya know?”

Sara nodded and gave him a patronizing smile, unconvinced.

John’s insides started to heat with anger. He wasn’t going to let some stranger make him feel like shit because he wasn’t feeling chatty.

“What are you a writer or something?” John’s tone was derisive and mocking.

Sara’s smile changed from patronizing to warmth. “I write, but I don’t know that that makes me a writer.”

Just as quickly as it heated, John’s anger cooled. He cupped the mug with both hands again, but let it rest on the table in front of him. His shoulders lowered and a smile cracked across his face.

“What…” he paused to clear the lump forming in his throat.”What kind of stuff do you write?” He cleared his throat again. Raising his fist to his mouth, he looked down and mumbled, “Sorry. Getting over a cough.”

“I… write.” Sara tilted her head to her right and shrugged her shoulders bringing her chin in towards her clavicle. John’s eyes met hers just as she looked down. He noticed her high cheekbones and shallow cheeks. She had a tiny dimple exactly in the middle of each cheek. He traced the lines of her face back to her ears. They were pierced but today she wore no earrings. The top of her ear was covered by her hair which was tied back in a loose bun. Her jaw line was clear as her skin.

“Keep it in your pants, man.” He was 6’ 2” with a high and tight hair cut. He put his hand on Sara’s shoulder and leaned over the table towards him. His pectorals were bursting through his shirt and seemed to tear open his blazer.

John stood up in a hurry to face him, the legs of the chair screeching against the tile floor as he shoved it back with his knees, his stance wide and sure but his opponent was nowhere to be seen. John looked around, then down at his jeans. They were still wet from the knees down.

“You’re leaving?” Sara’s face contorted in disbelief.

“Uh… Sure… I mean, no. I’m just going to the bathroom. Be right back.”

After walking a few steps, he had already forgotten where he was headed. He paused for a moment. A 5 year old boy with a bowl cut, baby blue polo and khakis asked him if he was lost. He looked down at the boy. The boy looked eerily familiar.

“Do you know where I was going, young man?” John squatted down and asked the boy.

“Maybe…” The boy paused, put his chin down and put his finger to his nose. “You were going to the bathroom?”

“Are you a wizard?” John asked.

“Of course, I am!” the boy laughed as if it was obvious.

“Well then where’s your beard? I don’t think you can be a wizard without a beard.”

The boy laughed again and skipped away.

John stopped just short of the entrance of the bathrooms. “Don’t look into the mirrors. I cannot look into the mirrors.” He kept saying it over and over again waiting outside the bathroom.

“Are you in line?”

“No, go ahead.”

John returned to his mantra about the mirrors. After a very long time, he reached for the handle of the bathroom.

This was it. Now or never. Do or die.

John burst into the bathroom and hurried past the mirrors to the urinal. He looked down to make sure everything was arranged and got as close as he could to the porcelain to avoid being seen. He looked around nervously. No one else was in the bathroom. He was alone, again. Realizing this, he quickly zipped up. He kept his gaze down, avoiding the mirror, as he walked toward the sink. The soap dispenser was busted. Why? Why was the soap dispenser busted, at a time like this? Didn’t they realize he needed that soap? His eyes darted around the room, looking for another soap dispenser but as he did, he caught a glimpse of his reflection in the mirror. Immediately, he ducked down below the sinks.

“This is a bad place.” John thought to himself as he crawled toward the exit, looking down at the floor so as to avoid any more glimpses in the mirrors. He bumped his head into the door, then sat up with his back against it and took a deep breath. A deep sense of accomplishment filled his soul. He stood up, held his head high and puffed out his chest, grinning ear to ear.

John made his way back to his table with a confident swagger. He pulled his chair back with grace and sat down.

“Sara, right now, I am on top of the world.”

“Well, look at you! I’m happy to hear that.”

“If this was a bar, I’d buy us both a drink.”

“That’s very nice of you.”

“So, tell me about yourself. What makes you excited? What gets you out of bed every morning? Or should I say, who?” John demanded.

“I’m a writer. I write.” Sara smiled.

“That’s right. You said that. Show me some of your writing. What are you writing right now.”

He reached over the table and just before taking her notebook, he asked carelessly, “Do you mind?”

She shook her head as he looked down to study her notebook. There was a long, uncomfortable pause.

“This is good. No really, this is good stuff here.”

“That’s very nice of you.” She was starting to blush.

“Your attention to detail… your descriptions are very full. These characters are clear in my head and I’ve only read a few lines. This is really good, Sara!”

“Oh, stop. Now you’re flattering me.”

“Hardly. It’s my job to critique writing and in my professional opinion, you, Sara, are an excellent writer.”

Sara’s face was burning. She snatched her notebook back and said, “Give that back.” She clutched it to her chest and looked back at John. He leaned back in his chair, clasped his hands behind his head, stretched out and smiled.

“Listen Sara, I probably have about 15 minutes left to live. I wanna take you in the bathroom, bend you over a toilet and fuck your beautiful brains out. I want to come with my last breath.”

Sara was still looking back at him.

John collapsed his arms into his lap and looked down at his jeans. They were still damp.

“So, uh, have you been published?” John asked.

“Here and there.”

“Then I’m not the only one who thinks you’re good. Look, I’m an editor. I read shit everyday. I mean real shit. My nephew is 5 and can write better than some of the shit that I’m forced to read. Maybe I’m being a little pushy here but you, Sara, you have a gift. You really do and you need to get it out there. How much time do you spend writing everyday? Is this your full time gig?”

“I write when I can. I have bills, you know?”

“See? There’s the problem. Bills. If we could just convince the landlord she doesn’t need the rent, the world would be a better place. You could write full time and the whole world would be better because of it.”

“What’s your name again? I don’t think you told me your name.”

“John, as in John D Rockefeller.”

“What are you, 22? Fantasies of having more money than god, grabbing people’s private notebooks, filling their heads with idealistic fantasies, asking to fuck in the bathroom? Grow up, child.”

John’s face dropped. He looked down at his jeans. He looked up at his burrito. He’d only taken a bite from it. Some of the guacamole was oozing out of it. He poked at it with his fork.

“I’m sorry Sara, maybe I’m being too forward. I really do think you’re a great writer, but it wasn’t right for me to just grab your notebook like that.” He kept looking and poking at the burrito.

“No! No, no, no. John? Really, it’s ok. John? Look at me. You really made me feel good. And god, I wish! I wish I could write full time. That would be dreamy. We need more people like you, John. That was a bold move and you encouraged me to be bold, too. You got me thinking. I mean, really, what’s the worst that could happen?”

“Is that a serious question?” John was still poking at his burrito. He couldn’t bring himself to look up at her.

“Well, yes. I guess. Like, what is the worst that could happen?” Sara offered.

“Let’s say you quit your job to pursue writing full time. The first day with no job you’d probably write for 8 hours straight. The first week you’d go to bed every night feeling very satisfied. The second week a friend would ring you for some moral support. She just broke up with her boyfriend. You’re a good friend so you take the time to be her emotional dumping ground. You’d faithfully give her all the support you could muster. But her mood would rub off on you, just a little bit. You’d try to get back to your writing but other things would pop up. Personal things would pop up. You need some ‘me time’.”

“Yeah, well… that’s life. I mean, I’d still be writing…” Sara tried to jump in when he paused for a breath. John finally looks up from his burrito, perturbed because he hadn’t finished. He started talking over her.

“Let’s give you the benefit of the doubt and say you have some savings. They’d keep you comfortable for awhile but eventually, your finances would take up more and more of your mental energy. The bills keep coming and your savings are buckling under the weight. After a couple months, your landlord starts coming to your house and harassing you for the rent. Your gas would get shut off, your electricity would get shut off. You’d slink away to coffee shops, plug in your laptop and keep writing. Then one day, you’d go home and the locks would be changed. Whatever possessions you haven’t yet sold on the internet would be lost forever. You’d have no recourse to get them back. You’d try your keys again. You’d start banging on the door. Your neighbors would look on in disgust. You’d bang some more and eventually collapse, kneeling down in front of the door that is keeping you away from your clothes, your shoes, your bed, your books, your notebooks, all the memories locked away in your desk drawers. You’d begin to cry, weep, sob. Crouched on the steps leading to your home, it would start to rain. You’d reach for your phone to call the first person that came to mind, your ex-boyfriend. Only he wouldn’t pick up. You’d cry some more and in desperation, call your mother. Only instead of your mother picking up, you’d get an automated message telling you that your phone doesn’t work anymore. You haven’t paid the bill in two months and they’re denying you service.”

“Jesus Christ, John! You can stop now. I get it. What the hell is wrong with you?” Sara was keeping her voice just below what was acceptable for the coffee shop. She started gathering her things to leave.

“I’m about to die.” John answered casually.

Sara stood up. “You’re sick. You know that, John? Real sick. I can’t believe you’d joke about something like that.”

“That would be kind of a sick joke, right?”

“Uh, yeah.”

“How could I prove to you that I’m not?”

“Honestly, at this point you can go fuck yourself.” She shoved the chair back under the table then gave him the finger just in case he still didn’t get it.

Just as she turned away, foam started bubbling out of his mouth. His body started convulsing in the chair. He steadied his hand enough to pick up his fork and poked his burrito. A second later, his head collapsed onto it and squeezed out a little more guacamole.

A Day in the Office

April 21, 2014 9:32am

The temptation is to dig into your inbox as soon as you get to work on Monday. All the idiots that have no life create a pile of shit for you to deal with over the weekend. You leave work Friday, give yourself the weekend to relax and rejuvenate, but that’s not what everyone does. Maybe they have no friends. Maybe they’re boring assholes with nothing better to do than to send work emails. If you can skip that temptation and start working on something useful, you’re all the better off. Your inbox can wait.

I get to work 15 minutes early just about every day. It’s that or a half hour late. That’s just when the trains roll through. Works out for the most part. Most of my coworkers get in 15-20 minutes late so that gives me a half hour of quiet time to get a jump start on the week.
Once my co-workers start pouring in, one of two things happens. It’s Monday and they know the pile of shit that awaits them so they either a. put their heads down and dig in, or b. push it off and shoot the shit about their weekends. Today is one of those days where they put their heads down and get to work.

After a 45 minute sprint where I knock a few things off my to-do list, I’m ready for a break. It’s only 9:36 am and my day is already dragging. Is it too early to grab a smoke? Maybe now is when I get a fresh cup of Joe.
The coffee here is awful. It’s those godforsaken K-cups that are destroying Mother Gaia and have lowered the bar into the dirt for coffee in America. What brilliant capitalist mind thought up this shit? There’s a saying that goes, “No one in this world has ever lost money by underestimating the intelligence of the great masses of the plain people.” I’d modify it. Most people that have a ton of money, like the inventor of K-cups, make a habit of underestimating the intelligence of the great masses. If someone pitched the idea of a K-cup to me, I’d laugh them into the dirt. “You expect people to pay how much for that coffee maker and how much for these single servings of mud water?” This is why I’m a lower middle class employee and not a wealthy capitalist. I think entirely too highly of people.

I know the coffee is shit and yet I drink it. Why do I torment myself? There are a couple reasons. 1. It’s free. 2. It kills time. 3. It’s caffeine and I like to fill my body with all the working class, legal drugs I can.

April 21, 2014 10:29am

Cleaning my desk feels good. It feels really productive. I think it has something to do with interacting with the physical world. Working on a computer, clicking around in software, sending a dozen emails over the course of an hour doesn’t feel like you’re really doing anything. You’re just creating noise, generating static. Sitting here, staring at this screen, moving my wrist a few inches back and forth in this direction or that, clicking a button here, punching some keys there doesn’t make me feel like I’m actually doing anything. You don’t feel the pleasure of a job well done. At the end of the day, you feel sore from sitting for 8 hours straight, but it’s not like the soreness you feel after chopping wood or plowing the fields. There’s satisfaction when your body is sore and there’s something to show for it at the end of the day. You just feel like a shlub when it’s from sitting at a desk, staring at a screen all day.

April 21, 2014 11:59am

It’s that time of the day. Now I have to decide how I’m going to stuff my face. Sometimes I ask around the office to see if anyone is going to a nearby sandwich or burrito place. When I’m feeling frugal, I’ll hitch a ride to the grocery store and buy bread, deli, hummus, baby carrots and some soups for the week. Not only does this save me money, but it saves me decision making power. It’s lunch. It shouldn’t be complicated. There should be no wasted energy of any sort on how I’m going to keep myself nourished while I’m here in my well paid prison. I’ve been spending money like it’s water, eating like shit, and feeling generally spent. I’ll try and hitch a ride to get groceries today.

April 21, 2014 12:31pm

The thing that sucks about not owning a car and working in the suburbs is not being able to get around. The whole reason the suburbs were created was to stuff the pockets of Henry Ford and whoever the hell started the other car companies. The ‘American Dream’ was created to turn humans into mere consumers. People that bought shit and then worked harder to buy more shit.

But look at me. Here I am complaining because I have to wait for my coworker to finish whatever he’s working on and give me a ride to the grocery store. I’m a child of an even later, more sinister myth, the “EVERYTHING NOW! RIGHT FUCKING NOW!” myth. It’s the myth that I should have everything that pops into my head now. This myth is fueled by the internet, by smart phones, by online shopping and next day delivery, by big box stores with giant stock levels of everything the advertisers have tricked you into wanting. Back in the day, people had to wait for everything. You couldn’t click and have something. You couldn’t send an email and get a reply within minutes.

So I have to wait… so what?

Now my self-righteous brain is kicking in. You’re wasting employer’s time. You’re not optimizing your time to the fullest, waiting around for your co-worker to finish what he’s doing.

That’s another thing that irks me. Everything has to be optimal now. You can’t just work. You have to be as efficient as possible. It’s computers. Well, it started with the assembly line, but computers are even more efficient than the machines and workers on the assembly line. Computers can get things done instantly. And so we expect the same from the people that use them. It’s a funny thing. Our expectations match the tool. If you see someone using a big heavy cumbersome piece of machinery, you expect the same from the person using it. You expect their output to be along those lines. You see someone using a finely tuned piece of machinery, you expect their output to be precise.

April 21, 2014 2:53pm

Right now there is a piece of bad news that I don’t want to give to my client. Long lead times are expected on one of their recent orders. No one wants long lead times. Like I was saying earlier, we live in an age of instant gratification on crack. We’re so accustomed to getting everything exactly when we want it. We don’t want to wait for anything, especially not 5 weeks.

There’s only one way to deliver bad news: make it look like someone else’s fault and you’re trying to do everything in your power (which in this case is exactly zero) to “expedite the process.” Use lots of big words to mask the fact that you have no control over the situation and show your enthusiasm to please them and right this “wrong”.
Business, and life for that matter, is full of this. Telling people sweet lies to make them feel like you’re trying. You can’t say to your clients, this shit sucks and there’s nothing we can do about it. That’s not an option. There are always other options in today’s world. You can buy from someone else, you can harass your vendor until they pull something out of the clear blue sky and give you what you want; you can do pretty much anything other than wait for what you ordered. I blame McDonald’s. They got this whole trend of not waiting for orders with their fast food.

So now I have to harass my vendor. I hate harassing people. I like to give people the benefit of the doubt. Business would be so much simpler if we could just take people at their word. When they say they don’t have something, we could believe them. In the words of Christ, “Let your yays be yays and your nays be nays,” or something like that. Just be straight. It’s only money we’re dealing with here. No one’s lives are at stake. No starving children will perish in the meanwhile. No animals will be harmed if you don’t get your order by the end of the week. Wait is a four letter word.

April 21st, 4:35pm

It’s about now where I’m spent. My mind is a mush from jumping from one task to another, answering phone calls, replying to emails, all the while trying to do one or two actually productive things. So to make matters worse, I jump on my social media feeds: Facebook, Twitter, Instagram, reddit, RSS. I do the loop, scanning through my feeds looking for something interesting. I open new tabs with links to things that I think might be worth investigating further. Half of them get closed after the first five seconds of watching or reading because they weren’t as interesting as expected. I could do this in about 15 minutes a day, but for some reason, I keep going back. It’s like an addiction. You get a quick bump of pseudo-socializing. There have been days when I’ve done the loop dozens of times a day. At the end of the day, I feel worse. It’s all fake. It’s not real socializing. It’s not real information. It’s like trying to get nutrition from candy. You get an initial sugar surge, but you end up feeling gross and fat.

How I Learn

Here are some tips I’ve picked up thus far while learning to code.

Keep It Stupid Simple

Whenever you’re reading something or trying your fingers at some coding, make sure you can explain it to yourself in your mother tongue. Rephrase it in your head or write it down, but if you can’t explain it to yourself or better yet, to someone else, then you probably don’t understand it. Swallow your pride and cut out all the programming lingo that doesn’t make sense and explain it so that in 2 weeks from now when you look back, it’s as clear as day. Whenever you’re reading other people’s code make a copy of it and document it for yourself. This may seem excessive, but it’s worth it. You’re trying to learn something highly sophisticated and as with anything, you have to break things down into understandable bites.

Keep Moving

While learning to write source code, you will get stuck. There are times in the life of every programmer I’ve met, heard, or read about where you’re working on something and you just can’t make it do what you want. Move on. Don’t stick with a problem you can’t figure out for too long. If you have googled it, asked other more experienced programmers and you still don’t get it, just move on. Go learn something else, keep moving on in the same book you’re reading now or go for a walk or have a beer. And don’t feel badly about it. Everyone gets stuck and you’re only wasting time sitting and staring at a screen.

Keep a Scratchpad Handy

While reading through an instructional book, watching a screencast tutorial, or browsing through some code, you’ll want to jot down some ideas or make doodles or diagrams of what you’re learning to get a better hold of what you’re learning. Don’t worry about your work on your scratchpad making sense later when you’re in the heat of the moment. If you understand the code, it has fulfilled its purpose.

Find a Pal

Everyone knows having a partner in crime is the way to go. It’s surprising how much this is true when it comes to learning how to code. Somethings that have baffled you despite your best efforts will be simply understood and explained by someone else. No matter your or their level of experience, having a second eye on your code will help you see things differently, help you learn other and better ways of doing things and will better your creative problem solving skills which are so important to code.

Get Involved

Check out meetup.com and search for a group that is in your area and learning your language of choice. Don’t be shy. Just start shaking hands and introducing yourself. Sure, everyone at this meetup will know a million times more than you and you won’t understand what the heck they are saying most of the time, but that will improve. What’s more is that you will have constant inspiration to better your skills, you’ll see that it’s really possible, and you’ll see that all good programmers are still learning every single day. While you’re there, talk to people, ask if they can help you with something you’ve been stuck on, ask them to better explain a concept that you’re struggling with or just say hello and introduce yourself. I’ve found people that code to be a generally friendly bunch that like solving problems and getting stuff done. Those are my type of people.

Resources

If you’re like I was when I started this journey in July 2011, you’ve never even seen code before in your life. Here are some of the resources I used, with a quick review to get you started. The resources here start simple and get increasingly complex with extras at the end to make finding answers to your questions easier.

The Setup

First and foremost, I recommend you use the set up that Zed Shaw recommends here. We’ll get back to Zed in a moment but for now use his set up, install python 2.7 (I do NOT recommend starting with Python 3 as most learning resources haven’t caught up with that yet), learn how to open the command line and move around directories, move files and open .py and .txt files, learn how to save a .py file, get used to typing parentheses, brackets, and curly brackets. Fortunately python has VERY simple syntax, especially compared to other languages so don’t worry about spending all your time looking through your code for misplaced curly brackets, but you will have to use them and you should get comfortable typing them.

Snake Wrangling for Kids

The first book I recommend is called “Snake Wrangling for Kids” which is a childrens book for learning to code. Yes, it’s a kid’s book, but swallow your pride, read it and try a bunch of the exercises. I personally just skimmed through the end which has you drawing little spirographs using tkinter. This bores me and goes against my learning philosophy which is, learn what excites you.

Learn Python the Hard Way

This book is highly recommended and not just by me. The author, Zed Shaw, has a knack for teaching without making the subject overly complicated. You’ll be writing a fun choose your own adventure game in no time. You can use the html version for free, but if you can spare a few bucks, buy his book and support this very helpful programmer.

A few caveats… Zed doesn’t do the best job of explaining Test Driven Development. He doesn’t get into this till much later in the book so don’t worry about this too much. I do recommend learning this style of programming at some point, but if this book doesn’t do it for you, you are sure to run into it again later in your journey. Also, at the end he has you using a web framework you aren’t likely to use much after these exercises, with the option of Django. The popularity of Django is a detriment to beginners, in my humble opinion. It is powerful, but NOT easy, all things considered. More on web frameworks later.

How to Think Like a Computer Scientist

My next favorite book is “How to think like a Computer Scientist.” He gives you a much more thorough understanding of concepts then you’ll get from LPTHW. It takes you from absolute beginner to much more advanced subjects. There are lots of great exercises to drive the concepts home. This book honestly does what it says and teaches you how to think.

OpenCourseWare

If you are a fan of lectures from college professors and complex problem sets, then you have to check out the various opencourseware from top notch institutions like Harvard, Stanford and MIT. I’ve only used the MIT OCW but it is absolutely fantastic. You can also take advantage of help from other students taking the course through OpenStudy.

web2py

If you’re interested in learning web development, learn web2py. This should also wait until you’ve got a little python under your belt as your focus should be on learning a language (python) and not just a webframework (web2py). That said, this web framework was designed by a computer science professor for his students and it’s clear. It’s designed to always be backwards compatible and get you creating web apps in record time. There is a lot of magic (a word which hear means ‘lots of stuff happens behind the curtain which you don’t see’) which goes against the Zen of Python dictum ‘Explicit is better than implicit,’ but it’s a trade off with another dictum, ‘Simple is better than Complex.’ (For more on the Zen of Python, open your python interpreter then type: import this ).

Other

There are some other popular books that you may run accross. Dive into Python is one of them. I am NOT a fan of this book. It’s written by programmers, for programmers so if you already know some other programming language, then DIP will get you up to speed in no time. For the rest of us, however, this book is hard to differentiate from an intro to greek written in latin. Other books like, “Learning Python” and “The Python Cookbook” from Oreilly Publishing are good resources, but more like references (which you can get online by reading the docs) then instructional guides.

StackOverflow

Many Computer Programmers don’t like to let on that they don’t know everything. If you’re writing source code, you’re learning about new tools and concepts to make what you do more fun and effective. If you have a question, chances are someone else has asked it so do a search at StackOverflow.com. If it hasn’t been asked yet, chances are that someone else would like to ask it or will ask in the future so do yourself and others a favor and ask. This is a great site for doing just that.

Last Words

One last word to the wise. When you are first getting started it’s best to learn something popular. I’ve kept this in mind while writing this post. How does popularity translate in this situation? Something that has an active mailing list, IRC and otherwise good community support. Python and web2py both fit into this category.

Pre-Reqs

Learning to code is hip. CodeAcademy signed up tens of thousands and learn to code blogs are popping up all over the place (like this one). What follows are some skills, tools, and attitudes that will make your path to Coding Nirvana that much easier.

Learn to Type

You should know how to type proficiently. Writing code is done with a keyboard and though python is very forgiving, you will still have to use curly brackets, underscore and parentheses far more than you ever have. It gets better with progress, but if you’re a two finger typer, take a typing course and learn how to properly type. You’ll be happy you did.

Use Ubuntu

If you already use Ubuntu, open gedit / Text Editor now, type in

print "Hello World"

save it as hello.py in your home folder then open your terminal and type

python hello.py

and Viola! No need to install python, no need to find an editor and learn how to use it. You’ve already written your first program.

Now if you’re using some other operating system, there’s still hope. I can’t help you get up and running in Python but this link can. I’m no fan of either Windows or Mac OS X so if you want to use any other OS, good luck. I recommend you install Ubuntu as a virtual machine on your computer, especially if you use Windows. Most developers use a nix operating system (aka some Linux distro, Mac OS X, etc) and though all the cool kids are using Apple products these days, it is preferable to Windows.

Command the Command Line

You don’t have to be a super genious to work at the command line and you don’t need to know a ton of commands. Changing directories, moving files, opening files, and a few other handy commands should do the trick. Zed Shaw has a crash course here.

Google (the verb)

Effective google searches will come in handy. There’s no shame in using Google. Everyone does it, even experienced programmers. Google ‘effective google searches’ to learn more about that.

Love the Journey

This isn’t going to be easy. You’re going to want to quit. You’re going to feel really stupid sometimes and bang your head against your desk. A love for solving problems and tinkering (aka hacking) is needed to get past the introductory stages of programming.