code, tdd comments suggest edit

Although I agree in spirit with most of Joel’s discussion of methodologies and rock star programmers, I’m in a bit of disagreement over the quote from Tamir he posts.

For instance, in software development, we like to have people unit-test their code. However, a good, experienced developer is about 100 times less likely to write bugs that will be uncovered during unit tests than a beginner. It is therefore practically useless for the former to write these…

I disagree with this, but in part because I think this is based on a flawed assumption over the purpose of unit testing. This point assumes that the only objective for unit tests is to uncover bugs. In reality, unit tests serve a much larger purpose.

1. Unit Tests promote better interfaces.\ Certainly, if you are truly a rock-star developer, writing a class that is extremely usable might come intuitively to you. But I think even rock stars can benefit from writing client code that uses a class the developer is building. This process helps to make sure that the interfaces to the class are thought out, and probably doesn’t take much more time than thinking through the class design before coding.

2. Unit Tests are a great form of documentation.\ When learning a new API, often the first (or second) thing I want to see is sample code that uses the API. Well written unit tests are a great source of documentation for how a particular class is meant to be used.

3. Unit Tests are great as regression tests\ So you’re a rock star who doesn’t write buggy code. Are you sure the person who is going to maintain your code is also a rock star? What about the person who wrote the class your code is dependent on? As Code Complete states, 80% of a project’s timeline is spent after the code is deployed in the maintenance phase. At some point, someone will come in and modify the code and perhaps change it in a subtle way that doesn’t appear to be a bug, but violates an assumption made by the initial programmer. There are a thousand ways in which a developer can write perfect code, but have it break either now or later. Well written unit tests can provide a high degree of confidence that bugs that are introduced later are discovered quickly. It’s no panacea, but it’s sure as heck a lot better than having none.

So while I agree that blindly following methodologies is a hindrance to truly talented developers, I do believe that there are some practices that are worthwhile across the board. In a team environment, communication is of the utmost importance. Most developers don’t work in a vacuum and a writing unit tests is one of those practices that really help communication within a project and beyond. It helps communications with current team members as well as future team members to come.

So yes, being a monkey in a methodology is bad, but I think there are better illustrations of this than Unit Testing.

UPDATE: I’m not the only one who believes this. Seems Roy has a similar opinion to mine. As does Jason Kemp in my comments.

Technorati Tags: TDD

personal comments suggest edit

Soccer Ball Americans often have a low view of soccer players (though that is changing in recent years). They don’t think of the sport as physical as football or even basketball. However from my experience, soccer players are every bit as tough as their counterparts in other sports.

Case in point, for the past two weekends in L.A. it’s been rainy and cold (don’t laugh, cold for L.A.). Both weekends we had games scheduled on the most perfect pitch and a full squad showed up. However, there have been several times that we couldn’t get a full squad for my morning basketball game at the Y because it was raining, and we’re playing indoors!

Rain Back to the subject at hand, there’s nothing like playing a solid game of soccer (or Football for my European readers or futbol for my spanish speaking readers) with rain pouring down. The artifical turf (the kind with the rubber pellets) actually grips the ball pretty well compared to grass which sends the ball skidding like a runaway luge team. The only difficulty is that the ball itself gets a bit slick, creating many opportunities for “whiffing”.

On rainy days, it’s helpful to have hair. For instance, I sent a perfect cross to the center and my teammate planted his forehead firmly on the ball, only to have the ball slide off and away. He’s completely bald.

Unfortunately we lost due to an own goal on a corner kick which made the score 2 - 1. I hyper-extended my arm at the elbow, so I’m in a bit of pain today, but I think it’ll heal up nicely.

comments suggest edit

Recently I received some kind words from Scott Reynolds regarding my “excellent tutorial” on writing IBlogExtensions for RSS Bandit. Using my tutorial, he wrote a plug-in to send items in RSS Bandit to One Note. (There’s another plug-in that does the same thing here).

The same day I noticed this post on Channel9 in which a user wishes that using the “Blog This” plug-in that comes with RSS Bandit wouldn’t paste the entire text of the entry into w.bloggar. Instead, this user would prefer just the link to the entry.

Well, inspired by the kind words, I figured I could do this in a few minutes. So I built a new version of the IBlogExtension plugin that comes with RSS Bandit. This plug-in is configurable to allow posting the full text, the link only, or some generic text with the link. The generic text is something along the lines of

{Author} wrote this interesting post entitled “{entry title}” on {title of blog}.

The {entry title} is a link to the actual post while the {title of blog} is a link to the main blog. If some of this information is not available in the feed, the text is even more generic.

You can grab the plug-in dll here. Just copy it to the plugins directory within the RSS Bandit installation directory. For me, that’s in “c:\Program Files\RssBandit\plugins”. You might want to back up the old plug-in before overwriting it with this new one.

The Visual Studio.NET 2003 C# project file is also available here.

The plug-in makes use of embedded XSLT files for each type of post. In the future, it would be quite easy to allow user defined XSLT files that are not embedded. Please let me know if you find this useful. I’ll see if Dare and Torsten would like to include this in future releases of RSS Bandit. If you make improvements, please send them to me so I may update my files.

[Listening to: Feel So Good - Jamiroquai - A Funk Odyssey (5:21)]

comments suggest edit

Ouch that smarts!

During my flight today a bag of ice fell off the cart the flight attendant’s were pushing up the aisle. Thinking it was a simple bag of ice, I picked up the ice and put it back in the bag. As I was holding the ice, I realized that it was much colder than normal ice. Much much colder. So cold in fact, it burned a bit.

Not to worry though, those long cold winters in Alaska prepared me for such cold. I’m impervious to it. Except in L.A. for some reason, when it’s cold there, I’m succeptible.

comments suggest edit

I arrived in Toronto today and am staying at a very nice hotel. It’s called the SoHo Metropolitan and it sure beats the Super 8 I stayed in at Tech Ed 2004 (next door to Adam Kinney and Eric Porter). It’s too bad I’m only here one night as I was hoping to have time to check out the well equipped gym.

The reason I’m here is to get acquainted with the tech staff of our new parent company. I’ll be coordinating a lot of development with these guys. They primarily work with Java and we primarily work with .NET. However, XML is the glue that will help us all get along and sing Cumbaya around the campfire with group hugs and all that.

They’re in the process of exposing their platform as SOAP and I’ll be reviewing the architecture with my equivalent here. I’m looking forward to this as it will be an opportunity to really get some real world cross-platform experience.

In the meanwhile, my wife tells me the house is very quiet without me. I suppose because I am quite noisy. In any case, while she was walking Twiggy some guy in a car attempted to hit on her. Their conversation went something like this.

He asks, “Are you Thai?” “What?” she replies. “What ethnicity are you?” “WHY!?” she yells.

She’s quite the spunky one.

code comments suggest edit

This is a fabulous post (did I just say “fabulous”?) on how to create self contained NUnit tests when you need a web server.

As you may know (assuming you’ve read this blog for a while, which is a BIG assumption), I’m a big fan of self contained Unit Tests. It’s a key component to having a self contained location independent build process.

I have an approach similar to Scott’s in unit testing some of the functionality of RSS Bandit. For example, I have tests that will create a web directory, start a Cassini web server, and then use the RssLocator class to search for RSS feeds. However, one problem I had that I hadn’t resolved was the issue that Cassini.dll needed to be loaded in the GAC.

If you were to obtain a fresh build of the RSS Bandit unit tests and didn’t have Cassini.dll registered, many of the tests would fail. I was planning to add code to register Cassini into the GAC, but Scott has shown the path to a better way. He demonstrates a method such that doesn’t require Cassini to be placed in the GAC. Brilliant! Once I get home, I shall make this change and truly rejoice at having self contained tests.

comments suggest edit

My neighbor Chris is in Iraq as the #2 guy overseeing rebuilding projects as part of the Army Corp of Engineer. He’ll be over there for several months helping to rebuild the facilities necessary for providing clean drinking water and electricity.

Chris and his wife Susan are among the nicest people you will ever meet. Their dog Nelson was kind enough to show Twiggy the ropes as it comes to the best spots in the neighborhood for taking care of business. Susan is always offering to take Twiggy for a walk when we’re away at work.

In any case, with all the bad news coming from Iraq, it’s good to read about progress made in the rebuilding efforts. Here’s a snippet about his wild ride into Baghdad. Be glad your typical business trip doesn’t come with this sort of landing.

I’m safe in Baghdad….errr, well….I guess I’m just “in Baghdad.” The flight into Baghdad International Airport is one I will always remember, no matter how hard I drink to forget it. There’s 40 of us packed into a C-130, which was never intended as a passenger plane. There’s no “passenger area” in these planes, just the cargo hold with jump seats running down the sides and a row down the middle. Only two small port-style windows on either side. We’ve got a military dog on the plane with us, not real happy in his crate and letting the whole world know about it. It’s so noisy you have to wear earplugs and shout at each other to be heard. About 10 minutes outside of Bagdad, we begin our descent from 30,000 feet. That’s right, 30,000 feet in 10 minutes. Not to mention that the pilots fly a corkscrew pattern to avoid potential rockets (they haven’t had one yet, but nobody wants to be the first). Let’s just say, the dog wasn’t the only one howling on the way down. \ \ After a hard landing, they popped the hatches and we put our feet on Iraqi soil.

I’ve flown in a C-130 myself and can vouch for how uncomfortable a ride it is. However, I’ve never experienced a landing quite like his.

[Via Live from Baghdad]

His ATOM feed is here.

comments suggest edit

A while ago I wrote about AmphetaRate, a blog recommendation engine that takes user ratings of blog entries and serves an RSS feed of recommended blog entries.

Later on I wrote an article about how to build an IBlogExtension plugin which was added the the RSS Bandit documentation site.

As a warmup to writing that article I wrote an AmphetaRate plugin to work through the kinks of writing a plugin for RSS Bandit. However I never released that plug-in as I wasn’t ever sure if it was working since all my recommendations were “training” recommendations.

This is a classic chicken and egg problem. If there aren’t enough users using AmphetaRate, the quality of recommendations are poor.

In any case, I noticed today that Dare updated the RSS Bandit roadmap and the version (code named Nightcrawler) after the next version may include a “Thumbs Up/Thumbs Down” rating system, perhaps intergrated with AmphetaRate. This would certainly help solve the “Chicken Egg” problem.

In the meantime, I am releasing my plug-in with no warranties. Just copy the AmphetaRatePlugin.dll to the “plugins” subfolder of the RSS Bandit installation (on my computer that’s at “C:\Program Files\RssBandit\plugins”). The VS.NET 2003 solution can be downloaded here.

Note that although this plug-in implements the IBlogExtension interface, the configuration form implements a feature specific to RSS Bandit. When you configure this plug-in, I wanted to provide an easy manner to subscribe to a user’s recommendation feed. So I added a LinkLabel that when clicked does just that.

However, I had to cheat a bit to do that. Since the IBlogExtension interface doesn’t define methods you may want to call on the calling application, I used Reflection to call a method to bring up a pre-populated “New Feeds” dialog. You can see the source for that call below.

private void lnkSubscribeURL_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e)

{

    if(IsValidID(this.txtID.Text))

    {

        object banditApp = this.Owner.GetType().InvokeMember(“GuiOwner”, BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty, null, this.Owner, null);

        if(banditApp != null)

        {

            bool result = (bool)banditApp.GetType().InvokeMember(“CmdNewFeed”, BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, banditApp, new object[] {null, this.lnkSubscribeURL.Text, “Personalized AmphetaRate Feed”});

        }

    }

}

At some point, it’s possible this will become a fully supported feature of RSS Bandit. For now you’re stuck with this hack. If anyone’s interested, I’d love to discuss creating a new plug-in standard that’s a little more full featured than IBlogExtension. It works great for simple plug-ins, but doesn’t provide much support for a plug-in to interact with the application. I can think of several operations every aggregator pretty much supports that a plug-in might make use of such as “Subscribe To Feed”, “Mark Item As Read”, etc…

[Listening to: In da Club - 50 Cent - Get Rich or Die Tryin’ (3:13)]

comments suggest edit

I think it’s about time to found a group devoted to helping blogging addicts deal with a new and pervasive addiction. This occurred to me the other day when my wife needed help putting away the dishes and I mumbled something about “Only 86 more entries to go in Scoble’s link blog.”

Let’s just say that she was not amused.

So to help others out there who may suffer from the same affliction, I offer some scientific indicators that you too might be a blogging addict.

  • You’re name is Robert Scoble
  • You subscribe to Scoble’s link blog
  • You’re reading this post and it’s still Thanksgiving.
  • You’re blogging about your addiction…on Thanksgiving
  • You try to regale your friends with interesting stories, but they’ve already read it on your blog.
  • These same friends only email you with interesting links hoping to make your blog.
  • In order to get you to take out the garbage, your wife posts a comment on your blog.

Take heed of these indicators and if you identify yourself to be a blogaholic, join in my new Blogaholics Anonymous group. We’ll be meeting in the comments section of this post. Oh, and go help your wife with the dishes.

comments suggest edit

Today was my first day bringing the Tablet PC to work and I immediately put it to good use. I think that the paper pad metaphor that One Note uses may be implemented too well.

I was diagramming our existing site functionality and flow and had to erase some mistakes I made. So I took the stylus and rubbed the back of it on the screen to erase some of my scribblings.I then proceeded to take the side of my hand and brush the screen off.

Realizing what I had done, I started laughing out loud. It just occurred to me that I was instinctively going through the motion of wiping away the bits of eraser chunks that would normally be on a pad of paper after such intense erasing. The sort of chunks that aren’t created when you’re dealing with digital ink.

I better be careful before I start applying white-out to the screen.

comments suggest edit

Dave claims that inhaling puts him out of the running for President.

My mom admitted she was standing up for Arnie because she also is a naturalized citizen. I of course am not, and could serve as President without an amendment. Of course I did inhale, so I’m probably out of the running just on that count, if not for all the others.

Not So fast there professor! Our current president managed to get elected twice and he’s a confirmed “snorter”. In all likelihood our very first president smoked a bowl or two in his day. Don’t let “inhaling’ be a showstopper.

Perhaps your campaign slogan might be “An RSS feed in every Pot!”

comments suggest edit

From the Wintellect blog.

Today, I discovered that Microsoft was filing a patent for “an operator that returns true when two memory addresses are not equal”!   See http://appft1.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PG01&p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.html&r=1&f=G&l=50&s1=%2220040230959%22.PGNR.&OS=DN/20040230959&RS=DN/20040230959.   Surely, we can still come up with better ideas than this to patent, can’t we? Plus, I think there is a lot of prior art around this particular invention.

[Via Wintellog]

comments suggest edit

Colin asks the question “How do you organize your code?” and then goes on to describe the system in use at his shop.

Basically I adhere closely to the guidelines in the Patterns & Practices guide: Team Development with Visual Studio .NET and Visual SourceSafe. Chapter 3 of this guide focuses on structuring projects and solutions.

The guide recommends a single solution model whenever possible which I generally put in use with a slight modification. Chapter 3 talks about composing your source control tree into Systems, Solutions, and projects. So typically a large system might consist of only one solution, but could consist of multiple solutions. Ideally each solution is isolated from other solutions in that there are no project references from one solution to another.

However I’ve added a separate system called CodeLibrarySystem which contains a CodeLibrarySolution. When I create a new solution for a new system, I’ll add in the necessary projects from the CodeLibrarySolution into the current system. So this breaks the “isolation” model of a Single Solution Model, but provides the benefit of code sharing. Also, by merely getting latest on my current solution, I can get all the latest changes in the code library (which really shouldn’t be changing all that often).

At home and at work, I am constantly trying to refactor code so that it can be dropped in the CodeLibrarySolution as opposed to having a bunch of non-reusable code sitting in various solutions. This has worked out pretty well for me as I’m starting to have a significant code library at home. Any time I find an interesting example online, I add it to the code library (with appropriate licensing information if any).

comments suggest edit

C64It was really just a side question of this post on Rory’s blog having nothing to do with the main topic (some blather about Jury duty bla bla bla). For 50 bonus points, the question was what game featured the quote “You have summoned an elemental”?

My winning answer was Archon, thus securing the 50 pts redeemable for fame, fortune, and street cred. Interestingly enough, the question summoned a swarm of geeks reminiscing about the good ol’ days of gaming on the Commodore 64 in the comments section.

For good reason, Archon was a joy to play. I loved that game back in the day. It was pure fun. Technically, I didn’t play it on a Commodore 64. I had a Commodore 128, which I know is the same thing really, but it was a larger number and it had some funky CP/M mode that did nothing for me. In any case, in the comments of that post, I found that there’s a remake effort for Archon. Awesome! It’s interesting to see that there’s a thriving C64 retro gaming community with a C64 emulator to support the cause.

As can be seen by such communities, the C64 inspired huge loyalty among its fans back in the day which is still going strong. Heck even I joined in the computer worship with my C64 formatter for Rss Bandit. Of course once I upgraded to the Amiga 500, my Commodore 128 turned into a large paperweight. At that point I was a slave to Speedball, Pirates!, and the Bard’s Tale. Not to mention the Ultima and Phantasie series.

Ah, I miss the good ol’ days of gaming. They weren’t the good ol’ days because the games were much better necessarily (though many were quite good). Rather, they were the good ol’ days because I had this thing called “time” to actually play them.

comments suggest edit

So I was poking around the source code for how ASP.NET initiates session state etc… and noticed this method of the SessionId class. You gotta love the naming of this one. Steve McConnell (via Code Complete) would probably have recommended something like “IsValid” but he has no imagination nor flair.

internal static bool IsLegit(string s)
{
    bool flag1;

    if ((s == null) || (s.Length != 0x18))
    {
        return false;
    }

    try
    {
        int num1 = 0x18;
        while (--num1 >= 0)
        {
            char ch1 = s[num1];
            if (!SessionId.s_legalchars[ch1])
            {
                return false;
            }
        }
        flag1 = true;
    }
    catch (Exception)
    {
        flag1 = false;
    }
    return flag1;
}

MC Hammer would be proud!

comments suggest edit

Yesterday I posted a little quiz with an example of an HttpHandler implemented as an ASHX file.

Brad Wilson obviously knew the answer, but only gave a hint for others to elaborate on. BigJimSlade (no link given) expanded on the answer. BigJim, I have a GMail account for you if you want one.

Calling HttpResponse.Redirect(string url) actually calls an overload HttpResponse.Redirect(string url, bool endResponse) with endResponse set to true. If endResponse is set to true, HttpResponse.Redirect will make a call to HttpResponse.End().

That method in turn calls Thread.CurrentThread.Abort(). Oh the depravity! Once again, Thread.Abort rears its ugly head.

So as you see, the code sample will ALWAYS redirect to /default.aspx because the HandleRedirect method throws a ThreadAbortException every time. To fix this, I merely need to change the HandleRedirect method to call ctx.Response.Redirect("/special.aspx", false);.

The fact that this week seems to be “Thread.Abort Week” isn’t why I posted this quiz. I ran into this problem the other day in my carelessness. It’s a result of my old ASP 3.0 habits resurfacing after years of suppressing them. It took me a few minutes to realize why my code never made it to special.aspx.

comments suggest edit

This is a simplified version of a sneaky bug I ran into today (I’m fine thank you, but the bug is dead). The only prize I can offer is a GMail account if you want one.

Imagine that the method HandleRedirect actually does something interesting and if all the conditions pass, the user is redirected to special.aspx. This is the source code for an HttpHandler implemented as a .ashx file.

<%@ WebHandler Language="C#" Class="MyHandler" %>
using System;
using System.Web;
 
public class MyHandler : IHttpHandler
{
    /// <summary>
    /// Processs an incoming request.
    /// </summary>
    public void ProcessRequest(HttpContext ctx)
    {
        try
        {
            HandleRedirect(ctx);
        }
        catch(Exception)
        {
            ctx.Response.Redirect("/default.aspx");
        }
    }
 
    void HandleRedirect(HttpContext ctx)
    {
        ctx.Response.Redirect("/special.aspx");
    }
 
    public bool IsReusable
    {
        get { return true; }
    }
}