6 degrees of separation in understanding user queries

Cube network by Andrey Prokhorov@iStockphoto Be grateful. Be flattered. Be outright ecstatic. Why?

Because users think you’re a mind reader.

For some reason, they think telling you “I can’t do X. Please help.” is enough. They don’t tell you

  • which application it is
  • where or which screen in the application it is
  • any error messages they see
  • what they did (before they got the error message)

They sometimes just don’t tell you enough.

6 degrees of separation is already too much. Users expect you to make amazing leaps in intuitive logic from their pathetic amount of information to whatever is ailing them at that moment. That’s one giant step of deductive debugging.

How do you understand their queries better? Just ask. Ask for more information. This is where your people skills come into play. You’ve got to ask them in the way that makes them feel good about themselves. Basically, you want them to feel like they’ve done everything correctly and it’s really the fault of the software, even if you think they’re complete morons.

You’ve got to coax them into telling you stuff. And it doesn’t help if you keep calling them an idiot.

This brings us to the next problem. Users lie. They don’t lie outright. They just don’t tell the truth sometimes. And it’s not because they purposefully and specifically lie to you. Sometimes they just don’t know they’re telling a lie.

The spelling misunderstanding

For example, I recently had this user say he couldn’t use an application X because of an error. I probed further and managed to pry an error message out of him. Something about a missing file. There was this part “Pls check and proceed”.

Well, I thought, the more unique the error message is, the easier for me to locate where in the code the error occurred. Ever since I took over maintenance of legacy programs, I love it when there are unique error messages. Incorrect spellings, short forms of words, unusual text (like two consecutive spaces), incorrect grammar. Searching entire source code with unique search phrases means there are fewer search results, increasing the speed of finding the actual code.

So I typed in “Pls check” into the search box and ran the search. Nothing. What? I looked at the whole error message and nothing stood out as unique. So I got the user to give me a screenshot. The actual error message was “Please check and proceed”.

Did the user lie? Not really. He read and interpreted the error message correctly. It’s when he’s conveying the error message back to me that information was lost. For him, there’s no difference between “Please” and “Pls”. For me, it’s absolutely critical that every single letter was correct. Sometimes even letter casing matters.

This is the heart of understanding user queries: Understand the user.

I maintain many programs and applications, and I work with different sets of users. These sets of users usually don’t know that I work with other applications and users, so sometimes they ask me something expecting me to know the context of their query (when in fact I have no clue).

Here’s a list I use for probing

  • Ask for screenshots
  • Ask for error messages
  • Ask which application they’re using
  • Ask which screen or web page they’re on
  • Ask which button they clicked to get the error

No information is redundant. Debug like a CSI because you should “Follow what cannot lie, the evidence”. In this case, any information you get is evidence. If their version of the error message contradicts the one in the screenshot, then you can ask further. One or the other must be wrong. Either way, you get more information.

When you’re trying to understand user queries, there’s no such thing as too much information.

Your lifesaver, the screenshot

There’s another case where the user was asking why the update button doesn’t work and the application keeps hanging. No error messages, and he told me which application and screen he’s using and even which button (the update button).

In the end, I asked for a screenshot. Everything looked to be in order. Then I looked at the taskbar in the screenshot. He opened 3 instances of the same application, performing the same task at the same screen. That was the problem. Due to data concurrency and locking, the application instances simply got stuck. I told him to use just one instance and everything was fine after that.

Did he lie? Yes, because he didn’t tell me that he’s running 3 instances of the application, which wasn’t designed for that. Was it really his fault? Not really. He thinks doing different updates with 3 separate instances will speed up his work. Like he’s multitasking or something (a mindset shared unfortunately by many of my users…).

What you should strive for is answering the user query with whatever the user first supplied. That’s ideal of course, and usually hard to reach. The next ideal case is this:

  • User sends you email with query (with insufficient information)
  • You understand whatever is given
  • You formulate intelligent questions
  • You call (or email) the user and ask those questions
  • You finally understand what the user wanted
  • You close off the query, whether it’s fixing bugs or answering questions

Calling is usually better than sending another email. You can save a lot of emails bouncing back and forth if you can just talk on the phone. Your ultimate goal is to minimise back and forth communication.

You may not be able to understand and answer user queries in 1 degree of separation. But with a little thinking first, you can do so within 6 degrees of separation.

My computer got sick

2 days ago, the computer at my work place got infected with a computer virus. It’s a fortune that I was able to get it out of the computer. It was a misfortune that I wasn’t able to get any work done since I was scanning my computer, and I didn’t want anything to disrupt the scan.

My computer housed practically all the source code ever written in my department. Alright, I’m exaggerating, but it’s not far from the truth. If the hard disk was wiped out, let’s just say either I will be assured of another year of contract, or I’ll be out of a job.

So anyway, a reminder for everyone reading this: Have you backed up your computer?

Round cornered images in Paint.NET

Skyline gondola I’ve been experimenting with doing some simple image post processing for my posts. Rectangular images with sharp right-angled corners look a bit stark. I’m getting most of the images from iStockphoto (referral link), and it seemed a waste if I didn’t fit photos and text together nicely.

The easiest and fastest way to spruce up a stock photo is to create round corners in the image. I’ll be showing you how to do so in the freely available, fantastic and awesome image editor, Paint.NET (did I mention it was free?).

So, suppose here’s the original photo, after loading it into Paint.NET
Original picture

Then you add a new layer by either clicking [Layers] -> [Add New Layer] option
Add new layer by option
or click on the “Add New Layer” button in the “Layers” panel (placed near bottom right by default)
Add new layer by button in layer panel

Next, you want to focus on the 2nd layer for some editing first. On the “Layers” panel, uncheck the “Background” image.
Focus on layer 2

On the 2nd layer, we wash it over with white colour first, because by default it’s in “transparent” colour. We can talk about the difference between white and transparent some other time… We’ll use the paint bucket tool
Paint bucket
By default, if you haven’t changed the colour selection yet, then the primary colour is black and the secondary colour is white.
Primary and secondary colour selection
What this means is if you click and draw with the left mouse button, black is used. If you click and draw with the right mouse button, white is used.

So after selecting the paint bucket tool, go somewhere in the (transparent-coloured) image, and right-click. This will give you a nice clinical white patch.

We want to draw a rounded black rectangle on this white patch. We use the aptly named “Rounded Rectangle” tool
Draw rounded rectangle with filled shape
Some finger nimbleness will be needed here. Our test image is 160 pixels wide and 110 pixels tall. We’ll have to left-click (for black) in the image, at the cursor position of 0,0 and drag-move to cursor position 159,109. You can find out the cursor position by looking somewhere near the bottom of Paint.NET
Cursor position
We’re at cursor position 11,9 in this case.

You should then get this beauty
Black and white rounded corner

After that, go the “Layers” panel, and click on properties for the 2nd layer
Layer properties
and set the blending mode to “Additive”
Set additive blending mode

Check the “Background” layer back (to make it visible again) and you should see this
Skyline gondola

Save and you’re done!

I think a video tutorial would have done a better job. Anyone want to sponsor the Camtasia software for me?

PS. That “Skyline gondola” sign was taken at the halfway point on my practically vertical climb up the hill in Queensland, New Zealand. I was the only one (stupid enough) climbing up. Everyone else was going down… A story for another time perhaps…

[UPDATE: Use this plugin RadiusFillCorners. Much easier if you don’t mind a bit of jaggedness on the corners. But not noticeable on larger images.]

Podcast: Fairy tale recital

This is my very first podcast. Woohoo! Seriously, I didn’t know what to talk about, so given my interest in stories of all kinds, I decide to tell a story instead. Here it is:

Download mp3 [~ 3 minutes ~ 1.5 MB]

I recited a fairly well known fairy tale, and it’s only the beginning of the tale. If you know the name of the story, or even better, where the story was from, tell me about it!

You might have to turn up the volume a bit. For some reason, my headset microphone doesn’t capture my voice in a loud enough volume, so the resulting recording sounds soft. In my attempts to ramp up the volume, I cupped the microphone close to my mouth, so there’ll be a lot of “wind” sounds. You know, when you huff and puff (and you blow the house down). And no, “Three Little Pigs” isn’t the name of the story.

I’m going to see if I can get a better microphone. Any suggestions?

In case you’re wondering, I got the intro and outro music from Sound Rangers. Excellent online music store, and quite easy to navigate. I’m also using the Audio Player plugin.

[EDIT: Not using the audio player plugin anymore.]

If you have problems reading this in an RSS reader, please view the post itself for the mp3’s.

Remember to tell me the name of the story. Or submit your comments to this post.

ClearType in Windows XP

[warning: moderately intensive graphic loading ahead]
I just recently discovered that I can enable ClearType in Windows XP. For a long time, I thought Coding Horror just looked terrible on Firefox, but rendered fine on Internet Explorer. I couldn’t find the reason, and I just thought it was some CSS issue or something.

Then I read somewhere about enabling ClearType. Something clicked in my brain and I realised I had IE version 7, which offered the option of enabling ClearType while browsing, and I enabled it. That was why IE7 renders fine while Firefox sucked!

So here’s how IE7 renders:
ClearType on IE7

Here’s Firefox without ClearType enabled (in XP).
Firefox with no ClearType
Terrible, isn’t it? I thought Jeff missed out something. Even tried locating the style sheet. Then I thought, why bother? I can’t do anything with the CSS file anyway. So I stuck to my Google RSS reader instead, which renders fine.

Now, let’s see the site in Firefox after enabling ClearType.
Firefox with ClearType
Much better.

So how do you enable ClearType? Right-click on an empty space in your desktop and click “Properties”.

Then select the “Appearance” tab, and click on “Effects”.

On the dropdownlist under “Use the following method to smooth edges of screen fonts”, select “ClearType”

And you’re done!

A for question

Recently, I’ve had the opportunity to stumble upon this for loop question in the Dream In Code forum. Appalling code aside, it took me awhile to convince myself that, yes, programming can be hard sometimes. Ok, let’s take a look at this excerpt from the original thread starter:

for (i=j+k;; j+k)
break;

He claimed it worked. While I think modern compilers would fail it, I seem to remember older compilers are a bit more forgiving. Particularly the j+k incrementor part. Basically, it’s like a single statement

j+k;

Doesn’t do anything. Sure it adds j and k together, but without doing anything with the result, it’s not useful. But it’s valid for the older compilers I’ve worked with.

Well, assuming it works, he just assigned the sum j+k to the variable i, do no loop checks, breaks immediately, and so doesn’t even hit the incrementor part. Did anyone notice anything yet?

He doesn’t need the for loop.

He could’ve just assigned j+k to i and be done with it.

To clear up the mystery of the for loop, we’ll take a value doubling example, so let’s study the following:

int i, sum;
sum = 1;
for (i = 0; i < 5; ++i)
{
    sum += sum;
}

There’s the multiply by 2 method. There’s the shift left by one placing method. I chose to simply add itself to itself in each iteration.

That was the standard for loop structure. Usually, the same variable appears in the initialiser part, the loop terminator part and the incrementor part.
for (initialiser; terminator; incrementor)

Here’s the short, one-liner version:

int i, sum;
for (i = 0, sum = 1; i < 5; ++i, sum += sum) ;

The incrementor part is just a place where any code is executed before the terminator condition is checked. Technically speaking, you can put any code here. But please don’t. There’s a proper place for whatever you can have in mind. It’s called the loop body.

How about using a while loop?

int i, sum;
i = 0;
sum = 1;
while (i < 5)
{
    sum += sum;
    ++i;
}

Note the incrementing code ++i is now at the end of the loop body. But the end result is equivalent to the for loops above.

Then there’s the do-while loop:

int i, sum;
i = 0;
sum = 1;
do
{
    sum += sum;
    ++i;
} while (i < 5);

do-while loops have this unique property. The loop body is executed at least once. It’s like “do loop body, then check condition”. The while loop works like “check condition, then do loop body”.

Because of this unique property, the following code

int i, sum;
i = 0;
sum = 1;
do
{
    sum += sum;
    ++i;
} while (i < 0);

ends up with the variable sum storing 2 instead of 1, even though the terminating condition is always false (hence it breaks from the loop immediately).

You might like to read up on my introductory article on for loops for more information.

VS2008 not supporting .NET Framework 1.1

Visual Studio 2008 was just launched on 18 November. I’m excited and dejected at the same time. I’m probably going to have a tad bit of a challenge convincing the powers that be at my company that I really need to have VS2008 to do my work.

Anyway, since it’s out, I might as well go and have a look. I mean, really look at the niceties and stuff. I did a Google search, and found Scott’s blog entry on VS2008.

Unfortunately the VS 2008 multi-targeting support only works with .NET 2.0, .NET 3.0 and .NET 3.5 – and not against older versions of the framework. The reason for this is that there were significant CLR engine changes between .NET 1.x and 2.x that make debugging very difficult to support. In the end the costing of the work to support that was so large and impacted so many parts of Visual Studio that we weren’t able to add 1.1 support in this release.

What? I can’t target 1.1 anymore! I just managed to convince management that VS2005 was useful (with a 14-page proposal. Did I mention this before?).

I think the IT people in my company probably didn’t even know .NET Framework 2.0 hit the world. I didn’t even get to play with the cool stuff in VS2005 like master pages yet. Now there’s VS2008…

This is going to take some convincing work…

Computer games sharpen programming skills

Boy playing video game Can playing computer games be beneficial? It is, if you think about them. I mean, really think. While playing them, have you wondered how that special effect was rendered? Or how they modelled a simulation? Or how they implemented that enemy artificial intelligence?

Have you ever thought about the inner workings of a game?

1. Romance of the 3 Kingdoms

Back in the 1990’s, there was this role playing game called Romance of the 3 Kingdoms. There were mighty generals and fearsome warriors and intelligent advisors to recruit. The strongest warrior was Lu Bu. His strength statistic was set at 255. The cleverest of advisors was Zhu Ge Liang, with an intelligence statistic of 255. There were other stats, but they range from low 2 digits to 255.

I was young then, and I’ve often wondered why 255 was the highest. I mean 100 seemed the most natural choice for a maximum. It wasn’t until I studied computers and bytes that I realised that 255 was the most natural choice for computers. An unsigned byte stores a range of 0 to 255.

Still, the very act of thinking about why 255 was used got me wondering about other aspects of games…

2. Kingdom Hearts

In this 3D role playing game, there’s this place called Halloween Town. Since everything’s rendered in 3D, I’ve marvelled at the efforts to efficiently fool our eyes into forming those textured polygons into a believable scene. Well, there were these pumpkin lanterns lying around giving suffused light, and they looked quite beautifully rendered. I moved Sora (the main protagonist) so that the camera angle could let me see those lanterns better.

Light polygons
After staring at them for a few minutes, I finally figured out how it’s rendered. First, an example of the rendering. Ok, I suck at 3D modelling. Anyway, 3 square planes were used, crisscrossed at the centre at 60 degrees apart. Then each square plane was textured with a light map. Set up the diffusion, ambience and other colour and lighting parameters, and it looks like a convincing lantern (together with the pumpkin model of course).

With 2 triangles in one square plane, that’s a total of 6 triangles. An efficient use of polygons, I’d say.

3. Final Fantasy

Actually, it’s role playing games in general, but my all-time favourite is Final Fantasy, so I’ll use it as an example. Basically, it’s about data storage and presentation. There’s conversational text, menus, lists of items/weapons, tons of enemies (and their stats), maps and so on. How were they stored?

More importantly, how do you display all the items and allow the player to efficiently scroll through them?

I think about how certain consumables items (meaning they’re removed once used) were represented in code. Or if weapons and armour were stored differently? All items must’ve been tagged differently, because there’s a sorting function. Potions, remedies and other healing items together. Swords, staves and other weapons together.

Computer games rarely have the luxury of a database. Perhaps a multiplayer online game with a server that utilises databases. So, given that you can work with a database, how can you plan and code for data storage?

Oh yeah, if you’re a Final Fantasy fan, you’ll find this “College Saga” hilarious.

4. The Sims

I prefer to play console games rather than games on a computer. I’m using the term computer games to refer to games powered with hardware, whether console or hand-held or actually on a real computer.

The Sims, however, require the mouse to efficiently point and select options. At least that’s how I feel.

Anyway, as a people simulation game, I’ve wondered about the variables affecting each Sim (an avatar in the game). There’s probably a lot of psychological research done. Because, how do you simulate a human being? Feelings, wants, needs. Family, friends, relationships.

5. Action games

There’s too broad a genre for this. Fighting games (King of Fighters). Driving simulation (Gran Turismo). First person shooters (Doom). Any game that requires some form of reflex ability. These games improve mind, hand and eye coordination.

Rapid interpretation of game events (curved road approaching, fast punches) and speedy actions are part and parcel of action games.

So why are they useful? They train the mind to think and act quickly. You should be thinking and reacting so fast that your fingers have trouble typing out the code quickly enough. If you need to retrieve some data from a database, you should visualise the query statement rapidly and you’re just waiting for your fingers to finish typing out the query statement.

Conclusion

Given the right context, playing computer games can sharpen your programming skills. You just have to think of them in a different perspective. Ultimately, it’s about figuring things out. And that’s what programmers do best.

Piling programmers lead to devastating deadlines

Small red bomb Ever been in a situation where the deadline is getting closer yet the project is getting nowhere? Ever had deadlines looming closer and everyone’s attending meetings, doing discussions but nothing is really done? And the solution from management? Pile on more programmers.

This isn’t like hacking logs, where the more people who chip in to hack logs, the faster all the logs get splintered into firewood.

This isn’t like cleaning house, where the more people who sweep in to mop floors or wipe windows, the faster the house becomes brand new spanking clean.

This isn’t even like data entry, where the more people who come in to type information, the faster all the data gets into the computer database.

Programming is a thinking activity. Thinking activities call on quality, not quantity, of the people involved.

Synchronising actions is easy. Monkey see, monkey do. See log. Grab axe. Swing, splinter, repeat. See dirt. Grab broom. Sweep. Eye on data. Fingers flying on keyboard. Tappity tap, tappity tap. Synchronising thoughts is much harder.

Simply piling on more programmers doesn’t make the project progress any faster. In fact, it just leads to devastating deadlines. Why? It’s the human factor.

This reminds me of a time when I was in a team of 12 (I think). We were working on an enterprise web application (warning bells sounding), since I just joined, I was given documentation of the application framework to study. There were custom web controls, dynamic browser sizing based on user’s resolution, security logins, language resource handling, translations, workflow management class codes and on and on.

I was the new guy, so I was given all sorts of miscellaneous stuff to do while they decide how best to use me. Then I got something to work on. The resulting code wasn’t my best, but I learned a lot from the team and the experience.

Then the deadline started slipping, and management brought on 2 more programmers. While I had some professional experience to speak of, these 2 had hardly any, from what I had seen. She needed help getting a DataGrid sort and bind to work!

New staff, even if they’re experienced programmers, need time to get accustomed to the team and the project.

Me? I got relegated to testing the web application. Somewhere in my resume I stated I did test cases before, and that’s where I ended up, writing test cases. The whole application was finally coming together, and then some of the other colleagues were tasked to help with the testing.

At least management got this part right. Having me help with the coding wouldn’t have made much difference at that point. Testing the application would have smoothed the project’s progress back within deadline, while the last bits of coding were done simultaneously.

Estimating project deadlines is hard enough. Don’t introduce a new variable into the equation. New staff are new variables. And if you really want to hire new variables, make sure they’re polymath programmers.

Solve the actual problem, not the illusion

Have you ever finished a software project, only to find that the user really needed something simpler or even totally different? Ever solved your user’s software problem with an application only to find that it didn’t solve the big picture problem?

Are you solving the actual problem?

The one with the Excel report

There’s this project where my user wanted a consolidated report from one of the web pages in an existing web application. He just wanted to be able to have one more option from a dropdownlist, and he’d select that and be able to get the report he wants (there’s an export function to Excel).

I thought about it, and told him that it would require some effort as it affects some other parts of the application (even though it’s just one more list option). I asked further why he needed the report to have that functionality, and how he would use that exported Excel report.

It turns out that after he exported that report (once the additional change was finished), he’d use the summation function in Excel, and sum up one of the columns to get a figure. All that work just to get one number. I repeated what I understood to him, and he really just needed one number. It’s a monthly task he does, and he usually exports the entire report into an Excel file.

Due to the way the web page was structured, he had to export once for every option in that dropdownlist, then sum up the numbers in each of the exported Excel files to get that final number. Not very efficient, hence his request.

I want to emphasise this now. He doesn’t really want that extra dropdownlist option, because he would still have to do a summation. There are a lot of records and Excel has this internal 65536 row limit (pre-Office 2007), so it might not even be feasible to put all the records into one Excel file as he requested. What he really wants is a monthly sum total figure.

So I told him, I’d design a web page that specifically lets him export a report that is exactly what he needed: an Excel file with a month column and a sum total column.

If I had followed on his request as it was, I have done coding which didn’t help my user at all. He’d still have to do some calculations and manipulations with the resulting Excel file.

The one with the DataGrid columns

There’s another instance where the user asked me to do some table column width adjustments. The DataGrid displayed an HTML table that she didn’t like. She wanted me to shorten some columns and widen some columns.

And you know what? She doesn’t really want me to do all those column width changes.

What she really wanted was for all the displayed data to be on one line. Due to the column widths, the columns with more data (such as text descriptions) wrapped into 2 lines, making the HTML table longer in height. She’s still on her 800 by 600 pixel resolution screen, so scrolling up and down when there’s only like 10 records was making her cranky.

So I manipulated the table column headers instead. I broke some header text into 2 lines, thus shortening those columns. Hmm… let me show you instead. Say this is the HTML code

<table border="1" width="360">
<tr style="background-color:#eeeeee"><td>Text</td><td>Month Text</td><td>Total</td></tr>
<tr><td>This is the first description</td><td>200708</td><td>34</td></tr>
<tr><td>This is another description</td><td>200709</td><td>45</td></tr>
<tr><td>Oh my goodness, yet another description</td><td>200710</td><td>56</td></tr>
</table>

This is how it looks like
Shortening table column

What my user wanted was to lengthen the “Text” column and shorten the “Month Text” column. She believed it’d help a little if she gave more explicit instructions. What she really wanted was for all the data to be on one line, never mind the header text.

So what did I do? I forced the “Month Text” to break into 2 lines (even though it’s already broken into 2 lines by the browser) using the br tag, ending up with
Month<br />Text

With the forced break, the column “Month Text” automatically shortens, and because the table is on a fixed width, the column “Text” automatically lengthens, thus fulfilling her desired outcome.

If I had coded explicit widths into the td tags, it might not scale properly when other data is displayed. I’d also have the beginnings of a maintenance nightmare.

Afterthoughts

So what have you learnt? Sometimes, when users ask for something, they’re really looking to solve something else. What you need to do, is find out what that is, then solve the actual problem, not the illusory problem the user thinks they’re solving.