Google Apps trail MS Office, but for how long?

googlemirror This morning, I read a blog post describing how to add page numbers to a Google Docs document.  The crux of the technique was to embed some HTML into your doc such that page numbers are generated when the doc is printed via PDF.  "That's it!" I thought.  That's why Google Apps aren't ready to take down MS Office.

googleprintdialogThen, this afternoon, I just happened (dumb luck, I swear) to use Google Docs to print a draft of an article I'm working on, and I saw this dialog with - you guessed it - an easy way to add page numbers.   And just like that, I saw the problem for Microsoft.  Google, it's true, isn't there yet, but they're closing the gap -- fast.

Microsoft is clearly working hard to neutralize the Google Docs threat with their Office Live Workspace, but I'll bet they're glancing nervously in their rear-view mirrors constantly.

Reblog this post [with Zemanta]

Bug fixes that are more than just bug fixes

It's that time again - time to go through the bug list and do some cleanup.  As I work through these bugs one by one, I've noticed that at least half of them end up being slightly more than just bug fixes.  As I crack the hood and peer in, sometimes I see that there's code inside that's not quite up to the standards of the rest of the application. 

When I see this, I generally try to fix the whole bug, and that means cleaning up (refactoring) the messy bits.  In some cases, you're working on an application that someone else wrote, and in these cases it's pretty easy to blame the mess on the moron who coded it in the first place.  But what if the moron was you?  How do you end up with code that needs this sort of attention if you wrote the stuff originally?  There are tons of great articles and books on refactoring, and they cover this area in much more detail, but here are some of the things you're going to run into when fixing bugs:

  • Code built upon code.  This is probably the most common reason for refactoring.  None of the code you wrote was wrong when you wrote it, but Agile development stresses development one feature at a time, and this sometimes means that you're going to add new code on top of old code and create situations where common functions need to be pulled out, base classes need to be created, and so on.  These things should really be done during development when the problem can be seen for the first time, but sometimes they're missed.  When you see these needs during a bug fix, don't ignore them - they won't go away on their own.
  • New patterns that haven't been implemented everywhere.  This is a similar concept on a broader scale.  Often, we find better ways of doing something during the course of a project - a way we want to organize code, a set of CSS styles that we want to implement all over, or something like that.  Again, we really should take the time to go back and retrofit all of our existing code when we agree on a new way to do something, but sometimes that doesn't happen.  And again, if you're working in a section of your application that was "grandfathered", take the time now to bring it up to spec.

Why bother cleaning up this other stuff if it was working?  For one thing, it's just the right thing to do.  If you don't take care of your code base in this way, your application is going to be legacy code before you go to production.  More fundamentally, though, is that the code probably wasn't working as well as you think if there are bugs logged against it.  Maybe the "old pattern" followed in this code is susceptible to problems that were fixed in newer code.  Maybe the code is more complex than it needs to be, allowing bugs to hide in the nooks and crannies.  Part of a good bug fix is to look for ways to prevent a bug like that from ever happening again, and very often, this means refactoring so that the "fixed" code can be painted onto the rest of your application.

There are times when you don't really want to rip up drywall in order to fix a surface blemish, of course.  If you're late in a release or making a production fix, you absolutely do not want to introduce any unnecessary instability.  This means you'll keep your fix as small as possible to limit the possibility of introducing new bugs with your fix.  Do yourself a favor, though - leave yourself a todo note in the code or a bug in your tracking system so you're reminded to go back at a more appropriate time and clean up.

The next time you fix a bug, take a little time to look around and look for the right fix - not just the quick fix.  You'll end up with a better code base in the long run.

Don’t bring an application home if you can’t feed it.

saddogsm About four months ago, I helped a client put an application into production.  This client has a mix of internal and external customers, and those customers are essentially captive (they have little choice about using this application).  As with any new application, there are infrastructure headaches, customer questions, training issues, and the like.

I was talking with someone today about a support issue, and I asked how they client was tracking calls, issues, and so on.  "Oh, we're not tracking them."  Ah.   And we talked about their customer service staff.  "Well, they're not so much customer service as they are department secretaries that take customer calls."  I see.  "But there's a help desk downstairs - I've seen it," I said.  It turns out that the help desk isn't staffed all the time.

Why?  No money.  And all the while, the customer calls are coming in, and the secretaries are doing what they can to help these poor customers, who don't have a choice but to keep soldiering on.

This organization is probably closer to the norm than we'd like to imagine.  It's pretty common, in fact, to look at the development price for an application and completely ignore the ongoing cost to maintain the system.

Purchased software is no less immune to this problem.  I've helped customers implement CRM systems, for instance, and a critical success factor is the ability an willingness for the customer to invest the time of their employees in the care of the system.  A CRM system is only as good as its data, and even the best systems require data maintenance and cleanup.  Duplicate records need to be merged, assignments need to be fixed, and dead data needs to be scrubbed.  Failure to invest in these activities will doom your system to obsolescence.

When your son or daughter wants to bring home a pet, most of us are comfortable explaining the responsibility of pet ownership.  "If you want a dog, you're going to have to take care of it."

But how many people apply this to their applications?

By the way, if you like the picture at the beginning of this post, check out http://www.imagechef.com/ - you can choose from dozens of stock photo backgrounds and add your own stylized text - pretty cool.

Do you know cause from effect?

I fixed a bug today - a bug that was introduced because a chunk of code was depending on side effects of another piece of code to work properly.  Depending on whether you're ever worked directly with a computer language, this may be a subtle transgression, but the problem is distinct and real, and here's the best part -- if you learn why this is a problem, you'll understand where this flawed thinking bites you in everyday business decisions, too.

So let's back up and look at a non-programming example. Let's say you go in to see you doctor because you're feeling under the weather. The doctor runs some tests and sees that your white blood cell count is higher than expected. A good doctor would know very well that there are lots of reasons this can happen, but someone a little less disciplined who's sitting at home playing "House, the Home Game" might shout out, "it's cancer!" before really having any evidence to support their crackpot theory.

Most of the time, mistakes like this are lots more subtle, but they always start with someone seeing an effect and thinking they know the cause. Sometimes, we guess and we get it right, but often, we don't.

How can we know when we've got it right? We need to relentlessly question the assumptions we make about the things we believe to be true. According to Alan Axelrod in his book, Patton on Leadership, Patton would frequently ask, "How do we know that?" His lesson is that we need to consider our sources of information, because some are intentionally misleading, others are unintentionally incorrect, and a few are reliable. If we can tell the difference, we're doing well.

Instead of asking, "how do we know," we could also ask, "why?" In a recent blog post, Joel Spolsky talks about his company's use of the five why's. Made famous at Toyota, and attributed for part of Toyota's legendary quality, the Five Why's are a structured approach to finding the root cause of a problem. In the case of a business problem, this might mean following a problem beyond our own department to uncover inter-departmental workflow issues, while in software development, this sort of root-cause analysis might lead us to find weaknesses in our architecture. The key here is not to stop asking questions when you get your first answer, because you're probably still missing something important.

In the case of my bug, the code was checking the state of a variable, but the variable wasn't a definitive indicator of the condition we were interested in. Rather, it was a variable the corresponded to the condition we were looking for most of the time. When this pattern changed, our code broke. The fix? Change our code to trap for the condition itself, not a coincidental side-effect.

Lest I lead you to believe that these problems are easy to spot, I'll assure you that many aren't. I've gotten caught a few times with the .Net framework, especially, when I've looked at the value of a .Net framework property while debugging and made assumptions about the general behavior of the property. By believing (falsely) that I knew how the framework was going to work, I left myself open to bugs.

Although it's not easy to train yourself to think this way, a questioning mindset can pay off in a better understanding of things that are really true versus the things we merely believe to be true. There's a world of difference.

Reblog this post [with Zemanta]

Printer-Friendly Calendars in Drupal

I'm maintaining a web site for a Boy Scout Troop, and I set up the Event module and associated bits and pieces a month or so ago in order to publish our calendar online.  Everything worked just fine until one of our parents pointed out that the calendars looked like drunken seagull tracks when they were printed.

Grrrrr.  So I went home and checked it out, and sure enough, the calendars wouldn't print.  So I googled for a solution and discovered that there's a great module for Drupal called, appropriately enough, "Printer Friendly".  I grabbed this, installed it, and sat back in amazement to see that my calendars now looked merely lousy, instead of the formerly illegible.  I have a feeling that the CSS powering the printer-friendly view could probably be tweaked, but I had a Plan-B up my sleeve.

The Events module also supports iCal.  So I wrote a little article explaining to everyone that we had a printer-friendly link, but we also have this cool little icon (  ) down at the bottom of the calendar that lets them load our events into Outlook, Google, or whatever toots their horns. So now, our users can grab all our events, sync them to the four corners of the globe, view them in their favorite calendaring app, and print them using *that* application!

   

Powered by ScribeFire.

Quote of the day

Here's a nice post talking about recent layoffs at an unnamed company.  Best quote:

And as a general rule, when your recently laid-off employees are looking up labour laws right afterward, you probably haven't handled things in the best possible way.

Been there, done that, looked up the laws.  Welcome the state of modern employment.

Paint.Net – more tool than I thought

paintScreenshotYou ever find out about something that's been right under your nose, and you just missed it?  I've known about Paint.Net forever.  It's a great little graphics program written in Microsoft's .Net platform.  Sort of a replacement for Paint, right?  I get it.

I didn't get it.

Think a little closer to Photoshop.  It turns out that Paint.Net has some pretty sophisticated capabilities hidden in there, including the biggie - plugin support.  There's an active community site with tutorials, tons of downloadable plugins, and more.  I downloaded some of these plugins and played with them a bit, and there's lots, lots more here than I'd been aware of.  If you don't already have a high-end graphics package, this is worth checking out.

Get free Microsoft e-Books

microsoft_booksHere's a great offer from Microsoft.  Although there certainly are moments when I wish MS would behave a little more openly, they've always, always taken great care of their developers.  Their learning programs show signs of renewed momentum with the release of Visual Studio 2008, and here's another example of that.  Just go to http://csna01.libredigital.com/?urvs5cn3s8 (sorry -- it looks like this ship has sailed) and view a chapter from any of these three books, then you'll be able to go back and download the entire book for free.  I'm looking forward to reading the LINQ book, and I'll definitely browse the Silverlight book, too.  I don't know if this is a time-limited offer, but you'd better get on it while you can!

Format Code for your blog in a web page

cs_formatter

You may have seen a comment I left in an earlier post about  a source code formatting plug-in for Microsoft Live Writer.  I still think that tool's pretty nice, but let's just say for the sake of argument that you're not a fan of Live Writer.  What's a blogger to do?

Enter the C# code formatter from manoli.net.  The name gives itself less credit than it deserves, since it also formats VB.Net, HTML, T-SQL, and MSH.  It lets you turn on line numbering and alternate line backgrounds, and colors can be manipulated with a stylesheet change.  Pretty cool.  And you can download the source code yourself and check it out if you want to see the RegEx that powers this cool tool.  Thank you, Jean-Claude.

What’s in your Start… Run dialog?

iisresetI use the Start ... Run dialog to quickly launch programs, rather than browsing through the hierarchy of shortcuts under Start.  If you've ever used the Run dialog, you'll know that is saves your last-used command, so it's there the next time you need it.

You know what's in mine???

iisreset.

You know why??

I'm debugging a web application in VS 2005.  It's an n-tier app, so I've got a solution with two projects -- a Presentation-tier web site, and a Business-tier web service.  Apparently, this is enough to throw IIS and/or Visual Studio into complete disarray, because I seem to spend more time resetting both of these than I spend on debugging.

I've tried running both of these projects using VS' built-in development web server, I've tried running both in IIS, and I've tried one in each.  I either lock up IIS or I'm not able to debug ("no symbols loaded" on my breakpoints).  I've googled this, and I've tried all of the stupid tricks in all of the articles I've read.  Some seem to help for a few minutes, and then I'm right back where I start.  I'm so sick and tired of chasing this -- words fail me.

I love the Visual Studio environment to no end, but at moments like this, I really wish I were deploying on Apache.

Does anyone have  a silver bullet for this (and spare the "switch platforms" bit -- it's not an option in this case)?