The Constant Handler

Posted in Error Handling, Programming, Work on October 27th, 2009 by andrew

We are starting a new project at work. It is always an exciting time because you get to take what you have learned recently and apply it to something fresh. You don’t have to work around the scar tissue from past patches and additions. You don’t have to work with that Frankenproject on which your company relies. Finally, you get to build something from the ground up and do it right this time.

For our new project the one thing we want to be very serious about is error handling. This is something that gets overlooked far too often in the early stages of software development and always creates problems later during testing. Most programmers have had to do battle with the error message that reads “Unexpected fatal error” or “Stack trace unavailable”. They are the worst because they not only don’t tell you where the problem occurred in the sometimes muddy river of references you have, but they also don’t give you a clue as to what failed.So here is what we think will really get the job done and also do a good job of informing us to problems later.

Identify Errors at the Source

So often is development, especially .NET development, it is easy for programmers to handle the errors they receive at the top of the event chain. We click a button that performs actions, so we put a try/catch around the event and inform the user to any errors that may occur during the process. But what does that do for us? We don’t really know where or why the error occurred. We only know that it happened whilst we tried to perform some action. So we tell the user there was an error while trying to do “A” and to try again.

But what if we were to go to the root of each process and handle the error there? we might really be able to do something! Let’s take an SQL command for example. Perhaps we have a button that searches a database for the purchase history of a customer. There are many things that could go wrong, but let’s look at just a few scenarios.

  1. The customer information you used to search returns no results.
  2. The information you use returns multiple results (assuming this is not good
  3. Some other error occurs during the query (timeout or something)

In case one, we can handle the error very easily if we return a defined error code to our client software telling it that no results were found. So now instead of “Error retrieving customer data” we get “No customer data found for these criteria”. Much more explanatory for both the user and the programmer. Case two is the same. In this case, it would tell the programmer that somehow, multiple customers with the same identification are coming up in queries designed to only find one. This would que the DBA to resolve the data conflict and the programmer to find out how it got into the database. In the third case, we have at least eliminated two other things it could have been. As we expand on our error handling, it allows us to better service the user and ourselves. That brings us to our next topic.

Handle Error at the Source

The other problem with handling errors at the top level is that you really don’t get a good chance to try and salvage proper operation without having the user know something is wrong. There are many cases where software could recover from an error without even having to tell the user something happened. For instance, let’s say we have a specialized print system that takes in printing requests for an entire company and distributes them out to printers in a certain manner. If a request comes in and the printer we are targeting is busy, there will be an error. However, if we handle the error at the low level, we can just tell the process to chill out while the printer finishes what it is doing and try again. In this way, we are able to provide a success state for our user without having to tell them that something went wrong. Why should they care that the printer queue was full?

The other way it helps us is to compartmentalize our code. If we can stop errors from propagating upwards through the call stack, we can eliminate the need to handle errors from class libraries to which we may or may not have code access. If I write a static class that will handle user identification, I can build into that class error handling so that it can intelligently depending on the error that is received. In this way, the calling class doesn’t have to worry about handling errors from class that aren’t expected. And, in any case, errors that could be passed out of the class definition should be conveyed in some manner to the programmer. Again I encourage programmers to think long and hard about what could possibly go wrong in their software and to plan for the worst. The more detailed your error messages are, the easier it is for you to fix the problem later.

Mother Tested

Not to be stereotypical, but it is true that most mothers are terrible at using computers. However, we should never underestimate their value at breaking things. If you think your program is iron-clad, let your mother, or other technically-inept acquaintance have a go at it. I guarantee they will find some input for a field that will make your program bed for mercy. Of course, this person doesn’t even need to be someone that is going to use the software. In fact, it is better that way, because they will then have a blank point of view for the situation. They won’t know what to expect or how it works. In this way, they won’t come into testing with an idea of what to do and, consequently, shall make the most grievous of mistakes.

Well, I am very tired, but thank you for reading and leave me a comment if you ever need it.

Tags:

Continual Cursing

Posted in Programming, T-SQL on October 27th, 2009 by andrew

I ran into an interesting problem at work today involving cursors. I was using a cursor to basically copy a set of rows with a change to one of the values. For simplicity lets say it looked something like this:


DECLARE @LowValue int,
@HighValue int

DECLARE cur CURSOR FOR
SELECT LowValue, HighValue
FROM Goals
WHERE Country = ‘US’

OPEN cur
FETCH NEXT FROM cur
INTO @LowValue, @HighValue
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO Goals (Country, State, LowValue, HighValue) VALUES (
SELECT ‘US’, ‘AL’, @LowValue, @HighValue)
FETCH NEXT FROM cur
INTO @LowValue, @HighValue
END

The beginning state of the table was that there were some rows from other countries, but only one set from the US. I had written a lot of cursors, so I was pretty confident in my abilities. When I ran the script, it just looped infinitely. I didn’t really understand until I started looking at the rows that were being inserted and saw that there was a pattern in the inserts as it had twice as much source material for the insert each loop.

My coworker mentioned something about different types of cursors (of which I was unaware) and, sure enough, there are some magic keywords that are very important when you are trying to insert into the table through which you are cursing. So today’s helpful hint is the STATIC keyword. When used in the cursor declaration thusly: DECLARE cur CURSOR STATIC FOR blah blah blah Everything works much better.

What I found out was that a normal cursor generates a position counter on where it is as it curses through a table. The default setting for that cursor is to blindly go through the rows until it reaches the end. Unfortunately for me, I was continuing to make rows that were appended to the table. The solution is to make the table static. In this way, the cursor will not pass through new rows as it operates. I didn’t look in to whether it simply doesn’t re-index the table after each loop or if it actually creates a temporary table that it reads, but either way it works quite brilliantly.

Cheers, mates.

Tags: , ,

T-SQL retains original state of tables in batches

Posted in Programming, T-SQL on July 13th, 2009 by andrew

So I was at work today and one of my co-workers tapped me on the shoulder and asked me to look at some T-SQL he was working on. He was working on a problem where he was adding columns dynamically to a temporary table then selecting from them at the end. The columns were taken from another table dictating columns associated with certain results. These results were different in a variety or situations so he couldn’t define the table statically.

The problem he was having was that if he used a “select * from #foobar” type query it would work just fine, but if he tried to define a list of columns to return like “select apples from #foobar”, it would tell him that column didn’t exist if it was one of the dynamically created columns.

Technical

So I spent about 2 hours trying to dissect the problem. During that process, my officemate jokingly suggested putting a GO statement before it…to make it go. I put it in to oblige our funny bones but, annoyingly enough, it made everything work. We thought about the problem and it actually makes a stupid amount of sense. When the T-SQL server is preprocessing the statement and building the execution plan, it would see the table in its static state. It would see the added columns, but it would not put them together when it went to run the select statement including column names. The reason it worked with a select * statement was because the * operator will force the system to iterate across the table instead of using an index.

The solution is to break your batch into two parts. The first part can contain the table definitions and the table modifications, but you have to place any select that uses the new columns in another batch. You can do this one of two ways. First, you can place a Go statement between the blocks, making T-SQL treat them like separate batches. The other things you can do that is a little less graceful but will allow you to keep variables in scope is to place the statement in a string and execute it using the ’sp_executesql’ function. Remember that if you use a Go statement, all local variables will be unavailable after that point.

Tags: , ,

Success in the land of opportunity

Posted in Uncategorized on June 30th, 2009 by andrew

One of my good friends, Andrew Meyer, asked me to start blogging again. As I thought about it, I decided it might be just what I need. I’ve had this site for a while, but I never really did anything meaningful except use it as a test box for various web projects. What I really want to do is discuss things that matter in my professional career.

I have been a software developer for 3 years. I really enjoy it, but wherever I look in the world I see software being used in terrible ways. I see point-of-sale units with horrid interfaces (burger shack), phones that get too loaded down with trivial things that they can’t answer calls (my BB Storm), and websites owned by large entities that quite literally lose them business (that used to be my workplace).

So what could I, a 22-year-old guy fresh out of college, have to say about all that? Quite a bit. I want to talk about common sense when designing software. I want to talk about coding standards. I want to talk about software trends and design paradigms. And I hope people will take an interest in my blog, check it out, comment, etc., and I can start making the kind of contribution I dream of.

I hope that I see you around my blog. Leave a comment, link to your blog. I want criticisms and compliments. Bring ‘um on.

Tags: , ,