Us vs. Them Round 20070828

There is a very interesting discussion going on over at Sasha Sydoruk’s blog. The signal to noise ratio is surprisingly high for the subject matter being discussed.

Sasha posed the question asking where are all the cool and new web sites that run ASP.NET. Other than MySpace, which moved from ColdFusion to ASP.NET a few years ago, and really isn’t that cool or new anymore, why are all the other “cool” sites running some other technology?

Reading this discussion is the first time I’ve actually missed doing the other the “P” or Rails type web development. I was starting to see some of my old feeling in the comments posted. I haven’t been all that impressed with webforms in asp.net for quite sometime.

MonoRail is pretty damn cool. In fact, MonoRail is so close to a “P” or the “R” type web development experience.

I think maybe that I just miss web development a bit. Which is insane! I hate web development. It is a huge pain in the ass. JavaScript is a pain. CSS is nice and all, but I find it painful. Maybe I find it painful because I never properly mastered it so I always have to reference docs to see if I have selectors right. But no. I think it has more to do with the fact that it would be insane to not continue to target IE6, since it is still the most widespread browser, yet it is nasty, nasty, nasty to try to use nice web features like CSS2 and CSS3 which are supported by Firefox and Opera, which will never be supported by IE6.

Maybe it is because “P”, the “R” and even Webforms are slowly becoming irrelevant on the UI side as Flash via Flex and Silverlight become more capable of building great web applications instead of just great games. On the back end side I know what development experience I like. It has little to do with Visual Studio and more to do with C# and CodeRush. Maybe I’m too tied to C#.

 I must say that I certainly think in C# these days. That is, when I look at python list comprehension, generators and even ruby blocks, I immediately think of them in terms of C#. C# can do all those things and they are actually very similar to how it is done in python or ruby. What I’m not very good at is thinking of a nice internal business-case DSL in C# and thinking about how it would look in Ruby or Python. I think this is my current thought limitation. I hope the discussion I read over at Sasha’s has caused me to find a place where I can learn and grow.

Search Results Due to Ads

I was just googling for something and got a very stupid result.

I googled for “worda wordb”. In the search result was a page with worda in the page, but wordb was only in the page because it was part of a google ad word in that page.

At first I thought google would be a little smarter about its search. The only thing I can think of is that this particular page had its ad words configured incorrectly and so google was indexing it incorrectly.

I was going to link to the page with with the google cache URL so that you could click it and see the highlighted words, but when I did I notice this at the top of the google cache header:

These terms only appear in links pointing to this page: wordb

So what I experienced is probably by design and not a goofy ad words configuration. Google is known to place pages higher in its rankings based on the link that points to the page. Ad-words is known to place ads in the list based on links pointing to the page. It was just strange for me to see what I saw.

Exception Handling 101

There is a lot of very good documentation on how to use Exceptions in .NET. If you don’t want to read these, and you are a programmer and unsure of how to use Exceptions, when to catch them, when to throw, or anything else surrounding the topic of exceptions, my recommendation is for you to do nothing.

The Must Reads are these:

  1. Best Practices for Handling Exceptions http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconbestpracticesforhandlingexceptions.asp?frame=true&hidetoc=true
  2. Error Raising and Handling Guidelines http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp?frame=true&hidetoc=true

 

This is a case where doing nothing is better than doing the wrong thing. If you REALLY feel like you should not crash, and continue if possible, and you just want to display a Message Box that says “ERROR” with a Red X then I give you these lines of code.

static void Main()

{

System.AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

...

}

static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)

{

    MessageBox.Show("An error has occurred.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);

}

static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)

{

    MessageBox.Show("An error has occurred.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);

}

 

Please please please don’t write code like this

 

 

public static void PleaseDoNotCodeLikeThis()

{

    try

    {

        if (batchFileName.Length > 0)

        {

            if (batchArchiveFolderName.Length > 0)

            {

                if (File.Exists(batchFileName))

                {

                    try

                    {

                        DoSomeStuffWithBatchFile();

                    }

                    catch (Exception ex)

                    {

                        throw (new Exception(“Error in batch file. “ + ex.Message));

                    }

                    string sWorkPath = TMP_DIR_PATH;

                    DoSomeOtherStuffWithResultsWhichMayNotExist();

                    if (Directory.Exists(batchArchiveFolderName))

                    {

 

                        sArc = batchSingleRow.outputFileName;

                        sArcPath = batchArchiveFolderName + Path.DirectorySeparatorChar;

                    }

                    else

                        throw (new Exception(“Invalid batch archive folder name.”));

 

 

                    foreach (object myObject in someCollectionOfJunkFromThisBatchStuff)

                    {

                        DoEvenMoreStuffIncludingForkThreadsWriteFilesAndOtherStuff();

                        try

                        {

                        ParsingAndDoingOtherStuffWithFiles();

                        }

                        catch (Exception ex)

                        {

                            DoStuffJoinThreadsCloseFilesWriteErrorLog();

                            continue;

                            //this.Close();

                            //return;

                        }

 

                        DoStuffJoinThreadsCloseFilesWriteErrorLog();

 

                    }

                    if (cnt == batchDataCollection.Count)

                    {

                        WowWeWereCountingAndItLooksLikeWeGotItAllBuildAMessageAndDisplayItToUserOhWellIfItWasNotAllDoneWeLeaveTheUserHanging();

                        MessageBox.Show(arcBatMsg, “Archive”, MessageBoxButtons.OK, MessageBoxIcon.Information);

                        this.Close();

                    }

                }

                else

                {

                    MessageBox.Show(“Error! Invalid batch file specified. “, “Error”, MessageBoxButtons.OK, MessageBoxIcon.Warning);

 

                }

            }

            else

            {

                MessageBox.Show(“Specify a folder for storing the new archives. “, “Error”, MessageBoxButtons.OK, MessageBoxIcon.Warning);

            }

        }

        else

        {

            MessageBox.Show(“Specify a valid file for archiving in batch mode. “, “Error”, MessageBoxButtons.OK, MessageBoxIcon.Warning);

        }

    }

    catch (Exception ex)

    {

        MessageBox.Show(“Batch Archive not created. “ + ex.Message, “Error”, MessageBoxButtons.OK, MessageBoxIcon.Error);

    }

}

If this code looks familiar to you, then you have my deepest sympathy.

If you aren’t sure what is wrong with code like this, then please, seek help.

I should be clear. Each of the longly named methods like DoSomeStuffWithBatchFile and DoSomeOtherStuffWithResultsWhichMayNotExist are of my own creation. This is where I removed between 50-200 or maybe more lines of code from this method. Yes, this is one method. The above has a Maintenence Complexity of 218. The original which I gutted has an MC of 1657. It isn’t even the highest MC in the application. I don’t have to look at the 2188 scored method that is a Windows Form clicked event handler.

 

Current Frustration Level: Moderately High

Current Amusement Level: Very High

Current “Wow, now I understand the frustration of others” Level: Record High

Anyone can write software. It probably won’t be maintainable.

A Proposal to Revise Maintenance Complexity Ideal Score Table

When Mark Miller introduced his new Maintenance Complexity metric, I wasn’t immediately in awe. I thought I would prefer Cyclomatic Complexity. I was wrong.

I’m looking at a small project with a couple of simple bugs which was thrown at me yesterday. I’m recognizing the “Ultra-complex method. Extremely challenging to maintain. High priority for simplification” interpretation of the 1000+ MC score.

Mark’s original table is pretty good.

MC Score Interpretation
<= 100 Simple method. Easy to Maintain.
101-200 Medium method. Relatively easy to maintain.
201-300 Large method. A little more challenging to maintain.
301-600 Complex method. Strong candidate for refactoring.
601-1000 Very complex method, challenging to maintain. Should be broken down.
1001+ Ultra-complex method. Extremely challenging to maintain. High priority for simplification

 

I propose a revision to the table.

MC Score Interpretation
<= 100 Simple method. Easy to Maintain.
101-200 Medium method. Relatively easy to maintain.
201-300 Large method. A little more challenging to maintain.
301-600 Complex method. Strong candidate for refactoring.
601-1000 Very complex method, challenging to maintain. Should be broken down.
1001-1499 You may want to find the person who wrote this and invite them to your local .Net User Group. Buy them Object Oriented Programming for Dummies. Make them read Code Complete. Make them browse, read, and submit patches to known good open-source projects. Try your damnedest to make them understand single responsibility and separation of concerns principles.
1500-1999 Suicide might cross your mind. You KNOW that it would be better to scrap this bit of code and rewrite, but then you would have to take responsibility for it and you would be stepping on peoples toes. You want to find the person who wrote this and strangle them and ask them WTF they were thinking.
2000+ Go postal. Find the original author and smash their fingers until they look like Sparks’s fingers in Der Dieb. Optionally treat them like Sparks’s until “It hurts really bad where…”. If this is foreign to you, study up on Sealab 2021.

 

If anyone could help me with other interpretations of high MC scored methods, I would appreciate it.

VIM Regular Expressions are the ugliest

PCRE is beautiful by comparison.

Here is a good reference:

http://www.geocities.com/volontir/#substitute

I wanted to basically Perl -pie ‘s/_(\w+)/<\1>\0<\/\1>/’  It is kinda ugly, but it isn’t too bad if you know regex.

In VIM, the + modifier and the grouping parentheses require escaping as well, so it turned into this:

:’<,’>s/_\(\w\+\)/<\1>&<\/\1>/

WOW. The only things not prefixed with a backslash in that regex is _, <, >, and &.

My head would be spinning, but I’m too happy that I got VIM to do what I want.

find files by date

I previously wrote about how I don’t like the find in Solaris and a work around. Well, I recently had to dig up the same work around on MacOSX, so I guess I hate it and BSD Find command equally as much as Solaris. Go GNU FIND!

The GNU find command which I like so much is this one:

find / -printf “%T+ %s %u %t %i %p\n” | sort -nr | less

It finds all the files on my system and shows me them sorted by date! I do some Unix systems administration part time contract work. When someone else was changing things on a system, this command comes in very handy to find out what was changed and when.

Of course any find expression will work with the given command so tacking on -xdev -type or anything else makes a lot of good sense.

WCF Service Host implementers beware

Jon Flanders has a great and very detailed post about implementing your own ServiceHost by extending ServiceHostBase instead of ServiceHost when using WCF.

He points out what I believe to be a serious flaw, not with the design of WCF and ServiceHost, but rather the implementation of the two. It turns out ServiceHostBase relies on specific behavior of ServiceHost. This is a typical OO no-no. Jon describes it very well and calls it a “magic method”. I just call it a mistake.

It is disappointing to think that there was not a CanInheritFromServiceHostBase test case out there in WCF-land somewhere. <snarky>I guess it was too difficult to write with mstest, and they weren’t allowed to use NUnit or MbUnit</snarky> :)

update: A link to the post would be helpful. :)