Sadly, I have a legacy PHP4 system that I continuously need to add features to. It doesn't look like there will be resources to do a port to PHP5 for several months if not several years. Over the course of the past few years, one of the major things that has bothered me is not having the ability to throw exceptions cleanly. Because of this, all kinds of error checking code has to constantly interrupt the flow of what's going on.
So on to the question: What is the best strategy that you have seen to emulate the cleanliness of exception handling in languages that have no exception model?
Joel has this to say regarding exceptions as noted in an answer:
http://www.joelonsoftware.com/items/2003/10/13.html
They create too many possible exit points for a function. To write correct code, you really have to think about every possible code path through your function. Every time you call a function that can raise an exception and don't catch it on the spot, you create opportunities for surprise bugs caused by functions that terminated abruptly, leaving data in an inconsistent state, or other code paths that you didn't think about.
A better alternative is to have your functions return error values when things go wrong, and to deal with these explicitly, no matter how verbose it might be. It is true that what should be a simple 3 line program often blossoms to 48 lines when you put in good error checking, but that's life, and papering it over with exceptions does not make your program more robust. I think the reason programmers in C/C++/Java style languages have been attracted to exceptions is simply because the syntax does not have a concise way to call a function that returns multiple values, so it's hard to write a function that either produces a return value or returns an error.
However, a good exception model in a language makes the called function specify that it will in fact throw an exception. This implies that there are exaactly zero additional places for the function to exit from (the code would just return false instead of throwing an exception), but there is exactly 1 additional place for the function to exit to... The catch block of the calling function. Anyone can write sloppy code that passes all exceptions upward to be dealt with by others , but that doesn't mean you should take away a tool that can be used cleanly and efficiently.
In fact, any function can return a value that is out of range of the expected return values from the calling code. A good programmer is going to deal with all possible return values, including error codes and conditions. The exception model just gives him a way to do it cleanly.