Papa’s got a brand new blog

"The Godfather" by Kathy Mackey Welcome to the new ViNull.com!

-ed. This post was originally titled “Meet the new blog, same as the old blog” but the Who references have been many and the Godfather demands equal time.

Aside from the ascetics and no longer digging the old design, the main reason for the new site is the economy.  No one is safe from layoffs, myself included, and while I haven’t been affected so far only a fool would say his job is safe right now.  Since it’s rare that I can show someone the latest code I’ve been working on (owned by a company and all), I use my blog as the resume – so this is really about updating the resume.

Quick hits – tagging works!  This has been a long time coming, but you can now click on a tag and find other posts with the same tag.  Tagging also helps drive the “Related Posts” feature when reading a post.  Gone are categories, though behind the scenes they add links to the code and speaking sections while also helping “Related Posts”.  A new search is powered by Lucene.Net, which currently indexes post bodies only.  This will change over time as I add in tags, titles, and comments, but I want to be careful here as weighting search engine results is tricky at best.  Oh, the data access layer is now fully cached for performance.

I plan on blogging a series of posts covering all the code under the hood, but if history (and this blog) is a judge, I’m very bad at following up on promises made in a post.

To finish up, I had to go back and tag all my old posts.  This made for a fun trip down memory lane. Terra Naomi’s album is now out and on Zune Pass (listening to it now).  I’m okay with changing my opinion over time, as Keynes said “When the facts change, I change my mind.  What do you do, sir?” (Interestingly he said this in regards to changing his stance on economic policy during the Great Depression).  Still, it’s nice to see I still agree with myself sometimes.

Other things I noticed:

You would think I rant against Apple the most, but looking back it’s Sony who get’s my ire. 

Charles Petzold is worth his own tag. 

I didn’t make a birthday post at 32. 

I still find this funny.

And this

You might think this post is the one I would delete first (if I deleted embarrassing posts), but actually it would be all those posts I fancied myself a poet and writer.  (Though, like many writers, I fail to understand the draw of my biggest success)

There is no danger of me abandoning this blog, as my reasons still remain valid.

Posted By Mike On Thursday, January 01, 2009
Filed under blog life | Comments (3)

ASP.NET SEO Interview on Polymorphic Podcast

image Craig Shoemaker just posted the latest episode of the Polymorphic Podcast: ASP.NET SEO - Interview with Michael Neel.  Yes, I've now appeared in a podcast that I didn't have a hand in recording!

Even if you don't listen to the show (and you should, Craig does an awesome job) check out the show notes.  SEO - or Search Engine Optimization - is one of those areas developers tend to overlook or outright ignore.  I think this is partly because it's not something we think about when knee deep in site code, but also because there is a stigma attached to SEO that it is dirty marketing stuff.  Truth is, a good design for SEO is also a good design for users and helps more people find what they need (I was glad to see StackOverflow realize the sitemap protocol is very helpful).

One thing I mention at the end of the podcast (at least I think it's the end - I haven't listened to it yet!) was the new support from System.Web.Routing to handle some of the code I have written myself in mapping urls to content.  Wally McClure has just recently posted an ASP.NET Podcast on Routing with WebForms that explains the new API.

Posted By Mike On Tuesday, October 14, 2008
Filed under podcast asp.net seo polymorphic | Comments (1)

Google Can You Hear Me?

Jumpin Pete! by Art Silva In June of 2006 I wrote an article titled "Google Can You Hear Me? How to design URLs that are search engine friendly" that also included a sidebar titled "The Worst Framework Bug You'll Ever Meet".  I've linked both of those to PDF versions of the article, as it appeared in the Marck 2007 edition of ASP.NET Pro magazine.  I've also uploaded the example project and code (C# and VB) that was available to download with the article.

When checking out the code, please keep in mind this was June of 2006 - ASP.NET 2.0 was still pretty new and we were all wondering which AJAX framework was best.  I was young then and life was easy - the Dow Jones Industrial Average was 11,000.  There are better ways to write a SiteMapProvider but the main point of the article - generating pretty URLs that get eaten up by search engines - is still just as valid.

Oh, the nasty framework bug that can keep your site out of the search engines was fixed with ASP.NET 3.5 SP1 - if you're running anything less than the latest service pack spend some time digging into the reasons for this bug and how to test your site by reading Get GoogleBot to crash your .NET 2.0 site.

Posted By Mike On Saturday, October 11, 2008
Filed under asp.net seo sitemaps | No Comments

Finding the difference between two Arrays, or un-LINQ-ing your code

imageLINQ is great, up to the point when it's not.  Then it's really not great at all.  When we trade simplicity of syntax for performance, we have to keep in mind there may come a point when we have to go back the code and factor out the shiny new toys.

My system is complex, but this task is simple.  I have about 95,000 video files to keep track of in a database.  Try as we might, at some point someone is going to make changes, add or remove files, without going through our software, so a periodic file audit is required.

I have two lists of file names, one is the list as it exists in the database, the other as it exists on disk.  This is greatly simplified, but the initial idea was something like this:

List<String> toAdd = (from f in existingFiles
                      where !indexedFiles.Contains(f)
                      select f).ToList();

List<String> toRemove = (from f in indexedFiles
                         where !existingFiles.Contains(f)
                         select f).ToList();

The power of LINQ, short and sweet.  Sadly, it appears to act like this under the hood:

List<String> toAdd = new List<String>();
foreach (String f in existingFiles)
    if (!indexedFiles.Contains(f))
        toAdd.Add(f);

List<String> toRemove = new List<String>();
foreach (String f in indexedFiles)
    if (!existingFiles.Contains(f))
        toRemove.Add(f);

These statements pegged the CPU for minutes at a time - can you see why?  How many times am I looping through each collection of strings?  Twice? Four times?  No, I'm afraid this is classic "Oh 2 Da N" performance here.  The problems lies in using the Contains() method - this method must search through the collection each time it's called, which is often.  To solve this, we'll have to kick it old school C-style:

indexedFiles.Sort();
existingFiles.Sort();

for (int iE = 0, iI = 0; iE < existingFiles.Count || iI < indexedFiles.Count; ) {
    if (iE >= existingFiles.Count) {
        toRemove.Add(indexedFiles[iI]);
        iI++;
    }
    else if (iI >= indexedFiles.Count) {
        toAdd.Add(existingFiles[iE]);
        iE++;
    }
    else {
        Int32 diff = existingFiles[iE].CompareTo(indexedFiles[iI]);
        if (diff == 0) {
            iE++;
            iI++;
        }
        else if (diff > 0) {
            toRemove.Add(indexedFiles[iI]);
            iI++;
        }
        else if (diff < 0) {
            toAdd.Add(existingFiles[iE]);
            iE++;
        }
    }
}

A quick sort of the lists and we can make some time saving assumptions as well as walk through both lists at the same time (.Net had no trouble sorting lists of 95,000 strings in record breaking time).  We start off comparing the strings at index 0 of each list (the first if and else if will be false - I'll come back to those shortly).  If they match, then the file both exists and is indexed - go to the next file in both lists.  If the existing string is greater than the index string, then we know the file no longer exists (remember, lists are sorted).  In this case only advance the index list to see if it "catches up" with the existing list.  If the existing string is less than the index string, the reverse is done.  If we run out of existing list before we finish the index list, those files no longer exist - which is what the first if statement handles (the first else if handles the other case for running out of index list first).

If you have to work through this for loop on scratch paper, don't feel bad - I did.  It's been a very long time since I've had to get this "raw" with my code.  It was worth it as the performance went from several minutes at 100% CPU to so fast I couldn't believe it had run.

I googled a bit to see if there were other solutions out there, and more importantly some method in the .Net framework that would solve this issue and came up empty.  I'm not convinced there isn't something in the bazillion methods living in the framework, so if you know of something, please let me know!

Posted By Mike On Friday, October 03, 2008
Filed under developer linq | No Comments

Microsoft Most Valued Professional (MVP)

DSCF5380Yesterday I received an email that simply stated the following:

"Congratulations! We are pleased to present you with the 2009 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others."

I am humbled and honored to have received this award.  Though my reasons for being involved in the developer community are not about awards (even this one), I would be lying if I said I didn't want this award.  The photo here shows my "MVP shrine" I created after speaking at the Alabama Code Camp, which sits on my windowsill above my desk and serves as a reminder that I'm working through my chosen dip.

The shrine started out with just one Maneki Neko (Lucky Cat), holding up my business card.  I cut out the MVP logo from another MVP's card (sorry Jim), and taped it to mine.  Luck alone is never something I will count on (but a second Maneki Neko doesn't hurt), so I added He-Man for strength, and the studying wizard frog for his knowledge.  The frog doesn't know many programming languages, but he does know how to score with a princess, so I thought that was qualification enough.  Buttercup brings the fierce determination, and the Starcraft Marine stands guard so the group isn't caught off balance.  The last addition, courtesy of Cicelie, is a plaque that reads "ambition is a poor excuse for not having enough sense to be lazy."

There are many, many people to thank for helping me get to this point.  Wally McCulre nominated me to the ASPInsiders and helped a great deal with CodeStock, as well Glenn Zahn who offered up most of his staff to run the event.  I'm very grateful to the people who attended my sessions and talks, and for the questions and feedback that followed every session.  Nathan Blevins, Ed Schmidt, Walter Lounsbery, Dylan Wolf, and Lewis Frazer have all been great to work with on CodeStock and the .Net Users Group.  There are many more than I could possibly name, but there is one person I do want to call out in detail...

Alan Stevens helped me through the hardest part - getting started.  I had attended the user group for a few months when an email from Alan went out asking for speakers.  I had been doing a lot of work digging under the hood with ADO.Net DataSets and asked if it was a topic the group would be interested in - to which I got a classic Alan response, "any topic you're passionate enough to present, is a topic I want to hear."  Later, during the DevLINK call to speakers Alan asked if I had submitted to speak at DevLINK - which I hadn't, but he convinced me that I should.  It wasn't a case that I didn't want to speak, it was I didn't think my name would make the cut.  Alan vouched for me with something like, "John, you gotta give this guy a slot."   Once I had spoken at DevLINK, I had a "resume" in the speaking world and this is in big part due to Alan's help.

It's not over now, not by a long shot.  I still have no end to ideas and things I want to do with the community.  CodeStock 2009 will be great I have no doubt, but I want to help it be amazing.  The open spaces ideals have really sunk into me and I want to apply them in interesting and unusual places.  I'd love to see a Knoxville Give Camp, and most of all I'd want to pass on the help Alan gave me to the next developer out there who wants to get involved in the community.

Posted By Mike On Thursday, October 02, 2008
Filed under mvp | Comments (5)

About Me

Father and developer, I'm just a guy trying to figure out where I left off a semi-colon...

 Subscribe to ViNull.com |  Comments

Follow me on Twitter | Contact Me

ASPInsiders Member

ETNUG Member