November 6, 2008
@ 08:39 PM


 
Categories: Commentary | Performace | Random

October 22, 2008
@ 10:12 AM

I have been getting hounded by our webmaster to supply a bio for our company bio page. Here is my first stab at it:

Bobby Johnson is a Senior Development Specialist and joined Alliance Enterprises in September 2008. Bobby is an Agile fanatic, Domain Driven Design enthusiast and Unit Testing maven who is not afraid to run with scissors. Bobby attended Southwest Missouri State University prior to bailing out to seek fame and fortune. He previously could not be contained by the Washington State Department of Labor & Industries or the Red Wind Casino.

I'll update when when the actual bio goes up.

UPDATE: Here is what actually hit the page:

Bobby Johnson is a Senior Development Specialist.  He joined Alliance Enterprises in September 2008. Bobby is involved with the implementation of the agile approach to development and also developing Unit Testing for the AWARE system.  Prior to joining Alliance, Bobby worked at the Washington State Department of Labor & Industries as a  Development Specialist.


 
Categories: Commentary | Random

August 21, 2008
@ 09:34 PM

IMG_0157

If you don't know why, you are dead to me. I couldn't get a fanboy picture of myself with John Lam, but this totally made up for it.


 
Categories: Events | Local | Random

 Taken in Blijdorp Michael Feathers, the amazing author of Working Effectively with Legacy Code, posted recently about technical debt.

What happens to code when you don’t refactor?  Anyone with any experience knows the answer.  It gets messy.  It becomes hard to change and the rate at which you can add features slows to a crawl.

I was on a project that inherited a tremendous amount of technical debt. The motivating force for the original team was meeting a hard deadline. As the deadline approached development process crumbled. Hero developers shot from the hip. Corners were cut. Non-critical bugs piled up. Quality was sacrificed to meet the deadline.

The technical debt was put on the American Express.

At the end of the project, the resulting application had a week long eventful launch full of rapid critical bug fix releases. The application was eventually brought up to an acceptable level of performance through Herculean effort of very skilled and talented people.

The technical debt bill was left ignored.

The following project cycle a new team was introduced to the application. A feature set to be added was defined. A deadline was set. A new requirement was added. All new features would have a emphasis on quality. No defects would be added to the already limping system.

The technical debt went into Universal Default and the APR was bumped up to 29%.

The team began moving forward except this time the business actively using the system kept running into critical issues that the team had to quickly deal with. The short cuts taken by the previous team became direct roadblocks to the new features slowing the implementation down. Each new line of code had to make sacrifices to work around quirks in the code base.

The 800 pound technical debt collection gorilla started calling demanding payment.

After a year of use the sheer size of the technical debt in the database caused leaks to spring which cascaded outward through out the application. New releases were viewed with dread by the entire organization. The DBA's were not happy. The help desk was not happy. The users were not happy. Morale on the project was through the floor.

The 800 pound technical debt collection gorilla had frozen all assets and put a lean on the house.

You can put that debt on the card. You can ignore it and buy some time. But eventually that gorilla is going to find you, climb on your back and beat you down.

Photo Credit:  Ruben Bos


 
Categories: Commentary | Development | Random

Over the course of the last couple months I have been working diligently to migrate the application I inherited from the wild wild west of unmanaged corner cutting contractor land to the happy kingdom of semi-intelligent source control.

I have successfully migrated what we have come to know as "what we think production is built with" source in to Team Foundation Server source control, cleaning up along the way. Why exactly this particular batch of contractors felt it was necessary to include references to both the 2.0 and 3.0 Enterprise Application Blocks, I may never know. I suspect they felt it was 2x more "Enterprise-y".

Next up on my path to Agile Nirvana, I whipped up a set of build scripts that produce a consistent build every time. Imagine that! My server support people are so happy with me.

The system I am working on is somewhat interesting. The application went live last summer and was officially handed over to a group of maintenance developers. A new project was immediately started to add new functionality while the maintenance guys fixed up bugs. I currently work with the New Development group.

The maintenance guys decided they wanted in on all this awesome TFS goodness. So I spun them off a branch and let them go on their merry way. That was until they decided they were ready to start rolling forward into production.

That is when I realized that all of my build scripts no longer worked. I would fire up a build using Team Builds in Team Explorer, it would do it's thing pulling down source code and firing off MSBuild to compile and then throw errors.

I checked on the build server in the location where source is downloaded and Team Build was no longer pulling down the source for my Main branch. The only thing be retrieved from Source Control was my Branches directory. Obviously the dirty maintenance branch hosed by lovely build process.

I checked my build definitions and mapping files. My source tree looks something like this:

$/PROJECT
..Branches
    ..2.0.1.0-APPLICATION-branch
..Main
   ..Framework
   ..APPLICATION
   ..Samples
   ..Utilites
..TeamBuildTypes
The 2.0.1.0 node is a branch of $/PROJECT/Main/APPLICATION. My workspace mapping pretty much looks like so:

<InternalMapping ServerItem="$/APPLICATION" LocalItem="flibbityjibits" Type="Map" />

I have a few cloaked paths as well all related to $/PROJECT/Main/Something. When I execute my Team Builds Branches and TeamBuildTypes are retrieved from source control and Main is ignored.

My buildlog shows that CoreGet is retrieving the latest:

Get Version="T" Recursive=True Force=True Workspace="NinjaWarrior"

There was something I was missing here. I shot off an email to the Seattle ALT.NET mailing list, more in a effort to articulate the issue well than expecting them to solve my issues or anything. Kinda just getting it all out as I understand the issue for the eventual call to tech support.

I went home that night utterly devastated that my painstakingly lovingly crafted system had failed so spectacularly.

At home I was playing some Lego Indy with the wife on the Xbox and letting the subconscious work on it. And finally the light bulb went off.

I have other branches in the Branches folder that caused no problem when they were created. I thought to myself, "Self, it's not the branch that did it.. It must be something that you did at the same time you created the branch."

My assumption about the branch breaking my build came directly from my Jump To Conclusions Mat.
I created this branch for an external group who is adding functionality. In an effort to keep my main pristine, I locked it down so that only members of the group "Tech Leads" could check in to Main.

This had to be the cause.. when I realized it last night I almost went back in to work... but come on its Lego Indy!

So I get to work this morning and checked the membership of "Tech Members" and surprise, surprise... TFSService is a member... The build service uses this account to access TFS...

So I quickly added it to the leads group and verified that my builds worked again and went to repair the dent I put in the wall from beating my head against it.

So Lessons Learned here:
1. Respect the build user, he can make you a very sad panda.
2. I've automated the build, its time to get a nightly build going so these changes are fresh in my mind when stuff breaks.
3. While I am at it might as well look into setting up CI to the Dev environment with the nightly.
4. Indy really can accomplish anything.

So in the end, I created my own problem. Thanks to all the ALT.NET mailing list readers for silently laughing at me while I verbalized (textualized?) the issue on the mailing list and worked through it.

I'll be here all week.


 
Categories: Development | MSBuild | Random

The closer your documentation gets to a static Microsoft Word Document, the farther away from current it becomes.


 
Categories: Random

I recently laid my hands on a copy of DevExpress' Code Rush and Refactor! Pro. They have a section on their site that allows you to watch training videos about these products. I wanted to watch them all but at my own pace and on my main TV in the living room.

Using  my new toys I whipped up the following code to download all of the movies from their site. Now I just need to convert them to AVI so I can watch them on the Xbox.

Code included just because I want to:

using System;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Net;

namespace SnagDevExMovies
{
    class Program
    {
        private static WebClient client = new WebClient();
        private static Uri site = 
                new Uri(@"http://www.devexpress.com/Products/NET/IDETools/CodeRush/Training.xml");
        private static UriBuilder siteResource = new UriBuilder(site);
        
        static void Main(string[] args)
        {

           string content = getContent(site);
           MatchCollection URLs = getMatches(content, 
                new Regex(@"bWatchExpanded.*LessonNewWindow\('(?<URL>.*)'\)"));
           processMatches(URLs);
        }

        private static void processResource(Uri uri)
        {
            Debug.Assert(uri != null, "uri is null.");
            Debug.WriteLine(String.Format("Processing: {0}", uri));

            string content = getContent(uri);

            MatchCollection URLs = getMatches(content, new Regex(@"(?<URL>\w*\.swf)"));

            if (URLs.Count > 0)
            {
                siteResource.Path = getResourcePath(siteResource.Uri) 
                        + URLs[0].Groups["URL"].Value;
                downloadFile(siteResource.Uri);
            }
        }

        private static MatchCollection getMatches(string content, Regex expression)
        {
            Debug.Assert(!String.IsNullOrEmpty(content), "content is null or empty.");
            Debug.Assert(expression != null, "expression is null.");

            MatchCollection matches = expression.Matches(content);
            Debug.WriteLine(String.Format("{0} matches found.", matches.Count));
            return matches;
        }

        private static void processMatches(MatchCollection relativePaths)
        {
            Debug.Assert(relativePaths != null, "relativePaths is null.");

            foreach (Match item in relativePaths)
            {
                siteResource.Path = item.Groups["URL"].Value;
                processResource(siteResource.Uri);
            }
        }

        private static void downloadFile(Uri uri)
        {
            Debug.Assert(uri != null, "uri is null.");

            Debug.WriteLine(String.Format("Downloading: {0}", uri.ToString()));
            try
            {
                client.DownloadFile(uri, getFileName(uri));
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }

        }

        private static string getResourcePath(Uri uri)
        {
            Debug.Assert(uri != null, "uri is null.");

            string resourcePath = uri.AbsolutePath.Substring(0,
                                uri.AbsolutePath.LastIndexOf("/") + 1);
            return resourcePath;
        }

        private static string getFileName(Uri uri)
        {
            Debug.Assert(uri != null, "uri is null.");

            return uri.Segments[uri.Segments.Length - 1];
        }

        private static string getContent(Uri uri)
        {
            Debug.Assert(uri != null, "uri is null.");

            string content = client.DownloadString(uri);
            return content;
        }
       
    }
}

 
Categories: Development | Random

April 15, 2008
@ 05:26 PM

I recieved a fully licensed copy of Office Ultimate 2007 (Retail $454.99) last night at the Olympia Code Trip event. I would like to trade it straight across for a copy of Code Rush (Retail $249.99).

If you are interested please, feel free to contact me.

UPDATE: Trade made to Dylan in Issaquah. Thanks Dylan.
 

Categories: Local | Random

March 25, 2008
@ 10:23 AM
So I needed a sample post to see how my layout is looking before I start to insert content. When I worked tech support for Adobe way back in the '90s, every one Lorem Ipsum in their designs to simulate text. Through the power of Google, I found a nice generator for Lorem Ipsum and this is my sample post that I have now turned into an actual post.

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.

Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.


 
Categories: Random