11/27/2012

Solve the Problem, Not the Behavior

In my past life of consultancy I became very used to working on other people's code.  One of the most important lessons I learned was to "find the problem first".  Errors are a behavior you witness.  Debugging is fixing those errors.  Most developers would consider those reasonable statements.  There is an underhanded trick here though.  Some developers might make the mistake of a direct connection between the two, but there isn't.  The error you witness may not be the error you need to fix.

The problem causing the witnessed behavior may itself be a behavior of a deeper problem.  This can be true for several levels of code.  The goal of fixing the behaviors is to find the root problem.  The rabbit hole in which we travel to find the root can be very deep.

This is in my mind now, because my team and I were recently the victim of this twisted villain.  Our front end code was querying a webdav server for text data.  That data was manipulated and then inserted into the DOM.  Our customer was noticing that apostrophes were missing from the displayed text.  Apostrophes were in the source text but were being stripped out by the data retrieval steps.  

The problem seems fairly straightforward, and jQuery was involved which might make debugging difficult, so the initial idea was to just address the behavior.  If the apostrophe is being stripped out, then make sure it isn't or put it back.  The team had a casual brain storm.  Some of the ideas my co-workers had were brilliant, and I have noted them for future potential use.  The assumption was made that we can catch the code before the ajax success function processes it, change the apostrophe to something else, then change it back once the function is complete.  This would solve the problem, right?  The behavior is mitigated, apostrophes remain in place.

This is where the mantra of "Find the Problem First" comes in.  I suggessted that we debug the code to find the problem.  The ajax code was inside a load function, so we started there.  First, we made sure the apostrophe was returning from the server request.  It was.  Second, we checked the result inside the ajax success function, and it was still there.  Finally, we checked the assignment of the response text to an html node.  Amazingly, the apostrophe was still there.  The text was fully intact after leaving the load function.  Well, now what?

Next, we went to where the load function was bring called.  The culprit was staring us in the face.  A cry of anguish was heard in the office as one of my co-workers almost collapsed into spasms of frustration.  Teeth were gnashed, and sobs of 'why' were heard.  A few lines after the load function was one line of code replacing all apostrophes and quotes with nothing; a fragment of the code base inherited from an earlier developer was the one stripping the apostrophe out.  Thus ended the Case of the Errant Snippet.

The problem wasn't the apostrophe not being displayed, nor was it the ajax call, and it was not because it was being stripped out.  All were behaviors of one root cause.  The real problem was an errant piece of code that needed to be removed.

Could we have made a solution to successfully put the apostrophes back in? Yes
Is the team I work on brilliant enough to find a solution that would be transparent to the user? Yes
Would it have solved the real problem? No
Was the problem the ajax loading code as originally assummed? No
Could this have come back to bite us in the future if we had implemented the hack? Absolutely

I try to keep a few things in mind when errors occur:

  • Never assume you know where the problem is, or the most likely cause.
  • Use debugging tools as much as possible.
  • Find the transition point.  It's important to see the bad values show up in the code before the error.
  • Don't fix the behavior, fix it before it becomes a behavior.

The errant code snippet case was not without a silver lining.  My colleauge put a post-it note on his monitor after the issue was resolved.  It reads "Find the Problem First".