January 30, 2006

Talking Solution Space

As I mentioned a while back, I've gone from a straight-ahead development role to more of a project management and development role. It's been an interesting challenge thus far. I do mean all shades of the word interesting there; from 'my life would be easier if I ran away and joined the circus' interesting to 'yay, we're having fun' interesting. Why such the range of experience? Well, it's because I've been exploring the solution space and I've made a lot of mistakes.

By solution space, I'm referring to a term that describes the range of possible solutions for a problem. The solution spaces between development and project management are vastly different. Let's say you get a lot of complaints from the users who claim that sorting is too slow in your application. As a developer, what are your possible solutions?

1. Debug the sort, isolate any inefficiencies and correct them.
2. Replace the sorting algorithm, leaving everything else in place.
3. Remove the sort feature.

Those are only a few solutions; you could expand that list several times. Conversely, let's take the same problem and approach it from the guise of a project manager.

1. Get together with Bob, tell him his sorting algorithm sucks.
2. Get together will Sally. Tell her that you don't think Bob is smart enough to fix his sorting algorithim. Ask her to fix it without telling anyone.
3. Get together with Bob, who wrote the sorting algorithm. Discuss the issue with Bob. Convince Bob that this issue is worth addressing. Get Bob to give you a time estimate. Double Bob's time estimate. Shift the rest of Bob's due dates back to allow time to fix the sort problem. Get Bob a spec for the change. Allow Bob to make the change, then test it to measure the improvement.

The first two methods would particularly good if you wanted Bob to punch you in the face or place a dead skunk in your office. Just like with the developer list, there are loads more solutions there. However, unlike the developer list, it's not just you and the problem; it's you, everyone else, and the problem. You can't solve the problem in code; you have to solve it in collaboration.

To me, that makes project management hard. You can't debug people (well you can, but you have to ask really nicely). There's no axiom that says once you've made three compelling arguments, a developer must go along with your suggestion. That's not to say that it's harder than coding. The solution space is just a little bit different.

Posted by Cody at 06:59 PM | Comments (0)

January 23, 2006

Lesson: Diagnose Build Failures

I like to take note whenever I make a mistake, so I can keep from making that mistake in the future. Sometimes, these lessons are valuable (don't eat thermometers), and other times, they're a little less valuable (Jerry Van Dyke is one heck of an entertainer). Just recently, I received one of those more-valuable lessons, courtesy of our automated build process. The lesson: never assume you know why the build is failing.

We needed a major database schema change made. At the same time the data was changing, our code was changing to reflect the new schema. The first time we checked that code in and ran the build, we got a SqlException. "Good," we yelled, "that's probably supposed to happen because the schema change hasn't been made yet!"

Time passed, the build continued to fail, and we continued not to worry about it; after all, the schema change hadn't been made yet. Then, the schema change went live. I ran the build, expecting to see a comforting green light. You can probably guess where this is going. The build failed again, with the same SqlException. All at once, everyone went back and checked the error message on the build. Yeah, it was definitely a SqlException, but if you dug a little bit, the error message had nothing to do with schema. We had a malformed query. Oops.

Sometimes, you expect a build to fail because of schema changes and whatnot; you can't get around these. However, if you expect it to fail, it does so, and then you don't verify the reason it failed, then you're setting yourself up to wear the dunce cap. You lose the best part of continuous integration then, in that you no longer care if your changes are valid. It could fail for any reason, and you could still lean back in your chair and declare, "I totally expected that."

No matter how certain we are, we must validate our assumptions, especially when they're that easy to check. If not, like the old saying goes, we allow the word "assume" to make an ass of you and me. Or maybe we're allowing the made-up, but similarly defined word "assus" to make an ass of us. Whatever the case, it's not good.

Posted by Cody at 07:45 PM | Comments (0)

January 19, 2006

Getting Tricky


We're tackling a pretty tricky problem at work right now. The application we're making allows the user to enter in an equation that we'll calculate for them. For example, let's say that one of these equations is Field2 from the database * 3 / 20. The user can store these equations in a table for use later on. The hard part isn't storing or retrieving or supplying the right values for the variables, it's evaluating the equation. Here are a few reasons why.

First, the equation is stored as text. A * isn't a multiplication sign, it's a '*', just another character. You have to interpret those characters as operators. That is to say, you have to know that a '*' means multiply. Will you support logs, natural logs, trigonometry? Right away, you're limiting what the user can do, because the only allowed operators are the ones you know to parse.

Second, you have to do something with the order of operations. Going back to the equation I listed before, you have to know that Field2 * 3 / 20 can't be calculated in the way we've outputted it. Instead, the calculations have to be done in a certain order according to the order of operations for us to get the right answer. (One of the few mnemonics that's ever stuck with me Please Excuse My Dear Aunt Sally, for the order of operations).

The order of operations is hard. If you don't believe me, try to come up with a rule of thumb for processing an equation like a^b/d*e^f/g*h^i^j. Where do you start there? You have to start at the right place, or else you'll come up with something distinctly wrong. Even if you know the order of operations, does the user entering the equation? It's possible that you can evaluate the equation correctly and deliver the wrong result, if they got their part wrong.

Assuming your language doesn't just have a magical evaluator that can handle these problems for you, you can apply some pretty far-out theories to problems like this. If you dig the formal language thing, you may want to dive into Parsing Expression Grammar and see what you can do. If you're a classicist, maybe Dijikstra's shunting yard algorithm will work (description is about halfway down that page). Don't let fancy terms like 'shunting yard algorithm' dismay you; it's just a way to transform something into Reverse Polish notation.

What do I suggest? Uhhhmm, I don't know yet. I'm going to meditate on it. I'm going to go to my happy place for a while, crunch the options, and see what makes sense. Right now, I'm leaning heavily towards just taping a Mickey Mouse calculator onto the jewel case when the app ships.

Posted by Cody at 08:19 PM | Comments (0)

January 16, 2006

A Great Step for ATM Users

Let's say there's a four-step process in an application. That process has been the same for years, and the steps must be processed in a very specific order. Now imagine that some usability bad ass (yes, such people exist) found a way to merge two of the steps, so that now it's only a three-step process. That'd be pretty cool, right? That person could rightly expect to be showered with rose petals, caviar, and really nice socks. Well, just recently, I've noticed a change like this; in the event no one else does, here are your virtual rose petals, caviar, and really nice songs, Mr. or Mrs. Usability Guru.

Here's the situation. At the ATM by my house, the machine always prompts you to select a language before you can do anything else. You select a language, enter your PIN, select the type of transaction, and enter the amount. That's the way it works; that's the way lots of ATMs work. Well, it seems completely obvious now, but what some smart soul did was to streamline the language selection/PIN entering steps.

Instead of asking the user to select a language, processing the choice, and then asking the user to enter the PIN, now it only asks you for your PIN. But the smart part is, it does it in two different languages. When you first roll up to the machine, it says "Please enter your PIN," and then right underneath, it says the same thing but in Spanish. Each language has its own button for you to click once you're done. Depending on which one you click, not only does the machine know your PIN, but it now knows the language you wish to read. Pretty cool stuff.

This impresses me because ATMs are a really well-known problem space. Certain steps must be done in a certain order, and there's not a lot of room for UI advancements. Well, someone at Bank of America (or some other place, perhaps) figured out. Get your freak on, ATM usability personnel!

Posted by Cody at 07:44 PM | Comments (0)

January 14, 2006

howto: Give a Good Demo

You've been working for months on a project. It's fast, it's slick, and the only feature it lacks is the ability to make waffes. People in the halls are talking about it, and inevitably, word has filtered down to the sales guys. They want to see it. They're not sure what your name is or what you do, but they want to see this app in action. How do you keep from screwing the demo up?

First, do a bunch of bad demos. Analyze what went wrong, and then apply those lessons. However, if you don't have time for that, I insist on sharing my own observations, gathered through my own demos that were both horrendous and glorious.

1. Make sure the app works. That sounds simple, right? In fact, it's almost too simple. If you've spent months working on a package, you know it works and you can navigate it like your name was Magellan. However, just because the software isn't crashing doesn't mean that it's behaving correctly. If it's performing a calculation, check the results in advance. If it's manipulating data, check the results by hand. A demo is a bad time to discover you messed up an algorithm, says a guy who has done it before (in my defense, I'm an idiot).

2. Write a script. If you were doing a demo for a group of mimes, what points would you make to them? Write that down in an easily-readable format; that's your script for the demo. The text should be concise and spaced-out (outlines work great), since you'll only be able to glance at it.

3. Throw in some metrics. If someone isn't a technical person, it could be hard to grasp just what an application does sometimes. To make it easier, share some numbers. "With this code, we can go from processing 10 widgets an hour to 10^78," or "This process is 2718% faster than the current one and could overtake the world in approximately 68 weeks." Don't make the numbers up; you should be able to demonstrate them if asked.

4. Practice. Once the software works and you have your script, run through the demo a few times. Do it for yourself and then do it for others, since that's a lot harder than just talking to yourself.

5. Stick to the script. If you're like me, you get nervous in these situations. Once the demo begins, don't worry about charming off their pantaloons with off-the-cuff zingers about the CEO's aftershave. You've already written what you wanted to say, so just follow that. The demo will be impressive enough without you babbling away.

And there you go. It's a simple process, but one that can definitely help you in looking like 78% less of a horse's ass (remember, people like metrics).

Posted by Cody at 09:29 AM | Comments (3)

January 12, 2006

We've Gone Modifier Crazy

I found a neat little C# 2.0 doo-dad today. We all know that one of the new features is v2.0 of the language is partial classes, where you can define a class in multiple places. Why is this useful? Well, it's very handy if you create a form and allow Visual Studio to insert all of its generated code into our class. With partial classes, you can segregate the messy, generated stuff from the beautiful, self-written masterpiece.

A question I had today was: what happens if, in a partial class scenario, you accidentally apply differing class modifiers in your class files? Let's say in Class1.cs, you say that Class1 is a public sealed class (can't inherit from it), and then in Class1.Designer.cs, you simply say it's a public class (so that it could be inherited). To contrast that, what if you say a class is abstract in one place and then not in another? Well, from my experiments, the compiler will apply the modifier, even if it's only in one spot.

What if the modifiers are completely opposing, like abstract and sealed? Then, the compiler will complain. As long as the modifiers don't create an erroneous situation, you can specify them independently all over the place. I could be wrong about that, but let's pretend I know what I'm talking about.

Now is this good or bad? That's a little harder to summarize. If I'm working in a partial class (usually in a Visual Studio-generated form), I'd much rather NOT have to touch the code generated by Visual Studio. If I can specify something once in a class declaration and see it carried over to the generated code, that's a good thing. At the same time, I could see how this would be harder to maintain, because you have to search out all declarations of the class to see what the modifier actually is. Let's call it a good/bad.

Posted by Cody at 07:41 PM | Comments (2)

January 03, 2006

Learning Lisp

I had two resolutions for 2006. The first is to stop sending disturbing letters to Regis Philbin. The second, and arguably more attainable, is to post more here. Okay, let's get into it.

Lately, I've been working on learning Lisp. I'm doing this because I'm a nerd and because I think it'd be useful. Wait, let me clarify. It wouldn't be useful in the sense of "Oh, you need a billing report, allow me to write it in Lisp." I just dig the concept of a programming programming language, and I believe that learning it would bring some bizarre and interesting ideas into my coding style. Does that count as actually useful? Probably not.

Anyway, in learning Lisp, I utilize two great resources. The first is Lisp in a Box, which essentially contains an IDE for Lisp (along with lots of other stuff). I wasn't smart enough to find that on my own; I got it from reading Practical Common Lisp, a great introductory text by Peter Siebel that's available for free on the web and for $$$ at your local bookstore. The progress is slow, but marked. Anyone looked to dip their toes into the Lispy waters would be well served to investigate these two resources.

Posted by Cody at 06:28 PM | Comments (3)