21

How do you go about teaching Exception Handling to Programmers. All other things are taught easily - Data Structures, ASP.NET, WinForms, WPF, WCF - you name it, everything can be taught easily.

With Exception Handling, teaching them try-catch-finally is just the syntactic nature of Exception Handling.

What should be taught however is - What part of your code do you put in the try block? What do you do in the catch block?

Let me illustrate it with an example.

You are working on a Windows Forms Project (a small utility) and you have designed it as below with 3 different projects.

  1. UILayer
  2. BusinessLayer
  3. DataLayer

If an Exception (let us say of loading an XDocument throws an exception) is raised at DataLayer (the UILayer calls BusinessLayer which in turns calls the DataLayer), do you just do the following

//In DataLayer
try {
    XDocument xd_XmlDocument = XDocument.Load("systems.xml");
} 
catch(Exception ex)
{
    throw ex;
}

which gets thrown again in the BusinessLayer and which is caught in UILayer where I write it to the log file?

Is this how you go about Exception Handling?

Andres F.
  • 5,119
  • 2
  • 29
  • 41
Kanini
  • 2,248
  • 5
  • 24
  • 28
  • 15
    If you _were_ going to do that, you don't want to catch(Exception ex) { throw ex; } - instead just catch { throw; } – Steven Evers Oct 26 '10 at 16:40
  • 4
    Lets not forget about finally blocks ? – Chris Oct 26 '10 at 16:42
  • 1
    You should specify the language in the tags. You're getting into more detail than is common to most implementations of exceptions, and ignoring things outside the blocks. In C++, for example, the most important part of exception handling is knowing how to write exception-safe programs. – David Thornley Oct 26 '10 at 20:42
  • possible duplicate of [Improving exception handling?](http://programmers.stackexchange.com/questions/48895/improving-exception-handling) and of [Efficient try / catch block usage?](http://programmers.stackexchange.com/questions/145941/efficient-try-catch-block-usage) – gnat Apr 30 '13 at 07:05
  • I hope you know it is a bad idea to catch any "Exception". You should have nested catch blocks to catch specific exceptions and handle them accordingly(not just throw the exception). – minusSeven Jun 18 '13 at 05:41

9 Answers9

29

To explain exception handling, explain the concept behind it: The code where an error occurs frequently does not know how to properly handle that error. The code that knows how to handle it properly could be the function that called that one, or it could be further up the call stack.

When you write a routine that calls a routine that might throw an exception, if you know how to handle that error correctly, put the call in a try block and put the error-handling code in the catch block. If not, leave it alone and let something above you in the call stack handle the error.

Saying "catch ex, throw ex" is not a good way to do exception handling, since it doesn't actually handle anything. Plus, depending on how the exception model in your language works, that can actually be harmful if it clears stack trace information that you could have used to debug the issue. Just let the exception propagate up the call stack until it hits a routine that knows how to handle it.

Mason Wheeler
  • 82,151
  • 24
  • 234
  • 309
  • 4
    +1 for "... since it doesn't actually handle anything", people new to exception handling so often think catching means handling and don't realize if you don't do something to repair the problem, it's *not* exception handling, just code bloat. – Jimmy Hoffa Oct 26 '12 at 20:41
13

Like most things, exceptions and exception handling will likely seem like a solution in search of a problem to new programmers until you show why the seemingly simpler solution (C-style return codes and errno) works so poorly. I would start out by motivating the problem and putting it in context. Show how error handling could be done using return codes or global/static variables. Then give examples of why it doesn't work well. Then and only then, introduce exceptions and explain that they're a form of out-of-band signaling and that the whole point is that the default behavior if you ignore an exception is to pass the buck up the call stack to someone who can handle it.

Bottom line: Showing how error handling was done in C will make the students understand what exceptions are really for and why catching exceptions that you can't really handle is basically simulating the way things were done in the Dark Ages.

dsimcha
  • 17,224
  • 9
  • 64
  • 81
  • 2
    +1 for the teaching practice of leading them in the traditional C style return codes and error numbers and showing them that it works poorly and therefore, teaching them how it will work is a brilliant! – Kanini Nov 02 '10 at 07:47
  • 3
    @Kanini: In general I think most relatively new/high level constructs seem like solutions in search of problems and are easy to use wrong if you don't understand what problem they were meant to solve and why they were invented. – dsimcha Nov 02 '10 at 17:02
  • I agree that showing how it would be done without exceptions is good, but then comes the burden of explaining when to use exceptions and when to use other technics (because not all situations are exceptional) – Matthieu M. Nov 04 '10 at 18:50
  • @Matthieu: Right. But if you understand what historical problems exceptions are meant to solve, rather than learning about them in a vacuum, it becomes more obvious that it's silly to use them for non-exceptional situations. – dsimcha Nov 04 '10 at 18:56
  • right, that's why you got my +1. I just felt your answer could be interpreted as "never use another mechanism" :) – Matthieu M. Nov 04 '10 at 19:01
5

I would start with Design Guidelines for Exceptions its short and includes DO, DO NOT and AVOID. It also gives the reasons why.

In your example case the revelvent section would be Wrapping Exceptions

And would expect it to be written this way. Note that it catches a specific exception and attempts to add information so that a more meaningful message is propagated. Also note that the inner exception is still maintained for logging purposes

//In DataLayer

try
{
XDocument xd_XmlDocument = XDocument.Load("systems.xml");
}
catch(FileNotFoundException ex)
{
        throw new TransactionFileMissingException(
                     "Cannot Access System Information",ex);
}

UPDATE Kanini asks is it even right to have this exception block in the Data Layer or should the checking the file be available to Business Layer.

Well first I'd like to point out that the rationale for Wrapping Exceptions is this

Consider wrapping specific exceptions thrown from a lower layer in a more appropriate exception, if the lower layer exception does not make sense in the context of the higher-layer operation.

So if you feel that have a higher layer should know about the file at all then your data layer should look like this

//In DataLayer

XDocument xd_XmlDocument = XDocument.Load("systems.xml");

No Try No Catch.

Personally I feel that unless your data layer can do something usefull like use a default systems.xml that is an assembly resource, doing nothing or wrapping the exception is a good bet since your logging will tell you what method and what file was the problem. (throw ex in this case or the preferred throw does too but adds no value). This means that once identified you'll be able to fix the problem quickly.

As an asside this particular example also has the following problem in that XDocument.Load can throw four execeptions

  • ArgumentNullException
  • SecurityException
  • FileNotFoundException
  • UriFormatException

We cannot safely guarantee that the following code won't throw and FileNotFoundException, simply because it could be there when we do existence check and gone when we do load. Having that available to the business layer would not help.

 if (File.Exists("systems.xml")) 
     XDocument.Load("systems.xml");

SecurityException is even worse because among other reasons for this being thrown if another process grabs has an exclusive file lock you'll won't get the error until you try an open it for reading because there's no File.CanIOpenThis() method. And if such a method existed you still have the same problem as with File.Exists

Conrad Frix
  • 4,155
  • 2
  • 18
  • 34
  • Fix: Thanks! But is it even right to have this exception block in the Data Layer? Should the whole thing of checking if the File is Available or Not not be in Business Layer? Otherwise, I do agree to your method of writing the code. – Kanini Oct 28 '10 at 04:40
  • Fix: In my native language, Kanini means a Computer whereas Kani means a fruit ;-) – Kanini Nov 02 '10 at 04:30
  • I can tell you're not too upset by my error, but I am very sorry and I have corrected it. – Conrad Frix Nov 02 '10 at 05:06
  • 1
    Fix: Upset? Not at all. Largely amused. My brother has not stopped laughing since I pointed this out to him primarily because, I do not resemble a fruit in anyway except maybe for the odd-shape... – Kanini Nov 02 '10 at 07:52
4

Lets do a role play. (this is not a joke post)

You should do a workshop where you act out the call chain. Each person is an object. You'll need some newbies and some people who understand the "game" helps.

Use a really simple issue like file IO. gui->model->file_io

The person being the file reader needs to tell the next one up....

First do it with return codes. ( use post-it notes ?)

if the interactions are just "what the code says" pretty soon you can get people to realize that exceptions are exceptional.

for return codes, pass a post-it note.

for exceptions, throw your hands in the air and say what the problem is.

then get them to do "catch x, throw x" and see ho much worse the diagnosis is what the GUI just gets "the model had an exception".

I think this will work to train the people you have because people understand interactions with other people pretty well.

Tim Williscroft
  • 3,563
  • 1
  • 21
  • 26
  • +1 for the role play idea. We never thought of it earlier. Whoever could have thought teaching programming could be done through Role Play? – Kanini Nov 03 '10 at 01:55
1

I would imagine to understand exceptions you first need to understand the child/parent relationship of classes for example. If you understand that a child can inherit functionality from a parent, they might be able to on an elementary level understand that if a child has a problem it cannot handle it will pass this problem (exception) up to its parent and let the parent deal with it.

This becomes a chained relation until you end up with a place where something knows how to handle the exception.

And as far as finally goes this is the trivial part... when a problem occurs something has to handle it so the program does not exit fatally, after that exception is handled the finally block is there which will always execute regardless of the try catch.

A good example of this might be with networking:

  • we make connection
  • connection is ok so we use it
  • when finished we close up and free resources

or in exception case:

  • make a connection
  • an exception occurs which something handles
  • at whichi point we free up connection and resources associated
Chris
  • 5,663
  • 3
  • 28
  • 39
1

Give an Application to the newbie which has very good Exception handling in it. Throw some exception somewhere and let them debug it with the help of Logs. By tracking the propogation of Exception they should be able to debug it. Do this exercise 3 or 4 times. Now just remove all the Exception handling from the code and let them try to track the same exception.

I believe the appreciation for the Exception Handling code will be instantly appreciated.

Geek
  • 3,951
  • 1
  • 24
  • 29
  • Sounds like a plan. Do you have any sample code available in the Internet (say, sourceforge.net) that you would recommend? – Kanini Nov 03 '10 at 01:52
0

IMO, you should think that exception handling and flow control statements are basically the same. You use them to control the flow of your programs based on what condition they are currently in. The difference is exception handling only will react when an error (or exception) occurs.

  • @denny: While I agree with the "exception handling only will react when an error (or exception) occurs", I am quite not sure about the statement that "exception handling and flow control statements are basically the same". I respectfully disagree there. The catch block admittedly does what it should do under that condition. The try block however is not at all about flow or control. The finally block, again is not at all about flow or control. Maybe, I misunderstood your answer, but can you clarify for the benefit of me and others? – Kanini Nov 02 '10 at 07:46
0

It probably wouldn't help a new programmer, but I found that I understood the concept of exceptions a lot better once I started using monads in functional programming. A monad forces you to consider every "channel" through which data can travel into or out of a program, since all it does it provide a convenient abstraction to "hide" some of that data flow.

The idea that a function can have different types of output, and an exception is like a higher-priority type of return from the function is pretty neat.

Mind you, I understand that isn't how exceptions work in most language (implementation details), but in an abstract sense, that's what is happening.

CodexArcanum
  • 3,421
  • 21
  • 23
0

Pretend a monkey is using the keyboard

I used to tell my guys when they are writing code to pretend that a monkey will be sitting at the keyborad and using this application.

This taught them how to anticipate all kinds of things:

  • Missing data
  • Missing files
  • Alpha characters when you expect numbers
  • Division by zero

I think it was the word picture of having a monkey just banging keys and doing whatever it wanted instead of following along nicely that did the trick. It worked for me.