While I Compile

… I compile my thoughts about programming

Let’s turn off all features to improve UX

Here’s a thought; what if all features on a new software upgrade were turned off by default?

What if when you bought a software upgrade, all the new features were disabled and the software worked exactly as if it did before you installed it? What if new software had all but the most structurally necessary features disabled?

Yes, I’m serious.

But why?

For a maximum user experience of course …

WTF? … how can you have a maximum user experience with everything turned off?

Because the biggest issue with user experience is surprises.

Well duh! But now we’re talking bugs, and everybody knows bugs suck.

Yeah, bugs suck, but that’s not what I’m talking about.

I’m talking about features that work to spec, but unfortunately the user doesn’t even know exist! Notice that I’m not talking about features that users don’t know how to use. I’m talking specifically about features, often intrusive features, which the user doesn’t know about.

Language Bar

Language Bar

Like what? … oh, I don’t know … like having my keyboard cycling between US, Canadian French, and Canadian Multilingual, in an apparently random pattern last week. This happened because the default hot keys on the Language Bar software were set to the same keys as is standard for highlighting text for cut & pasting. This took me days to figure out, for a variety of reasons, the biggest being that, the change is not obvious until I type a letter that has a different mapping, turning my your single quotes ‘, into “ or è! I was completely oblivious to the fact that utility even had keyboard shortcuts, as I’m sure the person who selected those keys was oblivious to the fact they are standard shortcuts. This was extremely frustrating, and notice it was not a bug.

The problem is that things did not work as expected.

Unfortunately, when the user doesn’t know ‘about’, let alone ‘how to use’, all the funky bells & whistles we added to improve their lives, their experience more closely resembles a series of surprises. And surprises suck … oh yes they do suck. I’m not talking “Ed McMahon showing up on your door step” surprises, I’m talking “your meeting starts in 5 minutes, and the printer doesn’t work, and when you reboot, a large Windows Update starts installing” surprises.

Surprises are frustrating and unproductive.

So why the surprises? Because users are diving into the software to get stuff done, and don’t have the time or are just unwilling to put in the effort to learn all the bells and whistles. And who can blame them? Who wants to read hundreds of pages of documentation just to use the one new piece of functionality they bought the upgrade for.

Maybe if we just gave them what they wanted, they might invest the 5 minutes to learn what they need, and we’d have a more educated user base. Maybe if we gave them functionality and an education in bite sized chunks, they’d be more inclined to learn more because the commitment is a 2-5 minute video, not a huge, 1000 page, $75 book, or worse, a help file which provides absolutely no indication of scope.

So what’s my solution?

I think software should install with all features disabled.

Then when the user wants to use the awesome feature he was sold on, they just kick up some kind of feature start up dialog, which prompts the user to watch a minimal length tutorial for the feature and make the decision to enable the feature right in the tutorial. Yes, there would need to be the option to bypass the tutorial of course, for those who already know it, or just want to fumble around in it, but just knowing the feature exists will make their fumbling more likely to succeed. Maybe functionality could even be presented (marketed) to the user in order of popularity, helping users decide what features to look into if they don’t already know them. It might also help software companies know what functionality they should not be spending time on.

Yes, I realize there will be some things that must be enabled due to structural integrity issues, where enabling / disabling a feature is just too much work. Or business has decided to require it, regardless, to force feed some type of functionality to the user (think Apple iTunes). Or it’s just a design decision. But maybe those auto-enabled features could have their (again, bitesized) tutorials queued according to the most invasive functionality so the user could still skip them, but again, at least they’d know what changed.

I think the biggest argument against this idea would come from the business end of software product companies who feel that it’s got to be setup immediately based on the most common users, assumed workflow, and I’m sure there will be many who believe it must be enabled because users just won’t enable it themselves … yeah … just think about that statement for a second please. I know that would be an argument from somebody.

So, in summary, turn off as many features as possible, preferably all of them and push the user through a bite sized tutorial before allowing them to enable each one.

July 23, 2010 Posted by | Uncategorized | 3 Comments

New Job

New job

I’m starting at a new job this morning. 

I’ve been looking since April. Well sort of; it took me a long time to accept the fact that full time might be the best choice for me at this point in my life. But once I accepted that, I went straight to Infusion Development and got in their interview process. 

I’ve known about Infusion since about 2006 via their ads on DotNetRocks. As I understood, they’ve been growing super fast, have reputation for having bright developers, & a bleeding edge development strategy.  For example, Infusion is a leading developer of Microsoft Surface apps … If you’re reading this, I’m sure you know about Surface already, but if you don’t, go to Google Video and do a search on it.  It’s an awesome product.

I won’t be working on the Surface though. I really want to work in ASP.NET MVC / jQuery, and that’s what I’ll be doing. 

I’ve wanted to work at Infusion for a long time, but didn’t act on it since I had a pretty good thing going as an independent consultant. But when my contract ended in April, a bit of soul searching led me to the conclusion that I needed to push my career to another level, and this might be the best strategy.

As I understand it, Infusion has over 100 developers in their Toronto offices. If you’ve ever looked my Twitter feed, you know I like talking to smart developers. So, yeah, I’ll be in heaven.  🙂

One thing I’ve noticed since I started looking for a job is that I seem to have missed an important exit in my career. Nobody looks for developers with more than 10 years experience. It seems that after 10 years most dev’s have moved to management or architecture, which makes sense, but as a ‘do it all’ independent consultant, I never made that distinctive leap. I made more of a indistinctive transition.

Based on conversations during interviews, I got the impression they would like to see me pursue a move to architect and will help me do it. So that’s nice … Assuming I did interpret that correctly. 

Infusion also has a wickedly awesome intensive training program as well, where you do intensive, 8 hours a day, in house, until you learn the new technologies.  I believe they even have their own training team. Freakin awesome!  

The HR lady was happy when I expressed excitement about the training. She said a lot of people don’t like it. I’m like WHAT!?!?. In all seriousness, I expect it won’t be too long before my manager gives me an ass kicking for signing up for too many training courses.

You know, I’m really too old to be naively enthusiastic about a new job, and I’m sure there will be things that suck, there always are. But for right now, I don’t think there is a job I would like more, is better for my career, or can best maximize my talents.

I am very excited about starting at Infusion today, helping them kick ass and take names. 😉

Wish me luck.

July 12, 2010 Posted by | Uncategorized | 3 Comments

Visual Studio Bug – ‘if’ followed by a try / catch causes debugger stepping error

Yesterday I was debugging and stepped into a method. I wanted to get past my parameter validation checks and into the meat of the method, so I quickly, F10’d my way down the method, but I noticed a line of code was stepped on which should not have been touched.

The code was a simple parameter validation like:

if (enumerableObj == null)
    throw new ArgumentNullException("enumerableObj");

with several similar parameter validation lines above it and a try/catch block containing the meat of the method below it.

The odd thing was, I thought I saw the debugger step on the throw statement even though the enumerableObj should have had a value.

I assumed I had somehow passed in a null value to the enumerableObj parameter and had nearly missed the problem in my haste. I had been moving quickly, so quickly in fact that I had stepped about 3 more lines into the method before I even stopped. To be honest at this point, I wasn’t even sure if I saw it step into the ‘if’ block, so I repositioned my debug cursor back to the ‘if’ condition, and stepped again. Sure enough, it stepped into the ‘if’ block.

I assumed I passed in a null parameter, but when I evaluated enumerableObj, it was set, what’s more, evaluating the entire enumerableObj == null expression resulted in false, as expected. But why the heck was I being stepped into the ‘if’ block when the ‘if’ condition was false?

I retried it again, just in case the enumerableObj had somehow been set as a result of a side effect somewhere, but even then, it still stepped into the ‘if’ block.

So, I did the standard stuff; cleaned my solution, deleted my bin and obj directories, reopening the solution, restarted Visual Studio, & rebooted, all the while rebuilding and retesting the project with each change. Nothing seemed to work. I even cut & pasted my code into notepad, then cut & pasted from notepad back into Visual Studio to ensure there was no hidden characters in my files.*

None of this worked, so I started commenting out code in the method, and eventually was able to isolate it to the above code failing if, and only if, it was followed by a try / catch block. Seriously! If the try / catch block was there, it would step onto the throw statement even though it should not have, but when you removed the try / catch block, everything worked just fine.

In order to isolate the problem for debugging purposes and to have something I could ask for help with, I isolated the problem to a simple command line app.

using System;
using System.Collections.Generic;

namespace IEnumerableBug
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                List lst = new List();
                lst.Add(999);
                IsIEnumerableNull(lst);
                Console.WriteLine("Post IsIEnumerableNull() call");
            }
            catch (Exception ex)
            {
                Console.WriteLine("-- Error --");
                Console.Write(ex.ToString());
            }
            finally
            {
                Console.WriteLine("\n\nPress any key to exit...");
                Console.ReadKey();
            }
        }

        public static void IsIEnumerableNull(IEnumerable enumerableObj)
        {
            if (enumerableObj == null)
            {
                // this should never be stepped over, but is (at least for me)
                // however execution moves to the next line once this is thrown instead of interupting execution
                // Also, a breakpoint on this line is never hit, as you would expect.
                throw new ArgumentNullException("enumerableObj");
            }

            // commenting out this line of code will cause the debugger to step through
            // the above control statement properly
            try {} catch { }
        }
    }
}

Once I got it isolated, I also realized that even though it was stepping onto the throw statement, it didn’t actually jump to the appropriate catch block, it just continued on it’s way to the next line of code. This is why I was able to F10 3 lines past the throw the first time I stepped on it.

Anyway, I threw the code up on Pastebin.com and asked my Twitter followers to see if the problem was repeatable for them. After the standard Twitter, 140 character limit, miscommunication confusion, everybody came back with a negative result. “It works fine on my machine.” … typical 😉

Stepping through the debugger with the throw statement, line of code, highlighted

Close up, click for a screen shot of the entire IDE

At this point I was wondering if it’s some wonky bug only on my machine or if I hadn’t gotten enough sleep and I was doing something so incredibly moronic that I was about to publicly brand myself as an idiot.

Fortunately 2 things happened at that point; 1) I remembered one of my old laptops had VS installed on it, and I was able to repeat the problem on that computer, and posted a screenshot, so people wouldn’t think I completely lost it.

And 2) @james_a_hart came back telling me that he could repeat it and that it was a problem with the way Visual Studio is stepping through the debugger symbols. He also reduced the problem a lot further than I had. I had been so caught up in the problem, I hadn’t even realized how much more the test command line app could be simplified.

using System;

namespace IEnumerableBug2
{
    class Program
    {
        static void Main(string[] args)
        {
            if (new object() == null) 
                throw new Exception(); 
            try { }  catch { }
        }
    }
}

I don’t know who James works for, but I think he has a pretty sophisticated VS virtual machine setup, because he was able to confirm the problem only happened on 64bit Visual Studio 2008 and 2010.

Oh and for the record, in my testing, this only seemed to happen only with a throw statement. Switching the throw statement with a Console.WriteLine(), worked as expected.

using System;

namespace IEnumerableBug2
{
    class Program
    {
        static void Main(string[] args)
        {
            if (new object() == null) 
                Console.WriteLine("Equals NULL");
            try { }  catch { }
        }
    }
}

It was a heck of a day, and a huge waste of time, but I’m just glad I now know what the problem is.

I want to thank everybody who helped me by brainstorming with me on this, or running my code to check if they could repeat the problem; @james_a_hart, @JMBucknall, @dullroar, @SteveSyfuhs, @InfinitiesLoop, @klmr, @SyntaxC4, @CarolFil, and @brianrcline.

* As I understand it, cs files are plain text, so this was unlikely to be the problem, but I felt it was an assumption that I should test.

July 2, 2010 Posted by | C#, Code, Programming | , , , | 1 Comment

   

%d bloggers like this: