2D Head with a clock as an eyeball.
 Friday, August 03, 2007

Obligatory Duck Photo by Wonderferret I'm not sure what to make of this. Deftflux has created a library to aid brave C# developers in their dark quests to use duck typing.

Given that C# 3.0 is around the corner with anonymous types I feel the duck typing library is a bold move towards Rubyesque abilities. While anonymous typing only gets you some of the niceties of duck typing, I think the greatest advantage of anonymous types is compiler checking goodness.

There is no doubt duck typing can save a lot of time coding. I admire languages like Ruby for their declarative, artistic form of expression. The .NET framework makes use of it too; duck typing has very real use cases.

The TDD crowd has a distinct advantage over the rest, in that one could happily duck type all day long, trusting in the safety of ones unit tests to provide alerts to type mismatches.

 Sure, if you write a thorough test suite you can theoretically avoid most of the dangers of duck typing. Though all it takes is one hole in the tests and the time saved coding is spent debugging. I would rather my compiler tell me about a type mismatch, than the beta testers complaining of unhandled InvalidCastExceptions. In the spirit of using the right tool for the job, surely the compiler is the right tool to inform us of type mismatch problems? It does a fantastic job of it. Cedric Otaku puts it in a way that's hard to ignore:

In a way that's typical for dynamically typed languages, the error will therefore only appear at runtime and only if such code gets run.

If you are duck typing in copious amounts and not writing tests, then you are walking on shaky ground.

I guess I like to be explicit in general; say what you mean and mean what you say. Life is simpler that way. I like suspense & innuendo in movies, not code. I can't wait for anonymous typing in C#, but perhaps even more so, I look forward to the day work lets me use languages like Spec# to enable me to be even more explicit to the compiler as to my intentions.


Filed under:  |  | 
 Wednesday, August 01, 2007

I often see superfluous use of Me.This and this.That lying around in code and it always bugged me, but tonight I found a reason it might be more than just my anal nature. Typing 'Me.' or 'this.' is not a clever way to fire up Visual Studio's Intellisense drop down. The Ctrl+<Space> keystroke is a much tidier, and quicker way of getting there.

Sure, there are circumstances where you need to use these keywords, for instance when you need to differentiate between your class and your base class. Me and MyBase, or this and base are valid ways to get around in that case.

The benefit of refraining from using these keywords until its necessary is that you could reduce the cognitive load on someone who has to understand your code. Every time you avoid the use of the Me keyword you will decrease your maintenance complexity score by 2 points every time you do so. In functions that address members heavily, this could represent a significant increase in the readability of your code.

So what is this metric, Maintenance Complexity? Its an idea coined by Mark Miller from Developer Express. Its been a feature in CodeRush and Refactor! Pro for some time now. The 2008 release of Visual Studio, codename Orcas will also provide code metrics visualisation. Simply, it recognizes the fact that the more code you write to achieve a goal, the harder that code is to maintain. That is to say, if you can achieve the same goal in less code, you have written it in a more maintainable fashion. It has been said before, the best developers code smaller.

Each type of construct attracts a score, much like letters do in the board game, Scrabble. At the end of a function you are scored by adding the values of each construct up. For a complete description of the metric, please visit Mark Millers blog entry on his creation.

There are some valid criticisms to this metric, and simply refactoring in aid of reducing MC scores is only cheating yourself. As such I suggest the reader use code metrics in general as an indicator rather than a developers divining rod.


Filed under:  |  | 
 Thursday, July 26, 2007

In my last post, I outlined why I felt that tab order is an easy way to measure your GUI's complexity, and in this post I intend to show you how. Bad tab order is on my top 5 pet peeve list, so it's one of the first things I look for in an application. As you can see, even the simplest of UI's can be over engineered, and layout metrics that are purely concerned with user interaction wont pick it up. Turning on the View > Tab Order will show that the devil truly lies in the detail.

clip_image001

Nested panels adjacent to more nested panels will make for some mind exploding tab ordering, as shown in the example above. This is definitely panel overkill, or panelcake as I have affectionately dubbed it, and the main culprits include the ToolStripContainer, the SplitContainer, the TableLayoutPanels, and finally the GroupBoxes. The depth is so great, the tab order obscures the design!

YAGNI applies to GUI's too, so lets rescue this poor innocent interface...DocumentOutlineView

In Visual Studio 2005, I press the Ctrl + W, U key chord to bring up the document outline viewer. This tool is absolute gold for rearranging hairy container hierarchies.

Step 2, set the window style to Fixed Window. Unless there is a compelling reason to be able to resize then there is no point in offering it. If it is needed, then careful use of Anchor and Dock properties will suffice for the most part. TableLayoutPanels should be used sparingly. YAGNI all the way.

Next, I lose the ToolStripContainer. Its function is to provide a drop target for ToolStrips and MenuStrips on the outer extremities of your Form. Does the user need to move the menu or tool strips from the top position? Nice idea, but probably not.

I continue to carve into the UI, removing all of the table layout panels and the split container until I am left with the fewest amount of controls to represent the data I need the user to edit. Careful choices for anchoring replicate much of the TableLayoutPanels functionality. Some grouping is beneficial to the user, and doesn't hurt when you need to alter the visibility state of groups of controls. What I am left with is a form that achieves the same end as the original, trimmed of unneeded function.

The acid test is that I can set the tab order in roughly 10 clicks of the mouse button. Not to mention the fact that you can see what you are doing.

GoodTabOrderUI


Filed under:  |  | 

Graphical user interface design is a subject dear to my heart, as it should be to most GUI developers. However, creating a useful, efficient and ergonomic user interface is easier said than done. All too often I see (and in the past have written) applications that just clearly get it wrong. There is nothing more frustrating to me, as a programmer, than using a poorly planned UI. Some UI's make you feel as though it would be quicker to write the program yourself.JimmyTheCanary

 So what is the proverbial canary in the mineshaft for a user interface? I've compiled a list of things I feel are good signs that your GUI needs a birthday, however since the list got quite long, I felt compelled to break them up into a blog mini series, so here goes...

When tab order is a nightmare

I know that tab order is that UI chore we all leave until the last moment or when the tester has run out of things to pick on. Incidentally, its the first thing I look at when deciding whether or not I like an interface.

If you are thinking about either buying or creating your own tool to help you sort out your tab order, then stop for a second have a think why. Sorting your tab order should be as simple as clicking on your controls in the order you would like your users to visit them.

A lot of research has been dedicated to UI complexity and metrics, and like your cholesterol count, you can ignore them at you own peril. I can't say I know much about the various computer science techniques to measuring UI complexity, but I do have my methods. Tab order complexity is my cheap and nasty, poor mans metric for GUI layout appropriateness. In my next post, I'll show you why.


Filed under:  |  | 
 Monday, July 23, 2007

I've been struggling with the concept of DI & IoC for a few weeks now. Its not because I don't understand the concept, or the benefits, I struggle with the implementation details. I'm one of those horrible visual learners who needs to see code  before the penny even gets close to dropping.

I found my holy grail of information today, and it was lurking right underneath my nose. I've only recently subscribed to Jeremy Miller's blog and the latter chapters in his series on building your own Composite Application Block seemed a little 'pie in the sky' for me. Ooo boy, was I wrong.

I started at part one this afternoon, and have been reading page after page of excellent content for the DI newbie.

So if you're in the same boat as me, struggling with the question; "How do I create a rich WinForm app, that is comprehensively unit tested, without sacrificing furry animals to the dark gods of the Enterprise Library?" then treat yourself to Jeremy Miller's series on building your own lightweight CAB.


Filed under:  |  |  | 
 Wednesday, July 18, 2007

9421665_f055539a8c_mFound this gem today, and yes - I wrote it.

Its a very simple class, I use it to tell NCover to ignore certain sections of code - fair enough right? Well... here it is.

<CoverageExclude()> _
Friend NotInheritable Class CoverageExcludeAttribute
    Inherits System.Attribute
End Class

Embarrassing. You can see another example of this kind of logic here.

So hands up people - give us your most recent stupid coding moment and make me feel better about myself.


Filed under:  |  |  | 
 Friday, July 13, 2007

I had the pleasure of treating myself to a new phone recently. I had a lot of options, but I finally settled on a Nokia N95. It is a good phone, with good features, and I would recommend it to anybody who wanted more out of their not so smart phone, but couldn't quite justify the use of a PDA. I'm with Robert Scoble, though, I'd prefer to get an iPhone, but that won't be released in Australia until early 2008.

For more info on the N95 visit the NSeries website, it will tell you more about my phone than I can.

There have been a few issues with the phone in regards to the GPS software included with the phone 'Nokia Maps' and there seems to be much forum confusion as to what the deal is in Australia. Hopefully I can clarify the situation:

  • As bought from the shop, you can find POI's, addresses, and calculate routes. It will cost you data using your chosen mobile Internet access point. As you move about the map, it will download imaging via your Internet connection. If you plan a route, you can simulate the route by downloading the voice commands, or you can have the GPS track you as you traverse the route
  • If you want to have real time navigation, you will have to pay around $130 AU for 3 years. This gives you the 3D view and a voice telling you when to turn.
  • The good news is, that you can download the entire map for any country using the abominable Map Loader program available from Nokia. The bad news is that in Australia, you will be lucky to get a download speed greater than 2.2kbps. The maps for Oz are 70MB.
  • Searching for POI's and addresses still uses Internet time, so plan your routes via your home WLAN to save money.

The maps take forever to download, so in the interest of being a nice Internet citizen, I have decided to begin sharing them on the ED2K network. Alternatively you can download it from me directly.

You will need something to open .rar files - I highly recommend WinRar.

To be honest, for the most part, Google Maps on the mobile is a nicer all round experience, but until it starts using the in built GPS, it is still a toy. If you want something to use in the car, go get yourself a dedicated unit, the N95 has better POI's but it still doesn't come close to the TomTom One XL.

Personally, I plan to use the GPS feature for bush walking, and Nokia provides an excellent route stat application called Sports Tracker. With it you can graph your movement, and save the results in Google Earth compatible files, XML, CSV. For this, the N95 absolutely rocks.


Filed under:  |  | 
 Thursday, July 12, 2007

For those of you who like to be early adopters, and are also masochistic enough to be reading my blog AND are reading it from a 64 bit version of windows you can now take pleasure in trying out the latest beta of Microsoft's Live OneCare anti virus solution, now available for 64 bit versions of Vista.

If your keen to jump into the beta program - here is the link.


Filed under:  | 
 Wednesday, July 11, 2007

I often get to play the maintenance role in my coding life, and I actually enjoy it, as I get to see how others tackle certain problems. I also like to challenge myself by fixing bugs with the smallest footprint possible. In doing so, I find a lot of common things that bring down the 'maintainability' of a class. I thought I'd share some pain that I encountered today.

Designer Death

All too often I find code that roughly translates to this example:

internal class MyForm : System.Windows.Forms.Form

   MyClass _myClass; 

   public MyForm() 
   { 

      _myClass = new MyClass(); 
      _myClass.MyPropertyChanged += DodgySideEffectEventDrivenCode; 
      _myClass.MyProperty = new object(); 
   } 

   internal void DodgySideEffectEventDrivenCode(Object sender, EventArgs e) 
   { 
      //Lets do something that requires, ooh I dunno....SQL access 
   }
}

I won't go into all the other reasons why this could be seen as bad code, but for the purpose of the example, changing DodgySideEffectEventDrivenCode to look like this can save a whole lotta WSOD's…

internal void DodgySideEffectEventDrivenCode(Object sender, EventArgs e) 

   if (this.DesignMode) return
   //Lets do something that requires SQL access, but only if we aren't in design mode
}

Poor Private Properties

The following is an example of a useless property. There are precious few situations where this would be beneficial to a class.

private static CultureInfo CC

   get { return CultureInfo.CurrentCulture; }
}

Why not use a private readonly field? While I admit there is the odd place where you might insist on a private readonly property, it is the exception rather than the rule. Now, I know Properties look cooler from the Intellisense dropdown, but c'mon, surely this is saving you some time:

private readonly static CultureInfo CC = CultureInfo.CurrentCulture;

Personally, I think the proof is in the IL pudding…

.field private static initonly class [mscorlib]System.Globalization.CultureInfo CC

Compare that to the IL of a readonly property get method:

.method private hidebysig specialname instance class [mscorlib]System.Globalization.CultureInfo get_CC() cil managed
{
    .maxstack 1
    .locals init (
        [0] class [mscorlib]System.Globalization.CultureInfo CS$1$0000)
    L_0000: nop
    L_0001: call class [mscorlib]System.Globalization.CultureInfo [mscorlib]System.Globalization.CultureInfo::get_CurrentCulture()
    L_0006: stloc.0
    L_0007: br.s L_0009
    L_0009: ldloc.0
    L_000a: ret
}

Boolean Badness or Enumerate Early

Sometimes coding isn't enough; sometimes you need to express your intent explicitly. Take the following function declaration which clearly does not:

internal void SetUIState(bool value)

and its usage:

SetUIState(true);

Can you tell how this function will work? Personally I like comments and documentation – and they would help, but self documenting code is worth a page of English documentation. For example:

internal enum UIState

   enabled, 
   disabled,
}

internal void SetUIState(UIState state)

Combined with a decent IDE, the usage and effect becomes apparent:

SetUIState(UIState.enabled);

An even simpler approach would be to just name the function to imply the usage of the state parameter in the first place. I.E

    EnableUI(true);

Personal choice comes into this a lot, but I think we can all agree that it's all about taking care with naming.

On that….

Unchanged UI

If I ever see another TextBox control named 'TextBox1' I'm going to have to hurt somebody. Seriously though, if you have labels and other miscellaneous controls laying about that you don't need to name because you never reference them in code, and you are using VS 2005 or greater then consider the following approach:

  • Use your control key and select the lot of them.
  • Move over to the properties window and set the GenerateMember property to false.

This will keep the controls initialization local to the InitializeComponents routine, thus reducing the clutter in Intellisense and other areas in the IDE quite significantly.

For the rest of your controls and objects, pick a naming convention, and stick to it like glue.


Filed under:  |  | 
© Copyright 2009 Jim Burger