Wednesday, September 28, 2011

High Volume Morning

Some days I'm away from my computer for most of the day. Meetings, events, travel time, even the occasional vacation all conspire to keep me away from my computer and my inbox for a chunk of time. I'm also pretty religious about keeping my inbox small. These two things obviously do not go well together!

I get to work the next morning, or get to my desk after a morning of meetings, and I have a bunch of emails. Some just need to be read and filed, some need a lot of work, and some need quick responses or quick actions.

So I declare it a high volume morning. Here's how it works:

  • I scroll through my inbox and pick out something that looks easy and/or fast.
  • I try to do it.
  • One of two things happen:
    • I finish it (yay!) and dump the email out of my inbox
    • It's harder than I thought, and I make a task in OmniFocus for it and dump the email out of my inbox.
  • Repeat for about 3 hours, or until my inbox is empty again.
This is a little bit outside the norm of how I work, since I'm usually pretty good about putting together a task list and working my way down it, doing big hard things when I'm most productive (which for me happens to be mornings). But...

But I just plain feel better when my inbox is under control, and when people haven't had to wait for days for things that simply don't take very long to do. After all, it only takes about 15 minutes to check the receipt time for an order for a client - why should they have to wait just because it's lower priority than the large project? 15 minutes is a "slip it in between breaks" duration. Enough of these and I'm not making progress on the bigger projects I'm doing, but that's why I time box it.

Sometimes it's okay to break routine, and to get through all of the simple stuff.... after all, in the end it's about balancing the easy with the hard, the urgent with the "should happen at some point", and making it so your work environment - including your inbox - is a happy place.

Monday, September 26, 2011

The Closest Thing To

My work experience is almost entirely with smallish companies, up to about 250 people, tops. I've also had the great fortune to have very large companies as clients (10,000+ employees), with engineering teams topping 100 people for a single project.

One of the things I've learned is that when you have 100 people on a software project, you get to have specialists. You have people who are really great release engineers, or SCM management types, or build engineers, etc. On smaller teams, we don't get that.

Instead, we get the guy who is "the closest thing to" the job we need. For example, I'm no UI designer, but with one of my teams, I'm the closest thing to it. That means I get to cut the images for the website. Am I as good as someone who does this and only this? Nope, but I'm better than anyone else on the team. So I cut images, and I'm glad to do it.

It's one of the hardest things to learn your first time on a small team: you aren't perfect, but if you've got some background in the area, you may be the closest thing we've got. Congratulations, those tasks are now yours. It makes for an incredible learning opportunity, and can expose you to many different aspects of software engineering. So have fun, accept that you'll be doing things that aren't easy for you to do, and learn. Maybe you'll find a new natural talent!

Wednesday, September 21, 2011

Summary Hints

When we as an engineering team start implementing something new, we almost always start with a summary. This is often followed by discussion, explanation, UI designs, requirements specifications, stories, tasks, and a whole lot of other stuff. The summary looks something like this:

Create a performant dashboard that shows all the widgets and lets you frobble them.

Here is where you get your first hints about which parts of the system really matter, and which parts are niceties. If it's in the summary, it's important. It may be important because it's promised to a customer, or because they've been burned in the past by not specifying something, or because it's what makes your version different from a competitive product, or any one of a number of other reasons.

In our example summary, what's important?

  • Performant: This almost always just means "can't be slow" rather than implying "it's incredibly fast", but it also usually means that the person asking for the feature has been burned by something slow. Ask about this - performance will matter, and just saying, "it works on my fast connection with my pretty solid dev box" is courting rejection.
  • All: "All" rarely means "every single one all the time", but it does mean you'll be looking at showing a large chunk of data on the screen. This brings up fun UI and performance considerations. It usually also implies filtering, searching, and other "sounds easy but takes time to do" considerations.
  • Dashboard: This is a very common term for "our user is going to sit on this page and pretty much never leave it". Updates, reloads versus AJAX-style refreshes, etc., are all going to be considerations.
When you're hearing about a new feature, listen very carefully to the summary. It'll usually tell you about most of the major risk areas and time sinks, and it's the heart and soul of what the user really wants, instead of all the things they think of that sound good. The summary is the part that you need to get right.... and that'll give you a happy customer.

Monday, September 19, 2011

From Zero to Multi-Mechanize

I'm working on a new project and the preference is for Python for test code. The current piece of the project is creating some load tests. Now, there's no good reason to write my own load test framework from scratch, so I did some research and started evaluating Multi-Mechanize.

Getting it set up on my Snow Leopard system wasn't completely trivial, so here's what I had to do:

  1. Upgrade to Tkinter 8.5.10. This is needed to get 64-bit Python to run properly with matplotlib.
    1. See for background information.
    2. Download ActiveTcl 8.5.10
    3. This is a standard .dmg file, so double click and follow the bouncing prompts to install. Take all the defaults.
  2. Upgrade Python to version 2.7. This is needed to run the latest version of matplotlib.
    1. Grab Mac OS X 64-bit/32-bit x86-64/i386 Installer (2.7.2) for Mac OS X 10.6 and 10.7 from
    2. This is a standard .dmg file, so double click and follow the instructions in the installer. Again, take the defaults.
  3. Install numpy. This is a prerequisite for matplotlib.
    1. Go to the installer site. Do not click the link at the top! It's tempting, but that's for OS X 10.3 and won't work. (And by tempting, I mean I did this.) Scroll down and grab this one instead:
    2. Look! Another .dmg file. You got it. Double click, bouncing prompts.
  4. Install matplotlib. This one you'll have to actually compile on your own.
    1. Do not download the .dmg file; that's also for OS X 10.3 and won't work. Instead, grab the source from here:  matplotlib-1.0.1.tar.gz
    2. Unpack the source and put it in a useful (temporary) location.
    3. Open matplotlib-1.0.1/ in your favorite text editor.
    4. Line 832 looks like this:  (Tkinter.__version__.split()[-2], Tkinter.TkVersion, Tkinter.TclVersion))
    5. Remove the [-2], so that it looks like this: (Tkinter.__version__.split(), Tkinter.TkVersion, Tkinter.TclVersion))
    6. In matplotlib-1.0.1 copy setup.cfg.template to setup.cfg
    7. In setup.cfg, uncomment line 10 and change it to read: basedirlist = /usr/X11
    8. Install! python2.7 install
  5. Install mechanize. Needed for, surprise, multi-mechanize.
    1. Download it: mechanize-0.2.5.tar.gz
    2. Unpack the source and put it in a useful (temporary) location.
    3. Install: python install
  6. Install multi-mechanize. Last step, promise.
    1. Download it from the project site.
    2. Unzip it and put it in a safe location. This one isn't an installer; it just runs, so watch where you put it.
Overall the process is tweaky but not difficult. Just make sure you get the right packaging for everything (32-bit versus 64-bit, versions of OS X), and it works just fine. Now off to play with a new (to me) load testing tool!

Friday, September 16, 2011

Pick One Measurement

I've been working with a new client who is attempting to use a variation on Scrum. They have two week sprints; and each sprint starts with the whole team getting together and talking through the stories on the backlog, estimating them, and then committing to them. Each sprint ends with a demo and retrospective. They're using Rally, so they have a burndown chart that shows their progress through the sprint, and accepted stories, etc. This is all fairly standard.

They're also making a very common mistake: measuring the same thing two ways. They measure points and they measure hours.

Stories are sized by points: 1, 2, 3, 5, or 8 points. Points are relative indicator of how large the story is. A 1 point story is pretty small, and a 3 point story is larger than a 2 point story but smaller than a 5 point story. An 8 point story is code for "we dunno, but it's huuuuge!"

Tasks are estimated in hours: 1 hour, 2 hours, etc. This is purely free form; any value is allowed.

Here's the thing, though. Stories are made up of one or more tasks. This effectively means that stories are estimated at some number of hours, where the number of hours is the sum of all the task estimations. (Rally, incidentally, is happy to do the summation for you.)

Now stories have both points and hours, and they're both trying to get at the same thing: "This is how much effort we need to accomplish this story".  We end up with a list like this:
Story 1: 2 points, 10 hours
Story 2: 3 points, 11 hours
Story 3: 2 points, 6 hours
Story 4: 1 point, 8 hours

That's mostly just confusing. The 1 point story is going to take longer than a two point story? Two stories that are the same number of points are going to take fairly different amounts of time (6 hours versus 10 hours)? That's a lot to reconcile.

If this were source code, we'd be cringing and saying, "But it's not DRY!" It's roughly equivalent to having a do_stuff and do_stuff_2, where do_stuff_2 is a copy of do_stuff but uses integers instead of floats for the math. They're almost but not quite direct copies of each other.... confusing!

Same goes for our sprint stories. We're trying to accomplish one thing: estimating effort. Let's accomplish one thing one way. It'll cut down on the confusion, and reduce the amount of time we spend micromanaging stories and tasks in an attempt to achieve consistency.

Pick one. Points or hours, it really doesn't matter. Just pick one and only one.

Wednesday, September 14, 2011

Getting By in Portuguese

I spent the last week in Lisbon, Portugal. My husband was there on business, but I wasn't, so I was free to go wander around the city, see all the tourist traps, stuff myself silly with all sorts of delicious food, etc. All in all, a great time.

There was only one drawback: I don't speak any Portuguese at all. I did learn "obrigada", "bom dia" and a few other key phrases, but effectively I was mute. Now, I got lucky in that there were many helpful people who spoke English, and I was able to get by. I was also helped by context; for example, when I was buying a bottle of water, I knew the next phrase in a simple purchase was probably going to be the price, so I knew to get out my money. Gestures and other contextual indications let me complete transactions successfully.

Now what does this have to do with software?

It's all about language. I got by but didn't thrive in Portugal because I couldn't speak the common language. The same is true in software, and particularly in software management.

If you speak the common language - pipelines and queues, or REST APIs, or whatever your jargon is - you can thrive. If you don't speak the common language, you'll never do more than get by on context and people who are feeling helpful.

So learn the language - and thrive.

Wednesday, September 7, 2011

Weird Jenkins Thing

File this one under "I have no idea why this did what it did." Be warned, I have no explanation for this.

I have Jenkins running on a Linux box, with a Windows 7 slave box. I'm using a fairly standard (I think) setup on the slave box:
- Jenkins 1.428 (slave) running as a service as the local user
- msys-git (aka git bash) for Git
- git plugin version 1.1.12

In my general configuration, I set up "windows git", which points to "C:\Program Files (x86)\Git\cmd\git.cmd".

In my project, I specified my clone URL and branch. Everything else was set as the default. I'm using SSH, so my clone looked like ssh://git@myrepo/myrepo.git.

In Git Bash, I:
- created an rsa keypair
- added the public key to my git repo
- proved to myself that I could clone the repo

Hooray! All set up! I fired up Jenkins, clicked "Build Now", waited 0.31sec and watched it fail with this error:
ssh: myrepo: no address associated with name
The remote end hung up unexpectedly

Huh? Yeah, it looks like a DNS problem.

The solution:
  1. add myrepo to the hosts file
  2. restart the Jenkins service
I have no idea if this will work for you; I only know it worked for me. I can't say I love the solution, but for now it'll do. And to anyone else who sees this problem, let me know if you find a more elegant solution.