Category: Skills

Automation: The Rule of Three

How many licks?

Building, Fixing, Writing, Saying something?

Do it one time – sounds good

Do it twice – a bit annoying

Do it three times – you’ve crossed the line


If you have to do the same thing the same way three or more times? Time to automate it.

Write a script, built a bot, buy a program, whatever.

You might spend as much time, or even a little more, automating it, but then the 4th+ times are free, performed accurately and correctly, and taken off your plate.

Now you can do something fun.

DRYing up tasks makes life easier

When writing scripts that perform the same task over and over again with different parameters, it is tempting to just cut and paste. Here’s an example of a bash script:

#!/usr/bin/env bash
grunt make_magic --dir=/foo
grunt make_magic --dir=/bar
grunt make_magic --dir=/lorem
grunt make_magic --dir=/ipsum
grunt make_magic --dir=/magnum

Imagine that goes on for hundreds of directories!

This isn’t very DRY. If we wanted to add an extra parameter to the grunt command, we’d have a lot of editing to do.

If we needed to do another command on those very same directories, we would have to enter the directory names again. As you can see, it would be very easy to forget to add all of them.


DRY stands for “Don’t Repeat Yourself”. If some code or commands are duplicated elsewhere, that’s a sign that there are inefficiencies in the code.

The idea behind this is to pull out common code into functions/methods. When a change to that code is required, it only needs to be made once. If a bug is identified in the code, once it is fixed, it is fixed “everywhere”.


Let’s take the example above and dry it up. We have to run the same command with different parameters (directories), so we will create an array of directories:

DIRS=( foo bar lorem ipsum magnum )

Now we write a “for…each” loop to do something for each element in the array:

for thedir in "${DIRS[@]}"; do
grunt make_magic --dir=/$thedir

This works on each element of the DIRS array and assigns it to thedir variable, which is now available inside the block.

Using this technique, it is very easy to add additional commands and/or directories.

How (not) to use Story Points

Abstract (tl;dr)

Story points should never be used to represent hours, but simply relative size of effort to complete a story. Over time, the team will tend to complete a consistent range of story points each sprint. Trying to tie story points to duration breaks the model and leads to inaccurate forecasting. Points should not be used to compare teams, nor should they be used to compare bugs.


In Agile projects, each work packet is called a Story. Each story has a point value assigned to it.

I prefer to use the Fibonacci scale for story points.

1, 2, 3, 5, 8, 13

Each number is the sum of the previous two numbers (3 = 2 +1; 8 = 5 + 3; etc).

But what do these points mean? We will get to that in a minute, but first let’s examine how difficult it is to estimate sizes.

Glass of Water

English: Glass of water sitting on a coaster.

How many ounces of water is in the glass? If you’re like most people, that is not an easy thing to guess.

On the other hand, if I compare it to the glass below, I might say is has roughly twice as much water, and I would be mostly correct.

en: A glass of water / de: Ein Glas Wasser / t...

This is the concept of story points.

1 is the baseline amount of work.

2 is twice as much effort

3 is three times as much, and so on.

Either 8 or 13 are “too big to do”—otherwise known as EPICs—and are slated to being broken up into smaller stories later.

The reason this is done is because it is easier for humans to judge a relative size than an absolute size.

Smallest amount of work

The effort of the smallest amount of work is considered a “1”. For web projects, this is often the effort required to change some element’s CSS style (color, font, size, etc).

Every other story is compared to this task.

Count the points

During the course of the sprint, the team completes the stories. And the end of the sprint, all completed story points are summed and that is the number of points completed for that sprint. After 3-4 sprints are completed, the average number of completed points for the prior three sprints is a good indicator of the number of points the team will complete in the next sprint.

Sprint 1 Sprint 2 Sprint 3 Average
14 18 14 15 (rounded down)

As you can see, points cannot be hours because the number of points varies, based upon many factors:

  • Team members’ skills
  • Team leader’s leadership
  • Distractions/work environment
  • Complexity of work
  • Tools/equipment quality

Points are not fungible

fungible (fŭnˈjə-bəl)

adj. Interchangeable.

Points are not fungible, that is, they are tied to the team. One can’t judge one team’s performance against another’s by counting points, because of the factors that cause variability in points. One team might complete 15 points in a sprint, while another might complete 40. The first team is not worse than the second team; points mean different things for the two teams.

Bugs don’t Point

Donald Trump enters the Oscar De LA Renta Fash...
HUUUUUGE! ( Wikipedia)

You can’t point bugs. Well, you can, but you’re making a huge (huuuuuge) mistake. When pointing stories, one needs to explicitly lay out the tasks required to complete the work. Then, that work is compared to the Smallest Amount of Work and given a point.

Bug HAVE NO defined tasks required to complete the work because no one knows what is causing the bug. What are the exact steps required to fix it? There aren’t any; one simply works the problem until it is fixed.

For example, let’s take the “bug” of me losing my car keys. How late will I be? If I estimate the tasks to find my keys, it will be something like:

I will look:

  1. In my backpack
  2. On the table
  3. In my pants
  4. On the kitchen counter
  5. On the bathroom counter
  6. On the nightstand next to my bed
  7. Under the nightstand next to my bed

Given all that, when will I find my keys? After #1? After #8? Later?

If I’m going to hire you, I don’t want to read your resume

Well, I take it back. I want to remember your name, and I’m terrible at names. So it helps if I have your name in front of me.

Dead-Tree Resume

“But,” you ask, “How will you know if the candidate has the skills and experience you need?”

Good question. Let’s look at the purpose of an interview.

The Two Questions

An interview must answer two questions:

  1. Can the candidate do the job now and in the future?
  2. Will the candidate be a good fit for the team?

Neither of these questions are answered by the candidate’s resume.

Wait a minute

Unless the candidate worked for a company doing the exact work, for the exact clients you have, their experience will not tell you if they can do the current job at your company.

Put it this way: would it make sense to compare your company to another in a different industry, with different customers and a different product, and then make a judgement about performance based upon that comparison?

Company Industry # Customers # Employees Product
MyCorp Pharmaceutical 3 7 Blue Pills
Acme, Inc Energy 150 70 Batteries
Initech Accounting Software 3,200 1,500 TPS Reports

We will investigate the 2 questions in a future post.

Adding defensive sanity checks

I recently needed to make a set of several favicons, so I went to the web to see if anyone had a script I could borrow steal.

Sure enough, I found one written by Joshua McGee: “Create a favicon with ImageMagick” (not reproduced here for copyright reasons).

It was a simple enough script, just a series of escaped commands. I noticed, however, that it assumed a few things:

  • An image file was specified on the command line,
  • The image existed, and
  • Imagemagik was installed.

In other words, the script was not developed defensively. This makes sense: it was just a bang-out.

The script had no inline documentation, and if a favicon file that already existed in the current directory would be silently overwritten—not good.

I’m clumsy: I delete and overwrite files all the time, so I could use a little help. Maybe I can tidy up the script? (more…)

The importance of turning on debugging

Debugging a php script with emacs in geben mode.
Debugging a php script with emacs in geben mode. (Photo credit: Wikipedia)

I was recently testing some wordpress plugin code for an upgrade. As part of my testing, I turn on debugging to see if any errors or warnings show up.

Imagine my surprise when several errors appeared, many of them deprecation warnings. After troubleshooting to determine the source of the errors, I discovered it was coming from the theme I was using.

Without turning on debugging, the site appears to behave normally, which is problematic. One of my objections to many languages and frameworks is that they hide problems from the developer. In many cases, for example, deprecation warnings don’t mean much—except they’re a ticking time bomb. At some point in the future, the code is going to break. Better to fix it now while it is easier to do, than scramble to diagnose and fix lots of code just after an upgrade.

In the case of WordPress (or PHP in general), it would be helpful if the admin area showed everything – bugs and warnings. For novice admins, of course, this would be a support nightmare, as they would have little clue what was going on. The upside is (hopefully) sloppy coders would fix their stuff promptly. Nothing will get a plugin/theme pulled faster than getting an error right after installing it.

Development Languages are not Just Syntax

I recall a conversation I had with a coworker years ago. This fellow mentioned he thought differences between languages (e.g., Perl and PHP) were simple syntax.

example of Python language
example of Python language (Photo credit: Wikipedia)

This is true, sort of. The nuts and bolts for each language (displaying a variable’s value and the like) are same in concept and similar in construct.

<?php =someVar ?>


<% puts someVar %>

You get the idea.

The difference (and where the coworker was wrong), is the concept of how the data flows through the system and which pattern(s) are encouraged/discouraged.

Some languages encourage MVC, whereas others encourage spaghetti and still others encourage a hybrid (or something else entirely, like modules).

What is a language best at?

Going beyond this, what is the language best at doing? Is it installed in places you want to host your code? Do you have data structures/stores that fit better with one language than another?

Picking the best tool for the job is important in delivering a quality product. Choosing which language to use isn’t trivial and can make it easier—or harder—to deliver the solution.


Goals differ from intentions or ideas in several key aspects.

Every goal:

  • Has a deadline
    • A goal is achieved at some point in the future. By having a deadline, the goal is focused, even if the deadline is not specific: “next week”, “next year”, etc.
    • A goal without a deadline is an intention.
  • Is measurable
    • One or more conditions that indicate when the goal has been reached, such as “built my house” (the house is ready for occupancy); “completing a course” (I passed the final / learned the material); “saved up to buy a car” (I have enough money to buy the car)
  • Has an owner
    • The person responsible for moving work forward to achieve the goal; may not be the same person as the one who does the work.
  • Must be reviewed on a regular basis
    • Conditions and people change, so it is important to review every goal to determine if it needs to be adjusted to fit reality.
    • Sometimes goals may no longer be necessary so continuing to pursue them is time better spent in other ways.
    • Some questions to ask about every goal:
    • is it necessary/desired?
    • is work on track to finish by the deadline?
    • is the deadline still applicable? and
    • is it still achievable?

How to ask for help the wrong way

When submitting  bug reports, it is a good idea to

A room full of computers all showing the BSOD

  1. Realize that you’re asking for help from people who (usually) have day jobs, and
  2. Expend at least some amount of effort to show you’re not expecting someone else to do all the work.

With that in mind, let me introduce to you the Best Bug Report Comment, Ever

First the bug report:


I don’t have the exact errors to post because I deleted my compile log, but they are the same errors you get if you don’t have the bzip2 development libraries installed, which of course I do in /www


Then someone helpful asks for more information.

Please recompile so that you can tell us te exact errors.


And then, GOLD:

The php developer who added/maintains bzip2 support will know what I am talking about. I am not going to compile when I know this! It would be a waste of my time.


Now, not to worry; a few minutes later the submitter saw the error of his ways, compiled his code, posted the exact error message and got help.

Learning how to ask questions is a skill. Mastering this skill can only help, because everyone (even the Super-cool techno guru) has to ask for help at some point, so why not be as effective as possible?

Until I find another one. That place is GOLD!

Enhanced by Zemanta