# Friday, October 12, 2007

If you look at all OSS projects out there (the good one's anyway), they don't even check in their AssemblyInfo.cs files, as these are auto generated when you run a build and the version # is just an MSBuild or NAnt property.  CC.NET should track the version number in its local project state file and pass that into the build script, or the version should be deduced from source control meta data.  Here are some typical responses from developers why they like keep version numbers in a text file checked into source control:

  1. But what if we need to do a local build which needs to be versioned with something besides 0.0.0.0?  Why on earth would you ever need to do that?  Local dev builds should never be official, thus should never be deployed.  The continuous integration server is the integration point, not your local desktop.
  2. But I need to use a specific version because my assembly is strong name signed to a specific version and I want to hot swap a DLL for testing purposes (or something more sinister).  If you really, really want a local versioned build, override the script's version property, but really you should be using a binding redirect in your app.config.
  3. What happens if the build server dies and we lose the state file?  That's why you label source control with the version # every build, which you can use to build a new state file on the new CC.NET server.
  4. We don't label source control, so now what happens if the autobuild server dies? You do output versioned builds somewhere don't you?  Look at your last build and rebuild your state file.
  5. But, but, but...  That's how I've always done it.  Why? Sure its nice to keep everything in source control, but in this case there's no need.  Really you should be using the meta data of your source control system to manage build version increments, not some text file in source control.

While your removing your version.txt from your source control system, consider switching to SVN while your at it.  ;-)

Friday, October 12, 2007 5:43:03 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

Its no wonder many programmers shy away from web programming, specifically HTML and CSS.  Most senior developers consider HTML programming, and UI programming in general, beneath their station.  I think they're hiding from the truth. 

Making an easy to use and pleasant looking user interface is much harder than consuming a web service or writing some highly concurrent middle tier layer, especially when that environment is the Internet where you have any number of browsers and operating systems to interact with.  Sure you think MAC, Windows, Linux, IE, Firefox, and mobile devices, but lets throw in another element most people don't think about - web browsing from a TV. 

Sure HDTVs have enough resolution from 2 feet away, but the issue is, people use their TVs from 10feet away or more, which effectively reduces your resolution because all of your fonts and images need to be double what they are on the PC.  Additionally the input device has changed from a mouse, to a remote control which also means you need to tab between buttons and hyperlinks, not mouseover - your fancy CSS rollover buttons don't work anymore.

Now try to get a page to look consistent across all these platforms and browsers!?  Good luck, its hard enough to get things to look consistent between FireFox 2.0 and IE7 on Windows.  What works in one browser for positioning and alignment falls flat on its face in another.  This leads to a lot of trial and error when coding up some HTML and CSS. 

I think this is why so many ASP.NET programmers hide behind ASP.NET server controls.  To touch the HTML and CSS is like assembly programming for a non-specific platform.  It hurts.  Building a nice UI for a TV doesn't fall into the realm of pre-built user controls, so I find I spend a lot of my time in "web assembly language."

At least when you're dealing with a complicated middle tier things are consistent, they either work or they don't.  Add in concurrency, threading, and scalability to your middle tier and you might have an argument that its as hard as UI programming.

Yeah, UI development is that kind of hard, especially when you throw in the subjective aspect of it.  Maybe that's why Mr. Coding Horror has so many blog posts about UI development.

Thursday, October 11, 2007 11:32:51 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [2]  | 
# Friday, October 05, 2007

I just bought an external Western Digitial 500GB MyBook hard drive that is capable of connecting through either eSATA or USB 2.0.  The drive only comes with a USB cable so I'm stuck using that until I got back to the store tomorrow to purchase a new eSATA cable.  I initially tried copying my source folder over to the drive (~1,8GB), but it was copying slower than I could check it out from SVN over the Internet.  Obviously something was wrong.  The culprit as it turns out was that the drive comes preformatted using FAT32 and I just tried using it as is.  Big mistake!  One NTFS reformat later and my drive is copying like a champ.

Friday, October 05, 2007 5:51:29 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, October 03, 2007

Don't include Windows.h -  I had to say it.  ;)

Always have a blank line at the bottom of each source or header file.  You get g++ compiler warnings if files don't have an extra carriage return at the bottom.

Compiler pragma warning disable statements should be ifdef'd for WIN32 only.

#include statements must match the case of the header file name.

#include "gpireader.h" // won't compile on g++, but

#include "GPIReader.h" // will compile on g++

 

Don't forget to use virtual destructors where appropriate, g++ will complain if they're missing.

Don't memset STL strings (std::string) to zeros.  Strange and odd memory corruption will occur if you do.

Don't memset structs which contain STL strings, see point above.

Don't include enum names. 

if (res == ResourceType::AccessBlock) // won't compile on g++, but

if (res == AccessBlock) // will compile on g++

 

Don't include the class prefix in header files for method declarations.

std::string GPIReader::GetXMLStringResource(ResourceType type);  // won't compile on g++, but

std::string GetXMLStringResource(ResourceType type); // will compile on g++

 

stricmp (case insensitive strcmp) function is not available on Linux, you must toUpper then compare or something.

C++ | Linux
Wednesday, October 03, 2007 6:07:53 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

Being the only one at work with any Linux experience, I was elected by default to port our C++ API over to Linux.  Luckily we had some CxxTests already being utilized on Windows, and good thing we did because as I found out, just getting our API to compile on Linux didn't mean it would run on Linux.  These unit tests saved me around 2 days of work (it only took me about 12 hours to port).

The Linux environment I chose to use was Ubuntu running Eclipse CDT.  After some Googling I found that there's an Eclipse plugin for CxxTest that is similar to the Eclipse JUnit runner.  That sounded very appealing; I sure wish there was Visual Studio CxxTest runner.  Unfortunately all of the instructions for the plugin are about getting it to work with Windows and Cygwin, which wasn't much help in my scenario.  To get the pluging to work I found I needed to:

  1. Install the BFD dev library onto my Ubuntu system using apt-get.
  2. Remove the -libintl flag from the test project's additional libraries section.

After making those changes I was able to get the CxxTest runner building and running just fine.  The one thing I did notice is that the tests run only after 2 rebuilds of the test project.  I'm not sure why that is, or if I was doing something wrong - it was getting annoying having to edit my test file, compile, edit it again, and then recompile a second time to get the tests to run.  There must be a manual way to force the tests to build...

Wednesday, October 03, 2007 5:19:55 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [2]  | 
# Tuesday, September 25, 2007

When extending existing MSBuild targets, its often wise to append to the build target properties rather than override an existing target.  Its appears there's no way to override a target and then call the base target, this really annoys me because often I just want to add additional behavior to the existing target.  It seems the way around this is to add a property or itemgroup to the DependsOn attribute of a target, even if the itemgroup is empty, it just leaves a place open in the future for extensibility.  Here's in example from my shared targets file:

<Target Name="CreateDiskImage" DependsOnTargets="@(BeforeDiskImage);Build">

Now in some script which imports this targets file I can just declare one or more BeforeDiskImage items and they will automatically get run before the CreateDiskImage target.  If you look at the the MS providded targets files you will see this is done in a similar manner all over the place.  Here's a good reference for the C# targets you can hook into:

http://blogs.msdn.com/msbuild/archive/2006/02/10/528822.aspx

Tuesday, September 25, 2007 4:35:04 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Saturday, September 22, 2007

Yesterday I came to the realization that I'm not paid to write code anymore, I'm paid to delete code.  If my employer was paying me by lines of code written, I would owe my employer tens of thousands of dollars just for the past few months of work.  Sure, I've written a few lines of code here and there to refactor our codebase, but even with adding unit tests (that were non-existent before), I've always managed to reduce the size and complexity of the code, because less code is more.

In most cases its just dead code and completely useless comments that I get to delete in effort to reduce noise.  In one memorable instance I deleted over 3000 lines of code from a DAO class!  3000 lines!  If the average programmer writes 10 lines of code per day, then I just deleted almost a years worth of work in about 10 minutes.  Perhaps I rationalized that a bit.  I'm pretty sure most boilerplate ADO access code is cut and paste anyway, but regardless, I must say, very satisfying.

In another instance I reduced the number of assemblies our installer deploys by half, and cut the size of the main executable down by 4MB (from 6MB) by deleting unused legacy resources and being smart in the way the remaining resources are handled.  It appeared that more a more assemblies were added to our installer, but none were ever removed, even when the need for those assemblies had long past.

I'm comfortable in my new deletor position because every line of code I delete is one less to worry about.  After all I just want to see what's important in front of me and get rid of the noise - thank you very much.

-- Thank you ReSharper, because without you I could not be Sneal, aka the deletor.

Saturday, September 22, 2007 7:00:03 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, September 07, 2007

Sometimes its just so hard to do the simple things with Windows, like unzip files without a 3rd party DLL.  After banging my head on this for a couple of hours I finally figured out a way to do it using Windows PowerShell and the Windows XP ZIP explorer extensions through the Shell32 COM interface.

function UnzipFile([string] $zipFile, [string] $destinationFolder)
{
    if(test-path($zipFile))
    {
        $shell = new-object -com Shell.Application
        $srcFolder = $shell.NameSpace($zipFile)
        $destFolder = $shell.NameSpace($destinationFolder)
        $items = $srcFolder.Items()
        $destFolder.CopyHere($items);
    }       
}

Friday, September 07, 2007 12:31:59 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [2]  | 
# Monday, September 03, 2007
Hooray!  I now have both of my LCD's working in Ubuntu, ala "TwinView."  I attemped to use the nVidia confiuration utility, but ended up needing to manually edit my xorg.conf file to get the right settings.  I think the utility would have worked if my secondary LCD was connected using a DVI cable, but unfortunately it only supports VGA so I think the resolutions were not getting auto-detected properly.

For future reference, here's the relevant portions of my xorg.conf file with the dual monitor stuff in bold:

Section "Monitor"
    Identifier     "Acer AL2216W"
    HorizSync       30.0 - 82.0
    VertRefresh     56.0 - 76.0
    ModeLine       "1680x1050" 146.2 1680 1784 1960 2240 1050 1053 1059 1089 +hsync -vsync
    Option         "DPMS"
EndSection

Section "Device"
    Identifier     "nVidia GeForce 8600 GT"
    Driver         "nvidia"
EndSection

Section "Screen"
    Identifier     "Default Screen"
    Device         "nVidia GeForce 8600 GT"
    Monitor        "Acer AL2216W"
    DefaultDepth    16
    Option         "UseFBDev" "true"
    Option         "RenderAccel" "true"
    Option         "TwinView"
    Option         "MetaModes" "1280x1024, 1680x1050; 1024x768, 1280x1024"
    Option         "TwinViewOrientation" "LeftOf"

    SubSection     "Display"
        Depth       16
        Modes      "1680x1050" "1280x1024" "1280x960" "1280x800" "1152x864" "1024x768" "800x600" "640x480"
    EndSubSection
    SubSection     "Display"
        Depth       24
        Modes      "1680x1050" "1280x1024" "1280x960" "1280x800" "1152x864" "1024x768" "800x600" "640x480"
    EndSubSection
EndSection

Monday, September 03, 2007 4:48:35 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  |