1001010.com

one zero zero one zero one zero dot com
one hundred ten ten dot com
binary representation of ascii 'J' (74) dot com

home code projects photos wiki resumé tombstone ?
Individual Entry Archive: The Experiments of Jason De Arte - Evil Lawn Dart Master, Toy Maker and Professional Software Engineer
« prev: More than a sore throat
» next: Things I dislike: Copy'n'Paste Comments
Code | Wednesday
Things I dislike: Hard-coded variable menu items
Posted by Jason on Wednesday September 07, 2005 05:41 PM  |  Permalink  |  Comments (0)

Hmm, that's not the best title - but maybe a contrived code sample or two will help out in explaining why sometimes I weep when I look at certain bits of code.

Imagine if you would, creating a context menu with a few dynamic elements without IDs


menu->append("Hello");
menu->append("This");
menu->append("is a");
menu->append("Test");

And you responded to the elements not by an ID number, but by a position index.


switch(selectedIndex):
{
    case 0: doHello(); break;
    case 1: doThis();  break;
    case 2: doIsA();   break;
    case 3: doTest();  break;
}

And then when you look at the code that creates the menu item with greater scrutiny, you notice it's not as simple as you once thought...


menu->append("Hello");
if(hasPermission(SECURITY_RIGHTS_THIS))
    menu->append("This");
menu->append("is a");
menu->append("Test");

That's why I wept.
If an unlucky user doesn't have SECURITY_RIGHTS_THIS all the following menu items will be off by one!
This isn't a hard coded COM interface contract, but it IS a handshake usage contract that a future maintenance programmer (such as myself) may not even be aware of!

So here's a simple solution (if you can't change it to use proper IDs because it would effect to many systems):
Keep a table of what menu items were added and their appended menu index. Maybe something along the lines of


enum PossibleMenuItems { pmiHello, pmiThis, pmiIsA, pmiTest, pmi_MAX };
typedef map<int, PossibleMenuItems> IndexToMenuItem;
IndexToMenuItem m_IndexToCommand;
...
int nMenuIndex = 0;
// For each item you add, append it AND record it...
menu->append("Hello");
m_IndexToCommand[nMenuIndex++] = pmiHello;

if(hasPermission(SECURITY_RIGHTS_THIS))
{
    menu->append("This");
    m_IndexToCommand[nMenuIndex++] = pmiThis;
}
...

Then in the menu handler...


IndexToMenuItem::iterator itFind = m_IndexToCommand.find(selectedIndex);
if( itFind != m_IndexToCommand.end() )
{
  switch( (*itFind) )
  {
    case pmiHello: doHello(); break;
    case pmiThis:  doThis();  break;
    case pmiIsA:   doIsA();   break;
    case pmiTest:  doTest();  break;
  }
}

Now it no longer matters if an item is not added to the menu. As long as the table is updated - I'm happy.

Comments (0)

Comments are closed