August 31, 2005

NDoc In The Hayouse

Man, NDoc rules.

We're beginning the design stage of a huge project, and one question we kept encountering was: how will we be able to design the methods in our classes? Our design documents contain a lot of UML class diagrams, which are really useful when it comes to creating your objects, but they don't describe how a method and its algorithms actually work. We could just write some notes on the methods in the design documents, but then how do you know if the developer (or you, for that matter) will make use of your method notes when he's implementing the design? That's pretty far removed from the actual code.

Well, one smart feller on the team (pretend his website says something) proposed that we could generate a few skeleton classes and their methods, and then document the methods inside the code file using the XML documentation features inside of Visual Studio .NET. Woo boy, it was a pickle to set up, but once I got that going, I had immediate results. Not only did it format all of my XML comments in my methods into something really readable (the resulting documentation looks just like the MSDN site), but the XML comments are still there in the methods for when it's time to code them. Game, set, match, Mr. Powell.

It's a great idea, and one that more folks should consider. Just because you put your comments into the code doesn't mean you're neither designing nor documenting. Wiht NDoc, you do both AND you ensure your notes are in a place where they must be read during implementation.

I would list some links to a similar tool for Java, but really, those people terrify me.

Posted by Cody at 06:51 PM | Comments (0)

August 25, 2005

Collections Get Funkay

Sometimes, the interactions between similar collections in C# and VB.NET can get weird. Not cats-and-dogs-living-with-each-other weird, but less than intuitive. For example, let's say you have a multi-select listbox on a form (we'll say it lists a bunch of cereals), and you need to convert its SelectedItems collection into an ArrayList for some part of your business logic. That should be pretty straight-forward, yes?


ArrayList cerealSelections = new ArrayList();
cerealSelections = (ArrayList) lbxCereal.SelectedItems;

That's a negatory, good buddy. The compiler will complain, telling you that's an invalid cast, even though they're both collections and both implement the ICollection interface.

Instead, you have to get tricky and do something like this:


ArrayList cerealSelections = new ArrayList();
cerealSelections.InsertRange(0, lbxCereal.SelectedItems);

What's the significance of this? Uhh, I have no idea. But it's something that confused me for a second earlier today and Google has very few results for it, thus I dump it all on you.

Posted by Cody at 08:04 PM | Comments (0)

August 23, 2005

Thread It Up

Recently at work, we got into a spirited discussion via email about the performance enhancements that can be obtained through multi-threading in the .NET Framework. If you read that sentence and think to yourself, "Those dudes know how to rock," you've definitely got a point.

There were a lot of opinions exchanged, but one that kept coming up was that threading actually slows down an application because it makes inefficient use of the processor. I'm no threading master; while I can write a good multi-threaded app, I'd rather tickle a rhino's behind than try to compute the Big O notation for multi-threaded, computationally intensive code. However, as a lazy programmer, I knew I could write up a proof-of-concept to evaluate the idea. That's just what I did.

Ladies and gents, I offer you ThreadTest (contains EXE and source code). Not only is it a pretty good introduction to threading in C#, it outputs performance information for a computationally-intensive task (determining the factors for a huge number) that's done once in a single thread and once in a multi-thread environment.

The EXE is meant to be run from the command line. You must supply it with two parameters: the number to be factored and the number of threads to spin off. When you run it (by typing something like TestThread 1000000000 5), it'll factor the number once in a single thread, and then it'll break the number into chunks, spin off the desired number of threads, and let each thread factor a chunk. Once completed, it tells you how long each method took, as well as which was faster.

It's pretty fun to play around with, plus it helps to provide some hard data on multi-threading. The results I obtained showed that a threaded, computationally-intensive task can perform in a fraction of the time that the same non-threaded, computationally-intensive can perform in. For a simple task, any gains to be had from threading are negated due to the complexity of spinning off the threads. Altering the number of threads didn't seem to have as large a performance effect as one might think.

Here are a few sample results I obtained on my single-processor laptop. This is all extremely unscientific, and only tried on one machine.
Results at bottom of page.

Posted by Cody at 06:47 PM | Comments (0)

August 22, 2005

Picnic Talk

Praise the Lord and pass the biscuits, I have like two more days of requirements left. I don't know if I've mentioned this or not, but I've been doing requirements nearly exclusively for six months now. It got old very quickly. The temptation to quit was strong. However, two things stopped me from doing so. First, I don't get paid for being pretty, no matter what you people think; I have to actually do what I'm told. Second, I thought of the entire development process as a big picnic. Here comes an analogy!

I like what I do; I think most developers agree. If I were forced into another line of work, I'd continue to code and design in my spare time because I like it. In a way, coding is like a leisure activity for me. For me, an afternoon of that is like an afternoon at a picnic, minus the crappy potato salad.

If it's a one-man picnic, it's pretty easy to arrange. I just make myself a sandwich, put it my picnic basket, and run. However, larger picnics are a little more difficult. You have to find out who's going to be there, what these people want to eat, and how much everyone will eat. You need to find out if the weather will cooperate, and what you'll do if it doesn't. The more people invited to the picnic, the more planning that must be done.

If development is a picnic, then requirements is the picnic planning. For most of us, requirements suck; I won't even accept debate on that issue. However, just like the plans for the picnic, they're needed. The better the plans, the better the picnic.

Imagine organizing a picnic for 20 people. You send out a huge email to all of them naming the date and time. Then, the date arrives and you show up, twenty minutes late with bare hands. "So," you say, "what'd you guys bring to eat?" Your friends promptly rise up and beat you into the dirt with any tree branches within grabbing distance.

Now imagine taking the other path. Imagine that instead of blowing the whole thing off, you invest hours and hours with all of the onerous activities I listed above. You do all of the planning, packing, and worrying. It takes forever and you hate it. Then, the date for the picnic comes. Not only does everyone NOT want to pummel you, they praise you. More importantly, you have fun. You put a lot of thought into your plans and it all comes out nearly flawlessly.

I realized this a few months ago, and it's this idea that's kept me going through revision after revision of my documents. I want this development picnic to be fun, not just for my coworkers but for myself. The only way for me to do that is to step up to the plate when it comes to the requirements. Of course, it hasn't been fun; if it were, people would want to do that instead of the actual picnic. These painful steps have been necessary, though,f or me and for everyone else on the team. And I know that now, having gone through all of this, I will be in a state of bliss for the entire coding and design process. That is, if I'm allowed to participate. If I'm not, I'm going to find a tree branch and get to whackin'.

Posted by Cody at 06:56 PM | Comments (0)

August 11, 2005

A Requirements Hypothesis, Part II

Last time, I mentioned that I'd been doing a veritable wheelbarrow-load of requirements over the past few months and that I'd come up with a theory on requirements. My starting point was that a requirement is like a hypothesis. I'd like to elaborate on that a bit this evening. Then, if there's time, punch and coookies will be served.

In science, the critical component of a hypothesis is falsifiability. The idea is, a hypothesis isn't valid if you can't disprove it. This applies to all hypotheses, from the big bang to quantum mechanics. (Sidenote: it's the lack of falsifiability in Intelligent Design that makes so many people mad about the theory being taught in science classes.)

Keeping with this idea, if a requirement is a hypothesis, we have to be able to disprove it. For me, this means I must write my requirements as directly and objectively as possible. Instead of writing, "Clicking this button brings up a listbox-sorta thing that's quite visually pleasing," I shoot for "Clicking this button brings up a listbox that supports multi-selection." If a requirement is a hypothesis, you've got to be able to look at the code in action and say, with certainty, that the code supports or refutes the requirement. Fortunately, there are methods in place that make this validation a snap.

How do you falsify a hypothesis? Well, if you're a scientist, you do it with an experiment and empirical data. To me, this is exactly what a unit test provides. Once your requirement has been defined and coded against, you should be able to test for it. Based soley on the requirements, I'd write a unit test that encompasses all conditions for the requirement. If the test passes, we've validated the requirements. If the test fails, it's time to examine what just went wrong.

It's subtle, but I found that if I write requirements with the idea of basing unit tests on them later, I write with more clarity. Knowing what I have to do later, the requirement details the exact conditions for validation. Essentially, it's my unit test in verbose form, and falsifiability is the main concern.

Yes, I realize I'm getting pretty abstract here. That's what defining requirements does to a fella. You should be lucky I'm not wearing a garbage bag for pants and screaming about the New World Order. Unfortunately for all of you, I'm not done with my requirements pontifications yet. Perhaps even more unfortunately, I'm keeping the punch and cookies for myself.

Posted by Cody at 08:29 PM | Comments (0)

August 09, 2005

A Requirements Hypothesis

I haven't posted anything here in a long while because I've been doing nothing but Requirements at work. It's been that way for quite a while. It's gotten so bad right now, if I saw a guy on the street approaching me with a gun, I'd ask him, "You're not going to make me do use cases, are you?" It's hard to be excited about anything, let alone this site, when my brain has smushed into a big, slimy requirements spec.

Anyway, during my hard months on the requirements chain gang, I've come up with something I called my Grand Unified Theory of Requirements. To write it all out would take way too long right now (although I plan to do it later), so I am just going to share the first idea right now. With all due fanfare, here is element 1 of the Grand Unified Theory of Requirements: a requirement is a hypothesis.

When I do requirements, I think of myself as a scientist, trying to formulate an explanation for a phenomenon. The phenomenon was the feature; my explanation was the requirement. What happens to hypotheses? They get tested by someone else. That's what happens with requirements. They get tested first by developers (Is it feasible?), then by testing (Is it well implemented?), and lastly, by the user (Is it what I want?).

Since the requirement will be tested so much, it needs to be clear, and more importantly, it needs to be concise enough that it can easily be tested. A requirement is a hypothesis; yeah, I do agree with that. Where the Bunsen burner comes in, I'm not sure.

Posted by Cody at 07:19 PM | Comments (0)

August 08, 2005

Speak, I Command You! (Pt. 2)

More fake content here! A few days ago, I posted a simple text-to-speech application I wrote in C#. Well, I've cleaned up the code and I'm putting it out there for general consumption. It's essentially just a wrapper for the SpeechLib object, although the Choose Voices part is pretty cool.

Anyway, open it up and let 'er rip. The code hasn't been tested or anything, so if it accidentally pokes your eye out, don't come looking in my direction. The code is released under the GNU Public License.

Posted by Cody at 06:53 PM | Comments (0)

August 03, 2005

Speak, I Command You!

Alas, real world has interrupted the vlog momentarily. Until I can get back to the important stuff, here's a little text-to-speech engine I wrote in C#. Nothing is funnier than making your computer talk about corny dogs.

(You need the .NET run-time to run it.)

Posted by Cody at 06:30 PM | Comments (0)