Sunday, July 31, 2005

Unit Test Duplication / Maintainability

Roy Osherove has a terrific post on patterns for keeping unit tests readable and easily maintainable. It's really about making use of sensible design patterns anyway: use factory methods, use helper methods when you've got several replicated patterns such as object configuration. As Instapundit would say, "Read the whole thing."

Thursday, July 28, 2005

How To Ask Questions Online

Gee, moments after posting my semi-rant note on Googling before pestering contacts, I run across this post from Josh Ledgard full of tips on how to best ask questions in an online forum. Learning the knack and etiquette of posting queries online really can benefit you by getting your question answered more quickly instead of ignored completely.

Use Google Before Pestering Folks Who Are More Smarter Than You

I do a lot of Googling because there are a great many things I don't know on a great many topics. It doesn't bother me to admit that because my stock answer is "I don't know the answer, but I can find it." I'm fortunate to have a couple contacts I can go to for hard problems, but I always, always (OK, almost always) spend some time researching the issue before I pester them. Those folks are much smarter than me and I don't want to burn up their time with continual pestering comments. (Besides, they're working at paying jobs and I can't expect them to take IM coffee breaks all the time when I'm looking for adult conversation instead of the chatter I get with my five and one year old kids...) Do you know anyone who isn't so considerate and needs a gentle reminder that they should do some legwork first? Take a look at this site. Read the info page and you can quickly figure out how to put together a Google query string to help lazy folks along.

Tuesday, July 26, 2005

Customized Coverage Stats with nCover

I've been fooling around with nCover in preparation for a Grok Talk at tomorrow's Dayton .NET Developers Group. nCover's a great unit test coverage tool which points out areas of your code base you have or don't have covered with unit tests. It's especially useful with the enhanced stylesheet by Yves Lorphelin and Jeff Key's nCoverBrowser, especially the latter. I generally write my unit tests in patterns: tests of borders (over and under any limits I've set), invalid data, valid data, and constructors. I was wondering if it was possible to have nCover give me stats for each of those groups. The answer's "Yes!" if you make use of nUnit's "Category" attributes. Here's a portion of a border test method:   [Test]   [Category("Border")]   public void CheckTextMaxSize()   {        PersonEntity pEnt = new PersonEntity();        try        {            pEnt.FName = BADVAL_LONGSTRING;        }        catch (ArgumentOutOfRangeException ae)        {            Assert.AreEqual(BADVAL_LONGSTRING, ae.ActualValue);        }     ... //remainder elided Note it's decorated with both [Test] and [Category("Border")] attributes. (Side note: I have waited so long to use the phrase "decorated with attributes." I think it makes me sound way smarter.) You can now use the /include switch of nUnit to run tests decorated only with specific [Category] attributes. Note that nUnit expects input files first with any option switches after. Now invoke nCover with the following command line, and please make careful note of the quotes around the /c arguments. ncover.console /w . /o Coverage-Border.xml /c "nunit-console" "TestDemo.UnitTests.dll /include=Border" The output file Coverage-Border.xml will hold coverage stats for all tests marked with the [Cagegory("Border")] attribute. (Sorry, just couldn't use "decorated" again.) OK, so this is slick and a neat trick, but I'm not really sure if it's useful in the real world or not. This sort of reminds me of Bing Crosby and Fred Astaire in Holliday Inn talking about the peach preserves Bing has brought from his farm. Neither know quite what to do with them: "Why they're great on..." "Yeah, or even on..." Puzzled silence follows. Let me know if you think this is something useful, especially if you're putting anything similar to use already.

Friday, July 22, 2005

Dark Horse Comics: Serenity

If you're a science fiction fan and you haven't seen the Firefly series, grab them up. (I blogged a very tiny bit about Firefly previously.) Buy 'em from Amazon, check them out from your library. Firefly's even available from Netflix if you're a member. (I'm not.) In advance of the upcoming movie Serenity, Dark Horse comics is releasing a set of three comic books supposedly meant to bridge the gap between events in the Firefly series and the movie. Dark Horse did something seriously cool and had nine different artists do a cover. Each issue will have three different releases. You can check out all the artwork here. My personal favorite is Joe Quesada's cover of Zoe. Man, what a great use of shadows and light! I especially like the way Zoe's left eye is a splashy point of light in the middle of a dark zone. Just a killer cover! The worst one is a tie between this awful rendition of Inara and this shallow one of Simon. Jones completely missed the grace that Morena Baccarin brought to Inara, and her hands look like they're something grafted on from a strangler. Yu's cover of Simon is just stupid. Why a gun? Simon was always a great doctor who was completely lost when he had a firearm in hand, a grand total of two times in the entire series if I'm the Firefly geek I think I am. Furthermore, he was always deeply conflicted about violence. Couldn't Yu have thought of something more complex? Maybe I'm too hard on Yu -- it could be that somewhere along the line in the comics Simon morphs from the great doctor into a brutally efficient, cold-hearted killer. Boy, would that suck. OK, so I'm overly geeked out about this whole Serenity thing, but I'm looking forward to this much, much more than Revenge of the Sith. UPDATE: If your system's got the horsepower, check out the high-definition 138MB trailer. Killer stuff, although it's amazing that the Universal folks have the brass ones to include digital licensing in the file. What, like anyone's going to sell a damned trailer?

Losing the Government's Digital History

Technology Review has a fascinating article on the huge tidal wave of records the goverment generates -- and loses due to a lack of standardized processes and formats. The article's thrust is from the National Archives and Records Administration's point of view, but it covers quite a bit of ground, even discussing how MIT (MIT!) is "losing its hold on research data--including the early studies and communications that led to the creation of the Internet itself." The government is generating petabytes of information in a vast number of formats. Go figure how you're going to store all that, keep it accessible, and keep up with it as the archives continue to grow. I sure can't.

Thursday, July 21, 2005

WinMerge & CVS Integration

Scott Hanselman's list of great tools points out WinMerge as a killer diff/patch tool. It is indeed, especially if you're using TortoiseCVS to interface with CVS somewhere, say, on a SourceForge project. WinMerge automatically updates TortoiseCVS's preferences to integrate itself as TortoisCVS's Diff viewer. This means you can simply right-click on a local file you've edited and select "CVS Diff". You'll be prompted for your password (unless you're using something like Pageant. See Haacked's great Quickstart Guide.), then WinDiff will pop open with a screen clearly showing the deltas between your edits and the last version in the repository. Lots of nifty diff tools stuck in WinMerge, but you can check them out yourself! I've been a years-long user of GVim as a quick editor and visual diff tool, but WinMerge's integration with TortoiseCVS have just knocked GVim from it's throne. (Although I still use GVim for all sorts of regex-based searchs and pattern replacements.)

Wednesday, July 20, 2005

Good UML Overview

Martin Shoemaker, creator of TabletUML, and a serious UML geek, is blogging an overview of UML in the aspect of a real-world project. <gasp!> Nice start to it so far!

ReSharper 2.0 EAP Has Started!

Great news if you want to get in on helping drive the next version of ReSharper: the v2.0 Early Access Program has started! This is an Early Access Program, so you'll be in front of the bleeding edge. Expect "issues." That said, traffic on the ReSharper newsgroup makes it look like the folks at JetBrains are really quick to respond to problems. I'm downloading it as I type.

Recipe Blogging: Fennel Salad

Fennel's great stuff. I use it in soups and stews, I'll braise it as a side dish, and it's terrific as part of a summer salad.

Fennel Salad

2 bulbs fennel, stalks trimmed 1 head red leaf lettuce, well rinsed and torn into pieces (substitute whatever's on hand) 1/8 c. thinly sliced red onion 1/8 c. chopped pecans (pine nuts are a good subsititue) 1/4 c. crumbled feta cheese 2 Tbs rice vinegar pinch sea salt fresh ground black pepper 1 tsp Dijon mustard ~3 Tbs good extra virgin olive oil 1 tsp. minced fresh rosemary Trim the root end off the fennel. Peel off the outer layer if it has any brown spots. (Save the stalks and outer layer in a bag in the freezer for your next batch of stock.) Cut the bulb in half lengthwise, roll the bulb onto the cut side and thinly slice. Repeat with remaining fennel. Toss the fennel, lettuce, onion, pecans, and cheese into a large bowl. For the dressing, in a small bowl mix the vinegar, salt, and pepper until the salt is disolved. Add the mustard, olive oil, and rosemary. Mix well. Drizzle over the salad mix. NOTES: Fennel bulbs are male and female. No, really. The female bulbs are rounder and squatter. The male bulbs are more elongated. The female bulbs are preferrable. Orange slices make a great addition to this salad.

Tuesday, July 19, 2005

Has Your VS 2005's IDE Lost Its Mind? (A Potential Fix)

My VS2005B2 lost its mind this morning. Keyboard shortcuts for bookmarks weren't working and I couldn't copy/paste anything. Rather frustrating, especially since I hadn't yet had my second cup of good coffee. Restarting VS2005 didn't work, nor did bouncing my system. (No, I don't mean tossing it across the room, I mean recycling it. Really. Some people.) Thankfully James had two suggestions: 1) Run "devenv /setup" which resets many of Visual Studio's settings. That didn't work, and I was getting out my DVD for a reinstall when James mentioned 2) Delete Visual Studio's local settings under C:\Documents and Settings\<your homedir>\Application Data\Microsoft\VisualStudio. You'll lose VS-specific settings, but of course solution and project settings aren't impacted. Thankfully #2 did the trick and I'm back running. Geeze, you'd think that guy wrote a book or something.

Testing Nullable in NUnit

I've been learning about Nullable types in .NET 2.0. They're very handy, especially in the case of Business Entities (Data Transfer Objects) which interract with a database. Database fields may have null entries, which are a pain in the keester when it comes to value types like int, bool, and structures. I've also been figuring out how NUnit deals with Nullable types. It's not clear in the documentation I saw, so I had to do a bit of trial and error. Assert.AreEqual() won't directly compare two Nullable types, but you can use the Nullable.Compare() method and check its return as needed. Below is an example of a underborder test using Nullable.Compare(). I'm testing that my bounds checking in my PostEntity's PostID property correctly barfs when it sees a negative number. (I don't want negative IDs for my posts.) PostEntity.PostID is a Nullable<int>. Note that you've got to pass it a Nullable int as well; Plain Old Int won't work. Note that Nullable.Compare() returns the usual suspects for a compare operation: 0 if equal, -1 if the first param is smaller, 1 if it's larger. [Test] public void CheckPersonIDNegative() {     PersonEntity pEnt = new PersonEntity();     Nullable negVal = -1;     try     {        pEnt.PersonID = negVal;        Assert.Fail("Expected ArgumentOutOfRangeException");     }     catch (ArgumentOutOfRangeException ae)     {        Assert.AreEqual(0, Nullable.Compare(negVal,        (Nullable)ae.ActualValue),"Failed compare");     }     catch (Exception ex)     {        Assert.Fail("Unexpected Exception: " + ex.Message);     }     finally     {        pEnt = null;     } }

Monday, July 18, 2005

NUnit 2.2 and VS2005 B2: BadImageFormatException

Getting BadImageFormatException errors when trying to use NUnit 2.2 with VS2005 Beta 2? There are several spots with the answer on the web. I found my solution at IdentityCrisis. Edit the nunit-gui.exe.config file and add support for the latest framework. Move it to the top of the list of supported runtimes or it won't fix the issue. <startup>    <supportedRuntime version="v2.0.50215" />    <supportedRuntime version="v1.1.4322" />    <supportedRuntime version="v1.0.3705" />    <requiredRuntime version="v1.0.3705" /> </startup>

Sunday, July 17, 2005

Garden Blogging: Glorious Tomatoes!

My favorite part about summer: wonderful tomatoes fresh from the garden sliced up with a bit of real mozzarella cheese, fresh basil, some top-notch olive oil, a bit of good sea salt, and a dusting of fresh ground pepper. A bit of leftover grilled chicken rounds out a simple, light summer meal. Now I'm hungry again.

Friday, July 15, 2005

VS 2003 Post-Build Events

I'm sure this is old hat to folks experienced in Visual Studio, but it's something new for me. Maybe someone else will find this useful. Post-Build Events in Visual Studio let you handle things like moving or copying files around your build environment. Very handy stuff if you need to do a little massaging of your solution/project's output. I'm working on a CodeSmith template project which has a Helper class to do string manipulation, type parsing, etc. (I wasn't the guy who did the initial work, that was another fellow more smarter than I am.) The DLL generated from the Helpers class needs to land in the template directories for use by CodeSmith. Create Post-Build events on a per-project basis by right-clicking on the project and pulling up the Properties dialog. Click on Build Events under the Common Properties folder. The Post-Build Event Command Line field is where you can enter your commands at. You can enter in any command-line executable in this field. Use the field's elipsis to pull up another dialog where you can enter longer commands. The "Macros" button on this dialog also gives you access to a handy set of properties for the build -- you'll find a list of directories, paths, etc. Construct your commands, one per line, using free text and macros as needed. Use any regular command like 'copy', 'move', etc. You can also call other batch files via the 'call' command. Important: Remember to surround paths with quotes in case your paths have spaces in them. The Post-Build Event actually creates a batch file in the project's output directory, then calls it after the build is complete. All macros you use are expanded when that file's written, so it's a good source of information when trying to troubleshoot a failed post-build event. You can quickly see if you forgot to do something like surrounding your path with quotes. Not that I know anyone who'd make such a basic mistake. I'm just tossing that out there for others.

"Microsoft Doesn't Listen to Their Customers"

Yeah, right. There have been and will continue to be plenty of things I don't like about Microsoft, but take a look at this blog post from Josh Ledgard. Then tell me that Microsoft doesn't want input from its customers. I realize that one fellow isn't Microsoft in its entirety, but I still think this is 1) a great thing to see for Microsoft and 2) an amazing use of blogs.

FreeMind Mapping Software

Ben Carey wrote about MindManager, a terrific visual planning/productivity/organizing package. I've been evaluating it for the last month and think it's absolutely terrific. Mind maps are wonderful things, and I've used them for outlining projects, brainstorming, and task breakdowns. MindManager also has a killer save to website feature which produces a terrific HTML output showing the visual maps, richly linked web of great information. I used this feature to export some project thoughts to a potential client. MindManager's only problem: its price. I'm at the point with the startup of my company where I really need to pay attention to expenses. There are a lot of terrific productivity enhancers I could use (this comes to mind, as does this, or even one of these), but I've got to be extremely disciplined about the number of cool $300 - $500 things I buy. Reality sucks. Thankfully, Phil from geekyinfo.com left me a comment about FreeMind, an open source mind mapping package implemented in Java. I loaded it not long after his recommendation, but didn't play around with it much. Now that my MindManager eval is finished, I'm taking another look at FreeMind. It's actually going to fit the bill for what I need now very nicely. I'm using it for task breakdowns, to do lists for development, and it's doing just great in that role. It's also just as handy for brainstorming as MindManager is, although MM's "brainstorming" mode is really handy. Overall, FreeMind gets a big thumbs as an interim solution. Plus FreeMind's price is right.

Wednesday, July 13, 2005

Tips and Thoughts on Founding A User/Developers Group

It's been something like three or four months since I started working on founding the Dayton .NET Developers Group. It's been a heck of a fun roller coaster ride so far, and I thought I'd pass on some lessons learned in case anyone out there happens to look for info on starting a user group. First off, make sure you understand where I'm coming from. This post is supposed to be a bit of realistic advice from someone who is absolutely enjoying the process. Having a realistic picture of an effort before starting is an important thing! This is written from the point of view for a .NET group; however, many things are applicable to starting any group regardless of its specific theme.

Commitment

Be damned sure you've got an inkling of the commitment you're making. Building up a developers group takes a heck of lot of sweat equity. You'll be spending a lot of time on the phone trying to publicise the group. You'll be spending a lot of time writing e-mails. You'll be spending a lot of time contacting other event organizers to try and get on their coat tails. It's sheer marketing hack work, but it's absolutely worth it.

Organize, Organize, Organize

You don't have time and energy to forget or redo a lot of stuff. Get in touch with your organizational inner self by using methods from Take Back Your Life - Using Microsoft Outlook to Get Organized and Stay Organized. Another good book (so I've heard) along the same line is Getting Things Done. There's also a good-looking GTDTiddlyWiki if you want a non-Outlook tool.

Vision, Vision, Vision

Create a mission statement for your group. Think about what you want to accomplish by founding the group. Think about what benefits your members will gain by joining the group. Think about the benefits sponsors will get by giving you funds to support the group. Think about what benefits employers will get by possibly cutting their staff loose a bit early once a month to attend meetings. Think about how your members will benefit from incredible networking opportunities and exposure to industry-leading trends and speaker. Write all that down in a clear, professional fashion. Use it to build a call script for when you start making calls to companies in search of new members.

Get in touch with national resources.

First stop should be contacting your Microsoft regional developer evangelist. Drew Robbins, the DE for my region has been an incredible asset -- plus he founded the Columbus group so he's had terrific tips for me. How do you find your regional DE? Contact other .NET groups in the area and check with them! Second stop should be registering with CodeZone which holds MSDN user groups. Third stop should be registering with the International .NET Association (INETA). INETA has a moderately useful white paper on starting a user group.

Get in touch with regional resources

Check out user groups in the region. Contact their leaders. Most leaders, not all, will be very happy to help you get your group going. I've had killer, fantastic support from the guys at the Columbus and Cincinnati groups. Smart menschen should see your founding group as an asset to the region, not as competition. Furthermore, think about pairing your meeting dates with a nearby group. I paired our meetings up next to Columbus's. This will let us work together to get speakers in for two meetings on one trip. I think this helps a smaller group get bigger names in to speak if they can pair up with a larger, better-established group.

Get in touch with local resources.

Search out other user groups, particularly something like generic computer user or software developer groups. Heck, touch bases with other specific groups! Other good resources include local publications like your newspaper and local business journals. Also check to see if there's a IT-related talk show on any of your local stations. I was lucky enough to hook up with the guys at IT Matters, and they had me in the studio for an hour gig about our group. Make sure to look for any local or regional groups which have the mission of helping boost IT industry in the area. We're lucky to have the Greater Dayton IT Alliance here in the greater Dayton metro area. These folks are a terrific help.

Hit the phones

Build a list of local IT companies to call. Search Monster.com, your local paper's job listings, and any other resource you can think of to build a list of companies who might be interested in, or are already doing .NET development. Create a call script talking about the group's mission (See Vision above) and why that company's developers and tech leads would benefit from membership. It's tough, but try to speak with IT managers or CTOs. Marketing people won't be much help, nor will secretaries. Important note here: the folks you're speaking with are very busy. Have your script ready and rehearsed so you can get your message across in as short a time. Conversely, your script should just be talking points, not something you read out word-for-word. Do you want calls from telemarketers? Nope. Don't do the same to the folks you call!

Find a kickoff event

See if you can't find a local tech-related event to use as a kickoff for your group. Does your Chamber of Commerce or other organization have an event you can use? What about some Microsoft product launch? Is there an expo around? Research and find one of those, then latch onto that event's organizers like an alien on John Hurt's face. Cheerfully use every bit of publicity from them you can, and then some. See if you can inject publicity announcements into any mailing list they've got. Be a shameless leech. Smile while you're doing it, and be very sure to thank them repeatedly.

Group resources

Keep polling your membership to see if folks are interested in helping out. The burden of running a developers group is a very stiff one. You need help to get it done. Break tasks out into small jobs so your members can nibble of pieces of your workload. Here's a tough bit of reality: You won't get anywhere near the help you might expect. Your new members are folks with lives outside of work, and they're not going to be willing to take on the huge burden like you are. You'll have folks who offer to help, but won't follow through when you pass on tasks. You'll have mass silence when you mention a few opportunities to help during meetings. Don't get frustrated. (OK, too frustrated.) Before long you'll find one or two folks to help out. Take advantage of them, but make sure you understand exactly what level of commitment they're willing to take on. Don't overburden them past their borders -- you don't want to frustrate those folks who are willing to step up.

Load up on swag

Stoop to shameless bribery of your members. Round up as much loot as you can to give away. Several book publishers are great supporters of user groups. Check out programs from Apress, Addison-Wesley, and O'Reilly. I had lousy luck trying to get ahold of anyone from Wiley/Wrox: rude folks who couldn't have cared less. Let me know if you have better luck with them -- they've got great books. Furthermore, look to publishers of neat tools and other software. See if they'll donate a copy or three for you to give away.

Closing Thoughts

OK, I've rambled on enough. There are undoubtedly many things I've forgotten (Should have used GTD more better!), but this is a pretty good list. Leave me a comment if you stumble across this and find it useful, or if you've got suggestions to add to it. My work over the last few months has been fairly staggering, but it's been tremendously productive and interesting. Founding a developers group gets you in the door with some amazing folks. I've found contacts which will help me tremendously in my career, learned a lot of great things, and most importantly made some good friends.

Tuesday, July 12, 2005

Great Music Never Dies

Some songs are always classics. I was singing this to my daughter the other day and thought I'd look to see if it was anywhere on the web. Boy, am I glad it's still alive and kicking! Even archived on a Boy Scout site. Now THAT is posterity, folks!

Innovation is a Cold Fish in the Face

So I must be the last person in the .NET development world to run across Rory Blyth's blog. He's got a hysterically on target post about how "Innovation" is wildly over-used, over-rated, over-everything. Wish I had the dude's artistic skills.

SourceForge CVS Configuration Tips

Here are a couple good links if you're needing to get access to SourceForge's CVS system. I haven't found any plugins which interface CVS to Visual Studio, but there are a couple good workarounds. Haacked uses TortoiseCVS for his interface. (via James) SourceForge's Survival Kit and their Introduction to CVS Services are great helpers too. SF's examples use WinCVS which is a somewhat confusing, overly complex interface to CVS. Hmmm... CVS often seems somewhat confusing and overly complex, so it's actually a good pairing. It's been a couple years since I used CVS. It certainly takes a bit of getting used to again.

Monday, July 11, 2005

Garden Blogging: Lavender Wave

We love lavender! We had a wonderful bush in our garden when we lived in Germany during the last century. (Heh. Doesn't THAT make me sound like an old fart!) We've been looking for something similar since we moved to Ohio and finally found some great bushes from Goodwin Creek. This wave of beautiful lavender is the result of three bushes planted two years ago. It's on the southern exposure and the ground's covered with weed cloth and a layer of pea gravel. The lavender just sucks up the heat radiating off the gravel and brick wall. What's really cool is that the lavender attracts huge numbers of bumblebees. There are between, no kidding, 45 - 60 bees swarming on the bushes at any time during the day. The bushes are right out our French door, so we're able to watch the swarm working its way through the lavender during the day. My five year old daughter and one year old son love to sit (safely!) inside and watch the little critters go at it. We've got several other bushes planted along the same wall, but none is as spectacular as these three.

Friday, July 08, 2005

Bad Pundits, Part II

I missed a real howler in Gwynne Dyer's column I blogged about earlier. Dyer says "The point is they're only terrorists, and they can't hurt all that many people." I guess Dyer doesn't count nearly 3,000 dead in New York and Pennsylvania on September 11, 2001 as "that many." Maybe he doesn't count nearly 4,000 murdered by Islamic terrorists since 1993 as "that many." (Perhaps he missed the Sun's article Evil across our planet which details the terrorist attacks.) Maybe polemics on the right like Ann Coulter and Sean Hannity are writing similar dreck from the other side, but I don't waste my time at their sites so I wouldn't know. Dyer's stupid column really got my goat though, as you can tell. Enough of this. I'm back to having breakfast with my daughter, then it's back to the grindstone.

"You're Out of Your Tiny Minds"

This Letter To The Terrorists, From London may be one of the best things I've seen written about yesterday's horrible bombings. One of the worst things (and there's inanity aplenty on both sides of the political spectrum) I've read was Gwynne Dyer's column in today's Dayton Daily News. (Sorry, it's not online at the DDN's site, nor can I find it elsewhere.) Dyer, who holds a doctorate in military and Middle Eastern history and a masters in history, talks about how the bombings of London in WWII were not because of the Brits' way of life, but rather because of British policies abroad. He goes on that "the people who organized teh bombs wanted Britain out of the Second World War." Seems to me Hitler was pretty bent on putting all of Europe, and eventually the world, under his Nazi party's boot. The scum in Germany those days weren't just looking to be left alone, they were looking to take over the world. The fascist, murdering scum masquerading as Islamists these days aren't looking to be left alone, they're looking to take over the world. Dyer's got education aplenty. It's apparent he's either got no smarts, or is one of the many talking heads who starts first with an opinion and then looks to distort facts to fit their assumptions.

Thursday, July 07, 2005

AVOID!!! vb.doc addin for VS.NET

I've been trying to find decent tools for generating XML comment files from VB.NET code. VB-Commenter only works sporadically in the IDE, and can't be used from command line tasks like NAnt. (The owner's suggestion? Call devenv.exe instead of NAnt's solution task. Not gonna happen.) I also tried VB.DOC and it's nicely killed my VS.NET installation. The Visual Studio Add In appears to eat Ctrl-V and Shift-Ins for Edit -> Paste shortcuts. No remapping works, the keypresses just get eaten. I got bored of hitting Alt-E -> P (I'm a lazy SOB), so I decided to try deinstalling the plugin. (James was some help in pointing out Dave had the same trouble caused by an add-in James couldn't remember.) One small problem: Uninstalling kills VS.NET. Uninstall the piece of crap add-in and you're unable to load any VB.NET projects because "the Visual Basic .NET compiler can't be created." I've tried several different methods for uninstalling the add-in, all to no avail. I've submitted a bug report at the project's SourceForge site. Hopefully I'll get a bit of help. In the meantime, I'm forced to reinstall the cursed software because I don't want to waste an entire afternoon reinstalling VS.NET.

More on NUnit Config Files

I blogged a couple days back about the mystery of NUnit config files, and how they differ if you're using the command-line test or the GUI project. I finally stumbled across more documentation on the NUnit site: Under the "Documentation" menu, check out the Supplemental PDF file. [NOTE: that link's not working too well at the moment.] Also, NAnt lets you point an nunit2 task to an NUnit GUI's project config file. This saves a lot of mess trying to fool with linking or copying config files around to their appropriate location during a NAnt build, plus you can use the same project file for both GUI and NAnt runs. I believe there are some differences in how the two sorts of config files, but I haven't had problems so far. Here's how my task looks: <nunit2>    <formatter type="Xml" usefile="true" extension=".xml" outputdir="${core.reports}\" />    <test appconfig="${core.source}\MyAppNunit.config" >       <assemblies basedir="${core.output}\">          <include name="*Tests.dll"/>       </assemblies>    </test> </nunit2>

Wednesday, July 06, 2005

Handy NAnt Target

NAnt's -projecthelp option only shows targets in NAnt.build or whatever you've named your initial build file. Targets in included files don't get shown. Here's a helpful widget using NAnt's "script" capability to write a C# function. Paste this into your common or core build file and you'll have the ability to see all targets in your merged build files. I can't take credit for this -- I found this snippet a year or more ago somewhere on the web, perhaps on the NANT-USER mailing list. I don't recall who wrote it, but here's a virtual beer mug raised in your direction. <!-- 'nant -projecthelp' shows only targets in NAnt.build, not in included files --> <target name="showtargets" description="Show targets in all included build files">    <script language="C#">       <code><![CDATA[          public static void ScriptMain(Project project) {             foreach( Target t in project.Targets ){                Console.WriteLine( t.Name + ":\n\t " + t.Description);             }          }       ]]></code>    </script> </target>

Moving Woes

Pal Ben Carey's had a horrible experience moving. It sounds like both Allied Van Lines and their agent Berger Allied have been the usual near-criminal scumbags that too many movers are. We've moved six times in the last 11 years, all due to military relocations. Moving sucks. Most movers suck. Badly. There are also plenty of criminal thugs masquerading as movers -- they'll hold your household goods hostage until you cough up another $30K - $50K to cover "additional expenses." Moving's is a crappy experience even if everything goes well. It can easily turn into your worst nightmare. Make sure you do a lot of preparation before the movers show up. Understand what you need to do to protect yourself. Clark Howard's website has plenty of resources if you search on "moving". He's also got resources if you get screwed as badly as Ben did.

Versioning Using NAnt

I've posted already on how much I'm getting out of Marc Holmes' Expert .NET Delivery using NAnt and CruiseControl .NET. (Marc's no relation to me, at least none that I know of.) One of the topics within is versioning. Marc uses the version task from nant-contrib to increment build numbers held in a Build.Number file. This gets used in the same work task to create the assembly information via the asminfo task. I found one mistake in his example code, plus made one enhancement to it. Changes are below. (I should say I think I found a mistake. I haven't heard back from him yet.) The mistake seems to be that the incremented version number isn't used when generating the AssemblyVersionAttribute. The enhancement I did was wrapping the Build.Number file into Source Safe, checking it out before incrementing the version, then checking it back in afterwards. Below is the updated XML for the task. I'm not going to fill in all the NAnt properties created upstream from this task-- they're pretty obvious. Note that Marc's strategy uses the debug property to control whether the build number's incremented or not. You don't have to increment build numbers if you're just testing additions to the NAnt scripts. I may rename this property in the future since "debug" means different things to me. Marc also uses a CommonAssemblyInfo file which he links to individual projects within a solution, a great trick for cutting duplication of redundant information. ("Duplication of redundant..." Clever, no?) <target name="version1" description="Increments version number in CommonAssemblyInfo file.">    <property name="sys.version" value="0.0.0.0"/>    <ifnot test="${debug}">       <!-- Enhancement: check out Build.Number file from source control -->       <vsscheckout             username="${vss.username}"             password="${vss.password}"             localpath="${core.source}\"             recursive="false"             dbpath="${vss.dbpath}"             path="${vss.path}\${solution.name}.Build.Number"       />       <version buildtype="Increment"             revisiontype="Increment"             path="${core.source}\${solution.name}.Build.Number"/>       <!-- Bugfix: store version task's output back to sys.version property if we're incrementing -->       <property name="sys.version" value="${buildnumber.version}" />       <!-- Enhancement: check Build.Number file back into source control -->       <vsscheckin             username="${vss.username}"             password="${vss.password}"             localpath="${core.source}\${solution.name}.Build.Number"             recursive="false"             writable="false"             dbpath="${vss.dbpath}"             path="${vss.path}\${solution.name}.Build.Number"             comment="Incrementing for version ${sys.version}"          />       </ifnot>       <attrib file="${core.source}\CommonAssemblyInfo.vb" readonly="false" />       <asminfo output="${core.source}\CommonAssemblyInfo.vb" language="VB">          <imports>             <import name="System" />             <import name="System.Reflection"/>          </imports>          <attributes>             <attribute type="AssemblyVersionAttribute" value="${sys.version}" />             <attribute type="AssemblyProductAttribute" value="${solution.name}" />             <attribute type="AssemblyCopyrightAttribute" value="Copyright (c) 2005, ${company.name}"/>             <attribute type="AssemblyCompanyAttribute" value="${company.name}" />             <attribute type="AssemblyTrademarkAttribute" value="Trademark by ${company.name}" />          </attributes>       </asminfo>       <attrib file="${core.source}\CommonAssemblyInfo.vb" readonly="true" /> </target> This approach may not work for everyone. In particular, the linked CommonAssemblyInfo file won't work with Web projects because of their pain-in-the-ass broken up directory structure. It also doesn't give granular control down to each assembly. That's OK, because Marc says frequently in his book that his topics aren't solutions for everyone, they're guides to get you started. So there you have it. UPDATE: Marc pointed out that sys.version is the property set by nant-contrib's <version> task -- in earlier versions of nant-contrib. I'm using 0.85RC3 which defaults to buildnumber.version. I should have checked that from the get-go!

Monday, July 04, 2005

"Refactoring" Web Sites

OK, so I've spent a couple hours refactoring my LLC's website. Can one refactor HTML and CSS? It's not really code (I once saw a shirt which said so, hence it must be true), but I do think one can indeed refactor the stuff. More tricks learned from Meyer's wonderful Cascading Style Sheets: The Definitive Guide, 2nd Edition, more fun playing around with site design. (And it's obvious that I'm no graphics wiz like this incredible lady.) Meanderings aside, this was a good chance to fix a couple things which had been bugging the heck out of me. Text size changes don't bust everything now, the content's centered in a floating box thanks to margin-left:auto and margin-right:auto plus a new <div> surrounding my content, which means my menu bar, title, and other elements stay nicely tied together when resizing. The only small hitch is a slight bounce if content runs off the bottom of the screen and a scrollbar appears. Can't fix everything right now, what would I have to do later? I also got rid of the transluscent tan color box for the left sidebar list and just made that a separate background-color property. Having some transluscency let the background image show through which I thought was cool; however, the resizing text issues just made it a mess, so now it's a solid background color. In the earlier version I'd cheated and made the tan box transluscent by overlaying it on the background image while working in PaintShop Pro. That looks cool until somebody resizes text or gets funky with aspect ratios and the sidebar text ends up somewhere in Puerto Rico sipping rum on a beach. Unfortunately, there's no good way to do transluscency in images -- at least according to The Zen of CSS Design: Visual Enlightenment for the Web. Leave me comments if you know otherwise. So there you have it. More refactoring to make my site look more better more better. I'm still a long way off from being a sharp web designer, but that's not where I'm going. I'm pretty satisfied with what I've got now! (By the way, my rose graphic logo was done by my friend Jenn Farington. She's a great artist who makes wonderful handbags, scarves, etc. from beautiful materials. Check out her great works at Piece Lily.)

Wonderful Web "Standards"

I've just noticed that my LLC's site looks like crap in IE. The left sidebar doesn't display, only the colored background, plus the margins are all crappy. Arrgghh. I thought I'd checked all this out in both IE (sucky) and Firefox (killer). My CSS and XHTML all validates, so now it's off to delve into the subtle "feature" CSS handling of IE. Hopefully this was something in one of the last couple changes I did, otherwise I'll have had a long period of lookign like the web design bozo I really am. Ptooey.

Happy July 4th!

Celebrate the founding of our country on July 4th, 1776. Celebrate the founding of a creaky, ever-developing, wonderful experiment called representative democracy. Celebrate the founders who risked all to create this beautiful thing called the United States of America. Celebrate a land where lefty polemics like Michael Moore can make anti-government propaganda films staggering in their dishonesty (see also Leni Riefenstahl) and not only stay out of prison but make millions while doing so. Celebrate a land where conservative polemics like Ann Coulter write empty hyperbole and get action figure dolls modeled after them. Celebrate a land holding cities like New York, Los Angeles, Chicago, and a myraid of others where people of amazingly diverse backgrounds live in relative tolerance. (Sure, we have issues here, but compare us to Rwanda, Boznia, etc.) Celebrate a land reviled by students of hate-filled Islamic massadrases, yet so loved by masses of others around the world that they'll risk stowing away in cargo containers to escape oppression in their native homelands for a chance at opportunity in this land. Celebrate a land where a Hungarian immigrant can create a wealth of billions by shady dealings in financial markets and spend 28 million of those dollars creating disengenuous, hate-filled organizations in an attempt to unseat our President. Hey, Soros: I'm a starving developer with a family and a mortgage. How about giving me some of that money? Celebrate a land where an Austrian immigrant can land on our shores with lint in his pocket, yet rise to the top of Hollywood and govern the nation's most populous state. (And have an action figure doll made after him.) Celebrate this land called the United States of America. Long may her amber waves of grain and alabaster cities serve as a shining beacon to those wanting liberty and freedom.

Friday, July 01, 2005

Great NAnt & CruiseControl.NET Book

I'm working my way through Expert .NET Delivery using NAnt and CruiseControl .NET from Apress. Holy smokes, what a terrific book! This is real world stuff diving deep into details, not a light fluff overview. What's cool is that the author, Marc Holmes (no relation), approaches the process of designing a good delivery system/methodology just like designing good softare: a few use cases with expected outcomes which are used as guidelines for building up the various scripts needed to get delivery tasks done. Marc also uses refactoring to get the scripts up and working: build something a bit kludgy to test your assertions, then refine it. Marc shows off some pretty cool stuff about the NAnt, including how to wrap in third-party tools (FxCop, before its inclusion as a nant-contrib task, e.g.), plus he walks through some good tutorials on extending NAnt. Right now I'm in the chapter on getting a database into the picture for testing and it looks pretty impressive so far. Marc covers using the Red Gate SQL Bundle, a set of tools which ease integration of database activities into the test and delivery processes. The package isn't chump change ($350), but it's most likely worth it if you're doing at least a moderate amount of SQL work in your projects. An important note: I think this book is really applicable to cross-platform use. Sure the specific tools are NAnt and CruiseControl.NET (plus many other widgets), but the concepts are applicable to folks doing Java development using Ant and CruiseControl. Furthermore, I think this book pairs up terrifically with Steve Loughran's Java Development with Ant. Loughran's book was a terrific eye opener to me for specifics of laying out projects with abstracted build files, plus he hits testing, deployment, and library inclusion too. Both books together really help out folks using Ant/NAnt and CruiseControl/.NET. I'm looking forward to finishing up Marc's book. Everything's been great so far, and I've gotten some terrific ideas so far. <disclaimer>I got this book free as part for giveaways at the Dayton .NET Developers Group. If you think my opinion gets skewed because I got something for free, well then, you haven't gotten a good feel for who I am. Check out the rest of my blog and maybe it will convince you otherwise.</disclaimer>

NUnit and Config Files

I'm writing NUnit tests using System.Configuration.ConfigurationSettings.AppSettings to read in database connection strings. NUnit needs a configuration file, but the documentation's confusing on where it needs to go. Thankfully, Ross Pressner posted a clearly written description to microsoft.public.dotnet.general back in September, 2004. If you're testing using a dll holding your tests, then your config file needs to be co-located with that dll. If your tests are located in an NUnit project file, then your config file needs to be co-located with that file. For example, tests in the assembly D:\projects\MyApp\DataLayerTests\bin\DataLayersTests.dll needs a config file like so: D:\projects\MyApp\DataLayerTests\bin\DataLayersTests.dll.config Tests in the NUnit project file D:\projects\MyApp\MyTests.nunit need a config file like so: D:\projects\MyApp\MyTests.config Be sure to carefully note the naming variants.

Subscribe (RSS)

The Leadership Journey