Archive for September, 2007

The Baffling World of Microsoft Music

Can anybody on planet Earth explain Microsoft’s music strategy?

“I am a cipher wrapped in an enigma smothered in a secret sauce.” – Jimmy James

Windows Media Player version 11 is actually — surprisingly — a decent application. Upon opening Media Player, you’ll notice an integrated music service called Urge. Urge has a decent music selection and offers an unlimited download subscription option as well as an iTunes-like music purchase option.

What about Zune?

But why Urge? Microsoft, unbelievably, is its own competitor. Zune is not integrated into Media Player, and its DRM is not compatible. Zune requires a separate download. Vista comes bundled with something called “Sync Center” that is deeply integrated with Windows Media Player. I don’t know if this works with Zune software.

This is just weird.

It Gets Worse

News flash: Urge is now dead. OK…Mr. Obvious thinks “now they’ll consolidate under a single brand.” Nope. Urge is merging with Rhapsody, which is NOT integrated into Windows Media Player. Instead, you have to download and install the proprietary Rhapsody client software. Here’s what it looks like:

Rhapsody Bug

Rhapsody crashes constantly. And (as I found) if you leave the “auto login” checkbox checked, it won’t auto-login. Worse, you have to exit, go to IE, clear ALL browser caches, and then restart. Sometimes several times. If you are lucky you can play a few songs, but eventually it kicks you out.

Rhapsody sucks ass.

If you downloaded a library of songs from Urge, you can allegedly transfer them to Rhapsody. It turns out you *can* import the songs, but after a few days or weeks the DRM expires and bricks the music. You have to re-download everything at this point.

This assumes the songs are even available. I’ve found that Rhapsody appears to offer LESS music than Urge. Almost every album appears to have partial content, with at least 2-3 songs missing:

Many Songs Not Available

Those are the best songs on the albums. The fillers are still available for monthly-subscription customers.

In their defense, these missing songs are available for MP3 purchase. Surprisingly, these are 256 Kbps DRM-free MP3, just like DRM-free MP3s from Amazon. (makes you wonder why there is SO MUCH BUZZ about Amazon’s MP3 downloads, when you can get the same thing from Rhapsody? Maybe if Rhapsody didn’t crash so often…)

In Summary…Please Explain

So back to the original question. Can ANYBODY offer a logical explanation for Microsoft’s music strategy? Allow me to summarize:

  • There is no brand. Consumers are given a bewildering array of choices…Windows Media Player, Urge, Rhapsody, Zune…???
  • Many choices are not integrated — at all — with Vista’s otherwise decent Media Player and Sync Center
  • Software like Rhapsody crashes and is complex to configure
  • Many songs simply are not available, despite other parts of the album being available
  • Rhapsody is part of the new breed of DRM-free MP3 providers, just like Amazon, but nobody’s really talking about that. Surely that should be a prominent part of Microsoft’s marketing?

Here is my theory. I don’t think they are stupid, nor do I think they are intentionally trying to fail. I think this is mostly a case of a huge corporation that is dominated by special interest groups, bureaucracy, and committees. Trying to please everybody leads to wishy-washy shit that inspires nobody.

Microsoft needs a dictator.

4 Signs You Are Fighting Your Version Control Tool

Are your habits and procedures at odds with your version control tool?

1. Afraid to delete

Some people don’t like to “delete” other people’s code. When they fix a bug, they’ll comment-out snippets of bad code, add their bug fix, and commit both. Over time these commented-out snippets of clutter accumulate. Your version control tool maintains history. Go ahead and delete the junk, you can always get it back.

2. One Giant Commit

Some people get it right by working in a branch of some sort. But even so, they don’t commit changes until their work is 100% complete. If your tool supports branching, you should commit to your branch frequently. This gives you a great backup mechanism and lets you easily back out unwanted changes should you discover a problem with your approach. Too often, people work on huge tasks for days and weeks at a time, performing a single monolithic commit at the end of their task. This introduces great risk should your hard drive go bad near the end of your task.

3. Using Physical Copies as a Backup Mechanism

How many times have you seen this? Before making a change, programmers copy their source code — manually — to some “backup” location on their hard drive. This gives them a sense of security because in their minds, they can easily revert to the original version of the source files. Uh, this is what your version control tool does for you.

4. Human Edited History Logs

This “worst practice” is frequently mandated by coding standards committees. Comment blocks like this:

// Audit history
// 10/15/2006 - J Smith - Made the account number longer
// 10/22/2006 - W Bannerman - Fixed NullPointerException
// 01/06/2007 - JJ - performance enhancements

These comments are generally wrong because one or more programmers forget to update them. Manual human practices are highly prone to failure. These comments are completely redundant with the history provided via the version control tool. It’s better to simply mandate revision comments whenever committing changes.

Most Programmers Don’t Write Tests

What percentage of programmers write automated tests on a regular basis? Has anybody attempted to answer this question through some kind of rigorous scientific analysis?

Based on my own anecdotal observation, I estimate less than 5%. Hardly anybody writes tests.

Questions for you:

  1. Do you typically write automated tests for your code?
  2. What percentage of your colleagues write as many tests as you do?
  3. When it comes to testing, do you feel your work environment is typical compared to the industry at large?

Feel free to answer other questions not listed above. And don’t forget to subscribe to my Atom feed.

Comic Tribute to Crazy Bob

Building on the success of last week’s comic, I present…

Comic Tribute to Crazy Bob

See also: Cedric, Bob, and of course Guice.

Paying my Taxes

This talk about continuous tax is timely for me. I spent several hours earlier this week tracking down a problem with some Ruby Subversion hooks. There were two bugs that contributed to my woes.

This particular comment by Emmanuel Pirsch on Cedric’s blog caught my attention:

There is a “continuous tax” for any system that is being maintained. The fact that the system is build with a statically or dynamically typed language has nothing to do with that.

It all comes down to how well the system is designed and documented. While statically typed language offer a bit more “default” documentation, they do not offer any more insight about the behaviour of an API than a dynamically linked language.

I call bullshit, although the scare quotes are a great tactic that I use often. The “default” documentation offered by explicit type declarations and return statements seems like a Very Good Thing to me, at least they did a few days ago when I was cursing at some Ruby code I could not understand.

The World is Not TRUE/FALSE

Positions like this always seem suspect, because the world I live in is not this clear cut. Consider the finality of his statements:

  • …has nothing to do with that…
  • …It all comes down to…
  • …do not offer any more insight…

When trying to maintain and fix problems in someone else’s code, static typing and a more explicit syntax are often helpful. Allow me to describe the two bugs I tracked down.

First, one of the Ruby methods had a comment indicating it returned an array of strings. This threw me off because in reality the method did not return an array at all. It returned a single string. The comment was wrong, which of course is possible in ANY language:

/**
 * @return an array of error messages if something goes wrong.
 */
public String doSomething() { ... }

Yet as you can see, static typing and explicit compiler-checked syntax are helpful in this case. I can look at the method and immediately know it returns String rather than an array, despite the bogus comment.

I made up the Java code above. I am not making up the Ruby bug I had to diagnose. The bad comment really threw me for a loop. So there you have it. One example where explicit compiler-enforced syntax offers more insight into the code, even when the comment is wrong.

Does Not Offer “Any” More Insight?

The second bug took me far longer to understand and was more insidious. In Ruby you don’t even have to say “return” at the end of a method. Instead, the result of whatever expression happened last is automatically returned. Invisible magic is the quintessential example of a feature that saves the original coder a few extra keystrokes but makes every downstream programmer pay the continuous tax for years to come.

I made the problem worse by adding a simple “if” statement to the end of the method, thinking I could explicitly change a bogus error message to nil. But now the method didn’t even return a string any more…I inadvertently changed the return type from a string to a boolean.

The final fix? I added an explicit return statement to the end of the method. I’m sure I’ll eventually write more Ruby code, and when I do, I’ll probably adopt a convention of using explicit return statements whenever possible. But since this is not enforced by the language, I’m sure I will eventually have to maintain something that relies on this magic.

Duck!

Bring on the flames. Seriously, I’m not making any profound statement about Java versus Ruby here. It just seems silly to take such hardened TRUE/FALSE positions on every issue.

Static typing and explicit return statements have SOMETHING to do with my ability to gain insight into code.

SwingWorker is Fixed, You Should Upgrade your JDK

After I posted about surprising SwingWorker behavior a few days ago, Igor Kushnirskiy let me know about bug 6493680, fixed in Java 1.6.0_01.

I ran my test program numerous times this morning and confirmed the issue is indeed fixed.

If you are still running Java 1.6.0, definitely upgrade to the latest 1.6.0_0x release.

Surprising SwingWorker Behavior

SwingWorker makes it easy to execute background tasks and report progress to the Event Dispatch Thread (EDT). Once on the EDT, your code can safely update GUI components like progress bars. This figure shows the general idea:

SwingWorker Threads

The general steps in my example are:

  • Extend the SwingWorker class.
  • Override doInBackground() to perform your background task.
  • While working, periodically call publish(...).
  • The SwingWorker will, in turn, periodically call process(...) on the EDT.
  • You can override process(...) to update the GUI as work proceeds.
  • You override done() to know when work completes. (or so you may think)

It turns out done() does not really work like that. Let’s look at some Java 6 code.

Sample Code

I’ll just present the entire application. This loops through fifty iterations in a background thread, pausing for random intervals between each iteration. It publishes the results and prints them to the console in the process(...) method. The done() method prints a message as well. Here it is:

public class Demo extends JFrame {
  private Random rand = new Random();

  private AbstractAction startAction = new AbstractAction("Start") {
    public void actionPerformed(ActionEvent e) {
      startClicked();
    }
  };

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        new Demo().setVisible(true);
      }
    });
  }

  public Demo() {
    super("SwingWorker Demo");
    add(new JButton(startAction), BorderLayout.CENTER);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    pack();
    setLocationByPlatform(true);
  }

  private void startClicked() {
    startAction.setEnabled(false);
    new DemoWorker().execute();
  }

  private class DemoWorker extends SwingWorker<String, String> {
    protected String doInBackground() throws Exception {
      for (int i = 0; i < 50; i++) {
        publish(Integer.toString(i));
        TimeUnit.MILLISECONDS.sleep(rand.nextInt(25));
      }
      return null;
    }

    @Override
    protected void process(List<String> chunks) {
      System.out.println("process: " + chunks);
    }

    @Override
    protected void done() {
      System.out.println("done.");
      startAction.setEnabled(true);
    }
  }
}

Expected Output

Each time you run the program, you see slightly different results. That’s because publish(...) coalesces events and only calls process(...) “occasionally”. This is a really nice feature because it helps avoid bogging down the EDT. Here is the output:

process: [0, 1, 2, 3]
process: [4, 5]
process: [6, 7, 8]
process: [9, 10, 11, 12]
process: [13, 14, 15, 16]
process: [17, 18, 19]
process: [20, 21]
process: [22, 23, 24, 25]
process: [26, 27, 28, 29]
process: [30, 31, 32]
process: [33, 34, 35, 36]
process: [37, 38, 39, 40, 41]
process: [42, 43, 44]
process: [45, 46]
process: [47, 48, 49]
done.

See? Just what we expected. Let’s run it again:

process: [0, 1, 2, 3]
process: [4, 5]
process: [6, 7, 8, 9]
process: [10, 11, 12, 13]
process: [14, 15]
process: [16, 17, 18, 19]
process: [20, 21, 22, 23]
process: [24, 25]
process: [26, 27, 28]
process: [29, 30, 31, 32, 33]
process: [34, 35, 36]
process: [37, 38, 39]
process: [40, 41, 42]
process: [43, 44, 45]
process: [46, 47]
done.
process: [48, 49]

Surprising Results

What just happened? It turns out process(...) is sometimes called after done()! You don’t really have any control over this and cannot predict when it will happen.

This is not a bug. The JavaDocs for SwingWorker only say this for the done() method:

Executed on the Event Dispatch Thread after the doInBackground() method is finished…

All we really know is that done() is called “sometime” after doInBackground() completes.

Lesson Learned

You cannot rely on the order of process(...) and done(). A co-worker discovered this last week and brought this to my attention. If your process(...) method simply prints some message to the screen or updates a progress bar, this phenomenon is probably harmless. But in his application, his done() method actually changed the state on some data, but then (to his surprise) process(...) was called later, which caused a problem.

If you really need to know when your SwingWorker is done, and if you override both done() and process(...), you must come up with your own protocol to definitively know when your worker really is “done”.

For instance, your doInBackground() method might set a volatile boolean flag to true upon completion. Or perhaps the message you send to publish() can include a completion status indicator.

Comic Tribute to Java Versus Ruby

This has been a great week for Java/Ruby geek blogging.

Gavin and Obie

It all started here, which eventually led to this. I love it.

Has reCAPTCHA Been Defeated?

Without reCAPTCHA, it is not uncommon to receive hundreds of spam comments per day. Akismet can help, but it still requires blog authors to spend a lot of time wading through suspected spam. Even worse, I’d see almost weekly “false positives” from Akismet. They do an admirable job, but spam remains a big burden on site maintainers.

With reCAPTCHA, my spam count immediately dropped to zero. So I deactivated Akismet. For awhile, the problem was solved.

SPAM

Last week, however, I received a spam comment. Today, one more. Both originated from Amsterdam. The first comment made absolutely no sense. It said something along the lines of “nice post”, but the web site it linked to was invalid. I don’t understand spam like this. If the spam has no usable links, how does it help the spammer sell a product? Today’s spam at least gets credit for including a link to a real web site.

For now, it is a minor nuisance. Since I moderate all comments, the spams still aren’t making it past me. There’s no way to know if a machine defeated reCAPTCHA or if a human typed in the text. Or perhaps they are exploiting a bug in WordPress or reCAPTCHA. I suppose if the problem gets worse, I’ll have to re-activate Akismet as a second line of defense after reCAPTCHA.

Spammers, you all suck. But blogs that disallow comments also suck. So I will continue to fight this battle.

Almost Bullet-Proof CSS Calendar

Check out the calendar detail to the left of the post title. I created this with a combination of some simple div tags, two background images, and some CSS. It looks really good in Firefox, and “ok” in IE. If you change the text zoom size in IE, the borders get a bit flaky. I’m sure with a bit more hacking we can make it look better in more browsers.

This diagram shows how the div tags fit together:

Datebox Exploded

Here is the CSS for the outer box:

.datebox {
  width: 50px;  /* same width as the background image */
  float: left;
  margin-right: 1ex;
  margin-bottom: 1em;
}

The width matches the width of the background image, which is anchored to the top of the .month box. (shown next). The float tells the entire datebox where to go on the page, and the margins ensure text does not smash up against the box. The values 1ex and 1em are just pulled out of thin air. Other values work fine.

The month box contains the background image anchored to the top edge. It is important to know the exact color of this image so you can make the background color of the box match. Furthermore, the image must not be transparent, otherwise the background color of the box bleeds through the top edge of the image.

.datebox .month {
  font-family: Cambria,"Times New Roman",Times,serif;
  font-size: 0.9em;
  padding-top: 0.3em;
  padding-bottom: 0.1em;
  text-align: center;
  background: #660033 url('images/calendar-top.png') left top no-repeat;
  color: #dddddd;
}

The top padding gives just a bit of space to allow the background graphic to show. The bottom padding is arbitrary, I just tweaked it until I liked the way it looks.

Finally we have the CSS for the day box:

.datebox .day {
  font-family: Cambria,"Times New Roman",Times,serif;
  font-size: 1.4em;
  text-align: center;
  padding-bottom: 0.1em;
  color: #333333;
  border-right: 1px solid #660033;
  border-bottom: 1px solid #660033;
  border-left: 1px solid #660033;
  background: #faf8d2 url('images/page-fold-small.png') right bottom no-repeat;
}

The folded paper image is anchored to the bottom right. This box also provides a 1-pixel border that matches the background color of the other elements.

That’s it. If you are a better artist than me, you can probably improve on the look of this calendar. But after trying to zoom the text on several other people’s blogs, I think my CSS version scales pretty nicely.

WordPress Code

Here is the actual WordPress PHP code. I added this to index.php and single.php:

<div class="datebox">
  <div class="month"><?php the_time('M') ?></div>
  <div class="day"><?php the_time('d') ?></div>
</div>

I do think some stone-tablet graphics would go better with my theme.