Why Worry? (Ajax Edition)

An ajax version of last week's Why Worry? post

Requires Javascript ;-)

As a programmer there are only two things to worry about:

(Instructions... you, um, click the button to begin, yeh?)

Here's the original

 

Marketing Weasels Who Write Code

code snippet form a microsoft ad

When I flick through a geeky book I'm more likely to browse the code snippets than the text.

Unfortunately, marketing weasels are aware of this. And hence, you see a lot of dumb ads that use Source Code to hook you in.

The amusing thing, for me anyway is that the code they use is always broken in some way.

Here's the code from a current microsoft ad i saw here:

Public Function ProjectCompletionTime() as String
  If DevTool <> "Visual Studio 2005" Then
    return "Sorry, I'm going to have to cancel tonight"
  Else If DevTool = "Visual Studio 2005" Then
    return "I'll meet you for dinner at 7pm"
  End if
End Function

Okay -- this is probably one of the better pieces of code i've seen in advertising. But there's still about five things wrong with it.

(Continues...)

Firstly -- you'd expect a function called 'ProjectCompletionTime' to return a DateTime. When you inspect the code you find that what it actually returns is a statement about your availability tonight. I'd recommend the function be renamed to 'AvailabilityTonight' -- or 'ExcuseForTheWife'

Secondly, the redundant logic is plain annoying. A C# rendering of this same logic would return the error that 'not all code paths return a value'

Personally, I'd use a 'guard clause' technique to reduce the nesting. I like guard clauses. YMMV.

Public Function ExcuseForTheWife() as String
  If DevTool <> "Visual Studio 2005" Then
    return "Sorry, I'm going to have to cancel tonight"
  End if
    
  return "I'll meet you for dinner at 7pm. You're paying. I blew all my money on Microsoft Tools."
End Function

Also, I wonder where this 'DevTool' variable is declared? And as a variable, I'd prefer to see it in camel case.

Strange too that it's just a string. You'd expect it to be an object, never mind. Let's pass it in as a parameter:

Public Function ExcuseForTheWife(devTool as String) as String
  If devTool <> "Visual Studio 2005" Then
    return "Sorry, I'm going to have to cancel tonight"
  End if
    
  return "I'll meet you for dinner at 7pm. You're paying. I blew all my money on Microsoft Tools."
End Function

Now the real thing that annoys me here is that they're clearly not using Visual Studio as their code editor.

The code does not have syntax highlighting! And the lower case 'as' and 'return' are also a dead give away.

I pasted my snippet into Visual Studio, and copied it back out using 'CopySourceAsHtml' (the excellent plug in from Colin Coller at JtLeigh.com). (I had to apply extra styles to give it a 2005 look... the plug in i have only works in 2003). Here's the result:

Public Function ExcuseForTheWife(ByVal devTool As String) As String

    If devTool <> "Visual Studio 2005" Then

        Return "Sorry, I'm going to have to cancel tonight"

    End If

 

    Return "I'll meet you for dinner at 7pm. You're paying. I blew all my money on Microsoft Tools."

End Function

Finally -- brevity is wit etc. While I do love VB, I think C# would be punchier and less wordy for the ad:

public string ExcuseForTheWife(string devTool) {

    if (devTool == "Visual Studio 2005") {

        return "Meet you at 7 PM!";

    }

    return "Can't make it tonight. Still fixing broken code.";

}

 

ReDim for C#, using Generics

As an exercise in using Generics, I wrote a ReDim function that works in C#.

Bugs, feedback, criticism, welcome and appreciated.

/// <summary>

/// Redimensions the length of array down(or up) to equal "length" (parameter)

/// This is based on the VB "redim" function, and like that one it does

/// cause a memory overhead and a performance hit. So please use this one

/// sparingly. For example, don't call it in a loop.

/// (Hint: prefer List<T> with it's .Add() method, for frequently redim'd lists)

/// </summary>

/// <typeparam name="T">The Type of Array to be re-dimmed</typeparam>

/// <param name="arr">The array to be re-dimmed</param>

/// <param name="length">The new length of the array</param>

private void ReDim<T>(ref T[] arr, int length)

{

    T[] arrTemp = new T[length];

    if (length > arr.Length) {

        Array.Copy(arr, 0, arrTemp, 0, arr.Length);

        arr = arrTemp;

    } else {

        Array.Copy(arr, 0, arrTemp, 0, length);

        arr = arrTemp;

    }

}

 

Amphetamines for Query Analyser

But not the sort of amphetamines that destroy your nervous system and send you to an early grave.

SQL Prompt from red-gate gives you intellisense-style behaviour inside Sql Query Analyser. Amazingly, you can download Sql Prompt for free. Not a time-limited or feature limited version, but the full version. Requires registration -- but if you instruct them not to spam you, they won't.

This is a genuine endorsement by the way, not a sponsored one. ;-)

continues with animation...

Here's a picture of it in action:

SQL Prompt in Action

By the way, if you currently use Enterprise Manager for editing Stored Procedures, I recommend you start using Query Analyser instead. It is years ahead in development. If you haven't used it since SQL 6.5 days, you'll be quite impressed by the progress it's made.)

 

Why Worry? (Programmer's Edition)

as a programmer there are only two things to worry about:
whether your code has bugs or is bug-free.

if your code is bug-free then there's nothing to worry about.

if your code has bugs then there's only two things to worry about:
whether you can fix the bugs or whether you can't.

if you can fix the bugs then you have nothing to worry about.

if you can't fix the bugs then you have only two things to worry about:
whether you can find someone else to fix the bugs or whether you can't.

if you can find someone else to fix the bugs then you have nothing to worry about.

if you can't find someone else to fix the bugs then you have only two things to worry about:
whether the bugs will get you fired or whether they won't.

if the bugs won't get you fired then you have nothing to worry about.

if the bugs do get you fired then you'll be so busy catching up with old friends at the unemployment office that you won't have time to worry.

so why worry?

(The original wording of this was on a poster at my Grandmother's house. Exposure to this logic as a small child might be what turned my brother and i into programmers.)

 

New Invention: The EzyFridge

the Ezy Fridge

(thanks to google sketchup, i can finally unveil the details of my latest invention)

Are you tired of unpacking all those groceries when you get back from the shops?

Are you sick of breaking your back, putting the vegies in the crisper and the cheese in the cheese area??

Are you fed up with finding space in the door to keep the milk?

Just open the hatch on the front of your EzyFridge, and tip those groceries in!

Done!

Coming soon:

the Ezy House

The EzyHouse!

Tired of having to unpack all your possessions everytime you move?

With the EzyHouse, just open the hatch and tip your possessions in.

 

VB.Net Tip: IIF is a function, not a language feature

I think i've found a nice way to demonstrate this age old gotcha in VB.

What result do you expect from this line of VB code?

IIf(True, MsgBox("hello"), MsgBox("goodbye"))

(continues...)

Do you expect only the first message box to show up?

You might think it would just execute the:

MsgBox("hello")

But you'd be as wrong as a fez with a brim.

BOTH message boxes will come up, one after the other. Try it and see.

Is this a bug? Is this insane? Is this dangerous?

No, no and yes occasionally. The thing is that IIF is just a built in function. And when you try to send expressions to it, they get evaluated before the function sees them. The same happens any time you send expressions to any function.

So it's not a bug, and it's also unlikely to change in any version of VB, or any future version of the IIF function. So it's worth taking the time to remember it, understand it and work with it.

Now when is this likely to pose a problem?

To avoid a divide-by-zero error, many a coder has tried this:

IIf(divisor=0, c, a / divisor)

And they will of course still get a "Divide By Zero" error, if the divisor equals zero.

Again, that's because IIF is just a function. And like all functions in vb, it doesn't accept expressions as parameters. So the expressions must be evaluated before they are passed to the IIF function. Hence the error.

The longer syntax, using full if statements, will work as desired:

        If divisor = 0 Then

            Return c

        Else

            Return a / divisor

        End If

And that's pretty much the best way to skin this little kitten.

(thanks to derek for reminding me to post about this)


One little footnote, is that in Excel, if you type:

        IF (TRUE,TRUE, 5/0)

...you won't get an error message -- because some sort of shortcutting is happening, and the false code path isn't executed.

So, to get a "#DIV/0!" error message, you'd need to get that particular trouser leg of the if statement to fire, like so:

        IF (FALSE,TRUE, 5/0)

 

TimeSnapper 2.0 is near to completion

This article, "Stardock's 10 rules for success" puts it quite nicely:

TimeSnapper's chief developer, Atli, ... (continues)

TimeSnapper's chief developer, Atli, put a halt to adding new features a week or two ago, so we can get ready for releasing version 2.0.

I'm glad he did. The closer we get to a release date, the more features I think of. "Oh oh! It's just got to have this!" Damn it's hard to stop.

I've been compiling lists, big lists, of features for version 3.0. Version 4. Version 53. The tighter the pressure to stop adding features: the more powerful the creative drive.

TimeSnapper has the ability to grow in a number of different directions. (At this point, you can picture an ice crystal forming -- spreading out in a beautiful though slightly assymmetric way)

It has these divergent goals:

  1. A Time Tracker
    • Personal time
    • Official time
  2. A Scenario Capturer
    • Lazy capture: e.g. "oops my computer just crashed, what did i do to cause it?"
    • Deliberate capture: e.g. "I'll record this action, and then turn it into a movie." (not yet a feature)
  3. A Productivity Booster
    • Self-awareness, e.g. "How do I usually get distracted?"
    • A complement to a "Getting Things Done" system.
  4. And, as people love to point out:

  5. Surveillance
    • (A direction we've deliberately avoided)

With all those possible goals and sub goals, the array of possible features becomes a vast fractal monster. We've continually sought suggestions and help from our user-base. Not so much to generate ideas, but to give some weighting to the cornucopia of ideas the product has already given us.

It's a weird little product, you know. While other software is doing similar things on some fronts, I think that the TimeSnapper package represents a unique and special niche that is previously unexplored. Thus the voluminous possibilities.

Of course this too presents more possible tasks: create a website where people can suggest features, vote on features, give reasons for liking features and so on. Add features to the feature voting website. Have people vote on what features to add to the features website. Or survey the existing software out there for doing this. Which software is best? Maybe I could write a website where people vote on their favourite software for conducting polls about what features to add to their feature suggestion website. Or maybe we could... maybe we could just finish version 2.0 of TimeSnapper, and build up the courage to release it to the world.

Even the world's simplest code generator is on hold for now. With my current featuritis, i can't be let anywhere near that product. It risks becoming the world's most complex code generator, data miner and email client. With a sandwich maker and hybrid-fuelcell/chicken-coop-cleaner on a collapsible side panel.

Enough. Back to the grind.

 

The Actual Minimum Every Gmail User Must Know About Unicode and Character Sets (Excuses welcome)

I've had 'garbled' looking emails turn up from time to time (particularly due to the world-wide nature of TimeSnapper support) and it makes my eyes glaze over.

"Ah encoding" i say. "I'm an expert on this. Let me think." And then I realize I'm not an expert. The mind is utterly blank. It's very zen.

I try not to think about encoding too much, if ever. I remember reading this 'joel on software' article about it "The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)" and i understood it all perfectly at the time. It made such sense, it was beautiful.

But then i hit the reset button on my brain and forgot it all. I've read it again since. But again, the reset button.

So when a garbled message turns up at gmail, the wisdom of joel spolsky is not upon me. I look at the screen in a panic, and bash at the "more options" link (to the left of the date received). At that moment, one of the 'options' given says "message text garbled". Yes, that's the one.

I press that link and the email opens in a new window. It's in a non-proportional font. Very raw looking. But perfectly readable. The encoding problem has magically gone away.

So gmail user's remember this alone:

If you get a garbled looking message, hit the "more options" link, and start fishing around for a suitable option. You'll soon find it.