That’s an interesting thread and an interesing point by the questioner about REST services returning 404 as a regular flow state rather than an error. That obviously wouldn’t have been the case for HTTP servers that were serving only HTML when Indy was first written.
The point of that part of the exercise, for me, was to understand how expensive exceptions are
I was pretty sure that was what you were doing.
Also, just saying, if you google “exceptions are bad and should be avoided” … there’s plenty of discussion.
I’ve just been involved in porting some C code to Delphi. C has no exceptions so that code had lots of checking of boolean return values, and lots of special case return values e.g. -1 indicating an error.
After we completed the line by line exact translation to Delphi, I went back and Delphi-fied the code. One of the things I did was to replace most of those boolean and special case return values with exceptions.
It simplified the code considerably. Being able to remove all those return value checks reduced the line count of some of those calling functions substantially and as a result they are much more readable now.
There were just a few instances in the translated Delphi code where I left the return values in. From memory they were in sections where the original code was taking a trial and error approach within a tight loop. If I’d converted those functions to use exceptions I would have seen the kinds of performance issues you’ve been documenting.
Within the rest of the translated C to Delphi code almost all the checks of the return values basically emulated the behaviour of exceptions anyway. A function returned a failure, the calling function detects that failure and then itself returned a failure, and so on right back to the original caller.
It’s pretty common to see that sort of return value based error checking code follow that “exception lite” pattern, of just giving up and returning all the way back to the original caller. In my opinion that’s because writing meaningful error recovery code is in most cases just too damn hard.
Return values can make sense at the micro level but at the macro level exceptions are usually my tool of choice.