2004-08-25
| Rate This Article: | Add This Article To: |
Let's face it, no matter how carefully we design, how diligently we test, we're bugged. Pretty much every piece of software has its — shall we say — Moments of Interest, when something goes kaboom.
It's a fact of life. Unless a program does absolutely nothing, it probably contains bugs. Big bugs, little bugs, hairy bugs, small, fuzzy and rather silly bugs. The trick is to manage those critters and get them fixed if necessary.
The management starts, believe it or not, at the application's design stage. You've got to plan for insect-stomping.
Edward Jezierski, one of the architects in Microsoft's Patterns and Practices group, suggests that developers think about versioning early on. Segment the code appropriately to allow for clean updates. His nine-step plan for designing maintainable code may not be rocket science, but it can go a long way towards building a patchable application.
Jezierski's Nine-Step Plan
- Identify versioning packages (what would change together, what would not).
- Identify variability points (separate interfaces from implementation, use design patterns such as strategy, plug-ins, etc. to separate concerns).
- Identify sensitive areas (e.g. you need to be very responsive to a security update, so don't lump code that deals with security into something everything depends on, allow yourself to version that independently).
- Separate out components that have high dependency on platform components that may change.
- Plan and test deployment and rollout of updates. Choose a packaging scheme early, and include its building and testing into the app development lifecycle.
- In a business app, define and stick to your layering schemes.
- Use unit, functional, integration, etc., testing, and keep the testing practice alive. Testability is an important aspect of maintainability.
- Keep the environment alive. Building unit tests, automated tests, and everything to verify correctness of the application is worthless if, after the first deployment, it is archived and lost. Recommended: having a Virtual PC with all the test and build environments set up for an app/library, so it's easy to "rehydrate" all the environment by any team member, especially in smaller organizations.
- Build patches cumulatively. Branching or doing private builds is an issue. Things start breaking, and a neighborhood with one broken window soon has many.
Once the basic design is complete, think about bug reporting. How will it occur? How will you accumulate the reports, so you can decide what needs patching, and how do you do it in a disciplined way?
Those items have to be in the design as well. Jezierski suggests the following steps:
- Use a logging and instrumentation strategy that helps the right audiences acquire relevant and actionable information.
- Use a pluggable scheme to determine the destination of these events: files, WMI, localized event logs, centralized databases.
- Use instrumentation messages with schemas to allow easier processing and automation of tasks by operators.
- Choose exception management boundaries carefully, implement instrumentation throughout the application, and make it an up-front design (not an afterthought).
- On the back-end, send a subset of events to developer databases where they can be analyzed for later analysis.
Once all the design is done, coding can begin. But don't forget the basics, such as comprehensible error messages. This application may outlive you, and cryptic messages whose meaning exists only in your brain are not useful to the helpdesk folks who have to troubleshoot them, or the poor soul who has to fix the problem.
And, yes, Real Programmers do write commented, structured code!
Okay. The app is deployed, and the reports are in. There are, users have discovered, bugs in the application, despite careful design and testing. What now? Which ones do you fix?
Some of these decisions are, necessarily, business decisions, not technical ones. Which problems impact the business, and with what severity? A critical fix is not required just because the VP of Finance doesn't like the font on his reports, for example, but a security hole warrants immediate attention. Establish procedures for deciding what gets patched, and when; don't let enthusiastic folks just rampage around "fixing" things. Document, document, document.
Think about how the patch will be distributed. Idiot-proof is best — a self-installing fix that can validate itself and examine its environment so it installs the right components for the platform — but patching can be as simple as copying a file. The ultimate methodology depends on factors like who will be installing the patch (minimizing user involvement is usually safest), how many systems need patching, how complex the process is. You don't want users hacking the Registry, for example.
Whatever your decision, test and test again. Someone, somewhere, will break the patch, or the patch will break the app on their system. Your job is to minimize that possibility.
Don't distribute the patch to all users at first; try it out on a controlled subset first. Make the operations atomic, with undo. A patch that goes bad is more easily forgiven if the user can recover.
An insider tip from support folks, courtesy of Jezierski: "Provide a 'nuke' script to the support team, that erases all traces of the app on the box, and a 'probe' script that simulates the app by accessing the same resources in the same way."
And what is the most common blooper in patching? Here's Jezierski's take, from painful experience:
"Not planning or testing for it. By the time the first line of code of the patch is written, most of critical decisions have been taken.
"Not long ago, we had to update the Updater block to work with BITS 2.0, a platform component that had changed with Win XP SP2. So we built the appropriate plugin for BITS 2.0. What we didn't think about was that customers would need the same versions of the app rolling out independently of SP2 rollouts. So we had to build a small shim to the plug-in that decides whether BITS 1.0 or 2.0 is on the system. I guess the obvious corollary is: if a patch helps with a platform change, don't assume everyone needs it, and test the patch on the old system as well. I feel slightly dumb telling the story (hindsight = 20/20), but it was our recent experience."
See - you are not alone. Everyone puts his foot in it from time to time and has to patch.
Fortunately, there are lots of online resources to help out in the patching process.?For example, Microsoft's patterns and practices team, with strong participation from the developer community, provides tested reusable components called Application Blocks, provided as source, for you to use. So get out there and stomp those bugs.
Online Resources
- The Patterns and Practices group home page: http://www.microsoft.com/practices.
- A few samples: there's the Updater Application Block that helps applications have self-update capability: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/updater.asp
- There's Click-once, Microsoft's strategy for this technology: http://www.windowsforms.net/FAQs/default.aspx?PageID=3&CategoryID=24&SubcategoryID=27&tabindex=2
- Blocks that help in dealing with exceptions can be found here: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/exceptdotnet.asp
|
![]() |
|


