Tuesday, March 31, 2009

Bug free software?

A little while ago, my wife and I purchased a new version of Adobe Photoshop CS4. About a week later, she came to me complaining that we spent several hundred dollars for a software package that crashes on her. It's not frequent; she's had one occurrence in many, many hours of operation. But still, when it happened she lost some work and was frustrated.

Over the last several months, I noticed the separator between the minutes and seconds on the front panel of my treadmill did not display. I thought it odd, because there were times I knew it did. One day I watched it more closely during my workout and I determined when it showed and when it didn't. The combination of conditions were such that I'm sure it was not intended behavior.

Bugs exist, whether its in a large, complex package with probably several million lines of code or in an embedded controller with around three orders of magnitude fewer lines. Nevertheless it is frustrating, particularly for uses like my wife because, not knowing the incredible complexity of software, their expectations are higher than mine.

All this to introduce tongue-in-cheek, long time favorite quote that basically says software bugs are a way of life:
Every program has at least one bug and can be shortened by at least one instruction - from which, by induction, one can conclude that every program can be reduced to one instruction that doesn't work. -- Unknown

Saturday, February 7, 2009

Microsoft's OfficeUI Ribbon: Adding non-button controls

There are quite a few controls included with the new Microsoft OfficeUI Ribbon library. I recently wanted to incorporate this into a prototype application I was working on. All the examples I found showed how to use it with a button but I wanted a richer UI than just buttons on the ribbon. I did some web searching and found precious little information on using other controls and I did not find any documentation. Using the little information I did find, a lot of reverse engineering and some trial and error, I finally came up with something that works. Therefore, in an effort to help someone else, here are some things I discovered.

First, I wanted a simple mini-form for doing text searches. All it needed was an edit box, a go button and a couple check boxes in a ribbon group. Here is a screen shot of what I wanted:
Ribbon panel specification

In my first attempt, I knew I needed a group to put the controls in, so I naively added one to my ribbon and added the desired controls. The designer immediately became unstable. I was able to compile after stopping and restarting the IDE. However, when running the application, I got a null reference exception loading the form.

Through some routine diagnostic sleuthing, I determined the cause: having multiple groups without assigning GroupSizeDefinitions. If there is only one group, it will work properly without defining a GroupSizeDefinition. However, with more than one group, each group must have a GroupSizeDefinition assigned. I hope that Microsoft will fix this bug before the final release.

In spite of fixing the null reference problem, the layout did not work as desired. Things did not size appropriately. Controls did not position the way I wanted. It was a UI mess.

I had gone to a session at PDC2008 where they demonstrated the control so I went to find that presentation. A bit of information was gleaned from slide 36 [pptx] of session PC45 where the ItemsPanel property was discussed. Unfortunately it was entirely too brief and ended up somewhat misleading. It did give me a clue to start looking for other things though.

After a bit of searching, reading blog articles and forum posts, I found the key to figuring this out in a short post by Mike Cook. I found it best to add an ItemsPanel to the RibbonGroup containing a UniformGrid. The controls then went in this container.

In order to get the controls formatted the way I wanted, I needed to put each row in a DockPanel. However, the only things that can go in a RibbonGroup are things that implement IRibbonControl. To handle this, I created two of my own controls that extend DockPanel and implement IRibbonControl. This ended up working well because I needed to add additional code to each one to work the way I wanted and this helped encapsulate this code.

In formatting the top line, the first thing I found was the RibbonButton, used for the Go function, always assumes there is an image associated with it. For the purposes of this form, I wanted the image to the left of the label, associated with the entire line, not over on the right associated with the button. In order to turn this off, I had to find the image in the button's template and set its Visibility to Collapsed.

After getting the button's image removed, the next thing I found was the RibbonTextBox sizes the text box to its content. This seemed ugly to me and I did not find any way of altering this behavior with simple property settings so I started investigating the VisualTree for the control. After some trial and error, I found I could set the Width of a Border inside the RibbonTextBox and the internal TextBox would remain that size. This strikes me as a pretty ugly and fragile hack, but it works. I hope that this will improve before the final release.

The second row is more straightforward with just two RibbonCheckBoxes on it. It does have a slight oddity though. The Executed property must have a method assigned to it for the check box to be active. The issue is, in this particular use case, I did not need to have anything happen when the user checks the box so there is a required method that has nothing in it. This seems silly to me.

At the end of the day, I was able to get what I wanted out of the library. I think it looks nice for the user and functions well. But, it is not terribly pretty for the programmer and there was quite a bit of frustration getting it to work as I intended, mostly due to poor and lacking documentation. I hope someone else finds this useful. If there are any errors or omissions, please leave a comment to let me know and I will do my best to correct it.

Source code

The ribbon control is publicly available on the OfficeUI web site after agreeing to a long, overwhelming license. (Here are the how-to-get instructions.) As I understand it, this is going to be bundled into the base System.Windows name space with CLR 4.0, so I'm not quite sure why there's such an onerous license on it at this point.

Here is complete source code [zip] for this article. Note that it does contain a reference to RibbonControlsLibrary, the package containing the Ribbon controls, which is not included due to licensing restrictions. In order for this to compile, you need to get this library from Microsoft (see links above) and then update this project to point to your copy of it.

Wednesday, December 10, 2008

C# odditiy: Object initializer scope

I was reviewing some code today and ran across something that looked like this:
SomeProperty = SomeProperty

Odd, I thought that doesn't do anything, probably not what the writer intended. I sort of ignored it since I was doing some refactoring that removed that line anyway and went on. When I realized I didn't have any tests covering this bit of code, I saved my changes, reverted the unit, wrote a test and ran it, expecting a failure. Much to my surprise, it worked.

In context, the function looked sort of like this:
public class SomeClass
{
    public string SomeProperty { get; set; }

    public object Clone()
    {
        return new SomeClass { SomeProperty = SomeProperty };
    }
}

Looking at this, I expected both the SomeProperty properties to be in the scope of the object initializer and end up not doing anything, essentially assigning the property to itself. The test seemed to indicate otherwise. Thinking I had a problem with my test, I set some breakpoints and did some evaluation at run-time. I didn't see anything wrong with the tests and everything seemed to be working.

Still convinced something had to be wrong, I did some searching on the web trying to find somebody who talked about scoping rules in object initializers. Of course, I may not have hit on the correct search terms, but in any case I didn't find anything. So I wrote the following console application:
namespace TestObjectInitializerScopeConsole
{
    public class TestClass
    {
        public string TestText { get; set; }
    }

    class Program
    {
        public static string TestText { get; private set; }

        static void Main(string[] args)
        {
            TestText = "Some random text";
            Console.WriteLine("this.TestText = \"{0}\" (initially)", TestText);

            var test1 = new TestClass();
            Console.WriteLine("test1.TestText = \"{0}\" (without initializer)", test1.TestText);

            var test2 = new TestClass { TestText = TestText };
            Console.WriteLine("test2.TestText = \"{0}\" (with initializer)", test2.TestText);

            Console.WriteLine("Enter to finish...");
            Console.ReadLine();
        }
    }
}

According to this test, it seems to indicate the scope for items on the left hand of the assignment are the new object and those on the right hand are what you'd normally expect for the method. It seems pretty odd and anti-intuitive to have different scope like this.

Any comments? Am I missing something? Is this defined somewhere that I've missed? Does it seem weird to anyone else?

Friday, December 5, 2008

How to show WWSGD text in Blogger

I've been doing quite a bit of reading regarding the ins and outs of blogging, search engine optimization and building readership. In the course of this, I read 21 Ways to Make Your Blog or Website Sticky. In that article, Darren Rowse mentioned a WordPress plug-in by Richard Miller called What Would Seth Godin Do. Based on an observation by Seth Godin, this plug-in allows customized messages to viewers based on the number of times they visit your site.

Intrigued by this idea, I set off to find something similar for Blogger (a.k.a. Blogspot) based sites. After a lot of searching, I failed to find anything. I figured it couldn't be too hard; I'd just roll my own. It took a bit more work than I expected, but I finally came up with my own variation. There is no code shared at all with the WordPress plug-in; it's simply similar functionality inspired by Seth's observation and Richard's implementation. The following explains how to configure a Blogger site display different text based on a user's visit count.

First, go into the Layout tab for your site and then the Page Elements sub-tab. Click on Add a Gadget. Select the HTML/JavaScript option. In the Content section, place something like this:
<div id="NewVisitor" style="display: none;">Thanks for visiting! Use the RSS feed or e-mail subscription to keep up to date on what's happening on this site.</div>
<div id="ReturningVisitor" style="display: none;">Welcome back! We're glad you enjoy our writing. If you especially like a particular article, please consider casting a Digg vote. Thanks!</div>
I'm no copywriter and obviously you'll want different text, but the important thing is to have two div sections with IDs of NewVisitor and ReturningVisitor, and with a style attribute for both set to display: none;. When the page is loaded, one section or the other will be changed to visible based on the result of a cookie.

Except for the limitations of ID and style, the rest is normal HTML. You can put things that are common to both text sections outside the div sections. Inside the div sections, put things you want displayed for the context identified by the ID attribute.

Save the gadget. Since the text is inside a gadget, you can move it to where you want it to display.

Next, select the code below and copy it to the clipboard. Then go to the Edit HTML section of your blog configuration and scroll down through the template code until you find the line that says <body>. Just above this line, there will be one that says </head>; paste the copied code just above the </head> line.

<!-- Start of script for "WWSGD" div manipulation -->
<script type='text/javascript'>
function getCookie(c_name)
{
  if (document.cookie.length > 0)
  {
    c_start=document.cookie.indexOf(c_name + "=");
    if (c_start != -1)
    {
      c_start=c_start + c_name.length+1;
      c_end=document.cookie.indexOf(";",c_start);
      if (c_end==-1) c_end=document.cookie.length;
      return unescape(document.cookie.substring(c_start,c_end));
    }
  }
  return "";
}

function setCookie(c_name,value,expiredays)
{
  var exdate=new Date();
  exdate.setDate(exdate.getDate()+expiredays);
  document.cookie=c_name+ "=" +escape(value)+
      ((expiredays==null)
        ? ""
        : "; expires="+exdate.toGMTString()+
      "; path=/");
}

function checkCookie()
{
  wwsgd_count=getCookie('wwsgd_count');
  if (wwsgd_count == null || wwsgd_count == "")
  {
    wwsgd_count = 0;
  }
  else
  {
    wwsgd_count = parseInt(wwsgd_count);
  }
  setCookie('wwsgd_count',wwsgd_count+1,365);
  visibleTag = 'ReturningVisitor';
  <!-- This will show the "new visitor" text three times.
      Change 3 to the desired value. -->
  if (wwsgd_count &lt; 3)
  {
    visibleTag = 'NewVisitor';
  }
  divToSee = document.getElementById(visibleTag);
  if (divToSee != null)
  {
    divToSee.style.display = "block";
  }
}
</script>
<!-- End of script for "WWSGD" div manipulation -->

(For those with sharp eyes, JavaScript's less than operator is encoded above. This is by intent. It needs to be encoded in the Blogger template when it is saved. It gets converted to a real less than sign and used properly when it is sent to the client's browswer.)

Finally, on the <body> line, before the closing ">", add onLoad='checkCookie()'. When done, this line will look like:
<body onLoad='checkCookie()'>

When these three things are finished, the site should show the items inside the NewVisitor div section the first three times it is visited. After that, the items inside the ReturningVisitor should be displayed. If you want a different count for the first message, change the numeral 3 in the script (indicated by a comment) to the desired number. If cookies aren't enabled, then nothing will be displayed.

Leave a comment if you have any thoughts or find this useful. Thanks!

Resources

Thanks to the following for information found useful in the development of this tool:

Monday, November 24, 2008

Microsoft's OfficeUI Ribbon: Application template

I've been working with the recently released Ribbon control from Microsoft's Office UI group. There are several cookie-cutter setup steps to get an application ribbon aware. In order to facilitate setting up a new application, I made a Visual Studio 2008 template that creates a blank application containing a ribbon bar with some empty controls.

Here is the template file. Copy this zip file to My Documents\Visual Studio 2008\Templates\ProjectTemplates\Visual C#. When Visual Studio is started, the New project dialog displayed when File | New | Project... will have a new Ribbon Application option under My Templates. Select this to create a skeleton ribbon application.

When the application is created, an error will be displayed indicating the ribbon control library cannot be found. This is because this library needs to be acquired directly from Microsoft. To get it you need to go to the OfficeUI web site. (Here are the how-to-get instructions.)

Once the library is downloaded and installed on your computer, go to the new ribbon application's References, remove RibbonControlsLibrary and then add it in again, pointing to the location on your computer.

The skeleton application contains a Close option on the application menu to stop the application. There is a single tab with a single group containing a single button. Finally, there is a single button on the quick access toolbar. These all can be used as templates to easily add more.

More information on creating Visual Studio templates can be found on the MSDN site. (Thanks to paranoid ferret for the pointers on to how to create templates.)

Friday, November 14, 2008

How much of the implementation can be hidden by interfaces?

Short answer: All of it.

Consider this example:
unit uSomeManager;
interface
type
    ISomeManager = interface
    ...
    end;
function SomeManager: ISomeManager;
implementation
type
    TSomeManager = class(TInterfacedObject, ISomeManager)
    ...
    end;
var
    gSomeManager: ISomeManager;
function SomeManager: ISomeManager;
begin
    if not Assigned(gSomeManager) then
       gSomeManager := TSomeManager.Create;
    result := gSomeManager;
end;
Notice what is in the interface part of the unit. There are two things: the interface that is being defined and a global function which returns something implementing that interface. There is no class information  whatsoever. The entire implementation of this interface, including the class declaration, is in the implementation section of the unit. This prohibits others from using this class in any other way. They can't extend it, override it or instantiate another copy of it. If they want a different implementation of this interface, they have to completely re-implement it.

Whether or not this is a Good Thing is another discussion, but it does make it very clear to the user that it is intended to only have one instance of this. I find it works well for places where you might want to use a singleton, without the low-level messiness normally associated with them in Delphi.

Thursday, November 6, 2008

Splash screens are evil! 8 ways to improve them.

Ok, perhaps evil is too strong a word, but ideally splash screens should not be needed. They represent a failure on the part of the development team to make an application that can load fast enough that the user isn't left wondering what happened when they double click its icon. The best case is to make the program load fast enough that it's not needed. As a developer, I realize minimizing application start-up time can be a really hard problem, possibly hard enough that it's not worth the resources to invest in this area of optimization.

Faced with this reality, here are some guidelines, splash screen etiquette if you will, to make it less obnoxious. These are things I've come up with as a user of many different software packages over the years within the context of having done a fair bit of reading in the area of user interaction and experience. I find it interesting that after a bit of searching on the topic, both on the web and in some dead-tree resources, I have found many people talking about splash screens' visual design but no one describing their functionality.

1. Not centered: that's where I'm working!

I typically have a minimum of three applications open. Quite frequently I have two or three times that number. When I start an application, the odds are I have something else I'm working on, and want to continue working on, while the new application is starting. The center of the screen is where my focus is normally going to be for those other applications. Therefore, the center of the screen is the worst place the splash screen can go. It's going to be right in the way of my doing anything else.

2. Not modal: I'm trying to do something else.

The splash screen should should not be system modal. I am working on something else while the new application tries to get going. There is no reason to think the splash screen is more important than what I'm working on. The splash screen should not ever cover up my current work.

3. Not focused: I'm not typing to you.

The starting application should not grab focus unless no other application has it. If another application has focus, it should maintain it. If I'm typing, I'm not typing into the not yet started application, I'm typing to the existing application. (Microsoft Office Outlook team, do you hear me?!?)

4. Not too big: you're not that important.

All the splash screen needs to do is tell me it's working. To do this it just needs a small, unobtrusive animation. I'm willing to give splash screens 5% of my screen. If it can't let me know it's there in a 300 x 300 pixel box, the designers need to rethink what they're trying to do. Ideally, I should be able to size it to the dimensions I want, including minimized.

5. Not fixed: I want that space.

Even when it's not centered, I should still be able to move it where I want it so it's out of the way. No matter where the designers set it by default, there is always going to be the case where, for someone, that location is in the way. Make the silly thing movable, like any other window on my system.

6. Not default: remember what I've told you.

After I've told you where and how big, remember it! Next time I start the application, odds are my system is going to be about the same configuration. I've gone through the hassle of moving it and sizing it; I shouldn't have to do it again tomorrow.

7. Not a non-task: be on the task bar.

The splash screen should cause a button to appear on the task bar; preferably the same button that will be used by the main form when it finally appears. This way, one of the sizes I can give it (see #4 above) is minimized. This allows me to know the application is starting without it having to take any of my precious screen space.

8. Not needed: delay initialization.

Finally, the ideal is to not need a splash screen at all. Consider making the main form visible immediately with things disabled. As modules are loaded and initialized, then build the form and enable the various areas for the user.