Monday, June 07, 2004

Instant Insanity

One of my coworkers is attending a “Creativity Class,” and he brought over a puzzle made from blocks of wood. Essentially there are four cubes. Each side of the cube is painted with one color out of a palette of four colors. The object of the puzzle is to arrange the blocks in a single row and have only one of each color present on each of the four sides of the column of blocks. You may get a better idea of this visually.

Being in a group of people intrigued by riddles and puzzles, we attempted to solve this puzzle. After about 30 minutes, we gave up on it for the day. Thanks to Eric Lippert, I am now re-interested in writing algorithms. So I wrote one to solve this problem. It would have taken less time to have written the algorithm in the first place.

My solution is iterative, although a recursive solution is easier. I’d encourage anyone to try writing some code to solve this one. In a few days, I’ll post some comments as to the mathematics involved and give my solution. Go ahead and use the colors from the link above as a starting point.

What is Excellence in Software Development?

I recently attended an awards banquet, and after thinking about the events that transpired, I had to sit down and write this entry. One of the VP’s who was honoring the award recipients had a great concept buried in his speech that I am now paraphrasing – that we need to recognize everyday excellence, not just the people who are acting in “Firefighter mode.”

What are “Firefighters?” In any company this type of stuff happens more than we would like to admit. The situation may be a big demo. Six hours before the demo, your equipment arrives. What remains of the shipping crates looks like it was used as landing gear for the transport plane. After selling your soul to the devil, you manage to replace the damaged equipment with parts from an automatic toilet flush valve and pull off a successful demo. Is this excellence? Sure. Is this everyday excellence? Hopefully not. Stories of Firefighting make for great press, but are usually not indicators of overall excellence.

Shortly after the firefighting speech, a video was shown of an individual praising a particular developer. There were some great one line examples of this individual’s abilities – and the person was truly deserving of the award based on these alone. What got most of the video time was related to this developer’s rewrite of what was accepted as a truly terrible piece of code. We have a typical story here: Developer worked more hours in a week than most work in a month to get the rewrite completed. Is this a sign of Excellence, or is it an example of Firefighting?

My answer to this question is a resounding NO for both. If you have to work excessive hours for days/weeks/months on a scheduled project, it is the exact opposite of excellence. In industry terms, this is known as a Death March. Someone, somewhere screwed up bad. Perhaps it was the design. Perhaps it was the implementation. Maybe the fault was in the management expectations. Regardless of cause, this is a huge, flashing neon sign that something is horribly wrong. Perhaps we all need to read (or re-read) Debugging the Development Process: Practical Strategies for Staying Focused, Hitting Ship Dates, and Building Solid Teams by Steve Maguire. In my personal experience, EVERY project that required long hours by the developer ultimately failed for a multitude of reasons and with a multitude of negative outcomes:

  • QA is often scrunched to get the project out the door.
  • Because of the above, there are serious undiscovered bugs that get shipped.
  • The resulting code is difficult to maintain.
Although I have no personal experience with this project and its outcome, anecdotal reports from people I spoke with confirmed the above bullet points. There are plenty of references to this topic, most of which are buried in research and justifications to development methodologies known as “agile.” While describing agile methodologies and concepts is outside the scope of this entry, one interesting paper worth a read that supports my assertions is Estimation as hypothesis, by Alan Shalloway. I highly doubt that anyone would want to encourage this type of coding behavior by using it as a justification for an award! Although up until now I have covered what is NOT excellence in Software Development, but I have not covered what IS excellence of the everyday kind.

Boneman’s Principles of Software Excellence:
  • Know your customer - This is an extremely vague topic, but if you are developing software that provides simplistic configuration of widgets for Biscuit Welders, and most Biscuit Welders have a preschool education, your interface and documentation must reflect that understanding. This may involve following your customer around during one of their typical workdays to understand their job and their workflow. Any employer that does not allow, encourage, or suggest this during a new employee orientation and thereafter as required is not worth working for.

  • Know and follow best practices - These days, security is a primary concern. Does your application comply with industry best practices? Do you know that such things exist? When was the last security related continuing education session held at your organization. If this answer is greater than one month ago, the developer with the most excellence will be scheduling one – hopefully this person is you.

  • Compliance with current industry coding standards.

  • Evangelism - Are you talking up industry standards and best practices with your teammates? Are you using code reviews as opportunities for education and not as a forum to criticize? Do you even have code reviews?

  • Non-use of Programmer Quotes - You correct (harshly but constructively) any developer who utters one of the quotes found on this page because your code understand that all user input, data, or machines are evil until proven otherwise.

  • Take the blame - If you get a call from a support person, it is almost always your fault, and you admit it. Most often this is due to the lack of error checking or useful error messages in the code you wrote. Instead of merely answering the question or fixing the problem, immediately adjust the code in question to provide useful feedback to the user. While you are at it, you write a Unit Test that exhibits this behavior.

  • When you are stuck, you admit you are stuck - If you are behind schedule, you immediately admit it and ask for help. Recognizing that you or your project is in trouble is the first step, asking for help is what separates the men from the boys. Remember that you are part of a team. Even if you are the sole software developer in the organization, you need the support and understanding of your team to get through any coding crisis. This does not make you any less of a programmer, in fact, the ability to admit you need help will earn you my vote for a place on my team, anytime, and anywhere.

  • Check with the helpdesk, implementation, and training personnel for issues related to your code - Every successful pro athlete reviews his or her performance on video after the big game. Why? So the athlete understands what they did right, and what they did wrong. In the world of software, all of the above listed people are the first line of customer contact. If your code nailed the extremely complicated but infrequent widget refactoring process you stayed up late thinking about, but bombs when previewing the daily report unless the user is wearing a green hat, you need to know this, correct this, and put into place a process to prevent these simple but frequent (not to mention annoying) bugs from happening in the code you are writing today.

The above is not even close to a comprehensive list, but rather what was on the top of my head as I created it. Sadly, I can’t think of a single person that within the last six months has actually lived up to this list, including myself. It looks like some things are going to change around here – and for the better. Please feel free to add to this list in the comments below.

Sunday, June 06, 2004

Custom actions that should be standard actions

On the MSI front, Aaron Stebner from Microsoft posted a list of Common custom actions that should be standard actions. It is a fairly good list. Please check the link and add to the list!

Aaron is quite correct that writing a solid (read best practices compliant) custom action is difficult. Number 3 on his list is "Create user accounts." If you need to do this, make sure to check the Platform SDK, as well written sample code for this action is included.

I'm going to head over and add my two cents to the list...

Thursday, June 03, 2004

VBScript (and Jscript) MSI Custom Actions (don't have to) suck

One of the greatest things about blogging and its popularity (especially at Microsoft) is that you can get solid information and advice straight from the horse's mouth. In the Windows Installer world, the sole blogger at Microsoft (that I am aware of) is Rob Mensching. A recent post by him entitled VBScript (and Jscript) MSI Custom Actions suck was one that struck some discord with me.

Script custom actions do not have to "suck," contrary to what Rob points out. I prefer to use the KISS concept. There are several concepts that ANY developer, REGARDLESS of using script or C++ Custom Actions must understand.

  • Debugability - If this is a real word, it would mean the ability of an individual to debug the Custom Action. In C++, use of DebugBreak() after attaching the debugger to the process is a simple way. In script, I have not found any way of attaching a debugger to a Custom Action (if you know of a way, that would be a great feedback point). In either case, it is difficult, if not impossible, to debug a Custom Action gone bad in the field. Turning on logging, with judicious use of Session.Message is one tactic regardless of Custom Action language. As an aside, I don't understand why the MSI does not allow the author to specify some minimum level of logging.
  • Understand your Lowest Common Denominator (LCD) - If you are attempting to instantiate an ADO object on an otherwise vanilla NT4 machine, you deserve what you get - a failure. If the application you are trying to install requires something, make sure it is already installed via a LaunchCondition, or that it is going to be installed. If you depend on it in a Custom Action, make sure the install action takes place BEFORE you attempt to use it. In the C++ world, a missing dynamic link library such as MFC could get you into trouble...
  • Use the right language for the job - Lets say you ignore Rob's advice and make a script custom action to use ADO. Some ADO objects take variables by reference. VBScript supports this, JScript does not. This is no different from the debate on which language you used to code your application. You can code yourself into a corner using the "easier" languages, but on the other hand C++ can sometimes be overkill.
  • Other Considerations - With the plethora of third party software and networking techniques in use today, a developer must be fluent in new technologies. It is uncommon for a system to have no virus/worm protection. Products such as Symantec's Norton Antivirus have script blocking technologies to block against certain objects being instantiated in script that are typically used in worms and viruses. Instantiating the FileSystemObject will likely fail on systems with this type of protection. If your script is dependent on actions or objects outside the Session or Installer object, I would suggest using only C++ CA's to ensure the installation does not suffer in the future. Additionally, some firewalls prevent applications from accessing the internet (even XP SP2). If your setup uses or relies on these capabilities, be aware of the target audience and its possible setup.

Rob's assertion that a robust script Custom Action cannot be written is indefensible. I can (and surely have) written unrobust C++ Custom Actions. The beauty of software development is you can be as robust as you want to be, no matter the language. You, as the Custom Action author, are responsible for providing a meaningful error messages that can direct the user to the appropriate action to get the installation to work correctly.

To play Devil's Advocate, one point against script custom actions he didn't make include obscurity. Since MSI is easily decompileable, and the scripts can easily be viewed, edited, and replaced, it is likely there are some things you would like your competition to devote more time to reverse-engineering.

InstallShield provides its own scripting engine that can be used in Custom Actions. Although there is additional debugability and no antivirus blocking concerns, be aware that the size of the MSI increases (it has to install the scripting engine), and you are locked into InstallShield until the action is rewritten. I was able to quickly migrate almost everything from Wise for Windows Installer to InstallShield because I stuck to the MSI standards and ignored Wise's custom functionality. Better yet, I can move back if Wise leaps in front of InstallShield.

Welcome (or something like that)

This blog is dedicated to random musings in software development and related topics I (or you the reader) may be interested in. I hope I don't receive any death threats though...

A bit about myself... I am a software developer for a Fortune 500 company (not that it gives me any credibility :) specializing in software deployment technologies and enterprise application management, although I do other stuff as well. In a typical day I may have several applications open - Visual C++ 6.0, Visual Studio .NET 2003 (C++ and C#), Source Safe (yuk!), Wise 9 (double yuk!), InstallShield DevStudio 9, Visual Build Pro, and SQL Enterprise Manager.

As far as development, my current areas of development include MSI (Windows Installer), and the Win32 API. The MSI stuff is mostly Custom Actions in both C++ and script. The Win32 stuff is mostly remote machine management in nature. Since there is no Blogging policy in effect at my employer, I prefer to not be more specific.

In my past, I have done lots of cool stuff related to audio fingerprinting and recommendation, and some general algorithm work. This was done in a cross-platform manner to work on both Win32 and Linux systems, using wxWindows (now called wxWidgets) for UI work as necessary. On Win32 we supported both WinAmp and Windows Media in addition to MP3 and other generic audio types.

Since this is more or less an open blog, please feel free to suggest topics of interest that you may want me to rant about. Welcome and thanks for reading!