Don’t only track your time for clients

Tick tock. Tick tock.

I think time tracking is one of the top complaints freelancers have about the business. (Right below finding clients and dealing with problem clients)

You’d think by now it would be a solved problem. I mean, the only thing you’re doing is keeping track of what task you’re working on when you’re working.

It’s nowhere near as complex as the US tax system.

It’s not like it’s rocket surgery.

Yet it’s still a major complaint amount freelancers.

Yummy, yummy data

I’ll admit it. I’m a data and numbers person. I like metrics and measuring. I always have.

Since I’m so numbers-oriented I started tracking my time right away when I started Little Stream Software in 2007. And I’ve continued to this day.

I even track my time on non-client projects and internal stuff like taxes and email.

There is one benefit that many freelancers miss when they decide to ignore time tracking,

I track my time to know how much of it is used on good tasks and on bad tasks.

Time spent on the phone selling a client: good task.

Time spent on the phone to get a server fixed: bad task.

Value is in the review

Tracking time, it and of itself, isn’t that valuable. It’s valuable when you analyze and review that data.

Every few months I’ll do an analysis of where I spend my time.

  • How much time did I work on billable client work?
  • How much time did I work on my products?
  • How much time did I spend on marketing?
  • How much time did I use on other tasks?
  • How long were my days, on average?
  • How long were my weeks, on average?

And most important of all:

  • Are there any long-term trends in these?

This analysis let me discover many things in the past, such as:

  1. I was billing most of my time but wasn’t marketing, which lead to a lean time a few months later.
  2. My total billable time each month for each client would fit into a month, which lead to replacing my hourly rate with a weekly rate.
  3. There’s an average of 20 days per month which I could bill.

I could have happened across these insights without tracking my time, but they would have just been guesses. Realistically, I wouldn’t have seen them at all.

Even if you don’t track all of your time, try to do an analysis like this on the time you do track (e.g. client work). You might be surprised at what you find.

Eric Davis

Want weekly freelancer training like this?

QUnit – Tech Learning

This post is part of my tech learning series, where I take a few hours each week to try out a piece of technology that I’d like to learn.

This time I’m back to using JavaScript but instead of using a framework or library to build an application, I decided to try out the testing framework called QUnit.

QUnit came from the jQuery project and is now a general purpose JavaScript testing framework. I’ve used Jasmine for my JavaScript testing in the past but I’m not a fan of the BDD/spec style it uses. Maybe that’s because I learned unit testing on Ruby’s Test::Unit but I’ve always preferred assert style tests over expect.

Testing with QUnit

Since I don’t want to build an application just to use QUnit, I decided to port an existing test suite from Jasmine to QUnit. My A/B Test Calculator was the perfect candidate:

  • it’s small
  • it’s self-contained
  • it has an existing, high coverage test suite

Getting started with QUnit was easy. Their documentation was pretty through and all that I needed was to create an HTML file that did a few things:

  • loaded the QUnit css
  • had a div with the id of qunit
  • had a div with the id of qunit-fixture (though I didn’t use it in these tests)
  • loaded the QUnit JavaScript
  • loaded my test suite


One thing that threw me for a loop was I was trying to use grunt to run the tests on the commandline. Normally QUnit runs automatically on the page load, but in Grunt that wouldn’t work.

Instead, you need to stop QUnit from starting automatically, load your tests, and then start QUnit manually.

  <script src="qunit-1.14.0.js"></script>
  <script>QUnit.config.autostart = false;</script>
  <script src="tests.js"></script>

Test layout

Instead of using nested functions or methods like Jasmine and Ruby to separate contexts, QUnit takes a simpler approach. Making a function call to QUnit.module("name") will end your current context and start a new one.

At first I thought this was confusing but it actually prevented my tests from getting deeply nested. I could see this being an advantage when refactoring tests because you wouldn’t need a dummy commit to re-indent everything after moving code around.

Each module can also have setup and teardown functions that run but none of my tests needed them.


Each test is started using QUnit.test("test name"), function(assert) with the function acting as your test body. The assert object is where your assertions are called on. Though I wouldn’t do it, you could use a different name like expect and make it spec-like:

QUnit.test("test name"), function(expect) {
  expect.equal(a, b)

Calling it should might be interesting though:

QUnit.test("test name"), function(should) {
  should.equal(a, b)

Running QUnit tests

Running the tests couldn’t have been easier. I was using grunt on the commandline and they’d work exactly how you think.

I was also able to open the test HTML file in a browser using file:/// and QUnit worked exactly how you’d expect.


I really enjoyed using QUnit. It feels more direct and simple than Jasmine though I don’t know how many third party libraries are out there for it.

I’d also be curious to see how to integrate it with Rails and the asset pipeline. That’s one of the main reasons why I started with Jasmine, it had some great Ruby integration and it felt like a good fit there.

I’ll definitely be adding QUnit to my standard toolkit. It won’t be replacing Jasmine yet, at least until I get an opportunity to try QUnit in Rails and in a production application.

Would you like to hire me?


The HTML test runner which loads the tests and qunit.

<!DOCTYPE html>
  <meta charset="utf-8">
  <title>QUnit Tech Learning</title>
  <link rel="stylesheet" href="qunit-1.14.0.css">
  <div id="qunit"></div>
  <div id="qunit-fixture"></div>
  <script src="../src/qunit-tech-learning.js"></script>
  <script src="qunit-1.14.0.js"></script>
  <script>QUnit.config.autostart = false;</script>
  <script src="tests.js"></script>

The test suite which has two modules.

QUnit.test("sanity test", function(assert) {
  assert.ok(1 == "1");
QUnit.test("SplitReview loaded", function(assert) {
// Based on abingo and http://20bits.com/article/statistical-analysis-and-ab-testing
var treatmentA = [
  { impressions: 182, conversions: 35},
  { impressions: 180, conversions: 45}
var treatmentB = [
  { impressions: 182, conversions: 35},
  { impressions: 189, conversions: 28}
var treatmentC = [
  { impressions: 182, conversions: 35},
  { impressions: 188, conversions: 61}
var treatmentD = [
  { impressions: 182, conversions: 35},
  { impressions: 189, conversions: 14}
var treatmentE = [
  { impressions: 182, conversions: 282},
  { impressions: 189, conversions: 114}
QUnit.test("should return a scoring object", function(assert) {
  var result = SplitReview.score(treatmentA);
  assert.equal(typeof(result), "object");
  assert.ok(result.z, "z should be defined");
  assert.ok(result.p, "p should be defined");
  assert.ok(result.winner, "winner should be defined");
QUnit.test("should show the experiment as a winner against treatment A at 90%", function(assert) {
  var result = SplitReview.score(treatmentA);
  assert.equal(result.a_rate, 19.23);
  assert.equal(result.b_rate, 25.0);
  assert.equal(result.winner, 'b');
  assert.equal(result.z, 1.33);
  assert.equal(result.p, 0.10);
QUnit.test("should show no winner against treatment B", function(assert) {
  var result = SplitReview.score(treatmentB);
  assert.equal(result.a_rate, 19.23);
  assert.equal(result.b_rate, 14.81);
  assert.equal(result.winner, null);
  assert.equal(result.z, -1.13);
  assert.equal(result.p, null);
QUnit.test("should show the experiment as a winner against treatment C at 99%", function(assert) {
  var result = SplitReview.score(treatmentC);
  assert.equal(result.a_rate, 19.23);
  assert.equal(result.b_rate, 32.45);
  assert.equal(result.winner, "b");
  assert.equal(result.z, 2.94);
  assert.equal(result.p, 0.01);
QUnit.test("should show the control as a winner against treatment D at 99.9%", function(assert) {
  var result = SplitReview.score(treatmentD);
  assert.equal(result.a_rate, 19.23);
  assert.equal(result.b_rate, 7.41);
  assert.equal(result.winner, "a");
  assert.equal(result.z, -3.39);
  assert.equal(result.p, 0.001);
QUnit.test("should show the control as a winner against treatment E at 99.9% (over 100% conversion rate based on unique counting)", function(assert) {
  var result = SplitReview.score(treatmentE);
  assert.equal(result.a_rate, 154.95);
  assert.equal(result.b_rate, 60.32);
  assert.equal(result.winner, "a");
  assert.equal(result.z, -12.27);
  assert.equal(result.p, 0.001);
Go logo, by Renée French

Go – Tech Learning

This post is part of my tech learning series, where I take a few hours each week to try out a piece of technology that I’d like to learn.

This week I decided to try something completely new and spend some time with Go.

Go is a programming language that has seen some success in system programming. My goal with learning Go is to replace some shell scripts and services I run.

This tech learning was a bit harder though, since Go is an entire programming language and a type of language I don’t have much experience with.


The official Go website has a lot of official documentation. The Tour of Go and How to write Go code sections were useful for me to get started. Other sites like Stackoverflow where useful for specific problems.

Todo list application with Go

Like other weeks, I wanted to build a todo list application with Go. I’ve done enough of them that I know the scope of the application, so I can focus on learning how Go works.

This time the application was going to be purely command line based. I know Go can be used for web applications but I wanted to keep things simple in my limited time.


That meant that the feature-set would stay small. But even then, I didn’t have enough time to complete them all.

  1. List all open todo items
  2. Add a new todo item
  3. Complete a todo item
  4. Delete a todo item
  5. Save todo items to disk for persistence


Being a command line application, my todo program would be using standard input and output for most of its work. I also figured I’d persist the todo items into a file, but I was open to the format of the file (e.g. serialized, json, text).

main(), command parsing

The first part was to accept commands from the command line. I’ve always like the svn and git style of subcommands over flags so I designed this application the same way. It would be called like:

todo list
todo add "The todo item text"
todo complete N
todo remove N

For this I found the os package with the os.Args function to work great. I had to do a bit of input handling to check the options but a multi-step if statement worked for that (which I plan to change to a switch later).

Once the correct command was found, the flow would be passed off to the instance of the todolist.

todolist and todo structures

The main object used is a todolist structure which holds an array of todos. These todos are composed of a name and a done flag.

My intention was to have a single todolist that would serve as the behavior for managing the list.


The list() function would take the existing todolist and print out every todo item to standard output. Nothing too complex here, just a for loop and fmt.Println.


The add() function would take a string, from the command line, and create a new todo item on the list with it.

The interesting thing here was how Go treats arrays and slices. Coming from a Ruby background, it felt odd. What would have been a simple append operation, took a bit of research to figure out. Even though I ended up using the append function, I couldn’t tell you if it was creating a new array, creating a slice, or creating a slice and converting it into an array.

The final code works and is simple to read, but I’d like to dig into what’s going on to better understand it later.

todolist.save() and todolist.load()

Before I was done I wanted to work on the persistence. What good is a todo list that isn’t saved?

(Actually, that might be a good idea if you’re overworked…)

I intending to have a function called save() that would take the current todo items and save them to a file, along with a corresponding load(). Ideally they’d be in a plain text or human readable format but I was open to any format really.

The problem I ran into was saving the todo items to disk. I needed a byte array to save to the file, but each todo item was using a string. Since there could be zero to a near-infinite number of todo items, I had to be dynamic in how I got each item. I tried a few different conversion methods but I couldn’t get them to completely work.

I’d like to blame my lack of a C background for this.

If I had a bit more time, I’m sure I could have figured it out.


Go was a different enough language from regular work so it stayed interesting. I was frustrated by the type system but I think that’s because I didn’t spend enough time with it.

The ability to compile to a static binary really appeals to me. That feature alone would make it worth porting some Ruby scripts I have to Go (e.g. text transformation, basic network I/O).

Overall, I’m still interested in Go. I’m not ready to port anything over to it or to take on a project that uses Go heavily, but I’m interested enough to learn more about it.

Need custom Ruby development?


package main
import (
type todolist struct {
	todos []todo
type todo struct {
	name string
	done bool
// 2. Add new
func (l *todolist) add(name string) bool {
	newItem := todo{name: name, done: false}
	l.todos = append(l.todos, newItem)
	return true
// 1. List open todos
func (l *todolist) list() bool {
	fmt.Println("Your todo list is:")
	for i := 0; i < len(l.todos); i++ {
		fmt.Println("- ", l.todos[i].name)
	return true
// 3. Complete
// 4. Remove
// command data
func main() {
	var command, data string;
	if len(os.Args) > 1 {
		command = os.Args[1]
	if len(os.Args) > 2 {
		data = os.Args[2]
	l := new(todolist)
	if command == "list" {
		// No-op, always print list
	} else if command == "add" {
	} else if command == "complete" {
	} else if command == "remove" {
	} else {
		fmt.Println("Unknown command:", command)
	// Always print

AngularJS – Weekly Tech Learning

This post is part of my weekly tech learning series, where I take a few hours each week to try out a piece of technology that I’d like to learn.

After last week’s experience with riot.js I decided to experiment with another JavaScript library/framework I’ve been hearing a lot about, AngularJS.

Angular bills itself as a way to extend HTML for dynamic views in web applications. This sounded a bit strange but after seeing how Angular works and embeds itself into HTML, it makes sense.


The first place I start with anything new is the documentation. I’m the kind of person who reads the manual for a new camera before using it.

Angular’s documentation really shines. The homepage has videos, several example apps, and there are a ton of resources deeper into the site.

What was really surprising is that Angular exceptions have a link on the JavaScript console that point to the angular website with details about what happened. This made debugging much easier because I could take my specific exception and find out what it meant in the more general sense.

Todo list application with AngularJS

Like my other applications, I built a todo list application with Angular. I’ve done enough of them that I know the scope so I can focus learning how Angular works.

Surprising, one of the demo applications on Angular’s homepage was a simple todo application. If you compare it to mine, you’ll notice I used much of the same code. But I still built my by hand so I can see how it works step-by-step.


Being a todo list, I kept the feature-set short.

  1. Single page app without refreshes
  2. List all open todo items
  3. Add a new todo item
  4. Complete a todo item
  5. Delete a todo item

Since the demo application did most of this, I had extra time to add a basic localStorage persistence feature.


The first thing I noticed with Angular is that much of its view is put into the HTML. You decorate various elements and sections with ng values to connect them to Angular. This was a bit shocking to me, since years ago there were movements to get JavaScript out of the HTML (unobtrusive JavaScript, progressive enhancement). To see non-standard HTML used by Angular felt odd, like a step backwards.

But if you go back to what Angular’s goals, it makes sense. It wants to extend HTML, which means it will be changing what I’d consider HTML.

The first hiccup I had was getting my controller to connect. I had my ng-app and ng-controller declared, Angular was loading, and everything looked right. But my controller kept appearing as undefined. After some debugging, I found I needed to use ng-app differently than the demo code. I needed to fully declare my app (ng-app vs ng-app='tech-learning').

Once that was in place, things started working like they were supposed to.

Data binding

Like knockout.js, AngularJS puts some control flow and loops directly into the HTML. In my case I needed that for listing each todo item with a standard template (ng-repeat). In that loop, {{todo}} was used to reference the current todo item, just like most templates.

Completing a todo

The interesting thing with the demo application is that they used only the data binding to mark a todo as complete or not. The checkbox has a ng-model="todo.done" which toggles the done value of a todo object. This happens automatically and it also changes the css class for the todo text. With some css, that means it automatically gets a strike-through when it’s completed, right from the checkbox.

This did cause a problem with my localStorage though. Because the view was accessing the model directly, I couldn’t call the function to persist the data. I’m sure if I had more time I could hook up the persistence a bit more transparently so ng-model would automatically save.

Controller (and Model, kinda)

With the HTML page acting as the View, a JavaScript file functions as the Controller. What was odd, coming from a Rails background, is that the Controller also embedded the Model. The Model wasn’t explicitly declared but you could see it.

Maybe this was because a todo list application is simple so it doesn’t need a separate Model. But it still seemed like keeping them together would be a bit of a pain to test and maintain over time.

Much of Angular’s View-Controller connection is done through the scope, or $scope in the code. This seems to be a shared object that the view can access as well as the controller where it’s passed in as a parameter.

Data and behavior defined on this scope object let the View call it. In fact, I guess this ease of callability is what helps Angular be easy to develop with.


The load() function was an addition that I added to support localStorage. Basically it checks localStorage to see if there are any todo items there and returns them.

This works in conjunction with the todos variable which is where the controller tracks the list of todo items (and which the View uses to build its list).


This function has three behaviors:

  1. Add a new todo item based on the form submission
  2. Clear the todo field name
  3. Persist the data to localStorage

The View is hooked up to this through the ng-submit="add()" declaration on the form. This works like a binding that takes the submit events and sends it to the add() function. The name field is also given a ng-model declaration so the controller can access it (e.g. getting the value, clearing).


I also wanted to be able to delete a todo item. The deleteTodo() function does this by searching for the todo item and removing it from the todos array.

The interesting thing was that I hooked it up using the ng-click and was able to pass in the current todo from the View. This meant I didn’t have to bother with ids or some unique key to search on.


The persist() function is just a simple little wrapper for saving the current todos into localStorage.

localStorage compatibility

Based on my experience with localStorage in the past, I’ve created a simple compatibility object for browsers who don’t support localStorage. All it does it mockup the API I need with no-op functions.

(In a larger application, this isn’t the best approach. Feature detection will notice this object and think that a browser actually does support localStorage. So watch out if you try this.)

Final thoughts

That’s it. All together, my AngularJS todo application is around 30 lines of JavaScript with a dozen or so of HTML. It’s one of the smaller ones I’ve built, which isn’t surprising since Angular is supposed to be a higher-level library than others.

Overall though, I wasn’t happy with a few things in AngularJS.

Code in HTML

I strongly dislike putting that much “code” into my HTML. I’ve seen too many teams start with a little bit of code and then they end up with a mess that is impossible to work in. (knockout.js also suffers from this.

With a good team, the right practices, and an eye for problems this could be worked around. But it’s easy to fall off.

(Granted the alternatives aren’t much better: building HTML strings in JavaScript is horrible and JavaScript templates can become a pain too. It’s not an easy problem.)

One plus with AngularJS from what I understand is that you can scope it to a specific part of the HTML document. So instead of one ball of mess, you might have several smaller Angular controllers.

(I also seems like SEO can be a bit of an issue with angular. Some people say angular content is invisible because it’s JavaScript, others say that Google will run angular code and see the content. All I know is that you’ll have to do your own tests if you have a public angular site.)

Large API

AngularJS’s API is large. Even if you’re just looking at the core, there’s a lot there. It seems like it also has its own API for events, which could be interesting if you use jQuery also.

As part of my advancing age, I’m starting to prefer libraries and frameworks with a smaller footprint. Not just in size but also in how many methods/functions they expose. Having less of an API to remember means more of my application can fit in my head.

It was good to see Angular has separated some components out of the core, which reduces both its size and API footprint.



I can see using AngularJS with some applications. I’m not putting it into my general purpose toolkit quite yet, but I’d feel comfortable working with it in an existing codebase.

I also hear the 2.0 version is going to have some significant changes which improve some of the problem areas.

If you’d like to use a demo version of the application, you can find a copy running at http://angular-tech-learning.apps.littlestreamsoftware.com/ with the unminified version of the JavaScript and localStorage.

Need custom JavaScript development?


Basic HTML page with the skeleton structure, ng declarations, and the todo list.

<!-- www/index.html -->
<!DOCTYPE html>
<!--[if lt IE 7]>      <html ng-app='tech-learning'  class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html ng-app='tech-learning'  class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html ng-app='tech-learning'  class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html ng-app='tech-learning' class="no-js"> <!--<![endif]-->
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width">
        <!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
        <link rel="stylesheet" href="css/normalize.css">
        <link rel="stylesheet" href="css/main.css">
        <link rel="stylesheet" href="css/app.css">
    <body ng-controller="TodoController">
      <ol id="todos">
        <!-- http://mutablethought.com/2013/04/25/angular-js-ng-repeat-no-longer-allowing-duplicates/ -->
        <li ng-repeat="todo in todos track by $id($index)">
          <input type="checkbox" ng-model="todo.done">
          <span class="done-{{todo.done}}">{{todo.text}}</span> 
          <a class="todo-delete" ng-click="deleteTodo(todo)" href="#">(X)</a>
      <form id="addNewTodo" ng-submit="add()">
          <input id="todoName" name="name" ng-model="todoText" />
          <button type="submit">Add</button>
        <!-- JS -->
        <script type='text/javascript' src='js/jquery-2.1.0.min.js'></script>
        <script type='text/javascript' src='js/angular.min.js'></script>
        <script type='text/javascript' src='js/tech-learning-angular.js'></script>

The full angularJS application, including the simple localStorage wrapper.

// www/js/tech-learning-angular.js
// Test if localStorage is present and supported in the browser
if (typeof(localStorage) == 'undefined') {
  localStorage = new Object();
  localStorage.getItem = function(key) { }
  localStorage.setItem = function(key, value) { }
  localStorage.clear = function() { }
var todoApp = angular.module('tech-learning', [])
  .controller('TodoController', ['$scope', function($scope) {
    $scope.load = function() {
      var todosJSON = localStorage.getItem("todos-angular");
      if (todosJSON) {
        return JSON.parse(todosJSON);
      } else {
        return [];
    $scope.todos = $scope.load();
    $scope.add = function() {
      $scope.todos.push({text: $scope.todoText, done: false});
      $scope.todoText = '';
    $scope.deleteTodo = function(todo) {
      var index = $.inArray(todo, $scope.todos);
      if (index > -1) {
        $scope.todos.splice(index, 1);
    $scope.persist = function() {
      localStorage.setItem("todos-angular", JSON.stringify($scope.todos));

Helping new entrepreneurs build a successful software business.

Need more freelance clients?