@adamghill

Pretty sure everything here is wrong

RSS Feed

Curated list of software bootstrapping resources

Comments Off

Bootstrappers, microISVs, micropeneurs, small software businesses — whatever you want to call them, they are way more interesting (to me, anyway) than the over-hyped Silicon Valley bullshit that so many are infatuated with.

Unfortunately, sometimes it is hard to find information about going this route, so I figured I would cull the links I have floating around and share the love. They inspire me to continue to pursue my passions even if I am not making any money (yet).

Blogs

  • Kalzumeus Software: Patrick McKenzie (or patio11 on the internets) is the creator of Bingo Card Creator and an email marketing/SEO maven; BCC has made more than $250k selling bingo software to elementary teachers; did consulting for 2 years with the likes of Fog Creek; has started a new venture in the more enterprisey space with Appointment Reminder
  • Software By Rob: Rob Walling (along with Mike Taber) coined “micropeneur” for their specific style of one-person startup; automation and virtual assistants are used to scale out parts of the business; suggests attempting to tackle small niches that don’t require large amounts of resources; wrote Start Small, Stay Small; runs Micropeneur Academy and MicroConf
  • Unicorn Free: Amy Hoy details bootstrapping Freckle Time Tracking; very opinionated and design-oriented; heavy into UX and JavaScript; wicked sense of humor
  • Dan Norris: started inform.ly; heavy into content marketing strategies; very open with sales figures and take-aways

Podcasts

I used to listen to a lot of other podcasts in this space, but these are the two that I’ve continued with and I enjoy the most.

  • Startups for the Rest of Us: Rob Walling and Mike Taber talk about their current products (HitTail/Drip and AuditShark, respectively), talk about current topics and answer listener questions; very focused; very actionable
  • Bootstrapped: Ian Landsman and Andrey Butov talk about their current products (HelpSpot/Snappy and UberDeck, respectively), have guests, and mostly chew the fat; less actionable, but always interesting
Filed under startups

Git completion in your shell

Comments Off

This will enable git <tab><tab> and, even nicer, git branch <tab><tab>. From your favorite shell:

git --version</li>
wget https://raw.github.com/git/git/v{GIT_VERSION}/contrib/completion/git-completion.bash
sudo cp git-completion.bash /opt/local/etc/bash_completion.d/git-completion

To update your prompt to include the current branch, update your PS1 in ~/.bash_profile to something like this:

PS1='\u@\h: \W$(__git_ps1 "(%s)")\$ '
Filed under git

Installing NodeJS 0.8.x on WebFaction

Comments Off

WebFaction has been great for the $10 I pay per month. Their forum (based on StackOverflow) also has a ton of users with some great information. The only issue is that their default Python install is 2.4.x and most everything expects at least 2.6 at this point, including installing NodeJS. I finally got everything working by following these links:

Filed under node.js, webfaction

The Cost of Jealousy

Comments Off

TechCrunch comments are the dregs of coffee in the bottom of my french-press-brewed cup of joe: bitter and cold. This happens on HackerNews as well, but it seems the signal to noise ratio on TechCrunch is incredibly low. Very rarely are the negative comments constructive or even helpful. I also sometimes fall into the same trap and it seems like my thoughts fall into either of these forms: ”I could do that” or “I did that”.

I could do that

As a developer, every day I look at problems and try to figure out how to solve them. As if by magic, my brain automatically jumps to piecing together a solution. The same happens when I look at a website. Unfortunately, all I see is the external surface. I see the current user interface and the current use cases that are being solved. What I don’t see is the thousands of technical iterations to get to the product, the involved learning about the market, any internal tools, the hardware scaling issues, the network configuration, the user interface wireframes, the brainstorming about features, or the marketing to get actual users.

In other words, if you say you can build Pinterest in a week, then you are probably missing a lot of what actually attracts so many to Pinterest.

I did that

Oh, I built a Pinterest/Stackoverflow/Hackernews/Instagram clone in a week? Fantastic. Where is it? How many people use it? What happens once I have 410TB of data?

Even without technical challenges, for a sufficiently experienced developer, the expertise to build a product might be relatively easy; however, you still need to know what a customer wants and get them to your site.

Who isn’t commenting on TechCrunch stories about what they could do, or what they did? Actual entrepreneurs. They know the struggle. They don’t have the time to whine because they have their own  bugs to fix, features to build and users to please.

Filed under hackernews

Developers don’t know how easy they have it

Comments Off

Are you a developer? Is it a stressful day? Do you have another meeting with HR about what is and what is not considered a respectful hand-signal? Are you tired of dealing with that legacy system that no one else knows anything about? Sick of debugging SOAP calls or pulling an extra angle bracket out of your XML?

You get paid to sit at a computer and push buttons.

Yes, I know your job is much more complicated (yes, your job has way less to do with pushing buttons than most people think), but that is ostensibly what you do.

I started working when I was 12, which I am not even sure was legal. I think back on all of the jobs I had before and realize how difficult it is to complain about writing code for a living.

In roughly chronological order I have: assisted in an office, cleaned offices, taught gymnastics and swimming to children, landscaped for a summer, cooked in a terrible restaurant until 3 AM, stocked shelves and handled customers in retail, took scalding metal cabinet off the line in a factory, helped users in a computer lab in a college library, setup website and performed general computer help for a client, setup websites and took 100-200 pictures per day for a sleep-away camp, programmed as an intern at a floundering startup, programmed as a developer at the aforementioned startup, and then programmed at my current job.

Sometimes I find it helpful to have a little perspective and reflect on my past experiences when my day turns into a disaster.

Filed under work

No one cares about your programming language

Comments Off

No one cares about your programming language.

Well. No one should care. If you are writing something in Ruby and, out of the blue, someone tells you to rewrite it in Python, you can safely discount their opinion.

It just doesn’t matter.

If you like CoffeeScript, then who cares that others don’t? Knock yourself out.

Think Java is the bee’s knees? Go ahead, boss.

I am pretty sure that no language is perfect for every situation. All languages were designed with certain pre-conceived notions of the world, how to interact with it, and what is important (or not). Every language has implicit trade-offs.

I mean, yeah, sometimes it actually matters.

If you are Twitter it might matter.

But, you aren’t Twitter (unless you actually do work at Twitter, in which case, why are you reading this?!).

If you want pull requests, then maybe you should reconsider writing your website in brainfuck.

If you are doing high-frequency trading, maybe you shouldn’t write in Ruby.

But, if you are a website that just “does some stuff”? Who cares. Solve the pain-point. Fix the problem. Make the world better.

Try a new language every third side-project or so and you will soon find a language that fits your brain. Write in whatever language has the best ecosystem. Write in the language that allows you to churn out code quicker. Whatever allows you to resolve your issue in the least amount of time.

Being wed to a programming language is like only driving Fords. Why artificially limit yourself? You already know how to drive, so try something else out. Try a stick shift. It will blow your mind. It will provide context for the automatic.

The world is full of those with opinions they mistake for facts. People with no context of the actual problem, but lots of solutions. Your choice of programming language is probably not the issue. They are the new religion of the technical theocracy.

Filed under misc

I’m famous

Comments Off

Callbacks considered a smell received over 1,000 hits, mostly from HackerNews. And that was just with the submission on the new page (it didn’t get anywhere close to the homepage). It is probably the one and only time any prose I have written has been read by so many people.

Weirdly, I sort of obsessed over watching the Google Analytics numbers rise all day, even though I didn’t spend that much time actually writing the post. Writing the sample code took a night, but was really for an informal presentation at my job. 1,000+ visits is nothing for any internet-famous blogger, but apparently obscure people who write link-bait headlines can get a little bit of traffic, too.

Filed under Uncategorized

Callbacks considered a smell

Comments Off

Here are the ways I have approached dealing with nested callbacks in my own JavaScript code. My samples all set 3 keys in a fake database, then retrieves those 3 keys and prints the values as a decent approximation of dealing with callbacks and I/O. These samples were part of a Intro to Node.js talk I gave at The Motley Fool.

Callbacks

This what was my JavaScript looked like when I first started writing callback-heavy code. It quickly gets unwieldy and hard to refactor because of the nested anonymous functions, and the implicit dependencies.

var db = require('./db/callbackDb');

db.set('key1', 'value1', function(err) {
	if (err) throw err;

	db.set('key2', 'value2', function(err) {
		if (err) throw err;

		db.set('key3', 'value3', function(err) {
			if (err) throw err;

			var str = '';
			db.get('key1', function(err, value) {
				if (err) throw err;
				str += value + ' - ';

				db.get('key2', function(err, value) {
					if (err) throw err;
					str += value + ' - ';

					db.get('key3', function(err, value) {
						if (err) throw err;
						str += value + ' - ';

						console.log(str);
					});
				});
			});
		});
	});
});

Events

If you have the ability to change your underlying code, you can add an EventEmitter so you can follow the observer pattern. My fake evented database has been updated with a wrapper that fires when the functions are finished.

var db = require('./db/eventedDb');
var str = '';
var counter = 0;
db.eventEmitter.on('onGet', function(value) {
  str += value + ' - ';
  counter++;

  if (counter === 3) {
    console.log(str);
  }
});

db.eventEmitter.on('onSet', function(key) {
  db.get(key);
});

db.set('key1', 'value1');
db.set('key2', 'value2');
db.set('key3', 'value3');

Promises

Promises (or defereds or futures) are a way to represent the outcome of an asynchronous call. They used to be included in the core of Node.js, however, they were pulled out around 0.2. However, There are a many user-land modules that attempt to follow the promises interface. For more details on promises, this article explains them in much more detail. For promises to work, you have to return a promise object from the underlying code, so my fake db got some more love.

var db = require('./db/promisesDb');
var str = '';

db.set('key1', 'value1').then(function(key) {
	return db.set('key2', 'value2');
}).then(function() {
	return db.set('key3', 'value3');
}).then(function() {
	return db.get('key1');
}).then(function(value) {
	str += value + ' - ';

	return db.get('key2');
}).then(function(value) {
	str += value + ' - ';

	return db.get('key3');
}).then(function(value) {
	str += value + ' - ';

	console.log(str);
});

Control flow

In addition to the basic promises concept, there are many control flow modules that help sequence asynchronous calls. I used caolan’s async because that is the one I am most comfortable with, but there are a ton floating around. Most of them allow you to parallelize a set of async calls and wait for their end result, or force async calls into a particular series.

var db = require('./db/callbackDb');
var async = require('async');

async.series([
  function(callback) {
    db.set('key1', 'value1', function(err) {
    	callback(err);
    });
  },
  function(callback) {
    db.set('key2', 'value2', function(err) {
    	callback(err);
    });
  },
	function(callback) {
    db.set('key3', 'value3', function(err) {
    	callback(err);
    });
  },
  function(callback) {
    db.get('key1', function(err, value) {
    	callback(err, value);
    });
  },
  function(callback) {
    db.get('key2', function(err, value) {
    	callback(err, value);
    });
  },
  function(callback) {
    db.get('key3', function(err, value) {
    	callback(err, value);
    });
  }
],
function(err, results) {
	// results = [ undefined, undefined, undefined, 'value1', 'value2', 'value3' ]
	var str = '';

	results.forEach(function(result) {
		if (result) {
			str += result + ' - ';
		}
	});

	console.log(str);
});

Named functions and Modules

In my opinion, the best way to escape callback hell is to split your code into modules that do one particular thing with named functions. This is basic code refactoring, but it becomes pretty important when dealing with nested callbacks. My fake database has been wrapped once more which lets our code be more succinct.

var db = require('./db/wrapperDb');

function concatValues(keys, callback) {
	db.getValues(keys, function(err, values) {
		if (err) return callback(err);

		var str = '';

		values.forEach(function(value) {
			str += value + ' - ';
		});

		return callback(null, str);
	})
}

db.setValues(['key1', 'key2', 'key3'], ['value1', 'value2', 'value3'], function(err, keys) {
	if (err) throw err;

	concatValues(keys, function(err, str) {
		if (err) throw err;

		console.log(str);
	});
});

Hopefully this article gives developers some more ammunition when faced with nested anonymous functions in their own forays into JavaScript.

Filed under node.js

Stable or Volatile: Uh… both?

Comments Off

Rands (from randsinrepose.com) posted Stables And Volatiles the other day and my visceral reaction is… ugh. Let me step back and try to break that down into something constructive.

First, I just finished Managing Humans, so I’ve recently had my fill of Rands’ writing and I might just have an overdose of quirky anecdotes that get generalized into two personalities that people are. Not personalities that people have bits of. Not, sometimes people exhibit some of this or that. No, people are stable, or are volatile. It might be fun to throw people into buckets, but it probably isn’t all that helpful.

For all the dumb corporate-speak, Predictable Success and The Synergist have been much more helpful to me trying to figure out my place in corporate America — which is to say, understanding why some people just rub me the wrong way. They’re smart, they get things done, people seem to like them — but for some reason when I work with them, I seem to spin my wheels and there is frustration from both parties. I used to just chalk it up to personality quirks, but having a better framework (and language) actually helps.

Rands also mentions “that many successful Stables used to be Volatiles who are recovering from the last war”, but I wish he had gone further. I’d posit that some Volatiles used to be Stables that are just tired of being bogged down by “going slow”. Or sometimes people flip-flop depending on the context. Or, they are like me and mentally flip between the two numerous times before making a decision.

The best developers I know are those that know when to be pragmatic and when to be audacious, when complexity is required and when simplicity is is beneficial, when to doggedly pursue and when to give up the ghost. Painting people with broad generalized strokes sure is fun, but doesn’t seem as productive as learning how you best work and how to get the best out of your co-workers.

Filed under work

Installing Django on Heroku

Comments Off

Getting Django up and running on Heroku was a little more of a challenge than what I would have liked. Here are some notes.

“You need to specify NAME in your Django settings file.”

You need to promote the database to set up DATABASE_URL (from stackoverflow).

heroku pg:promote HEROKU_POSTGRESQL_<COLOR>

Most of my other tricks were cribbed from the Django/Heroku quickstart for existing applications, however, I did find out that even if you override INSTALLED_APPS with another settings file, it doesn’t seem like Heroku picks up on the changes. It does work for other variables, though.

Filed under django, heroku

GitHub

GitHub Octocat

adamghill @ GitHub

  • Status updating...